63
63
* which can be found at <https://www.eyrie.org/~eagle/software/rra-c-util/>.
64
64
*
65
65
* Written by Russ Allbery <[email protected] >
66
- * Copyright 2015 Russ Allbery <[email protected] >
66
+ * Copyright 2015, 2023 Russ Allbery <[email protected] >
67
67
* Copyright 2012-2014
68
68
* The Board of Trustees of the Leland Stanford Junior University
69
69
* Copyright 2004-2006 Internet Systems Consortium, Inc. ("ISC")
@@ -121,7 +121,7 @@ x_malloc(size_t size, const char *file, int line)
121
121
real_size = (size > 0 ) ? size : 1 ;
122
122
p = malloc (real_size );
123
123
while (p == NULL ) {
124
- ( * xmalloc_error_handler ) ("malloc" , size , file , line );
124
+ xmalloc_error_handler ("malloc" , size , file , line );
125
125
p = malloc (real_size );
126
126
}
127
127
return p ;
@@ -137,7 +137,7 @@ x_calloc(size_t n, size_t size, const char *file, int line)
137
137
size = (size > 0 ) ? size : 1 ;
138
138
p = calloc (n , size );
139
139
while (p == NULL ) {
140
- ( * xmalloc_error_handler ) ("calloc" , n * size , file , line );
140
+ xmalloc_error_handler ("calloc" , n * size , file , line );
141
141
p = calloc (n , size );
142
142
}
143
143
return p ;
@@ -150,11 +150,27 @@ x_realloc(void *p, size_t size, const char *file, int line)
150
150
void * newp ;
151
151
152
152
newp = realloc (p , size );
153
- while (newp == NULL && size > 0 ) {
154
- (* xmalloc_error_handler )("realloc" , size , file , line );
153
+ if (size == 0 )
154
+ return newp ;
155
+
156
+ /*
157
+ * GCC 13.2.0 (and some earlier versions) misdiagnose this error
158
+ * handling as a use-after-free of p, but the C standard guarantees
159
+ * that if realloc fails (which is true in every case when it returns
160
+ * NULL when size > 0), p is unchanged and still valid.
161
+ */
162
+ #if __GNUC__ >= 12 && !defined(__clang__ )
163
+ # pragma GCC diagnostic push
164
+ # pragma GCC diagnostic ignored "-Wuse-after-free"
165
+ #endif
166
+ while (newp == NULL ) {
167
+ xmalloc_error_handler ("realloc" , size , file , line );
155
168
newp = realloc (p , size );
156
169
}
157
170
return newp ;
171
+ #if __GNUC__ >= 12 && !defined(__clang__ )
172
+ # pragma GCC diagnostic pop
173
+ #endif
158
174
}
159
175
160
176
@@ -164,10 +180,27 @@ x_reallocarray(void *p, size_t n, size_t size, const char *file, int line)
164
180
void * newp ;
165
181
166
182
newp = reallocarray (p , n , size );
167
- while (newp == NULL && size > 0 && n > 0 ) {
168
- (* xmalloc_error_handler )("reallocarray" , n * size , file , line );
183
+ if (size == 0 || n == 0 )
184
+ return newp ;
185
+
186
+ /*
187
+ * GCC 13.2.0 (and some earlier versions) misdiagnose this error
188
+ * handling as a use-after-free of p, but the documentation of
189
+ * reallocarray guarantees that if reallocarray fails (which is true in
190
+ * every case when it returns NULL when size > 0 and n > 0), p is
191
+ * unchanged and still valid.
192
+ */
193
+ #if __GNUC__ >= 12 && !defined(__clang__ )
194
+ # pragma GCC diagnostic push
195
+ # pragma GCC diagnostic ignored "-Wuse-after-free"
196
+ #endif
197
+ while (newp == NULL ) {
198
+ xmalloc_error_handler ("reallocarray" , n * size , file , line );
169
199
newp = reallocarray (p , n , size );
170
200
}
201
+ #if __GNUC__ >= 12 && !defined(__clang__ )
202
+ # pragma GCC diagnostic pop
203
+ #endif
171
204
return newp ;
172
205
}
173
206
@@ -181,7 +214,7 @@ x_strdup(const char *s, const char *file, int line)
181
214
len = strlen (s ) + 1 ;
182
215
p = malloc (len );
183
216
while (p == NULL ) {
184
- ( * xmalloc_error_handler ) ("strdup" , len , file , line );
217
+ xmalloc_error_handler ("strdup" , len , file , line );
185
218
p = malloc (len );
186
219
}
187
220
memcpy (p , s , len );
@@ -207,7 +240,7 @@ x_strndup(const char *s, size_t size, const char *file, int line)
207
240
length = p - s ;
208
241
copy = malloc (length + 1 );
209
242
while (copy == NULL ) {
210
- ( * xmalloc_error_handler ) ("strndup" , length + 1 , file , line );
243
+ xmalloc_error_handler ("strndup" , length + 1 , file , line );
211
244
copy = malloc (length + 1 );
212
245
}
213
246
memcpy (copy , s , length );
@@ -231,7 +264,7 @@ x_vasprintf(char **strp, const char *fmt, va_list args, const char *file,
231
264
status = vsnprintf (NULL , 0 , fmt , args_copy );
232
265
va_end (args_copy );
233
266
status = (status < 0 ) ? 0 : status + 1 ;
234
- ( * xmalloc_error_handler ) ("vasprintf" , status , file , line );
267
+ xmalloc_error_handler ("vasprintf" , status , file , line );
235
268
va_copy (args_copy , args );
236
269
status = vasprintf (strp , fmt , args_copy );
237
270
va_end (args_copy );
@@ -255,7 +288,7 @@ x_asprintf(char **strp, const char *file, int line, const char *fmt, ...)
255
288
status = vsnprintf (NULL , 0 , fmt , args_copy );
256
289
va_end (args_copy );
257
290
status = (status < 0 ) ? 0 : status + 1 ;
258
- ( * xmalloc_error_handler ) ("asprintf" , status , file , line );
291
+ xmalloc_error_handler ("asprintf" , status , file , line );
259
292
va_copy (args_copy , args );
260
293
status = vasprintf (strp , fmt , args_copy );
261
294
va_end (args_copy );
@@ -278,7 +311,7 @@ x_asprintf(char **strp, const char *fmt, ...)
278
311
status = vsnprintf (NULL , 0 , fmt , args_copy );
279
312
va_end (args_copy );
280
313
status = (status < 0 ) ? 0 : status + 1 ;
281
- ( * xmalloc_error_handler ) ("asprintf" , status , __FILE__ , __LINE__ );
314
+ xmalloc_error_handler ("asprintf" , status , __FILE__ , __LINE__ );
282
315
va_copy (args_copy , args );
283
316
status = vasprintf (strp , fmt , args_copy );
284
317
va_end (args_copy );
0 commit comments