* misc/sys/cdefs.h (__warndecl, __errordecl): For GCC 4.3+ define
authorUlrich Drepper <drepper@redhat.com>
Wed, 26 Sep 2007 20:45:18 +0000 (20:45 +0000)
committerUlrich Drepper <drepper@redhat.com>
Wed, 26 Sep 2007 20:45:18 +0000 (20:45 +0000)
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
debug/tst-chk1.c
libio/bits/stdio2.h
misc/sys/cdefs.h
posix/bits/unistd.h
socket/bits/socket2.h
stdlib/bits/stdlib.h
wcsmbs/bits/wchar2.h

index 682c2e3..ed21b4f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,56 @@
+2007-09-26  Jakub Jelinek  <jakub@redhat.com>
+
+       * 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  <drepper@redhat.com>
 
        [BZ #5058]
index 78a61be..487b071 100644 (file)
@@ -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
 
index 841a0ff..8889540 100644 (file)
@@ -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)
index 26b9490..4650d5f 100644 (file)
 /* 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)
index 331e8ea..efd7f75 100644 (file)
@@ -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
index 9fac756..5c4cb47 100644 (file)
@@ -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);
 }
index 7ee7bf5..f6af5e5 100644 (file)
@@ -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);
 }
index e1b7c13..0c940d7 100644 (file)
@@ -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