From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 29533 invoked by alias); 26 Sep 2007 17:35:10 -0000 Received: (qmail 29516 invoked by uid 22791); 26 Sep 2007 17:35:09 -0000 X-Spam-Check-By: sourceware.org Received: from sunsite.ms.mff.cuni.cz (HELO sunsite.mff.cuni.cz) (195.113.15.26) by sourceware.org (qpsmtpd/0.31) with ESMTP; Wed, 26 Sep 2007 17:35:01 +0000 Received: from sunsite.mff.cuni.cz (localhost.localdomain [127.0.0.1]) by sunsite.mff.cuni.cz (8.13.8/8.13.8) with ESMTP id l8QHiPmq008870; Wed, 26 Sep 2007 19:44:25 +0200 Received: (from jakub@localhost) by sunsite.mff.cuni.cz (8.13.8/8.13.8/Submit) id l8QHiPJb008869; Wed, 26 Sep 2007 19:44:25 +0200 Date: Wed, 26 Sep 2007 17:35:00 -0000 From: Jakub Jelinek To: Ulrich Drepper Cc: Glibc hackers Subject: [PATCH] Use warning and error attributes in glibc plus fix a few -D_FORTIFY_SOURCE=2 wchar2.h bugs Message-ID: <20070926174425.GX2279@sunsite.mff.cuni.cz> Reply-To: Jakub Jelinek Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.4.2.2i Mailing-List: contact libc-hacker-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-hacker-owner@sourceware.org X-SW-Source: 2007-09/txt/msg00010.txt.bz2 Hi! This patch uses for GCC 4.3+ new error/warning attributes. In addition to changing __errordecl/__warndecl definitions, this also allows a lot of compile time checking with -D_FORTIFY_SOURCE{,=2}, without bloating the generated code. The trick is using REDIRECTs for the __*_chk functions, __*_chk_warn redirects to __*_chk, has the same arguments and other properties, just additional warning attribute. Until now only the GCC builtins were able to to do compile time diagnostics, with this patch and GCC 4.3+ even say char buf[6]; read (0, buf, 7); will display a warning. While working on this patch, I found a couple of bugs. Particularly, swprintf/vswprintf was passed __bos, but was actually expecting count of wide characters, similarly fgetws/fgetws_unlocked. And wcsncpy/wcpncpy got the test wrong, they compared __bos with __n (but __bos is number of bytes, while __n number of wide chars) and even the comparison was reversed, so for constant __n, if it (max number of wide chars to copy) was bigger than __bos (number of bytes), __*_chk was not called, otherwise it would. 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. --- libc/misc/sys/cdefs.h.jj 2007-09-16 07:09:53.000000000 +0200 +++ libc/misc/sys/cdefs.h 2007-09-26 11:28:24.000000000 +0200 @@ -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) --- libc/stdlib/bits/stdlib.h.jj 2007-03-21 21:22:17.000000000 +0100 +++ libc/stdlib/bits/stdlib.h 2007-09-26 12:00:41.000000000 +0200 @@ -27,12 +27,24 @@ extern char *__realpath_chk (__const cha 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, ch 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 (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 (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); } --- libc/libio/bits/stdio2.h.jj 2007-09-15 17:18:47.000000000 +0200 +++ libc/libio/bits/stdio2.h 2007-09-26 12:34:12.000000000 +0200 @@ -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 *__restri 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 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_unlock (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) --- libc/wcsmbs/bits/wchar2.h.jj 2007-09-15 17:18:54.000000000 +0200 +++ libc/wcsmbs/bits/wchar2.h 2007-09-26 16:43:45.000000000 +0200 @@ -29,13 +29,27 @@ extern wchar_t *__REDIRECT_NTH (__wmemcp (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 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 (__wmempc (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 * 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 (__wcsncp (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 (__wcpncp (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 __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 /* 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 __ __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 *_ 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_unl (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 (__mbsrtowc __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 (__wcsrtomb __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 (__mbsnrtow __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 (__wcsnrtom __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 --- libc/socket/bits/socket2.h.jj 2007-03-21 21:22:17.000000000 +0100 +++ libc/socket/bits/socket2.h 2007-09-26 13:56:50.000000000 +0200 @@ -25,13 +25,23 @@ extern ssize_t __recv_chk (int __fd, voi 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_al (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); } --- libc/posix/bits/unistd.h.jj 2007-03-21 21:22:17.000000000 +0100 +++ libc/posix/bits/unistd.h 2007-09-26 13:16:32.000000000 +0200 @@ -25,13 +25,23 @@ extern ssize_t __read_chk (int __fd, voi 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 __n __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 (__readlin (__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 (__readlin 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, __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, 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, ch 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 __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 *__bu __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 *__ 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 --- libc/debug/tst-chk1.c.jj 2007-09-15 17:18:46.000000000 +0200 +++ libc/debug/tst-chk1.c 2007-09-26 18:06:44.000000000 +0200 @@ -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); @@ -514,11 +522,15 @@ do_test (void) 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 @@ -538,6 +550,14 @@ do_test (void) 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 Jakub