Skip to content

Commit

Permalink
Apply asm redirections in stdio.h before first use [BZ #27087]
Browse files Browse the repository at this point in the history
Compilers may not be able to apply asm redirections to functions after
these functions are used for the first time, e.g. clang 13.
Fix [BZ #27087] by applying all long double-related asm redirections
before using functions in bits/stdio.h.
However, as these asm redirections depend on the declarations provided
by libio/bits/stdio2.h, this header was split in 2:

 - libio/bits/stdio2-decl.h contains all function declarations;
 - libio/bits/stdio2.h remains with the remaining contents, including
   redirections.

This also adds the access attribute to __vsnprintf_chk that was missing.

Tested with build-many-glibcs.py.

Reviewed-by: Paul E. Murphy <[email protected]>
  • Loading branch information
tuliom committed Jul 14, 2022
1 parent 779aa03 commit d0fa09a
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 68 deletions.
1 change: 1 addition & 0 deletions include/bits/stdio2-decl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include <libio/bits/stdio2-decl.h>
2 changes: 1 addition & 1 deletion libio/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ subdir := libio
include ../Makeconfig

headers := stdio.h \
bits/stdio.h bits/stdio2.h bits/stdio-ldbl.h \
bits/stdio.h bits/stdio2.h bits/stdio2-decl.h bits/stdio-ldbl.h \
bits/types/FILE.h bits/types/__FILE.h bits/types/struct_FILE.h \
bits/types/__fpos_t.h bits/types/__fpos64_t.h \
bits/types/cookie_io_functions_t.h
Expand Down
111 changes: 111 additions & 0 deletions libio/bits/stdio2-decl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/* Checking macros for stdio functions. Declarations only.
Copyright (C) 2004-2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */

#ifndef _BITS_STDIO2_DEC_H
#define _BITS_STDIO2_DEC_H 1

#ifndef _STDIO_H
# error "Never include <bits/stdio2-decl.h> directly; use <stdio.h> instead."
#endif

extern int __sprintf_chk (char *__restrict __s, int __flag, size_t __slen,
const char *__restrict __format, ...) __THROW
__attr_access ((__write_only__, 1, 3));
extern int __vsprintf_chk (char *__restrict __s, int __flag, size_t __slen,
const char *__restrict __format,
__gnuc_va_list __ap) __THROW
__attr_access ((__write_only__, 1, 3));

#if defined __USE_ISOC99 || defined __USE_UNIX98

extern int __snprintf_chk (char *__restrict __s, size_t __n, int __flag,
size_t __slen, const char *__restrict __format,
...) __THROW
__attr_access ((__write_only__, 1, 2));
extern int __vsnprintf_chk (char *__restrict __s, size_t __n, int __flag,
size_t __slen, const char *__restrict __format,
__gnuc_va_list __ap) __THROW
__attr_access ((__write_only__, 1, 2));

#endif

#if __USE_FORTIFY_LEVEL > 1

extern int __fprintf_chk (FILE *__restrict __stream, int __flag,
const char *__restrict __format, ...);
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);
extern int __vprintf_chk (int __flag, const char *__restrict __format,
__gnuc_va_list __ap);

# ifdef __USE_XOPEN2K8
extern int __dprintf_chk (int __fd, int __flag, const char *__restrict __fmt,
...) __attribute__ ((__format__ (__printf__, 3, 4)));
extern int __vdprintf_chk (int __fd, int __flag,
const char *__restrict __fmt, __gnuc_va_list __arg)
__attribute__ ((__format__ (__printf__, 3, 0)));
# endif

# ifdef __USE_GNU

extern int __asprintf_chk (char **__restrict __ptr, int __flag,
const char *__restrict __fmt, ...)
__THROW __attribute__ ((__format__ (__printf__, 3, 4))) __wur;
extern int __vasprintf_chk (char **__restrict __ptr, int __flag,
const char *__restrict __fmt, __gnuc_va_list __arg)
__THROW __attribute__ ((__format__ (__printf__, 3, 0))) __wur;
extern int __obstack_printf_chk (struct obstack *__restrict __obstack,
int __flag, const char *__restrict __format,
...)
__THROW __attribute__ ((__format__ (__printf__, 3, 4)));
extern int __obstack_vprintf_chk (struct obstack *__restrict __obstack,
int __flag,
const char *__restrict __format,
__gnuc_va_list __args)
__THROW __attribute__ ((__format__ (__printf__, 3, 0)));

# endif
#endif

#if __GLIBC_USE (DEPRECATED_GETS)
extern char *__gets_chk (char *__str, size_t) __wur;
#endif

extern char *__fgets_chk (char *__restrict __s, size_t __size, int __n,
FILE *__restrict __stream)
__wur __attr_access ((__write_only__, 1, 3));

extern size_t __fread_chk (void *__restrict __ptr, size_t __ptrlen,
size_t __size, size_t __n,
FILE *__restrict __stream) __wur;

#ifdef __USE_GNU
extern char *__fgets_unlocked_chk (char *__restrict __s, size_t __size,
int __n, FILE *__restrict __stream)
__wur __attr_access ((__write_only__, 1, 3));
#endif

#ifdef __USE_MISC
# undef fread_unlocked
extern size_t __fread_unlocked_chk (void *__restrict __ptr, size_t __ptrlen,
size_t __size, size_t __n,
FILE *__restrict __stream) __wur;
#endif

#endif /* bits/stdio2-decl.h. */
62 changes: 0 additions & 62 deletions libio/bits/stdio2.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,6 @@
# error "Never include <bits/stdio2.h> directly; use <stdio.h> instead."
#endif

extern int __sprintf_chk (char *__restrict __s, int __flag, size_t __slen,
const char *__restrict __format, ...) __THROW
__attr_access ((__write_only__, 1, 3));
extern int __vsprintf_chk (char *__restrict __s, int __flag, size_t __slen,
const char *__restrict __format,
__gnuc_va_list __ap) __THROW
__attr_access ((__write_only__, 1, 3));

#ifdef __va_arg_pack
__fortify_function int
__NTH (sprintf (char *__restrict __s, const char *__restrict __fmt, ...))
Expand All @@ -54,15 +46,6 @@ __NTH (vsprintf (char *__restrict __s, const char *__restrict __fmt,
}

#if defined __USE_ISOC99 || defined __USE_UNIX98

extern int __snprintf_chk (char *__restrict __s, size_t __n, int __flag,
size_t __slen, const char *__restrict __format,
...) __THROW
__attr_access ((__write_only__, 1, 2));
extern int __vsnprintf_chk (char *__restrict __s, size_t __n, int __flag,
size_t __slen, const char *__restrict __format,
__gnuc_va_list __ap) __THROW;

# ifdef __va_arg_pack
__fortify_function int
__NTH (snprintf (char *__restrict __s, size_t __n,
Expand All @@ -89,15 +72,6 @@ __NTH (vsnprintf (char *__restrict __s, size_t __n,
#endif

#if __USE_FORTIFY_LEVEL > 1

extern int __fprintf_chk (FILE *__restrict __stream, int __flag,
const char *__restrict __format, ...);
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);
extern int __vprintf_chk (int __flag, const char *__restrict __format,
__gnuc_va_list __ap);

# ifdef __va_arg_pack
__fortify_function int
fprintf (FILE *__restrict __stream, const char *__restrict __fmt, ...)
Expand Down Expand Up @@ -136,12 +110,6 @@ vfprintf (FILE *__restrict __stream,
}

# ifdef __USE_XOPEN2K8
extern int __dprintf_chk (int __fd, int __flag, const char *__restrict __fmt,
...) __attribute__ ((__format__ (__printf__, 3, 4)));
extern int __vdprintf_chk (int __fd, int __flag,
const char *__restrict __fmt, __gnuc_va_list __arg)
__attribute__ ((__format__ (__printf__, 3, 0)));

# ifdef __va_arg_pack
__fortify_function int
dprintf (int __fd, const char *__restrict __fmt, ...)
Expand All @@ -162,23 +130,6 @@ vdprintf (int __fd, const char *__restrict __fmt, __gnuc_va_list __ap)
# endif

# ifdef __USE_GNU

extern int __asprintf_chk (char **__restrict __ptr, int __flag,
const char *__restrict __fmt, ...)
__THROW __attribute__ ((__format__ (__printf__, 3, 4))) __wur;
extern int __vasprintf_chk (char **__restrict __ptr, int __flag,
const char *__restrict __fmt, __gnuc_va_list __arg)
__THROW __attribute__ ((__format__ (__printf__, 3, 0))) __wur;
extern int __obstack_printf_chk (struct obstack *__restrict __obstack,
int __flag, const char *__restrict __format,
...)
__THROW __attribute__ ((__format__ (__printf__, 3, 4)));
extern int __obstack_vprintf_chk (struct obstack *__restrict __obstack,
int __flag,
const char *__restrict __format,
__gnuc_va_list __args)
__THROW __attribute__ ((__format__ (__printf__, 3, 0)));

# ifdef __va_arg_pack
__fortify_function int
__NTH (asprintf (char **__restrict __ptr, const char *__restrict __fmt, ...))
Expand Down Expand Up @@ -231,7 +182,6 @@ __NTH (obstack_vprintf (struct obstack *__restrict __obstack,
#endif

#if __GLIBC_USE (DEPRECATED_GETS)
extern char *__gets_chk (char *__str, size_t) __wur;
extern char *__REDIRECT (__gets_warn, (char *__str), gets)
__wur __warnattr ("please use fgets or getline instead, gets can't "
"specify buffer size");
Expand All @@ -245,9 +195,6 @@ gets (char *__str)
}
#endif

extern char *__fgets_chk (char *__restrict __s, size_t __size, int __n,
FILE *__restrict __stream)
__wur __attr_access ((__write_only__, 1, 3));
extern char *__REDIRECT (__fgets_alias,
(char *__restrict __s, int __n,
FILE *__restrict __stream), fgets)
Expand All @@ -269,9 +216,6 @@ fgets (char *__restrict __s, int __n, FILE *__restrict __stream)
return __fgets_chk (__s, sz, __n, __stream);
}

extern size_t __fread_chk (void *__restrict __ptr, size_t __ptrlen,
size_t __size, size_t __n,
FILE *__restrict __stream) __wur;
extern size_t __REDIRECT (__fread_alias,
(void *__restrict __ptr, size_t __size,
size_t __n, FILE *__restrict __stream),
Expand All @@ -297,9 +241,6 @@ fread (void *__restrict __ptr, size_t __size, size_t __n,
}

#ifdef __USE_GNU
extern char *__fgets_unlocked_chk (char *__restrict __s, size_t __size,
int __n, FILE *__restrict __stream)
__wur __attr_access ((__write_only__, 1, 3));
extern char *__REDIRECT (__fgets_unlocked_alias,
(char *__restrict __s, int __n,
FILE *__restrict __stream), fgets_unlocked)
Expand All @@ -324,9 +265,6 @@ fgets_unlocked (char *__restrict __s, int __n, FILE *__restrict __stream)

#ifdef __USE_MISC
# undef fread_unlocked
extern size_t __fread_unlocked_chk (void *__restrict __ptr, size_t __ptrlen,
size_t __size, size_t __n,
FILE *__restrict __stream) __wur;
extern size_t __REDIRECT (__fread_unlocked_alias,
(void *__restrict __ptr, size_t __size,
size_t __n, FILE *__restrict __stream),
Expand Down
17 changes: 12 additions & 5 deletions libio/stdio.h
Original file line number Diff line number Diff line change
Expand Up @@ -885,20 +885,27 @@ extern void funlockfile (FILE *__stream) __THROW;
extern int __uflow (FILE *);
extern int __overflow (FILE *, int);

#if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function
/* Declare all functions from bits/stdio2-decl.h first. */
# include <bits/stdio2-decl.h>
#endif

/* The following headers provide asm redirections. These redirections must
appear before the first usage of these functions, e.g. in bits/stdio.h. */
#if defined __LDBL_COMPAT || __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 1
# include <bits/stdio-ldbl.h>
#endif

/* If we are compiling with optimizing read this file. It contains
several optimizing inline functions and macros. */
#ifdef __USE_EXTERN_INLINES
# include <bits/stdio.h>
#endif
#if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function
/* Now include the function definitions and redirects too. */
# include <bits/stdio2.h>
#endif

#include <bits/floatn.h>
#if defined __LDBL_COMPAT || __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 1
# include <bits/stdio-ldbl.h>
#endif

__END_DECLS

#endif /* <stdio.h> included. */

0 comments on commit d0fa09a

Please sign in to comment.