(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
analyzer/
out-of-bounds-realloc-grow.c
       1  /* { dg-additional-options "-Wno-analyzer-too-complex" } */
       2  
       3  /* Reduced from gnulib/read-file.c.
       4  
       5     Tests that there is no false-positive on
       6     realloc when the buffer is growing.  */
       7  
       8  #include <stdlib.h>
       9  
      10  /* Indicate that the file is treated as binary.  */
      11  #define RF_BINARY 0x1
      12  
      13  #include <stdio.h>
      14  #include <stdint.h>
      15  #include <string.h>
      16  #include <errno.h>
      17  
      18  char *
      19  fread_file (FILE *stream, int flags, size_t *length)
      20  {
      21    char *buf = NULL;
      22    size_t alloc = BUFSIZ;
      23  
      24    if (!(buf = malloc (alloc)))
      25      return NULL; /* errno is ENOMEM.  */
      26  
      27    {
      28      size_t size = 0; /* number of bytes read so far */
      29      int save_errno;
      30  
      31      for (;;)
      32        {
      33          /* This reads 1 more than the size of a regular file
      34             so that we get eof immediately.  */
      35          size_t requested = alloc - size;
      36          size_t count = fread (buf + size, 1, requested, stream);
      37          size += count;
      38  
      39          {
      40            char *new_buf;
      41  
      42            if (alloc < PTRDIFF_MAX - alloc / 2)
      43              alloc = alloc + alloc / 2;
      44            else
      45              alloc = PTRDIFF_MAX;
      46  
      47             if (!(new_buf = realloc (buf, alloc)))
      48              {
      49                save_errno = errno;
      50                break;
      51              }
      52  
      53            buf = new_buf;
      54          }
      55        }
      56  
      57      free (buf);
      58      errno = save_errno;
      59      return NULL;
      60    }
      61  }
      62  
      63  /* Open and read the contents of FILENAME, and return a newly
      64     allocated string with the content, and set *LENGTH to the length of
      65     the string.  The string is zero-terminated, but the terminating
      66     zero byte is not counted in *LENGTH.  On errors, *LENGTH is
      67     undefined, errno preserves the values set by system functions (if
      68     any), and NULL is returned.
      69     If the RF_BINARY flag is set in FLAGS, the file is opened in binary
      70     mode.  If the RF_SENSITIVE flag is set in FLAGS, the memory buffer
      71     internally allocated will be cleared upon failure.  */
      72  char *
      73  read_file (const char *filename, int flags, size_t *length)
      74  {
      75    const char *mode = (flags & RF_BINARY) ? "rbe" : "re";
      76    FILE *stream = fopen (filename, mode);
      77    char *out;
      78  
      79    if (!stream)
      80      return NULL;
      81  
      82    out = fread_file (stream, flags, length);
      83  
      84    fclose (stream);
      85  
      86    return out;
      87  }