1  /* { dg-additional-options "-fanalyzer-fine-grained" }
       2     -fanalyzer-fine-grained is currently required; see PR analyzer/107851.  */
       3  
       4  #include <stdlib.h>
       5  #include <stdio.h>
       6  #include <stdint.h>
       7  
       8  /* Tests with symbolic buffer sizes.  */
       9  
      10  void test_1 (int32_t n)
      11  {
      12    int16_t *ptr = malloc (n * sizeof (int16_t));
      13    free (ptr);
      14  }
      15  
      16  void test_2 (int32_t n)
      17  {
      18    int32_t *ptr = malloc (n * sizeof (int16_t)); /* { dg-line malloc2 } */
      19    free (ptr);
      20  
      21    /* { dg-warning "allocated buffer size is not a multiple of the pointee's size \\\[CWE-131\\\]" "warning" { target *-*-* } malloc2 } */
      22    /* { dg-message "'\[a-z0-9\\*\\(\\)\\s\]*' bytes" "note" { target *-*-* } malloc2 } */
      23    /* { dg-message "'int32_t \\*' (\\\{aka '(long )?int \\*'\\\})? here; 'sizeof \\(int32_t (\\\{aka (long )?int\\\})?\\)' is '4" "note" { target *-*-* } malloc2 } */
      24  }
      25  
      26  void test_3 (int32_t n)
      27  {
      28    void *ptr = malloc (n * sizeof (int16_t));
      29    int16_t *sptr = (int16_t *)ptr;
      30    free (sptr);
      31  }
      32  
      33  void test_4 (int32_t n)
      34  {
      35    void *ptr = malloc (n * sizeof (int16_t)); /* { dg-message "'\[a-z0-9\\*\\(\\)\\s\]*'" "note" } */
      36    int32_t *iptr = (int32_t *)ptr; /* { dg-line assign4 } */
      37    free (iptr);
      38  
      39    /* { dg-warning "allocated buffer size is not a multiple of the pointee's size \\\[CWE-131\\\]" "warning" { target *-*-* } assign4 } */
      40    /* { dg-message "'int32_t \\*' (\\\{aka '(long )?int \\*'\\\})? here; 'sizeof \\(int32_t (\\\{aka (long )?int\\\})?\\)' is '4'" "note" { target *-*-* } assign4 } */
      41  }
      42  
      43  void test_5 (void)
      44  {
      45    int32_t user_input;
      46    scanf("%i", &user_input);
      47    int32_t n;
      48    if (user_input == 0)
      49      n = 3 * user_input * sizeof (int16_t);
      50    else
      51      n = 5 * user_input * sizeof (int16_t);
      52    void *ptr = malloc (n);
      53    int16_t *sptr = (int16_t *)ptr;
      54    free (sptr);
      55  }
      56  
      57  void test_6 (void)
      58  {
      59    int32_t user_input;
      60    scanf("%i", &user_input);
      61    int32_t n;
      62    if (user_input == 0)
      63      n = user_input;
      64    else if (user_input == 2)
      65      n = user_input * 3;
      66    else
      67      n = user_input * 5;
      68    /* n is an unknown_svalue at this point.  */
      69    void *ptr = malloc (n);
      70    int32_t *iptr = (int32_t *)ptr;
      71    free (iptr);
      72  }
      73  
      74  void *create_buffer(int32_t n)
      75  {
      76    return malloc(n);
      77  }
      78  
      79  void test_7(int32_t n) 
      80  {
      81    int32_t *buf = create_buffer(n * sizeof (int32_t));
      82    free (buf);
      83  }
      84  
      85  void test_8(int32_t n) 
      86  {
      87    /* FIXME: At the moment, region_model::set_value (lhs, <return_value>)
      88       is called at the src_node of the return edge. This edge has no stmts
      89       associated with it, leading to a rejection of the warning inside
      90       impl_region_model_context::warn. To ensure that the indentation
      91       in the diagnostic is right, the warning has to be emitted on an EN
      92       that is after the return edge.  */
      93    int32_t *buf = create_buffer(n * sizeof(int16_t)); /* { dg-warning "" "" { xfail *-*-* } } */
      94    free (buf);
      95  }
      96  
      97  void test_9 (void)
      98  {
      99    int32_t n;
     100    scanf("%i", &n);
     101    /* n is a conjured_svalue.  */
     102    void *ptr = malloc (n); /* { dg-message "'n' bytes" "note" } */
     103    int32_t *iptr = (int32_t *)ptr; /* { dg-line assign9 } */
     104    free (iptr);
     105  
     106    /* { dg-warning "allocated buffer size is not a multiple of the pointee's size \\\[CWE-131\\\]" "warning" { target *-*-* } assign9 } */
     107    /* { dg-message "'int32_t \\*' (\\\{aka '(long )?int \\*'\\\})? here; 'sizeof \\(int32_t (\\\{aka (long )?int\\\})?\\)' is '4'" "note" { target *-*-* } assign9 } */
     108  }
     109  
     110  void test_11 (void)
     111  {
     112    int32_t n;
     113    scanf("%i", &n);
     114    void *ptr = malloc (n);
     115    if (n == sizeof (int32_t))
     116      {
     117        /* n is a conjured_svalue but guarded such that we
     118           know the value is a multiple of sizeof (*iptr).  */
     119        int32_t *iptr = (int32_t *)ptr;
     120        free (iptr);
     121      }
     122    else
     123      free (ptr);
     124  }
     125  
     126  void test_12 (void)
     127  {
     128    int32_t n;
     129    scanf("%i", &n);
     130    void *ptr = malloc (n); /* { dg-message "'n' bytes" } */
     131    if (n == 5)
     132      {
     133        /* n is a conjured_svalue but guarded such that we
     134           know the value isn't a multiple of sizeof (*iptr).  */
     135        int32_t *iptr = (int32_t *)ptr; /* { dg-line assign12 } */
     136        free (iptr);
     137      }
     138    else
     139      free (ptr);
     140    /* { dg-warning "allocated buffer size is not a multiple of the pointee's size \\\[CWE-131\\\]" "warning" { target *-*-* } assign12 } */
     141    /* { dg-message "'int32_t \\*' (\\\{aka '(long )?int \\*'\\\})? here; 'sizeof \\(int32_t (\\\{aka (long )?int\\\})?\\)' is '4'" "note" { target *-*-* } assign12 } */
     142  }
     143  
     144  void test_13 (void)
     145  {
     146    int32_t n;
     147    scanf("%i", &n);
     148    void *ptr = malloc (n);
     149    if (n == n * n)
     150      {
     151        /* n is a conjured_svalue but guarded such that we don't have an
     152           equivalence class for it. In such cases, we assume that the
     153           condition ensures that the value is okay.  */
     154        int32_t *iptr = (int32_t *)ptr;
     155        free (iptr);
     156      }
     157    else
     158      free (ptr);
     159  }