(root)/
glibc-2.38/
malloc/
tst-realloc.c
       1  /* Copyright (C) 2013-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public
       6     License as published by the Free Software Foundation; either
       7     version 2.1 of the License, or (at your option) any later version.
       8  
       9     The GNU C Library is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; if not, see
      16     <https://www.gnu.org/licenses/>.  */
      17  
      18  #include <errno.h>
      19  #include <malloc.h>
      20  #include <stdint.h>
      21  #include <stdio.h>
      22  #include <string.h>
      23  #include <libc-diag.h>
      24  #include <support/check.h>
      25  
      26  static int
      27  do_test (void)
      28  {
      29    void *p;
      30    unsigned char *c;
      31    int save, i, ok;
      32  
      33    errno = 0;
      34  
      35    /* realloc (NULL, ...) behaves similarly to malloc (C89).  */
      36    DIAG_PUSH_NEEDS_COMMENT;
      37  #if __GNUC_PREREQ (7, 0)
      38    /* GCC 7 warns about too-large allocations; here we want to test
      39       that they fail.  */
      40    DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
      41  #endif
      42    p = realloc (NULL, -1);
      43    DIAG_POP_NEEDS_COMMENT;
      44    save = errno;
      45  
      46    if (p != NULL)
      47      FAIL_EXIT1 ("realloc (NULL, -1) succeeded.");
      48  
      49    /* errno should be set to ENOMEM on failure (POSIX).  */
      50    if (p == NULL && save != ENOMEM)
      51      FAIL_EXIT1 ("errno is not set correctly");
      52  
      53    errno = 0;
      54  
      55    /* realloc (NULL, ...) behaves similarly to malloc (C89).  */
      56    p = realloc (NULL, 10);
      57    save = errno;
      58  
      59    if (p == NULL)
      60      FAIL_EXIT1 ("realloc (NULL, 10) failed.");
      61  
      62    free (p);
      63  
      64    p = calloc (20, 1);
      65    if (p == NULL)
      66      FAIL_EXIT1 ("calloc (20, 1) failed.");
      67  
      68    /* Check increasing size preserves contents (C89).  */
      69    p = realloc (p, 200);
      70    if (p == NULL)
      71      FAIL_EXIT1 ("realloc (p, 200) failed.");
      72  
      73    c = p;
      74    ok = 1;
      75  
      76    for (i = 0; i < 20; i++)
      77      {
      78        if (c[i] != 0)
      79          ok = 0;
      80      }
      81  
      82    if (ok == 0)
      83      FAIL_EXIT1 ("first 20 bytes were not cleared");
      84  
      85    free (p);
      86  
      87    p = realloc (NULL, 100);
      88    if (p == NULL)
      89      FAIL_EXIT1 ("realloc (NULL, 100) failed.");
      90  
      91    memset (p, 0xff, 100);
      92  
      93    /* Check decreasing size preserves contents (C89).  */
      94    p = realloc (p, 16);
      95    if (p == NULL)
      96      FAIL_EXIT1 ("realloc (p, 16) failed.");
      97  
      98    c = p;
      99    ok = 1;
     100  
     101    for (i = 0; i < 16; i++)
     102      {
     103        if (c[i] != 0xff)
     104          ok = 0;
     105      }
     106  
     107    if (ok == 0)
     108      FAIL_EXIT1 ("first 16 bytes were not correct");
     109  
     110    /* Check failed realloc leaves original untouched (C89).  */
     111    DIAG_PUSH_NEEDS_COMMENT;
     112  #if __GNUC_PREREQ (7, 0)
     113    /* GCC 7 warns about too-large allocations; here we want to test
     114       that they fail.  */
     115    DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
     116  #endif
     117    c = realloc (p, -1);
     118    DIAG_POP_NEEDS_COMMENT;
     119    if (c != NULL)
     120      FAIL_EXIT1 ("realloc (p, -1) succeeded.");
     121  
     122    c = p;
     123    ok = 1;
     124  
     125    for (i = 0; i < 16; i++)
     126      {
     127        if (c[i] != 0xff)
     128          ok = 0;
     129      }
     130  
     131    if (ok == 0)
     132      FAIL_EXIT1 ("first 16 bytes were not correct after failed realloc");
     133  
     134    /* realloc (p, 0) frees p (C89) and returns NULL (glibc).  */
     135    p = realloc (p, 0);
     136    if (p != NULL)
     137      FAIL_EXIT1 ("realloc (p, 0) returned non-NULL.");
     138  
     139    /* realloc (NULL, 0) acts like malloc (0) (glibc).  */
     140    p = realloc (NULL, 0);
     141    if (p == NULL)
     142      FAIL_EXIT1 ("realloc (NULL, 0) returned NULL.");
     143  
     144    free (p);
     145  
     146    /* Smoke test to make sure that allocations do not move if they have enough
     147       space to expand in the chunk.  */
     148    for (size_t sz = 3; sz < 256 * 1024; sz += 2048)
     149      {
     150        p = realloc (NULL, sz);
     151        if (p == NULL)
     152  	FAIL_EXIT1 ("realloc (NULL, %zu) returned NULL.", sz);
     153        size_t newsz = malloc_usable_size (p);
     154        printf ("size: %zu, usable size: %zu, extra: %zu\n",
     155  	      sz, newsz, newsz - sz);
     156        uintptr_t oldp = (uintptr_t) p;
     157        void *new_p = realloc (p, newsz);
     158        if ((uintptr_t) new_p != oldp)
     159  	FAIL_EXIT1 ("Expanding (%zu bytes) to usable size (%zu) moved block",
     160  		    sz, newsz);
     161        free (new_p);
     162  
     163        /* We encountered a large enough extra size at least once.  */
     164        if (newsz - sz > 1024)
     165  	break;
     166      }
     167  
     168    return 0;
     169  }
     170  
     171  #define TEST_FUNCTION do_test ()
     172  #include "../test-skeleton.c"