(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
analyzer/
malloc-1.c
       1  /* { dg-require-effective-target alloca } */
       2  
       3  #include <stdlib.h>
       4  
       5  extern int foo (void);
       6  extern int bar (void);
       7  extern void could_free (void *);
       8  extern void cant_free (const void *); /* since it's a const void *.  */
       9  
      10  void test_1 (void)
      11  {
      12    void *ptr = malloc (1024);
      13    free (ptr);
      14    free (ptr); /* { dg-warning "double-'free' of 'ptr'" } */
      15  }
      16  
      17  void test_2 (void *ptr)
      18  {
      19    free (ptr);
      20    free (ptr); /* { dg-warning "double-'free' of 'ptr'" } */
      21  }
      22  
      23  void test_2a (void *ptr)
      24  {
      25    __builtin_free (ptr);
      26    __builtin_free (ptr); /* { dg-warning "double-'free' of 'ptr'" } */
      27  }
      28  
      29  int *test_3 (void)
      30  {
      31    int *ptr = (int *)malloc (sizeof (int));
      32    *ptr = 42; /* { dg-warning "dereference of possibly-NULL 'ptr' \\\[CWE-690\\\]" } */
      33    return ptr;
      34  }
      35  
      36  int *test_3a (void)
      37  {
      38    int *ptr = (int *)__builtin_malloc (sizeof (int));
      39    *ptr = 42; /* { dg-warning "dereference of possibly-NULL 'ptr' \\\[CWE-690\\\]" } */
      40    return ptr;
      41  }
      42  
      43  int *test_4 (void)
      44  {
      45    int *ptr = (int *)malloc (sizeof (int));
      46    if (ptr)
      47      *ptr = 42;
      48    else
      49      *ptr = 43; /* { dg-warning "dereference of NULL 'ptr' \\\[CWE-476\\\]" } */
      50    return ptr;
      51  }
      52  
      53  int test_5 (int *ptr)
      54  {
      55    free (ptr);
      56    return *ptr; /* { dg-warning "use after 'free' of 'ptr'" } */
      57  }
      58  
      59  void test_6 (void *ptr)
      60  {
      61    void *q;
      62    q = ptr;
      63    free (ptr);
      64    free (q); /* { dg-warning "double-'free' of 'q'" } */
      65    /* The above case requires us to handle equivalence classes in
      66       state transitions.  */
      67  }
      68  
      69  void test_7 (void)
      70  {
      71    void *ptr = malloc(4096);
      72    if (!ptr)
      73      return;
      74    __builtin_memset(ptr, 0, 4096);
      75    free(ptr);
      76  }
      77  
      78  void *test_8 (void)
      79  {
      80    void *ptr = malloc(4096);
      81    if (!ptr)
      82      return NULL;
      83    __builtin_memset(ptr, 0, 4096);
      84    return ptr;
      85    /* This needs phi nodes to affect equivalence classes, or we get a false report
      86       of a leak.  */
      87  }
      88  
      89  void test_9 (void)
      90  {
      91    void *ptr = malloc (1024);
      92  
      93    int i;
      94    for (i = 0; i < 1024; i++)
      95      free (ptr); /* { dg-warning "double-'free' of 'ptr'" } */
      96  }
      97  
      98  void test_10 (void)
      99  {
     100    void *ptr = malloc (1024);
     101  
     102    int i;
     103    for (i = 0; i < 1024; i++)
     104      foo ();
     105  
     106    free (ptr);
     107    free (ptr); /* { dg-warning "double-'free' of 'ptr'" } */ 
     108  }
     109  
     110  void test_11 (void)
     111  {
     112    void *ptr = malloc (1024);
     113  
     114    while (foo ())
     115      bar ();
     116  
     117    free (ptr);
     118    free (ptr); /* { dg-warning "double-'free' of 'ptr'" } */
     119  }
     120  
     121  void test_12 (void)
     122  {
     123    void *ptr = malloc (1024);
     124  
     125    while (1)
     126      {
     127        free (ptr);
     128        free (ptr); /* { dg-warning "double-'free' of 'ptr'" } */
     129      }
     130  }
     131  
     132  void test_13 (void)
     133  {
     134    void *p = malloc (1024); /* { dg-message "allocated here" } */
     135    void *q = malloc (1024);
     136  
     137    foo ();
     138    if (!q)
     139      {
     140        free (q);
     141        return; /* { dg-warning "leak of 'p'" } */ 
     142      }
     143    bar ();
     144    free (q);
     145    free (p);
     146  }
     147  
     148  void test_14 (void)
     149  {
     150    void *p, *q;
     151    p = malloc (1024);
     152    if (!p)
     153      return;
     154  
     155    q = malloc (1024);
     156    if (!q)
     157      {
     158        free (p);
     159        free (q);
     160        /* oops: missing "return".  */
     161      }
     162    bar ();
     163    free (q); /* Although this looks like a double-'free' of q,
     164  	       it's known to be NULL for the case where free is
     165  	       called twice on it.  */
     166    free (p); /* { dg-warning "double-'free' of 'p'" } */
     167  }
     168  
     169  void test_15 (void)
     170  {
     171    void *p = NULL, *q = NULL;
     172  
     173    p = malloc (1024);
     174    if (!p)
     175      goto fail;
     176  
     177    foo ();
     178  
     179    q = malloc (1024);
     180    if (!q)
     181      goto fail;
     182  
     183    bar ();
     184  
     185   fail:
     186    free (q);
     187    free (p);
     188  }
     189  
     190  void test_16 (void)
     191  {
     192    void *p, *q; /* { dg-message "region created on stack here" } */
     193  
     194    p = malloc (1024);
     195    if (!p)
     196      goto fail;
     197  
     198    foo ();
     199  
     200    q = malloc (1024);
     201    if (!q)
     202      goto fail;
     203  
     204    bar ();
     205  
     206   fail:
     207    free (q); /* { dg-warning "use of uninitialized value 'q'" } */
     208    free (p);
     209  }
     210  
     211  void test_17 (void)
     212  {
     213    void *ptr = malloc (1024); /* { dg-message "allocated here" } */
     214  } /* { dg-warning "leak of 'ptr'" } */ 
     215  
     216  void test_18 (void)
     217  {
     218    void *ptr = malloc (64); /* { dg-message "allocated here" } */
     219    ptr = NULL; /* { dg-warning "leak of 'ptr'" } */ 
     220  }
     221  
     222  void test_19 (void)
     223  {
     224    void *ptr = malloc (64);
     225    free (ptr);
     226    ptr = NULL;
     227    free (ptr);
     228  }
     229  
     230  void *global_ptr_20;
     231  
     232  void test_20 (void)
     233  {
     234    global_ptr_20 = malloc (1024);
     235  }
     236  
     237  int *test_21 (int i)
     238  {
     239    int *ptr = malloc (sizeof (int));
     240    if (!ptr)
     241      abort ();
     242    *ptr = i;
     243    return ptr;
     244  }
     245  
     246  void test_22 (void)
     247  {
     248    void *ptr = malloc (1024);
     249  
     250    int i;
     251    for (i = 5; i < 10; i++)
     252      foo ();
     253  
     254    free (ptr);
     255    free (ptr); /* { dg-warning "double-'free' of 'ptr'" } */ 
     256  }
     257  
     258  int *test_23 (int n)
     259  {
     260    int *ptr = (int *)calloc (n, sizeof (int));
     261    ptr[0] = 42; /* { dg-warning "dereference of possibly-NULL 'ptr' \\\[CWE-690\\\]" } */
     262    return ptr;
     263  }
     264  
     265  int *test_23a (int n)
     266  {
     267    int *ptr = (int *)__builtin_calloc (n, sizeof (int));
     268    ptr[0] = 42; /* { dg-warning "dereference of possibly-NULL 'ptr' \\\[CWE-690\\\]" } */
     269    return ptr;
     270  }
     271  
     272  int test_24 (void)
     273  {
     274    void *ptr = __builtin_alloca (sizeof (int)); /* { dg-message "region created on stack here" } */
     275    free (ptr); /* { dg-warning "'free' of 'ptr' which points to memory on the stack \\\[CWE-590\\\]" } */
     276  }
     277  
     278  int test_25 (void)
     279  {
     280    char tmp[100]; /* { dg-message "region created on stack here" } */
     281    void *p = tmp;
     282    free (p); /* { dg-warning "'free' of 'p' which points to memory on the stack \\\[CWE-590\\\]" } */
     283    /* TODO: more precise messages here.  */
     284  }
     285  
     286  char global_buffer[100]; /* { dg-message "region created here" } */
     287  
     288  int test_26 (void)
     289  {
     290    void *p = global_buffer;
     291    free (p); /* { dg-warning "'free' of 'p' which points to memory not on the heap \\\[CWE-590\\\]" } */
     292    /* TODO: more precise messages here.  */
     293  }
     294  
     295  struct coord {
     296    float x;
     297    float y;
     298  };
     299  
     300  struct coord *test_27 (void)
     301  {
     302    struct coord *p = (struct coord *) malloc (sizeof (struct coord)); /* { dg-message "this call could return NULL" } */
     303    p->x = 0.f;  /* { dg-warning "dereference of possibly-NULL 'p' \\\[CWE-690\\\]" } */
     304  
     305    /* Only the first such usage should be reported: */
     306    p->y = 0.f;
     307  
     308    return p;
     309  }
     310  
     311  struct coord *test_28 (void)
     312  {
     313    struct coord *p = NULL;
     314    p->x = 0.f; /* { dg-warning "dereference of NULL 'p' \\\[CWE-476\\\]" } */
     315  
     316    /* Only the first such usage should be reported: */
     317    p->y = 0.f;
     318  
     319    return p;
     320  }
     321  
     322  struct link
     323  {
     324    struct link *m_ptr;
     325  };
     326  
     327  struct link *test_29 (void)
     328  {
     329    struct link *res = (struct link *)malloc (sizeof (struct link));
     330    if (!res)
     331      return NULL;
     332    res->m_ptr = (struct link *)malloc (sizeof (struct link));
     333    return res;
     334  }
     335  
     336  struct link *test_29a (void)
     337  {
     338    struct link *res = (struct link *)malloc (sizeof (struct link));
     339    if (!res)
     340      return NULL;
     341    res->m_ptr = (struct link *)malloc (sizeof (struct link));
     342    if (!res->m_ptr)
     343      {
     344        free (res);
     345        return NULL;
     346      }
     347    res->m_ptr->m_ptr = (struct link *)malloc (sizeof (struct link));
     348    return res;
     349  }
     350  
     351  /* Without consolidation by EC, this one shows two leaks:
     352       warning: leak of '<unknown>'
     353       warning: leak of 'tmp.m_ptr' 
     354     We should only show the latter (favoring the most user-readable
     355     expression in the equivalence class).  */
     356  void test_30 (void)
     357  {
     358    struct link tmp;
     359    tmp.m_ptr = (struct link *)malloc (sizeof (struct link)); /* { dg-message "allocated here" } */
     360  } /* { dg-warning "leak of 'tmp.m_ptr'" } */ 
     361  /* { dg-bogus "leak of '<unknown>'" "leak of unknown" { target *-*-* } .-1 } */
     362  
     363  void test_31 (void)
     364  {
     365    struct link tmp;
     366    void *ptr = malloc (sizeof (struct link)); /* { dg-message "allocated here" } */
     367    tmp.m_ptr = (struct link *)ptr;
     368  } /* { dg-warning "leak of 'ptr'" } */ 
     369  /* { dg-bogus "leak of 'tmp.m_ptr'" "" { target *-*-* } .-1 } */
     370  
     371  void test_32 (void)
     372  {
     373    void *ptr = malloc (1024);
     374    could_free (ptr);
     375  } /* { dg-bogus "leak" } */
     376  
     377  void test_33 (void)
     378  {
     379    void *ptr = malloc (1024); /* { dg-message "allocated here" } */
     380    cant_free (ptr);
     381  } /* { dg-warning "leak of 'ptr'" } */ 
     382  
     383  void test_34 (void)
     384  {
     385    float *q;
     386    struct coord *p = malloc (sizeof (struct coord));
     387    if (!p)
     388      return;
     389    p->x = 0.0f;
     390    q = &p->x;
     391    free (p);
     392    *q = 1.0f; /* { dg-warning "use after 'free' of 'q'" } */
     393  };
     394  
     395  int test_35 (void)
     396  {
     397    void *ptr = malloc(4096);
     398    if (!ptr)
     399      return -1;
     400    __builtin_memset(ptr, 0, 4096);
     401    free(ptr);
     402    return 0;
     403  }
     404  
     405  void test_36 (void)
     406  {
     407    void *ptr = malloc(4096);
     408    if (!ptr)
     409      return;
     410    __builtin_memset(ptr, 0, 4096);
     411    free(ptr);
     412  }
     413  
     414  void *test_37a (void)
     415  {
     416    void *ptr = malloc(4096); /* { dg-message "this call could return NULL" } */
     417    __builtin_memset(ptr, 0, 4096); /* { dg-warning "use of possibly-NULL 'ptr' where non-null expected \\\[CWE-690\\\]" } */
     418    return ptr;
     419  }
     420  
     421  int test_37b (void)
     422  {
     423    void *p = malloc(4096);
     424    void *q = malloc(4096); /* { dg-message "this call could return NULL" } */
     425    if (p) {
     426      __builtin_memset(p, 0, 4096); /* Not a bug: checked */
     427    } else {
     428      __builtin_memset(q, 0, 4096); /* { dg-warning "use of possibly-NULL 'q' where non-null expected \\\[CWE-690\\\]" } */
     429    }
     430    free(p);
     431    free(q);
     432    return 0;
     433  }
     434  
     435  extern void might_use_ptr (void *ptr);
     436  
     437  void test_38(int i)
     438  {
     439    void *p;
     440  
     441    p = malloc(1024);
     442    if (p) {
     443      free(p);
     444      might_use_ptr(p); /* { dg-warning "use after 'free' of 'p'" "" { xfail *-*-* } } */
     445      // TODO: xfail
     446    }
     447  }
     448  
     449  int *
     450  test_39 (int i)
     451  {
     452    int *p = (int*)malloc(sizeof(int*)); /* { dg-message "this call could return NULL" } */
     453    *p = i; /* { dg-warning "dereference of possibly-NULL 'p' \\\[CWE-690\\\]" } */
     454    return p;
     455  }
     456  
     457  int *
     458  test_40 (int i)
     459  {
     460    int *p = (int*)malloc(sizeof(int*)); /* { dg-message "region created on heap here" } */
     461    i = *p; /* { dg-warning "dereference of possibly-NULL 'p' \\\[CWE-690\\\]" "possibly-null" } */
     462    /* { dg-warning "use of uninitialized value '\\*p'" "uninit" { target *-*-*} .-1 } */
     463    return p;
     464  }
     465  
     466  char *
     467  test_41 (int flag)
     468  {
     469    char *buffer;
     470  
     471    if (flag) {
     472      buffer = (char*)malloc(4096);
     473    } else {
     474      buffer = NULL;
     475    }
     476  
     477    buffer[0] = 'a'; /* { dg-warning "dereference of possibly-NULL 'buffer' \\\[CWE-690\\\]" "possibly-NULL" } */
     478    /* { dg-warning "dereference of NULL 'buffer' \\\[CWE-476\\\]" "NULL" { target *-*-* } .-1 } */
     479  
     480    return buffer;
     481  }
     482  
     483  void test_42a (void)
     484  {
     485    void *p = malloc (1024); /* { dg-message "allocated here" } */
     486    free (p + 64); /* this could well corrupt the heap.  */
     487    /* TODO: ^^^ we should warn about this.  */
     488  } /* { dg-warning "leak of 'p'" } */
     489  /* TODO: presumably we should complain about the bogus free, but then
     490     maybe not complain about the leak.  */
     491  // CWE-761: Free of Pointer not at Start of Buffer
     492  
     493  void test_42b (void)
     494  {
     495    void *p = malloc (1024); /* { dg-message "allocated here" } */
     496    free (p - 64); /* this could well corrupt the heap.  */
     497    /* TODO: ^^^ we should warn about this.  */
     498  } /* { dg-warning "leak of 'p'" } */
     499  /* TODO: presumably we should complain about the bogus free, but then
     500     maybe not complain about the leak.  */
     501  // CWE-761: Free of Pointer not at Start of Buffer
     502  
     503  void test_42c (void)
     504  {
     505    void *p = malloc (1024);
     506    void *q = p + 64;
     507    free (q - 64); /* this is probably OK.  */
     508  } /* { dg-bogus "leak of 'p'" } */
     509  
     510  void *
     511  test_42d (void)
     512  {
     513    void *p = malloc (1024);
     514    void *q = p + 64;
     515    return q;
     516  } /* { dg-bogus "leak of 'p'" } */
     517  
     518  #if 0
     519  void test_31 (void *p)
     520  {
     521    void *q = realloc (p, 1024);
     522    free (p); /* FIXME: this is a double-'free'.  */
     523    free (q);
     524  }
     525  
     526  void test_32 (void)
     527  {
     528    void *p = malloc (64);
     529    p = realloc (p, 1024); /* FIXME: this leaks if it fails.  */
     530    free (p);
     531  }
     532  #endif
     533  
     534  struct link global_link;
     535  
     536  void test_43 (void)
     537  {
     538    global_link.m_ptr = malloc (sizeof (struct link)); /* { dg-message "allocated here" } */
     539    global_link.m_ptr = NULL; /* { dg-warning "leak of 'global_link.m_ptr'" } */
     540  }
     541  
     542  struct link *global_ptr;
     543  
     544  void test_44 (void)
     545  {
     546    global_ptr = malloc (sizeof (struct link));
     547    if (!global_ptr)
     548      return;
     549    global_ptr->m_ptr = malloc (sizeof (struct link)); /* { dg-message "allocated here" } */
     550    free (global_ptr); /* { dg-warning "leak of '<unknown>'" } */
     551    /* TODO: should be more precise than just '<unknown>'.  */
     552  }
     553  
     554  extern void might_take_ownership (void *ptr);
     555  
     556  void test_45 (void)
     557  {
     558    void *p = malloc (1024);
     559    might_take_ownership (p);
     560  }
     561  
     562  void test_46 (void)
     563  {
     564    struct link *p = (struct link *)malloc (sizeof (struct link));
     565    if (!p)
     566      return;
     567    struct link *q = (struct link *)malloc (sizeof (struct link));
     568    p->m_ptr = q;
     569    might_take_ownership (p);
     570  }
     571  
     572  extern int maybe_alloc (char **);
     573  
     574  int test_47 (void)
     575  {
     576    char *p = ((void *)0);
     577    int p_size = 0;
     578  
     579    p = malloc (16);
     580    if (p) {
     581      free (p);
     582    } else {
     583      int retval = maybe_alloc (&p); /* this might write to "p".  */
     584      if (retval)
     585        return (retval);
     586      p_size = __builtin_strlen(p); /* { dg-bogus "non-null expected" } */
     587      free (p);
     588    }
     589    return p_size;
     590  }
     591  
     592  void test_48 (void)
     593  {
     594    int *p = NULL; /* { dg-message "'p' is NULL" } */
     595    *p = 1; /* { dg-warning "dereference of NULL 'p' \\\[CWE-476\\\]" } */
     596  }
     597  
     598  /* As test_48, but where the assignment of NULL is not at the start of a BB.  */
     599  
     600  int test_49 (int i)
     601  {
     602    int *p;
     603    int x;
     604  
     605    x = i * 2;
     606    p = NULL; /* { dg-message "'p' is NULL" } */
     607    *p = 1; /* { dg-warning "dereference of NULL 'p' \\\[CWE-476\\\]" } */
     608    return x;
     609  }
     610  
     611  /* Free of function, and of label within function.  */
     612  
     613  void test_50a (void)
     614  {
     615  }
     616  
     617  void test_50b (void)
     618  {
     619    free (test_50a); /* { dg-warning "'free' of '&test_50a' which points to memory not on the heap \\\[CWE-590\\\]" } */
     620  }
     621  
     622  void test_50c (void)
     623  {
     624   my_label:
     625    free (&&my_label); /* { dg-warning "'free' of '&my_label' which points to memory not on the heap \\\[CWE-590\\\]" } */
     626  }
     627  
     628  /* Double free after unconditional dereference.  */
     629  
     630  int test_51 (int *p)
     631  {
     632    int result = *p;
     633    free (p); /* { dg-message "first 'free' here" } */
     634    free (p); /* { dg-warning "double-'free' of 'p'" } */
     635    return result;
     636  }
     637  
     638  /* { dg-prune-output "\\\[-Wfree-nonheap-object" } */