about summary refs log tree commit diff
path: root/libio/bits
diff options
context:
space:
mode:
authorXi Ruoyao <xry111@xry111.site>2023-09-25 19:53:26 +0800
committerSiddhesh Poyarekar <siddhesh@sourceware.org>2023-09-26 20:11:38 -0400
commit64b1a44183a3094672ed304532bedb9acc707554 (patch)
tree41131e52fd02f763e2ab83cb9967386f4c40a515 /libio/bits
parent6b695e5c628734b9801fcf53149687cb4fe6926e (diff)
downloadglibc-64b1a44183a3094672ed304532bedb9acc707554.tar.gz
glibc-64b1a44183a3094672ed304532bedb9acc707554.tar.xz
glibc-64b1a44183a3094672ed304532bedb9acc707554.zip
libio: Add nonnull attribute for most FILE * arguments in stdio.h
During the review of a GCC analyzer test case, we found most stdio
functions accepting a FILE * argument expect it to be nonnull and just
segfault when the argument is NULL.  Add nonnull attribute for them.

fflush and fflush_unlocked are well defined when __stream is NULL so
they are not touched.

For fputs, fgets, fread, fwrite, fprintf, vfprintf, and their unlocked
version, if __stream is empty but there is nothing to read or write,
they did not segfault.  But the standard disallow __stream to be empty
here, so nonnull attribute is also added for them.  Note that this may
blow up some old code already subtly broken.

Also add __nonnull for _chk variants and __fortify_function versions for
them.

Signed-off-by: Xi Ruoyao <xry111@xry111.site>
Reviewed-by: Alejandro Colomar <alx@kernel.org>
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
Diffstat (limited to 'libio/bits')
-rw-r--r--libio/bits/stdio2-decl.h15
-rw-r--r--libio/bits/stdio2.h14
2 files changed, 17 insertions, 12 deletions
diff --git a/libio/bits/stdio2-decl.h b/libio/bits/stdio2-decl.h
index d7ef7283d6..3b60c72931 100644
--- a/libio/bits/stdio2-decl.h
+++ b/libio/bits/stdio2-decl.h
@@ -47,10 +47,12 @@ extern int __vsnprintf_chk (char *__restrict __s, size_t __n, int __flag,
 #if __USE_FORTIFY_LEVEL > 1
 
 extern int __fprintf_chk (FILE *__restrict __stream, int __flag,
-			  const char *__restrict __format, ...);
+			  const char *__restrict __format, ...)
+    __nonnull ((1));
 extern int __printf_chk (int __flag, const char *__restrict __format, ...);
 extern int __vfprintf_chk (FILE *__restrict __stream, int __flag,
-			   const char *__restrict __format, __gnuc_va_list __ap);
+			   const char *__restrict __format,
+			   __gnuc_va_list __ap) __nonnull ((1));
 extern int __vprintf_chk (int __flag, const char *__restrict __format,
 			  __gnuc_va_list __ap);
 
@@ -103,7 +105,7 @@ extern char *__REDIRECT (__fgets_chk_warn,
 
 extern char *__fgets_chk (char *__restrict __s, size_t __size, int __n,
 			  FILE *__restrict __stream)
-    __wur __attr_access ((__write_only__, 1, 3));
+    __wur __attr_access ((__write_only__, 1, 3)) __nonnull ((4));
 
 extern size_t __REDIRECT (__fread_alias,
 			  (void *__restrict __ptr, size_t __size,
@@ -119,7 +121,7 @@ extern size_t __REDIRECT (__fread_chk_warn,
 
 extern size_t __fread_chk (void *__restrict __ptr, size_t __ptrlen,
 			   size_t __size, size_t __n,
-			   FILE *__restrict __stream) __wur;
+			   FILE *__restrict __stream) __wur __nonnull ((5));
 
 #ifdef __USE_GNU
 extern char *__REDIRECT_FORTIFY (__fgets_unlocked_alias,
@@ -135,7 +137,7 @@ extern char *__REDIRECT (__fgets_unlocked_chk_warn,
 
 extern char *__fgets_unlocked_chk (char *__restrict __s, size_t __size,
 				   int __n, FILE *__restrict __stream)
-    __wur __attr_access ((__write_only__, 1, 3));
+    __wur __attr_access ((__write_only__, 1, 3)) __nonnull ((4));
 #endif
 
 #ifdef __USE_MISC
@@ -154,7 +156,8 @@ extern size_t __REDIRECT (__fread_unlocked_chk_warn,
 
 extern size_t __fread_unlocked_chk (void *__restrict __ptr, size_t __ptrlen,
 				    size_t __size, size_t __n,
-				    FILE *__restrict __stream) __wur;
+				    FILE *__restrict __stream)
+    __wur __nonnull ((5));
 #endif
 
 #endif /* bits/stdio2-decl.h.  */
diff --git a/libio/bits/stdio2.h b/libio/bits/stdio2.h
index 71226408ab..266dccdd1e 100644
--- a/libio/bits/stdio2.h
+++ b/libio/bits/stdio2.h
@@ -73,7 +73,7 @@ __NTH (vsnprintf (char *__restrict __s, size_t __n,
 
 #if __USE_FORTIFY_LEVEL > 1
 # ifdef __va_arg_pack
-__fortify_function int
+__fortify_function __nonnull ((1)) int
 fprintf (FILE *__restrict __stream, const char *__restrict __fmt, ...)
 {
   return __fprintf_chk (__stream, __USE_FORTIFY_LEVEL - 1, __fmt,
@@ -102,7 +102,7 @@ vprintf (const char *__restrict __fmt, __gnuc_va_list __ap)
 #endif
 }
 
-__fortify_function int
+__fortify_function __nonnull ((1)) int
 vfprintf (FILE *__restrict __stream,
 	  const char *__restrict __fmt, __gnuc_va_list __ap)
 {
@@ -191,7 +191,8 @@ gets (char *__str)
 }
 #endif
 
-__fortify_function __wur __fortified_attr_access (__write_only__, 1, 2) char *
+__fortify_function __wur __fortified_attr_access (__write_only__, 1, 2)
+__nonnull ((3)) char *
 fgets (char *__restrict __s, int __n, FILE *__restrict __stream)
 {
   size_t sz = __glibc_objsize (__s);
@@ -202,7 +203,7 @@ fgets (char *__restrict __s, int __n, FILE *__restrict __stream)
   return __fgets_chk (__s, sz, __n, __stream);
 }
 
-__fortify_function __wur size_t
+__fortify_function __wur __nonnull ((4)) size_t
 fread (void *__restrict __ptr, size_t __size, size_t __n,
        FILE *__restrict __stream)
 {
@@ -215,7 +216,8 @@ fread (void *__restrict __ptr, size_t __size, size_t __n,
 }
 
 #ifdef __USE_GNU
-__fortify_function __wur __fortified_attr_access (__write_only__, 1, 2) char *
+__fortify_function __wur __fortified_attr_access (__write_only__, 1, 2)
+__nonnull ((3)) char *
 fgets_unlocked (char *__restrict __s, int __n, FILE *__restrict __stream)
 {
   size_t sz = __glibc_objsize (__s);
@@ -229,7 +231,7 @@ fgets_unlocked (char *__restrict __s, int __n, FILE *__restrict __stream)
 
 #ifdef __USE_MISC
 # undef fread_unlocked
-__fortify_function __wur size_t
+__fortify_function __wur __nonnull ((4)) size_t
 fread_unlocked (void *__restrict __ptr, size_t __size, size_t __n,
 		FILE *__restrict __stream)
 {