From d6cd6bf4de43672803ad47f4c745ac6e510c6d61 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Wed, 26 Sep 2007 20:45:18 +0000 Subject: * misc/sys/cdefs.h (__warndecl, __errordecl): For GCC 4.3+ define with __warning__/__error__ attributes. (__warnattr): Define. * stdlib/bits/stdlib.h (__realpath_chk_warn, __ptsname_r_chk_warn, __mbstowcs_chk_warn, __wcstombs_chk_warn): New aliases with __warnattr. (realpath, ptsname_r, mbstowcs, wcstombs): Call __*_chk_warn instead of __*_chk if compile time detectable overflow is found. * libio/bits/stdio2.h (__fgets_chk_warn, __fread_chk_warn, __fgets_unlocked_chk_warn, __fread_unlocked_chk_warn): New aliases with __warnattr. (fgets, fread, fgets_unlocked, fread_unlocked): Call __*_chk_warn instead of __*_chk if compile time detectable overflow is found. (__gets_alias): Rename to... (__gets_warn): ... this. Add __warnattr. (gets): Call __gets_warn instead of __gets_alias. * socket/bits/socket2.h (__recv_chk_warn, __recvfrom_chk_warn): New aliases with __warnattr. (recv, recvfrom): Call __*_chk_warn instead of __*_chk if compile time detectable overflow is found. * posix/bits/unistd.h (__read_chk_warn, __pread_chk_warn, __pread64_chk_warn, __readlink_chk_warn, __readlinkat_chk_warn, __getcwd_chk_warn, __confstr_chk_warn, __getgroups_chk_warn, __ttyname_r_chk_warn, __getlogin_r_chk_warn, __gethostname_chk_warn, __getdomainname_chk_warn): New aliases with __warnattr. (read, pread, pread64, readlink, readlinkat, getcwd, confstr, getgroups, ttyname_r, getlogin_r, gethostname, getdomainname): Call __*_chk_warn instead of __*_chk if compile time detectable overflow is found. (__getgroups_chk): Rename argument to __listlen from listlen. (__getwd_alias): Rename to... (__getwd_warn): ... this. Add __warnattr. (getwd): Call __getwd_warn instead of __getwd_alias. * wcsmbs/bits/wchar2.h (__wmemcpy_chk_warn, __wmemmove_chk_warn, __wmempcpy_chk_warn, __wmemset_chk_warn, __wcsncpy_chk_warn, __wcpncpy_chk_warn, __fgetws_chk_warn, __fgetws_unlocked_chk_warn, __mbsrtowcs_chk_warn, __wcsrtombs_chk_warn, __mbsnrtowcs_chk_warn, __wcsnrtombs_chk_warn): New aliases with __warnattr. (wmemcpy, wmemmove, wmempcpy, wmemset, mbsrtowcs, wcsrtombs, mbsnrtowcs, wcsnrtombs): Call __*_chk_warn instead of __*_chk if compile time detectable overflow is found. (wcsncpy, wcpncpy): Likewise. For constant __n fix check whether to use __*_chk or not. (fgetws, fgetws_unlocked): Divide __bos by sizeof (wchar_t), both in comparisons which function should be called and in __*_chk* arguments. Call __*_chk_warn instead of __*_chk if compile time detectable overflow is found. (swprintf, vswprintf): Divide __bos by sizeof (wchar_t) in __*_chk argument. * debug/tst-chk1.c (do_test): Add a few more tests. --- ChangeLog | 53 ++++++++++++ debug/tst-chk1.c | 22 ++++- libio/bits/stdio2.h | 82 ++++++++++++++---- misc/sys/cdefs.h | 13 ++- posix/bits/unistd.h | 224 +++++++++++++++++++++++++++++++++++++++---------- socket/bits/socket2.h | 36 ++++++-- stdlib/bits/stdlib.h | 65 +++++++++++--- wcsmbs/bits/wchar2.h | 228 +++++++++++++++++++++++++++++++++++++++++--------- 8 files changed, 601 insertions(+), 122 deletions(-) diff --git a/ChangeLog b/ChangeLog index 682c2e3d1f..ed21b4f857 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,56 @@ +2007-09-26 Jakub Jelinek + + * misc/sys/cdefs.h (__warndecl, __errordecl): For GCC 4.3+ define + with __warning__/__error__ attributes. + (__warnattr): Define. + * stdlib/bits/stdlib.h (__realpath_chk_warn, __ptsname_r_chk_warn, + __mbstowcs_chk_warn, __wcstombs_chk_warn): New aliases with + __warnattr. + (realpath, ptsname_r, mbstowcs, wcstombs): Call __*_chk_warn instead + of __*_chk if compile time detectable overflow is found. + * libio/bits/stdio2.h (__fgets_chk_warn, __fread_chk_warn, + __fgets_unlocked_chk_warn, __fread_unlocked_chk_warn): New aliases + with __warnattr. + (fgets, fread, fgets_unlocked, fread_unlocked): Call __*_chk_warn + instead of __*_chk if compile time detectable overflow is found. + (__gets_alias): Rename to... + (__gets_warn): ... this. Add __warnattr. + (gets): Call __gets_warn instead of __gets_alias. + * socket/bits/socket2.h (__recv_chk_warn, __recvfrom_chk_warn): New + aliases with __warnattr. + (recv, recvfrom): Call __*_chk_warn instead of __*_chk if compile + time detectable overflow is found. + * posix/bits/unistd.h (__read_chk_warn, __pread_chk_warn, + __pread64_chk_warn, __readlink_chk_warn, __readlinkat_chk_warn, + __getcwd_chk_warn, __confstr_chk_warn, __getgroups_chk_warn, + __ttyname_r_chk_warn, __getlogin_r_chk_warn, __gethostname_chk_warn, + __getdomainname_chk_warn): New aliases with __warnattr. + (read, pread, pread64, readlink, readlinkat, getcwd, confstr, + getgroups, ttyname_r, getlogin_r, gethostname, getdomainname): Call + __*_chk_warn instead of __*_chk if compile time detectable overflow + is found. + (__getgroups_chk): Rename argument to __listlen from listlen. + (__getwd_alias): Rename to... + (__getwd_warn): ... this. Add __warnattr. + (getwd): Call __getwd_warn instead of __getwd_alias. + * wcsmbs/bits/wchar2.h (__wmemcpy_chk_warn, __wmemmove_chk_warn, + __wmempcpy_chk_warn, __wmemset_chk_warn, __wcsncpy_chk_warn, + __wcpncpy_chk_warn, __fgetws_chk_warn, __fgetws_unlocked_chk_warn, + __mbsrtowcs_chk_warn, __wcsrtombs_chk_warn, __mbsnrtowcs_chk_warn, + __wcsnrtombs_chk_warn): New aliases with __warnattr. + (wmemcpy, wmemmove, wmempcpy, wmemset, mbsrtowcs, wcsrtombs, + mbsnrtowcs, wcsnrtombs): Call __*_chk_warn instead of __*_chk if + compile time detectable overflow is found. + (wcsncpy, wcpncpy): Likewise. For constant __n fix check whether + to use __*_chk or not. + (fgetws, fgetws_unlocked): Divide __bos by sizeof (wchar_t), both + in comparisons which function should be called and in __*_chk* + arguments. Call __*_chk_warn instead of __*_chk if compile time + detectable overflow is found. + (swprintf, vswprintf): Divide __bos by sizeof (wchar_t) in + __*_chk argument. + * debug/tst-chk1.c (do_test): Add a few more tests. + 2007-09-24 Ulrich Drepper [BZ #5058] diff --git a/debug/tst-chk1.c b/debug/tst-chk1.c index 78a61be53b..487b071026 100644 --- a/debug/tst-chk1.c +++ b/debug/tst-chk1.c @@ -317,6 +317,14 @@ do_test (void) CHK_FAIL_START snprintf (buf + 8, l0 + 3, "%d", num2); CHK_FAIL_END + + CHK_FAIL_START + swprintf (wbuf + 8, 3, L"%d", num1); + CHK_FAIL_END + + CHK_FAIL_START + swprintf (wbuf + 8, l0 + 3, L"%d", num1); + CHK_FAIL_END # endif memcpy (buf, str1 + 2, l0 + 9); @@ -513,12 +521,16 @@ do_test (void) wmemcpy (wbuf + 1, L"abcdefghij", l0 + 10); CHK_FAIL_END + CHK_FAIL_START + wmemcpy (wbuf + 9, L"abcdefghij", l0 + 10); + CHK_FAIL_END + CHK_FAIL_START wmemmove (wbuf + 2, wbuf + 1, l0 + 9); CHK_FAIL_END CHK_FAIL_START - wp = wmempcpy (wbuf + 6, L"abcde", l0 + 5); + wp = wmempcpy (wbuf + 6, L"abcde", l0 + 5); CHK_FAIL_END CHK_FAIL_START @@ -537,6 +549,14 @@ do_test (void) wcsncpy (wbuf + 7, L"X", l0 + 4); CHK_FAIL_END + CHK_FAIL_START + wcsncpy (wbuf + 9, L"XABCDEFGH", 8); + CHK_FAIL_END + + CHK_FAIL_START + wcpncpy (wbuf + 9, L"XABCDEFGH", 8); + CHK_FAIL_END + CHK_FAIL_START wcpncpy (wbuf + 6, L"cd", l0 + 5); CHK_FAIL_END diff --git a/libio/bits/stdio2.h b/libio/bits/stdio2.h index 841a0ff6aa..8889540689 100644 --- a/libio/bits/stdio2.h +++ b/libio/bits/stdio2.h @@ -131,14 +131,16 @@ vfprintf (FILE *__restrict __stream, #endif extern char *__gets_chk (char *__str, size_t) __wur; -extern char *__REDIRECT (__gets_alias, (char *__str), gets) __wur; +extern char *__REDIRECT (__gets_warn, (char *__str), gets) + __wur __warnattr ("please use fgets or getline instead, gets can't " + "specify buffer size"); __extern_always_inline __wur char * gets (char *__str) { if (__bos (__str) != (size_t) -1) return __gets_chk (__str, __bos (__str)); - return __gets_alias (__str); + return __gets_warn (__str); } extern char *__fgets_chk (char *__restrict __s, size_t __size, int __n, @@ -146,13 +148,23 @@ extern char *__fgets_chk (char *__restrict __s, size_t __size, int __n, extern char *__REDIRECT (__fgets_alias, (char *__restrict __s, int __n, FILE *__restrict __stream), fgets) __wur; +extern char *__REDIRECT (__fgets_chk_warn, + (char *__restrict __s, size_t __size, int __n, + FILE *__restrict __stream), __fgets_chk) + __wur __warnattr ("fgets called with bigger size than length " + "of destination buffer"); __extern_always_inline __wur char * fgets (char *__restrict __s, int __n, FILE *__restrict __stream) { - if (__bos (__s) != (size_t) -1 - && (!__builtin_constant_p (__n) || (size_t) __n > __bos (__s))) - return __fgets_chk (__s, __bos (__s), __n, __stream); + if (__bos (__s) != (size_t) -1) + { + if (!__builtin_constant_p (__n) || __n <= 0) + return __fgets_chk (__s, __bos (__s), __n, __stream); + + if ((size_t) __n > __bos (__s)) + return __fgets_chk_warn (__s, __bos (__s), __n, __stream); + } return __fgets_alias (__s, __n, __stream); } @@ -163,17 +175,28 @@ extern size_t __REDIRECT (__fread_alias, (void *__restrict __ptr, size_t __size, size_t __n, FILE *__restrict __stream), fread) __wur; +extern size_t __REDIRECT (__fread_chk_warn, + (void *__restrict __ptr, size_t __ptrlen, + size_t __size, size_t __n, + FILE *__restrict __stream), + __fread_chk) + __wur __warnattr ("fread called with bigger size * nmemb than length " + "of destination buffer"); __extern_always_inline __wur size_t fread (void *__restrict __ptr, size_t __size, size_t __n, FILE *__restrict __stream) { - if (__bos0 (__ptr) != (size_t) -1 - && (!__builtin_constant_p (__size) + if (__bos0 (__ptr) != (size_t) -1) + { + if (!__builtin_constant_p (__size) || !__builtin_constant_p (__n) - || (__size | __n) >= (((size_t) 1) << (8 * sizeof (size_t) / 2)) - || __size * __n > __bos0 (__ptr))) - return __fread_chk (__ptr, __bos0 (__ptr), __size, __n, __stream); + || (__size | __n) >= (((size_t) 1) << (8 * sizeof (size_t) / 2))) + return __fread_chk (__ptr, __bos0 (__ptr), __size, __n, __stream); + + if (__size * __n > __bos0 (__ptr)) + return __fread_chk_warn (__ptr, __bos0 (__ptr), __size, __n, __stream); + } return __fread_alias (__ptr, __size, __n, __stream); } @@ -183,13 +206,23 @@ extern char *__fgets_unlocked_chk (char *__restrict __s, size_t __size, extern char *__REDIRECT (__fgets_unlocked_alias, (char *__restrict __s, int __n, FILE *__restrict __stream), fgets_unlocked) __wur; +extern char *__REDIRECT (__fgets_unlocked_chk_warn, + (char *__restrict __s, size_t __size, int __n, + FILE *__restrict __stream), __fgets_unlocked_chk) + __wur __warnattr ("fgets_unlocked called with bigger size than length " + "of destination buffer"); __extern_always_inline __wur char * fgets_unlocked (char *__restrict __s, int __n, FILE *__restrict __stream) { - if (__bos (__s) != (size_t) -1 - && (!__builtin_constant_p (__n) || (size_t) __n > __bos (__s))) - return __fgets_unlocked_chk (__s, __bos (__s), __n, __stream); + if (__bos (__s) != (size_t) -1) + { + if (!__builtin_constant_p (__n) || __n <= 0) + return __fgets_unlocked_chk (__s, __bos (__s), __n, __stream); + + if ((size_t) __n > __bos (__s)) + return __fgets_unlocked_chk_warn (__s, __bos (__s), __n, __stream); + } return __fgets_unlocked_alias (__s, __n, __stream); } #endif @@ -203,17 +236,30 @@ extern size_t __REDIRECT (__fread_unlocked_alias, (void *__restrict __ptr, size_t __size, size_t __n, FILE *__restrict __stream), fread_unlocked) __wur; +extern size_t __REDIRECT (__fread_unlocked_chk_warn, + (void *__restrict __ptr, size_t __ptrlen, + size_t __size, size_t __n, + FILE *__restrict __stream), + __fread_unlocked_chk) + __wur __warnattr ("fread_unlocked called with bigger size * nmemb than " + "length of destination buffer"); __extern_always_inline __wur size_t fread_unlocked (void *__restrict __ptr, size_t __size, size_t __n, FILE *__restrict __stream) { - if (__bos0 (__ptr) != (size_t) -1 - && (!__builtin_constant_p (__size) + if (__bos0 (__ptr) != (size_t) -1) + { + if (!__builtin_constant_p (__size) || !__builtin_constant_p (__n) - || (__size | __n) >= (((size_t) 1) << (8 * sizeof (size_t) / 2)) - || __size * __n > __bos0 (__ptr))) - return __fread_unlocked_chk (__ptr, __bos0 (__ptr), __size, __n, __stream); + || (__size | __n) >= (((size_t) 1) << (8 * sizeof (size_t) / 2))) + return __fread_unlocked_chk (__ptr, __bos0 (__ptr), __size, __n, + __stream); + + if (__size * __n > __bos0 (__ptr)) + return __fread_unlocked_chk_warn (__ptr, __bos0 (__ptr), __size, __n, + __stream); + } # ifdef __USE_EXTERN_INLINES if (__builtin_constant_p (__size) diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h index 26b9490bad..4650d5f74e 100644 --- a/misc/sys/cdefs.h +++ b/misc/sys/cdefs.h @@ -131,9 +131,18 @@ /* Fortify support. */ #define __bos(ptr) __builtin_object_size (ptr, __USE_FORTIFY_LEVEL > 1) #define __bos0(ptr) __builtin_object_size (ptr, 0) -#define __warndecl(name, msg) extern void name (void) -#define __errordecl(name, msg) extern void name (void) +#if __GNUC_PREREQ (4,3) +# define __warndecl(name, msg) \ + extern void name (void) __attribute__((__warning__ (msg))) +# define __warnattr(msg) __attribute__((__warning__ (msg))) +# define __errordecl(name, msg) \ + extern void name (void) __attribute__((__error__ (msg))) +#else +# define __warndecl(name, msg) extern void name (void) +# define __warnattr(msg) +# define __errordecl(name, msg) extern void name (void) +#endif /* Support for flexible arrays. */ #if __GNUC_PREREQ (2,97) diff --git a/posix/bits/unistd.h b/posix/bits/unistd.h index 331e8ea3b9..efd7f75a50 100644 --- a/posix/bits/unistd.h +++ b/posix/bits/unistd.h @@ -25,13 +25,23 @@ extern ssize_t __read_chk (int __fd, void *__buf, size_t __nbytes, size_t __buflen) __wur; extern ssize_t __REDIRECT (__read_alias, (int __fd, void *__buf, size_t __nbytes), read) __wur; +extern ssize_t __REDIRECT (__read_chk_warn, + (int __fd, void *__buf, size_t __nbytes, + size_t __buflen), __read_chk) + __wur __warnattr ("read called with bigger length than size of " + "the destination buffer"); __extern_always_inline __wur ssize_t read (int __fd, void *__buf, size_t __nbytes) { - if (__bos0 (__buf) != (size_t) -1 - && (!__builtin_constant_p (__nbytes) || __nbytes > __bos0 (__buf))) - return __read_chk (__fd, __buf, __nbytes, __bos0 (__buf)); + if (__bos0 (__buf) != (size_t) -1) + { + if (!__builtin_constant_p (__nbytes)) + return __read_chk (__fd, __buf, __nbytes, __bos0 (__buf)); + + if (__nbytes > __bos0 (__buf)) + return __read_chk_warn (__fd, __buf, __nbytes, __bos0 (__buf)); + } return __read_alias (__fd, __buf, __nbytes); } @@ -46,23 +56,47 @@ extern ssize_t __REDIRECT (__pread_alias, extern ssize_t __REDIRECT (__pread64_alias, (int __fd, void *__buf, size_t __nbytes, __off64_t __offset), pread64) __wur; +extern ssize_t __REDIRECT (__pread_chk_warn, + (int __fd, void *__buf, size_t __nbytes, + __off_t __offset, size_t __bufsize), __pread_chk) + __wur __warnattr ("pread called with bigger length than size of " + "the destination buffer"); +extern ssize_t __REDIRECT (__pread64_chk_warn, + (int __fd, void *__buf, size_t __nbytes, + __off64_t __offset, size_t __bufsize), + __pread64_chk) + __wur __warnattr ("pread64 called with bigger length than size of " + "the destination buffer"); # ifndef __USE_FILE_OFFSET64 __extern_always_inline __wur ssize_t pread (int __fd, void *__buf, size_t __nbytes, __off_t __offset) { - if (__bos0 (__buf) != (size_t) -1 - && (!__builtin_constant_p (__nbytes) || __nbytes > __bos0 (__buf))) - return __pread_chk (__fd, __buf, __nbytes, __offset, __bos0 (__buf)); + if (__bos0 (__buf) != (size_t) -1) + { + if (!__builtin_constant_p (__nbytes)) + return __pread_chk (__fd, __buf, __nbytes, __offset, __bos0 (__buf)); + + if ( __nbytes > __bos0 (__buf)) + return __pread_chk_warn (__fd, __buf, __nbytes, __offset, + __bos0 (__buf)); + } return __pread_alias (__fd, __buf, __nbytes, __offset); } # else __extern_always_inline __wur ssize_t pread (int __fd, void *__buf, size_t __nbytes, __off64_t __offset) { - if (__bos0 (__buf) != (size_t) -1 - && (!__builtin_constant_p (__nbytes) || __nbytes > __bos0 (__buf))) - return __pread64_chk (__fd, __buf, __nbytes, __offset, __bos0 (__buf)); + if (__bos0 (__buf) != (size_t) -1) + { + if (!__builtin_constant_p (__nbytes)) + return __pread64_chk (__fd, __buf, __nbytes, __offset, __bos0 (__buf)); + + if ( __nbytes > __bos0 (__buf)) + return __pread64_chk_warn (__fd, __buf, __nbytes, __offset, + __bos0 (__buf)); + } + return __pread64_alias (__fd, __buf, __nbytes, __offset); } # endif @@ -71,9 +105,16 @@ pread (int __fd, void *__buf, size_t __nbytes, __off64_t __offset) __extern_always_inline __wur ssize_t pread64 (int __fd, void *__buf, size_t __nbytes, __off64_t __offset) { - if (__bos0 (__buf) != (size_t) -1 - && (!__builtin_constant_p (__nbytes) || __nbytes > __bos0 (__buf))) - return __pread64_chk (__fd, __buf, __nbytes, __offset, __bos0 (__buf)); + if (__bos0 (__buf) != (size_t) -1) + { + if (!__builtin_constant_p (__nbytes)) + return __pread64_chk (__fd, __buf, __nbytes, __offset, __bos0 (__buf)); + + if ( __nbytes > __bos0 (__buf)) + return __pread64_chk_warn (__fd, __buf, __nbytes, __offset, + __bos0 (__buf)); + } + return __pread64_alias (__fd, __buf, __nbytes, __offset); } # endif @@ -88,14 +129,25 @@ extern ssize_t __REDIRECT_NTH (__readlink_alias, (__const char *__restrict __path, char *__restrict __buf, size_t __len), readlink) __nonnull ((1, 2)) __wur; +extern ssize_t __REDIRECT_NTH (__readlink_chk_warn, + (__const char *__restrict __path, + char *__restrict __buf, size_t __len, + size_t __buflen), __readlink_chk) + __nonnull ((1, 2)) __wur __warnattr ("readlink called with bigger length " + "than size of destination buffer"); __extern_always_inline __nonnull ((1, 2)) __wur ssize_t __NTH (readlink (__const char *__restrict __path, char *__restrict __buf, size_t __len)) { - if (__bos (__buf) != (size_t) -1 - && (!__builtin_constant_p (__len) || __len > __bos (__buf))) - return __readlink_chk (__path, __buf, __len, __bos (__buf)); + if (__bos (__buf) != (size_t) -1) + { + if (!__builtin_constant_p (__len)) + return __readlink_chk (__path, __buf, __len, __bos (__buf)); + + if ( __len > __bos (__buf)) + return __readlink_chk_warn (__path, __buf, __len, __bos (__buf)); + } return __readlink_alias (__path, __buf, __len); } #endif @@ -110,14 +162,27 @@ extern ssize_t __REDIRECT_NTH (__readlinkat_alias, char *__restrict __buf, size_t __len), readlinkat) __nonnull ((2, 3)) __wur; +extern ssize_t __REDIRECT_NTH (__readlinkat_chk_warn, + (int __fd, __const char *__restrict __path, + char *__restrict __buf, size_t __len, + size_t __buflen), __readlinkat_chk) + __nonnull ((2, 3)) __wur __warnattr ("readlinkat called with bigger " + "length than size of destination " + "buffer"); __extern_always_inline __nonnull ((2, 3)) __wur ssize_t __NTH (readlinkat (int __fd, __const char *__restrict __path, char *__restrict __buf, size_t __len)) { - if (__bos (__buf) != (size_t) -1 - && (!__builtin_constant_p (__len) || __len > __bos (__buf))) - return __readlinkat_chk (__fd, __path, __buf, __len, __bos (__buf)); + if (__bos (__buf) != (size_t) -1) + { + if (!__builtin_constant_p (__len)) + return __readlinkat_chk (__fd, __path, __buf, __len, __bos (__buf)); + + if (__len > __bos (__buf)) + return __readlinkat_chk_warn (__fd, __path, __buf, __len, + __bos (__buf)); + } return __readlinkat_alias (__fd, __path, __buf, __len); } #endif @@ -126,28 +191,39 @@ extern char *__getcwd_chk (char *__buf, size_t __size, size_t __buflen) __THROW __wur; extern char *__REDIRECT_NTH (__getcwd_alias, (char *__buf, size_t __size), getcwd) __wur; +extern char *__REDIRECT_NTH (__getcwd_chk_warn, + (char *__buf, size_t __size, size_t __buflen), + __getcwd_chk) + __wur __warnattr ("getcwd caller with bigger length than size of " + "destination buffer"); __extern_always_inline __wur char * __NTH (getcwd (char *__buf, size_t __size)) { - if (__bos (__buf) != (size_t) -1 - && (!__builtin_constant_p (__size) || __size > __bos (__buf))) - return __getcwd_chk (__buf, __size, __bos (__buf)); + if (__bos (__buf) != (size_t) -1) + { + if (!__builtin_constant_p (__size)) + return __getcwd_chk (__buf, __size, __bos (__buf)); + + if (__size > __bos (__buf)) + return __getcwd_chk_warn (__buf, __size, __bos (__buf)); + } return __getcwd_alias (__buf, __size); } #if defined __USE_BSD || defined __USE_XOPEN_EXTENDED extern char *__getwd_chk (char *__buf, size_t buflen) __THROW __nonnull ((1)) __wur; -extern char *__REDIRECT_NTH (__getwd_alias, (char *__buf), getwd) - __nonnull ((1)) __wur; +extern char *__REDIRECT_NTH (__getwd_warn, (char *__buf), getwd) + __nonnull ((1)) __wur __warnattr ("please use getcwd instead, as getwd " + "doesn't specify buffer size"); __extern_always_inline __nonnull ((1)) __attribute_deprecated__ __wur char * __NTH (getwd (char *__buf)) { if (__bos (__buf) != (size_t) -1) return __getwd_chk (__buf, __bos (__buf)); - return __getwd_alias (__buf); + return __getwd_warn (__buf); } #endif @@ -155,29 +231,48 @@ extern size_t __confstr_chk (int __name, char *__buf, size_t __len, size_t __buflen) __THROW; extern size_t __REDIRECT_NTH (__confstr_alias, (int __name, char *__buf, size_t __len), confstr); +extern size_t __REDIRECT_NTH (__confstr_chk_warn, + (int __name, char *__buf, size_t __len, + size_t __buflen), __confstr_chk) + __warnattr ("confstr called with bigger length than size of destination " + "buffer"); __extern_always_inline size_t __NTH (confstr (int __name, char *__buf, size_t __len)) { - if (__bos (__buf) != (size_t) -1 - && (!__builtin_constant_p (__len) || __bos (__buf) < __len)) - return __confstr_chk (__name, __buf, __len, __bos (__buf)); + if (__bos (__buf) != (size_t) -1) + { + if (!__builtin_constant_p (__len)) + return __confstr_chk (__name, __buf, __len, __bos (__buf)); + + if (__bos (__buf) < __len) + return __confstr_chk_warn (__name, __buf, __len, __bos (__buf)); + } return __confstr_alias (__name, __buf, __len); } -extern int __getgroups_chk (int __size, __gid_t __list[], size_t listlen) +extern int __getgroups_chk (int __size, __gid_t __list[], size_t __listlen) __THROW __wur; extern int __REDIRECT_NTH (__getgroups_alias, (int __size, __gid_t __list[]), getgroups) __wur; +extern int __REDIRECT_NTH (__getgroups_chk_warn, + (int __size, __gid_t __list[], size_t __listlen), + __getgroups_chk) + __wur __warnattr ("getgroups called with bigger group count than what " + "can fit into destination buffer"); __extern_always_inline int __NTH (getgroups (int __size, __gid_t __list[])) { - if (__bos (__list) != (size_t) -1 - && (!__builtin_constant_p (__size) - || __size * sizeof (__gid_t) > __bos (__list))) - return __getgroups_chk (__size, __list, __bos (__list)); + if (__bos (__list) != (size_t) -1) + { + if (!__builtin_constant_p (__size)) + return __getgroups_chk (__size, __list, __bos (__list)); + + if (__size * sizeof (__gid_t) > __bos (__list)) + return __getgroups_chk_warn (__size, __list, __bos (__list)); + } return __getgroups_alias (__size, __list); } @@ -187,13 +282,23 @@ extern int __ttyname_r_chk (int __fd, char *__buf, size_t __buflen, extern int __REDIRECT_NTH (__ttyname_r_alias, (int __fd, char *__buf, size_t __buflen), ttyname_r) __nonnull ((2)); +extern int __REDIRECT_NTH (__ttyname_r_chk_warn, + (int __fd, char *__buf, size_t __buflen, + size_t __nreal), __ttyname_r_chk) + __nonnull ((2)) __warnattr ("ttyname_r called with bigger buflen than " + "size of destination buffer"); __extern_always_inline int __NTH (ttyname_r (int __fd, char *__buf, size_t __buflen)) { - if (__bos (__buf) != (size_t) -1 - && (!__builtin_constant_p (__buflen) || __buflen > __bos (__buf))) - return __ttyname_r_chk (__fd, __buf, __buflen, __bos (__buf)); + if (__bos (__buf) != (size_t) -1) + { + if (!__builtin_constant_p (__buflen)) + return __ttyname_r_chk (__fd, __buf, __buflen, __bos (__buf)); + + if (__buflen > __bos (__buf)) + return __ttyname_r_chk_warn (__fd, __buf, __buflen, __bos (__buf)); + } return __ttyname_r_alias (__fd, __buf, __buflen); } @@ -203,13 +308,23 @@ extern int __getlogin_r_chk (char *__buf, size_t __buflen, size_t __nreal) __nonnull ((1)); extern int __REDIRECT (__getlogin_r_alias, (char *__buf, size_t __buflen), getlogin_r) __nonnull ((1)); +extern int __REDIRECT (__getlogin_r_chk_warn, + (char *__buf, size_t __buflen, size_t __nreal), + __getlogin_r_chk) + __nonnull ((1)) __warnattr ("getlogin_r called with bigger buflen than " + "size of destination buffer"); __extern_always_inline int getlogin_r (char *__buf, size_t __buflen) { - if (__bos (__buf) != (size_t) -1 - && (!__builtin_constant_p (__buflen) || __buflen > __bos (__buf))) - return __getlogin_r_chk (__buf, __buflen, __bos (__buf)); + if (__bos (__buf) != (size_t) -1) + { + if (!__builtin_constant_p (__buflen)) + return __getlogin_r_chk (__buf, __buflen, __bos (__buf)); + + if (__buflen > __bos (__buf)) + return __getlogin_r_chk_warn (__buf, __buflen, __bos (__buf)); + } return __getlogin_r_alias (__buf, __buflen); } #endif @@ -220,13 +335,23 @@ extern int __gethostname_chk (char *__buf, size_t __buflen, size_t __nreal) __THROW __nonnull ((1)); extern int __REDIRECT_NTH (__gethostname_alias, (char *__buf, size_t __buflen), gethostname) __nonnull ((1)); +extern int __REDIRECT_NTH (__gethostname_chk_warn, + (char *__buf, size_t __buflen, size_t __nreal), + __gethostname_chk) + __nonnull ((1)) __warnattr ("gethostname called with bigger buflen than " + "size of destination buffer"); __extern_always_inline int __NTH (gethostname (char *__buf, size_t __buflen)) { - if (__bos (__buf) != (size_t) -1 - && (!__builtin_constant_p (__buflen) || __buflen > __bos (__buf))) - return __gethostname_chk (__buf, __buflen, __bos (__buf)); + if (__bos (__buf) != (size_t) -1) + { + if (!__builtin_constant_p (__buflen)) + return __gethostname_chk (__buf, __buflen, __bos (__buf)); + + if (__buflen > __bos (__buf)) + return __gethostname_chk_warn (__buf, __buflen, __bos (__buf)); + } return __gethostname_alias (__buf, __buflen); } #endif @@ -238,13 +363,24 @@ extern int __getdomainname_chk (char *__buf, size_t __buflen, size_t __nreal) extern int __REDIRECT_NTH (__getdomainname_alias, (char *__buf, size_t __buflen), getdomainname) __nonnull ((1)) __wur; +extern int __REDIRECT_NTH (__getdomainname_chk_warn, + (char *__buf, size_t __buflen, size_t __nreal), + __getdomainname_chk) + __nonnull ((1)) __wur __warnattr ("getdomainname called with bigger " + "buflen than size of destination " + "buffer"); __extern_always_inline int __NTH (getdomainname (char *__buf, size_t __buflen)) { - if (__bos (__buf) != (size_t) -1 - && (!__builtin_constant_p (__buflen) || __buflen > __bos (__buf))) - return __getdomainname_chk (__buf, __buflen, __bos (__buf)); + if (__bos (__buf) != (size_t) -1) + { + if (!__builtin_constant_p (__buflen)) + return __getdomainname_chk (__buf, __buflen, __bos (__buf)); + + if (__buflen > __bos (__buf)) + return __getdomainname_chk_warn (__buf, __buflen, __bos (__buf)); + } return __getdomainname_alias (__buf, __buflen); } #endif diff --git a/socket/bits/socket2.h b/socket/bits/socket2.h index 9fac75669c..5c4cb47a6d 100644 --- a/socket/bits/socket2.h +++ b/socket/bits/socket2.h @@ -25,13 +25,23 @@ extern ssize_t __recv_chk (int __fd, void *__buf, size_t __n, size_t __buflen, int __flags); extern ssize_t __REDIRECT (__recv_alias, (int __fd, void *__buf, size_t __n, int __flags), recv); +extern ssize_t __REDIRECT (__recv_chk_warn, + (int __fd, void *__buf, size_t __n, size_t __buflen, + int __flags), __recv_chk) + __warnattr ("recv called with bigger length than size of destination " + "buffer"); __extern_always_inline ssize_t recv (int __fd, void *__buf, size_t __n, int __flags) { - if (__bos0 (__buf) != (size_t) -1 - && (!__builtin_constant_p (__n) || __n > __bos0 (__buf))) - return __recv_chk (__fd, __buf, __n, __bos0 (__buf), __flags); + if (__bos0 (__buf) != (size_t) -1) + { + if (!__builtin_constant_p (__n)) + return __recv_chk (__fd, __buf, __n, __bos0 (__buf), __flags); + + if (__n > __bos0 (__buf)) + return __recv_chk_warn (__fd, __buf, __n, __bos0 (__buf), __flags); + } return __recv_alias (__fd, __buf, __n, __flags); } @@ -43,14 +53,26 @@ extern ssize_t __REDIRECT (__recvfrom_alias, (int __fd, void *__restrict __buf, size_t __n, int __flags, __SOCKADDR_ARG __addr, socklen_t *__restrict __addr_len), recvfrom); +extern ssize_t __REDIRECT (__recvfrom_chk_warn, + (int __fd, void *__restrict __buf, size_t __n, + size_t __buflen, int __flags, + __SOCKADDR_ARG __addr, + socklen_t *__restrict __addr_len), __recvfrom_chk) + __warnattr ("recvfrom called with bigger length than size of " + "destination buffer"); __extern_always_inline ssize_t recvfrom (int __fd, void *__restrict __buf, size_t __n, int __flags, __SOCKADDR_ARG __addr, socklen_t *__restrict __addr_len) { - if (__bos0 (__buf) != (size_t) -1 - && (!__builtin_constant_p (__n) || __n > __bos0 (__buf))) - return __recvfrom_chk (__fd, __buf, __n, __bos0 (__buf), __flags, - __addr, __addr_len); + if (__bos0 (__buf) != (size_t) -1) + { + if (!__builtin_constant_p (__n)) + return __recvfrom_chk (__fd, __buf, __n, __bos0 (__buf), __flags, + __addr, __addr_len); + if (__n > __bos0 (__buf)) + return __recvfrom_chk_warn (__fd, __buf, __n, __bos0 (__buf), __flags, + __addr, __addr_len); + } return __recvfrom_alias (__fd, __buf, __n, __flags, __addr, __addr_len); } diff --git a/stdlib/bits/stdlib.h b/stdlib/bits/stdlib.h index 7ee7bf5587..f6af5e518c 100644 --- a/stdlib/bits/stdlib.h +++ b/stdlib/bits/stdlib.h @@ -27,12 +27,24 @@ extern char *__realpath_chk (__const char *__restrict __name, extern char *__REDIRECT_NTH (__realpath_alias, (__const char *__restrict __name, char *__restrict __resolved), realpath) __wur; +extern char *__REDIRECT_NTH (__realpath_chk_warn, + (__const char *__restrict __name, + char *__restrict __resolved, + size_t __resolvedlen), __realpath_chk) __wur + __warnattr ("second argument of realpath must be either NULL or at " + "least PATH_MAX bytes long buffer"); __extern_always_inline __wur char * __NTH (realpath (__const char *__restrict __name, char *__restrict __resolved)) { if (__bos (__resolved) != (size_t) -1) - return __realpath_chk (__name, __resolved, __bos (__resolved)); + { +#if defined _LIBC_LIMITS_H_ && defined PATH_MAX + if (__bos (__resolved) < PATH_MAX) + return __realpath_chk_warn (__name, __resolved, __bos (__resolved)); +#endif + return __realpath_chk (__name, __resolved, __bos (__resolved)); + } return __realpath_alias (__name, __resolved); } @@ -43,13 +55,22 @@ extern int __ptsname_r_chk (int __fd, char *__buf, size_t __buflen, extern int __REDIRECT_NTH (__ptsname_r_alias, (int __fd, char *__buf, size_t __buflen), ptsname_r) __nonnull ((2)); +extern int __REDIRECT_NTH (__ptsname_r_chk_warn, + (int __fd, char *__buf, size_t __buflen, + size_t __nreal), __ptsname_r_chk) + __nonnull ((2)) __warnattr ("ptsname_r called with buflen bigger than " + "size of buf"); __extern_always_inline int __NTH (ptsname_r (int __fd, char *__buf, size_t __buflen)) { - if (__bos (__buf) != (size_t) -1 - && (!__builtin_constant_p (__buflen) || __buflen > __bos (__buf))) - return __ptsname_r_chk (__fd, __buf, __buflen, __bos (__buf)); + if (__bos (__buf) != (size_t) -1) + { + if (!__builtin_constant_p (__buflen)) + return __ptsname_r_chk (__fd, __buf, __buflen, __bos (__buf)); + if (__buflen > __bos (__buf)) + return __ptsname_r_chk_warn (__fd, __buf, __buflen, __bos (__buf)); + } return __ptsname_r_alias (__fd, __buf, __buflen); } @@ -82,16 +103,27 @@ extern size_t __REDIRECT_NTH (__mbstowcs_alias, (wchar_t *__restrict __dst, __const char *__restrict __src, size_t __len), mbstowcs); +extern size_t __REDIRECT_NTH (__mbstowcs_chk_warn, + (wchar_t *__restrict __dst, + __const char *__restrict __src, + size_t __len, size_t __dstlen), __mbstowcs_chk) + __warnattr ("mbstowcs called with dst buffer smaller than len " + "* sizeof (wchar_t)"); __extern_always_inline size_t __NTH (mbstowcs (wchar_t *__restrict __dst, __const char *__restrict __src, size_t __len)) { - if (__bos (__dst) != (size_t) -1 - && (!__builtin_constant_p (__len) - || __len > __bos (__dst) / sizeof (wchar_t))) - return __mbstowcs_chk (__dst, __src, __len, - __bos (__dst) / sizeof (wchar_t)); + if (__bos (__dst) != (size_t) -1) + { + if (!__builtin_constant_p (__len)) + return __mbstowcs_chk (__dst, __src, __len, + __bos (__dst) / sizeof (wchar_t)); + + if (__len > __bos (__dst) / sizeof (wchar_t)) + return __mbstowcs_chk_warn (__dst, __src, __len, + __bos (__dst) / sizeof (wchar_t)); + } return __mbstowcs_alias (__dst, __src, __len); } @@ -103,13 +135,22 @@ extern size_t __REDIRECT_NTH (__wcstombs_alias, (char *__restrict __dst, __const wchar_t *__restrict __src, size_t __len), wcstombs); +extern size_t __REDIRECT_NTH (__wcstombs_chk_warn, + (char *__restrict __dst, + __const wchar_t *__restrict __src, + size_t __len, size_t __dstlen), __wcstombs_chk) + __warnattr ("wcstombs called with dst buffer smaller than len"); __extern_always_inline size_t __NTH (wcstombs (char *__restrict __dst, __const wchar_t *__restrict __src, size_t __len)) { - if (__bos (__dst) != (size_t) -1 - && (!__builtin_constant_p (__len) || __len > __bos (__dst))) - return __wcstombs_chk (__dst, __src, __len, __bos (__dst)); + if (__bos (__dst) != (size_t) -1) + { + if (!__builtin_constant_p (__len)) + return __wcstombs_chk (__dst, __src, __len, __bos (__dst)); + if (__len > __bos (__dst)) + return __wcstombs_chk_warn (__dst, __src, __len, __bos (__dst)); + } return __wcstombs_alias (__dst, __src, __len); } diff --git a/wcsmbs/bits/wchar2.h b/wcsmbs/bits/wchar2.h index e1b7c13023..0c940d7221 100644 --- a/wcsmbs/bits/wchar2.h +++ b/wcsmbs/bits/wchar2.h @@ -29,13 +29,27 @@ extern wchar_t *__REDIRECT_NTH (__wmemcpy_alias, (wchar_t *__restrict __s1, __const wchar_t *__restrict __s2, size_t __n), wmemcpy); +extern wchar_t *__REDIRECT_NTH (__wmemcpy_chk_warn, + (wchar_t *__restrict __s1, + __const wchar_t *__restrict __s2, size_t __n, + size_t __ns1), __wmemcpy_chk) + __warnattr ("wmemcpy called with length bigger than size of destination " + "buffer"); __extern_always_inline wchar_t * __NTH (wmemcpy (wchar_t *__restrict __s1, __const wchar_t *__restrict __s2, size_t __n)) { if (__bos0 (__s1) != (size_t) -1) - return __wmemcpy_chk (__s1, __s2, __n, __bos0 (__s1) / sizeof (wchar_t)); + { + if (!__builtin_constant_p (__n)) + return __wmemcpy_chk (__s1, __s2, __n, + __bos0 (__s1) / sizeof (wchar_t)); + + if (__n > __bos0 (__s1) / sizeof (wchar_t)) + return __wmemcpy_chk_warn (__s1, __s2, __n, + __bos0 (__s1) / sizeof (wchar_t)); + } return __wmemcpy_alias (__s1, __s2, __n); } @@ -45,13 +59,27 @@ extern wchar_t *__wmemmove_chk (wchar_t *__s1, __const wchar_t *__s2, extern wchar_t *__REDIRECT_NTH (__wmemmove_alias, (wchar_t *__s1, __const wchar_t *__s2, size_t __n), wmemmove); +extern wchar_t *__REDIRECT_NTH (__wmemmove_chk_warn, + (wchar_t *__restrict __s1, + __const wchar_t *__restrict __s2, size_t __n, + size_t __ns1), __wmemmove_chk) + __warnattr ("wmemmove called with length bigger than size of destination " + "buffer"); __extern_always_inline wchar_t * __NTH (wmemmove (wchar_t *__restrict __s1, __const wchar_t *__restrict __s2, size_t __n)) { if (__bos0 (__s1) != (size_t) -1) - return __wmemmove_chk (__s1, __s2, __n, __bos0 (__s1) / sizeof (wchar_t)); + { + if (!__builtin_constant_p (__n)) + return __wmemmove_chk (__s1, __s2, __n, + __bos0 (__s1) / sizeof (wchar_t)); + + if (__n > __bos0 (__s1) / sizeof (wchar_t)) + return __wmemmove_chk_warn (__s1, __s2, __n, + __bos0 (__s1) / sizeof (wchar_t)); + } return __wmemmove_alias (__s1, __s2, __n); } @@ -64,13 +92,27 @@ extern wchar_t *__REDIRECT_NTH (__wmempcpy_alias, (wchar_t *__restrict __s1, __const wchar_t *__restrict __s2, size_t __n), wmempcpy); +extern wchar_t *__REDIRECT_NTH (__wmempcpy_chk_warn, + (wchar_t *__restrict __s1, + __const wchar_t *__restrict __s2, size_t __n, + size_t __ns1), __wmempcpy_chk) + __warnattr ("wmempcpy called with length bigger than size of destination " + "buffer"); __extern_always_inline wchar_t * __NTH (wmempcpy (wchar_t *__restrict __s1, __const wchar_t *__restrict __s2, size_t __n)) { if (__bos0 (__s1) != (size_t) -1) - return __wmempcpy_chk (__s1, __s2, __n, __bos0 (__s1) / sizeof (wchar_t)); + { + if (!__builtin_constant_p (__n)) + return __wmempcpy_chk (__s1, __s2, __n, + __bos0 (__s1) / sizeof (wchar_t)); + + if (__n > __bos0 (__s1) / sizeof (wchar_t)) + return __wmempcpy_chk_warn (__s1, __s2, __n, + __bos0 (__s1) / sizeof (wchar_t)); + } return __wmempcpy_alias (__s1, __s2, __n); } #endif @@ -80,12 +122,24 @@ extern wchar_t *__wmemset_chk (wchar_t *__s, wchar_t __c, size_t __n, size_t __ns) __THROW; extern wchar_t *__REDIRECT_NTH (__wmemset_alias, (wchar_t *__s, wchar_t __c, size_t __n), wmemset); +extern wchar_t *__REDIRECT_NTH (__wmemset_chk_warn, + (wchar_t *__s, wchar_t __c, size_t __n, + size_t __ns), __wmemset_chk) + __warnattr ("wmemset called with length bigger than size of destination " + "buffer"); __extern_always_inline wchar_t * __NTH (wmemset (wchar_t *__restrict __s, wchar_t __c, size_t __n)) { if (__bos0 (__s) != (size_t) -1) - return __wmemset_chk (__s, __c, __n, __bos0 (__s) / sizeof (wchar_t)); + { + if (!__builtin_constant_p (__n)) + return __wmemset_chk (__s, __c, __n, __bos0 (__s) / sizeof (wchar_t)); + + if (__n > __bos0 (__s) / sizeof (wchar_t)) + return __wmemset_chk_warn (__s, __c, __n, + __bos0 (__s) / sizeof (wchar_t)); + } return __wmemset_alias (__s, __c, __n); } @@ -128,14 +182,25 @@ extern wchar_t *__REDIRECT_NTH (__wcsncpy_alias, (wchar_t *__restrict __dest, __const wchar_t *__restrict __src, size_t __n), wcsncpy); +extern wchar_t *__REDIRECT_NTH (__wcsncpy_chk_warn, + (wchar_t *__restrict __dest, + __const wchar_t *__restrict __src, + size_t __n, size_t __destlen), __wcsncpy_chk) + __warnattr ("wcsncpy called with length bigger than size of destination " + "buffer"); __extern_always_inline wchar_t * __NTH (wcsncpy (wchar_t *__dest, __const wchar_t *__src, size_t __n)) { - if (__bos (__dest) != (size_t) -1 - && (!__builtin_constant_p (__n) || __bos (__dest) >= __n)) - return __wcsncpy_chk (__dest, __src, __n, - __bos (__dest) / sizeof (wchar_t)); + if (__bos (__dest) != (size_t) -1) + { + if (!__builtin_constant_p (__n)) + return __wcsncpy_chk (__dest, __src, __n, + __bos (__dest) / sizeof (wchar_t)); + if (__n > __bos (__dest) / sizeof (wchar_t)) + return __wcsncpy_chk_warn (__dest, __src, __n, + __bos (__dest) / sizeof (wchar_t)); + } return __wcsncpy_alias (__dest, __src, __n); } @@ -147,14 +212,25 @@ extern wchar_t *__REDIRECT_NTH (__wcpncpy_alias, (wchar_t *__restrict __dest, __const wchar_t *__restrict __src, size_t __n), wcpncpy); +extern wchar_t *__REDIRECT_NTH (__wcpncpy_chk_warn, + (wchar_t *__restrict __dest, + __const wchar_t *__restrict __src, + size_t __n, size_t __destlen), __wcpncpy_chk) + __warnattr ("wcpncpy called with length bigger than size of destination " + "buffer"); __extern_always_inline wchar_t * __NTH (wcpncpy (wchar_t *__dest, __const wchar_t *__src, size_t __n)) { - if (__bos (__dest) != (size_t) -1 - && (!__builtin_constant_p (__n) || __bos (__dest) >= __n)) - return __wcpncpy_chk (__dest, __src, __n, - __bos (__dest) / sizeof (wchar_t)); + if (__bos (__dest) != (size_t) -1) + { + if (!__builtin_constant_p (__n)) + return __wcpncpy_chk (__dest, __src, __n, + __bos (__dest) / sizeof (wchar_t)); + if (__n > __bos (__dest) / sizeof (wchar_t)) + return __wcpncpy_chk_warn (__dest, __src, __n, + __bos (__dest) / sizeof (wchar_t)); + } return __wcpncpy_alias (__dest, __src, __n); } @@ -209,7 +285,8 @@ __NTH (swprintf (wchar_t *__restrict __s, size_t __n, __const wchar_t *__restrict __fmt, ...)) { if (__bos (__s) != (size_t) -1 || __USE_FORTIFY_LEVEL > 1) - return __swprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1, __bos (__s), + return __swprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1, + __bos (__s) / sizeof (wchar_t), __fmt, __va_arg_pack ()); return __swprintf_alias (__s, __n, __fmt, __va_arg_pack ()); } @@ -217,7 +294,8 @@ __NTH (swprintf (wchar_t *__restrict __s, size_t __n, /* XXX We might want to have support in gcc for swprintf. */ # define swprintf(s, n, ...) \ (__bos (s) != (size_t) -1 || __USE_FORTIFY_LEVEL > 1 \ - ? __swprintf_chk (s, n, __USE_FORTIFY_LEVEL - 1, __bos (s), __VA_ARGS__) \ + ? __swprintf_chk (s, n, __USE_FORTIFY_LEVEL - 1, \ + __bos (s) / sizeof (wchar_t), __VA_ARGS__) \ : swprintf (s, n, __VA_ARGS__)) #endif @@ -237,8 +315,8 @@ __NTH (vswprintf (wchar_t *__restrict __s, size_t __n, __const wchar_t *__restrict __fmt, __gnuc_va_list __ap)) { if (__bos (__s) != (size_t) -1 || __USE_FORTIFY_LEVEL > 1) - return __vswprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1, __bos (__s), - __fmt, __ap); + return __vswprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1, + __bos (__s) / sizeof (wchar_t), __fmt, __ap); return __vswprintf_alias (__s, __n, __fmt, __ap); } @@ -295,13 +373,25 @@ extern wchar_t *__fgetws_chk (wchar_t *__restrict __s, size_t __size, int __n, extern wchar_t *__REDIRECT (__fgetws_alias, (wchar_t *__restrict __s, int __n, __FILE *__restrict __stream), fgetws) __wur; +extern wchar_t *__REDIRECT (__fgetws_chk_warn, + (wchar_t *__restrict __s, size_t __size, int __n, + __FILE *__restrict __stream), __fgetws_chk) + __wur __warnattr ("fgetws called with bigger size than length " + "of destination buffer"); __extern_always_inline __wur wchar_t * fgetws (wchar_t *__restrict __s, int __n, __FILE *__restrict __stream) { - if (__bos (__s) != (size_t) -1 - && (!__builtin_constant_p (__n) || (size_t) __n > __bos (__s))) - return __fgetws_chk (__s, __bos (__s), __n, __stream); + if (__bos (__s) != (size_t) -1) + { + if (!__builtin_constant_p (__n) || __n <= 0) + return __fgetws_chk (__s, __bos (__s) / sizeof (wchar_t), + __n, __stream); + + if ((size_t) __n > __bos (__s) / sizeof (wchar_t)) + return __fgetws_chk_warn (__s, __bos (__s) / sizeof (wchar_t), + __n, __stream); + } return __fgetws_alias (__s, __n, __stream); } @@ -313,13 +403,26 @@ extern wchar_t *__REDIRECT (__fgetws_unlocked_alias, (wchar_t *__restrict __s, int __n, __FILE *__restrict __stream), fgetws_unlocked) __wur; +extern wchar_t *__REDIRECT (__fgetws_unlocked_chk_warn, + (wchar_t *__restrict __s, size_t __size, int __n, + __FILE *__restrict __stream), + __fgetws_unlocked_chk) + __wur __warnattr ("fgetws_unlocked called with bigger size than length " + "of destination buffer"); __extern_always_inline __wur wchar_t * fgetws_unlocked (wchar_t *__restrict __s, int __n, __FILE *__restrict __stream) { - if (__bos (__s) != (size_t) -1 - && (!__builtin_constant_p (__n) || (size_t) __n > __bos (__s))) - return __fgetws_unlocked_chk (__s, __bos (__s), __n, __stream); + if (__bos (__s) != (size_t) -1) + { + if (!__builtin_constant_p (__n) || __n <= 0) + return __fgetws_unlocked_chk (__s, __bos (__s) / sizeof (wchar_t), + __n, __stream); + + if ((size_t) __n > __bos (__s) / sizeof (wchar_t)) + return __fgetws_unlocked_chk_warn (__s, __bos (__s) / sizeof (wchar_t), + __n, __stream); + } return __fgetws_unlocked_alias (__s, __n, __stream); } #endif @@ -356,16 +459,28 @@ extern size_t __REDIRECT_NTH (__mbsrtowcs_alias, __const char **__restrict __src, size_t __len, mbstate_t *__restrict __ps), mbsrtowcs); +extern size_t __REDIRECT_NTH (__mbsrtowcs_chk_warn, + (wchar_t *__restrict __dst, + __const char **__restrict __src, + size_t __len, mbstate_t *__restrict __ps, + size_t __dstlen), __mbsrtowcs_chk) + __warnattr ("mbsrtowcs called with dst buffer smaller than len " + "* sizeof (wchar_t)"); __extern_always_inline size_t __NTH (mbsrtowcs (wchar_t *__restrict __dst, __const char **__restrict __src, size_t __len, mbstate_t *__restrict __ps)) { - if (__bos (__dst) != (size_t) -1 - && (!__builtin_constant_p (__len) - || __len > __bos (__dst) / sizeof (wchar_t))) - return __mbsrtowcs_chk (__dst, __src, __len, __ps, - __bos (__dst) / sizeof (wchar_t)); + if (__bos (__dst) != (size_t) -1) + { + if (!__builtin_constant_p (__len)) + return __mbsrtowcs_chk (__dst, __src, __len, __ps, + __bos (__dst) / sizeof (wchar_t)); + + if (__len > __bos (__dst) / sizeof (wchar_t)) + return __mbsrtowcs_chk_warn (__dst, __src, __len, __ps, + __bos (__dst) / sizeof (wchar_t)); + } return __mbsrtowcs_alias (__dst, __src, __len, __ps); } @@ -379,14 +494,25 @@ extern size_t __REDIRECT_NTH (__wcsrtombs_alias, __const wchar_t **__restrict __src, size_t __len, mbstate_t *__restrict __ps), wcsrtombs); +extern size_t __REDIRECT_NTH (__wcsrtombs_chk_warn, + (char *__restrict __dst, + __const wchar_t **__restrict __src, + size_t __len, mbstate_t *__restrict __ps, + size_t __dstlen), __wcsrtombs_chk) + __warnattr ("wcsrtombs called with dst buffer smaller than len"); __extern_always_inline size_t __NTH (wcsrtombs (char *__restrict __dst, __const wchar_t **__restrict __src, size_t __len, mbstate_t *__restrict __ps)) { - if (__bos (__dst) != (size_t) -1 - && (!__builtin_constant_p (__len) || __len > __bos (__dst))) - return __wcsrtombs_chk (__dst, __src, __len, __ps, __bos (__dst)); + if (__bos (__dst) != (size_t) -1) + { + if (!__builtin_constant_p (__len)) + return __wcsrtombs_chk (__dst, __src, __len, __ps, __bos (__dst)); + + if (__len > __bos (__dst)) + return __wcsrtombs_chk_warn (__dst, __src, __len, __ps, __bos (__dst)); + } return __wcsrtombs_alias (__dst, __src, __len, __ps); } @@ -401,16 +527,28 @@ extern size_t __REDIRECT_NTH (__mbsnrtowcs_alias, __const char **__restrict __src, size_t __nmc, size_t __len, mbstate_t *__restrict __ps), mbsnrtowcs); +extern size_t __REDIRECT_NTH (__mbsnrtowcs_chk_warn, + (wchar_t *__restrict __dst, + __const char **__restrict __src, size_t __nmc, + size_t __len, mbstate_t *__restrict __ps, + size_t __dstlen), __mbsnrtowcs_chk) + __warnattr ("mbsnrtowcs called with dst buffer smaller than len " + "* sizeof (wchar_t)"); __extern_always_inline size_t __NTH (mbsnrtowcs (wchar_t *__restrict __dst, __const char **__restrict __src, size_t __nmc, size_t __len, mbstate_t *__restrict __ps)) { - if (__bos (__dst) != (size_t) -1 - && (!__builtin_constant_p (__len) - || __len > __bos (__dst) / sizeof (wchar_t))) - return __mbsnrtowcs_chk (__dst, __src, __nmc, __len, __ps, - __bos (__dst) / sizeof (wchar_t)); + if (__bos (__dst) != (size_t) -1) + { + if (!__builtin_constant_p (__len)) + return __mbsnrtowcs_chk (__dst, __src, __nmc, __len, __ps, + __bos (__dst) / sizeof (wchar_t)); + + if (__len > __bos (__dst) / sizeof (wchar_t)) + return __mbsnrtowcs_chk_warn (__dst, __src, __nmc, __len, __ps, + __bos (__dst) / sizeof (wchar_t)); + } return __mbsnrtowcs_alias (__dst, __src, __nmc, __len, __ps); } @@ -425,14 +563,28 @@ extern size_t __REDIRECT_NTH (__wcsnrtombs_alias, __const wchar_t **__restrict __src, size_t __nwc, size_t __len, mbstate_t *__restrict __ps), wcsnrtombs); +extern size_t __REDIRECT_NTH (__wcsnrtombs_chk_warn, + (char *__restrict __dst, + __const wchar_t **__restrict __src, + size_t __nwc, size_t __len, + mbstate_t *__restrict __ps, + size_t __dstlen), __wcsnrtombs_chk) + __warnattr ("wcsnrtombs called with dst buffer smaller than len"); __extern_always_inline size_t __NTH (wcsnrtombs (char *__restrict __dst, __const wchar_t **__restrict __src, size_t __nwc, size_t __len, mbstate_t *__restrict __ps)) { - if (__bos (__dst) != (size_t) -1 - && (!__builtin_constant_p (__len) || __len > __bos (__dst))) - return __wcsnrtombs_chk (__dst, __src, __nwc, __len, __ps, __bos (__dst)); + if (__bos (__dst) != (size_t) -1) + { + if (!__builtin_constant_p (__len)) + return __wcsnrtombs_chk (__dst, __src, __nwc, __len, __ps, + __bos (__dst)); + + if (__len > __bos (__dst)) + return __wcsnrtombs_chk_warn (__dst, __src, __nwc, __len, __ps, + __bos (__dst)); + } return __wcsnrtombs_alias (__dst, __src, __nwc, __len, __ps); } #endif -- cgit v1.2.3