1 /* Test for reallocarray.
2    Copyright (C) 2017-2022 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4 
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9 
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18 
19 #include <errno.h>
20 #include <malloc.h>
21 #include <string.h>
22 #include <support/check.h>
23 #include <libc-diag.h>
24 
25 static void *
reallocarray_nowarn(void * ptr,size_t nmemb,size_t size)26 reallocarray_nowarn (void *ptr, size_t nmemb, size_t size)
27 {
28 #if __GNUC_PREREQ (7, 0)
29   /* GCC 7 warns about too-large allocations; here we want to test
30      that they fail.  */
31   DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
32 #endif
33   void *ret = reallocarray (ptr, nmemb, size);
34 #if __GNUC_PREREQ (7, 0)
35   DIAG_POP_NEEDS_COMMENT;
36 #endif
37   return ret;
38 }
39 
40 
41 static int
do_test(void)42 do_test (void)
43 {
44   void *ptr = NULL;
45   void *ptr2 = NULL;
46   unsigned char *c;
47   size_t i;
48   int ok;
49   const size_t max = ~(size_t)0;
50   size_t a, b;
51 
52   /* Test overflow detection.  */
53   errno = 0;
54   ptr = reallocarray_nowarn (NULL, max, 2);
55   TEST_VERIFY (!ptr);
56   TEST_VERIFY (errno == ENOMEM);
57 
58   errno = 0;
59   ptr = reallocarray_nowarn (NULL, 2, max);
60   TEST_VERIFY (!ptr);
61   TEST_VERIFY (errno == ENOMEM);
62 
63   a = 65537;
64   b = max/65537 + 1;
65   errno = 0;
66   ptr = reallocarray_nowarn (NULL, a, b);
67   TEST_VERIFY (!ptr);
68   TEST_VERIFY (errno == ENOMEM);
69 
70   errno = 0;
71   ptr = reallocarray_nowarn (NULL, b, a);
72   TEST_VERIFY (!ptr);
73   TEST_VERIFY (errno == ENOMEM);
74 
75   /* Test realloc-like behavior.  */
76   /* Allocate memory like malloc.  */
77   ptr = reallocarray (NULL, 10, 2);
78   TEST_VERIFY_EXIT (ptr);
79   TEST_VERIFY_EXIT (malloc_usable_size (ptr) >= 10*2);
80 
81   memset (ptr, 0xAF, 10*2);
82 
83   /* Enlarge buffer.   */
84   ptr2 = reallocarray (ptr, 20, 2);
85   TEST_VERIFY (ptr2);
86   if (ptr2)
87     ptr = ptr2;
88   TEST_VERIFY (malloc_usable_size (ptr) >= 20*2);
89 
90   c = ptr;
91   ok = 1;
92   for (i = 0; i < 10*2; ++i)
93     {
94       if (c[i] != 0xAF)
95         ok = 0;
96     }
97   TEST_VERIFY (ok);
98 
99   /* Decrease buffer size.  */
100   ptr2 = reallocarray (ptr, 5, 3);
101   TEST_VERIFY (ptr2);
102   if (ptr2)
103     ptr = ptr2;
104   TEST_VERIFY_EXIT (malloc_usable_size (ptr) >= 5*3);
105 
106   c = ptr;
107   ok = 1;
108   for (i = 0; i < 5*3; ++i)
109     {
110       if (c[i] != 0xAF)
111         ok = 0;
112     }
113   TEST_VERIFY (ok);
114 
115   /* Overflow should leave buffer untouched.  */
116   errno = 0;
117   ptr2 = reallocarray_nowarn (ptr, 2, ~(size_t)0);
118   TEST_VERIFY (!ptr2);
119   TEST_VERIFY (errno == ENOMEM);
120 
121   c = ptr;
122   ok = 1;
123   for (i = 0; i < 5*3; ++i)
124     {
125       if (c[i] != 0xAF)
126         ok = 0;
127     }
128   TEST_VERIFY (ok);
129 
130   free (ptr);
131 
132   return 0;
133 }
134 
135 #include <support/test-driver.c>
136