This is the mail archive of the libc-hacker@sourceware.org mailing list for the glibc project.

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Use warning and error attributes in glibc plus fix a few -D_FORTIFY_SOURCE=2 wchar2.h bugs


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  <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.

--- 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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]