diff options
Diffstat (limited to 'stdlib')
-rw-r--r-- | stdlib/Makefile | 3 | ||||
-rw-r--r-- | stdlib/stdlib.h | 16 | ||||
-rw-r--r-- | stdlib/tst-realpath.c | 82 |
3 files changed, 95 insertions, 6 deletions
diff --git a/stdlib/Makefile b/stdlib/Makefile index f5755a1654..ec30011b4c 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -87,7 +87,8 @@ tests := tst-strtol tst-strtod testmb testrand testsort testdiv \ tst-makecontext-align test-bz22786 tst-strtod-nan-sign \ tst-swapcontext1 tst-setcontext4 tst-setcontext5 \ tst-setcontext6 tst-setcontext7 tst-setcontext8 \ - tst-setcontext9 tst-bz20544 tst-canon-bz26341 + tst-setcontext9 tst-bz20544 tst-canon-bz26341 \ + tst-realpath tests-internal := tst-strtod1i tst-strtod3 tst-strtod4 tst-strtod5i \ tst-tls-atexit tst-tls-atexit-nodelete diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h index 6360845d98..0481c12355 100644 --- a/stdlib/stdlib.h +++ b/stdlib/stdlib.h @@ -550,6 +550,9 @@ extern void *calloc (size_t __nmemb, size_t __size) extern void *realloc (void *__ptr, size_t __size) __THROW __attribute_warn_unused_result__ __attribute_alloc_size__ ((2)); +/* Free a block allocated by `malloc', `realloc' or `calloc'. */ +extern void free (void *__ptr) __THROW; + #ifdef __USE_MISC /* Re-allocate the previously allocated block in PTR, making the new block large enough for NMEMB elements of SIZE bytes each. */ @@ -558,11 +561,13 @@ extern void *realloc (void *__ptr, size_t __size) between objects pointed by the old and new pointers. */ extern void *reallocarray (void *__ptr, size_t __nmemb, size_t __size) __THROW __attribute_warn_unused_result__ - __attribute_alloc_size__ ((2, 3)); -#endif + __attribute_alloc_size__ ((2, 3)) + __attr_dealloc_free; -/* Free a block allocated by `malloc', `realloc' or `calloc'. */ -extern void free (void *__ptr) __THROW; +/* Add reallocarray as its own deallocator. */ +extern void *reallocarray (void *__ptr, size_t __nmemb, size_t __size) + __THROW __attr_dealloc (reallocarray, 1); +#endif #ifdef __USE_MISC # include <alloca.h> @@ -788,7 +793,8 @@ extern int system (const char *__command) __wur; /* Return a malloc'd string containing the canonical absolute name of the existing named file. */ extern char *canonicalize_file_name (const char *__name) - __THROW __nonnull ((1)) __wur; + __THROW __nonnull ((1)) __attribute_malloc__ + __attr_dealloc_free __wur; #endif #if defined __USE_MISC || defined __USE_XOPEN_EXTENDED diff --git a/stdlib/tst-realpath.c b/stdlib/tst-realpath.c new file mode 100644 index 0000000000..2ae5e4fb2b --- /dev/null +++ b/stdlib/tst-realpath.c @@ -0,0 +1,82 @@ +/* Test to verify that realpath() doesn't cause false positives due + to GCC attribute malloc. + + Test failure exposes the presence of the attribute in the following + declaration: + + __attribute__ ((__malloc__ (free, 1))) char* + realpath (const char *, char *); + + Copyright (C) 2021 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <stdio.h> +#include <stdlib.h> +#include <malloc.h> + +#if defined __GNUC__ && __GNUC__ >= 11 +/* Turn GCC -Wmismatched-dealloc warnings into errors to expose false + positives. */ +# pragma GCC diagnostic push +# pragma GCC diagnostic error "-Wmismatched-dealloc" + +/* Associate dealloc as the only deallocator suitable for pointers + returned from alloc. + GCC automatically disables inlining of allocator and deallocator + functions marked with the argument form of attribute malloc but + it doesn't hurt to disable it explicitly. */ +__attribute ((noipa)) void dealloc (void *); +__attribute ((malloc (dealloc, 1))) char* alloc (void); +#endif + +void dealloc (void *p) +{ + free (p); +} + +char* alloc (void) +{ + return (char *)malloc (8); +} + +static int +do_test (void) +{ + char *resolved_path = alloc (); + char *ret = realpath ("/", resolved_path); + dealloc (ret); + + resolved_path = alloc (); + ret = realpath ("/", resolved_path); + dealloc (resolved_path); + + /* The following should emit a warning (but doesn't with GCC 11): + resolved_path = alloc (); + ret = realpath ("/", resolved_path); + free (ret); // expect -Wmismatched-dealloc + */ + + return 0; +} + +#if defined __GNUC__ && __GNUC__ >= 11 +/* Restore -Wmismatched-dealloc setting. */ +# pragma GCC diagnostic pop +#endif + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" |