summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZack Weinberg <zackw@panix.com>2018-02-10 11:58:35 -0500
committerZack Weinberg <zackw@panix.com>2019-01-03 11:12:39 -0500
commit03992356e6fedc5a5e9d32df96c1a2c79ea28a8f (patch)
tree01bb09abc25e7191f42a49042ea4f71f8f24c5cd
parent6f343c1f338ca70411772309a3bbb1d67c71f419 (diff)
Use C99-compliant scanf under _GNU_SOURCE with modern compilers.
The only difference between noncompliant and C99-compliant scanf is that the former accepts the archaic GNU extension '%as' (also %aS and %a[...]) meaning to allocate space for the input string with malloc. This extension conflicts with C99's use of %a as a format _type_ meaning to read a floating-point number; POSIX.1-2008 standardized equivalent functionality using the modifier letter 'm' instead (%ms, %mS, %m[...]). The extension was already disabled in most conformance modes: specifically, any mode that doesn't involve _GNU_SOURCE and _does_ involve either strict conformance to C99 or loose conformance to both C99 and POSIX.1-2001 would get the C99-compliant scanf. With compilers new enough to use -std=gnu11 instead of -std=gnu89, or equivalent, that includes the default mode. With this patch, we now provide C99-compliant scanf in all configurations except when _GNU_SOURCE is defined *and* __STDC_VERSION__ or __cplusplus (whichever is relevant) indicates C89/C++98. This leaves the old scanf available under e.g. -std=c89 -D_GNU_SOURCE, but removes it from e.g. -std=gnu11 -D_GNU_SOURCE (it was already not present under -std=gnu11 without -D_GNU_SOURCE) and from -std=gnu89 without -D_GNU_SOURCE. There needs to be an internal override so we can compile the noncompliant scanf itself. This is the same problem we had when we removed 'gets' from _GNU_SOURCE and it's dealt with the same way: there's a new __GLIBC_USE symbol, DEPRECATED_SCANF, which defaults to off under the appropriate conditions for external code, but can be overridden by individual files within stdio. We also run into problems with PLT bypass for internal uses of sscanf, because libc_hidden_proto uses __REDIRECT and so does the logic in stdio.h for choosing which implementation of scanf to use; __REDIRECT isn't transitive, so include/stdio.h needs to bridge the gap with a macro. As far as I can tell, sscanf is the only function in this family that's internally called by unrelated code. Finally, there are several tests in stdio-common that use the extension. bug21.c is a regression test for a crash; it still exercises the relevant code when changed to use %ms instead of %as. scanf14.c through scanf17.c are more complicated since they are actually testing the subtleties of the extension - under what circumstances is 'a' treated as a modifier letter, etc. I changed all of them to use %ms instead of %as as well, but duplicated scanf14.c and scanf16.c as scanf14a.c and scanf16a.c. These still use %as and are compiled with -std=gnu89 to access the old extension. A bunch of diagnostic overrides and manual workarounds for the old stdio.h behavior become unnecessary. Yay! * include/features.h (__GLIBC_USE_DEPRECATED_SCANF): New __GLIBC_USE parameter. Only use deprecated scanf when __USE_GNU is defined and __STDC_VERSION__ is less than 199901L or __cplusplus is less than 201103L, whichever is relevant for the language being compiled. * libio/stdio.h, libio/bits/stdio-ldbl.h: Decide whether to redirect scanf, fscanf, sscanf, vscanf, vfscanf, and vsscanf to their __isoc99_ variants based only on __GLIBC_USE (DEPRECATED_SCANF). * wcsmbs/wchar.h: wcsmbs/bits/wchar-ldbl.h: Likewise for wscanf, fwscanf, swscanf, vwscanf, vfwscanf, and vswscanf. * libio/iovsscanf.c * libio/fwscanf.c * libio/iovswscanf.c * libio/swscanf.c * libio/vscanf.c * libio/vwscanf.c * libio/wscanf.c * stdio-common/fscanf.c * stdio-common/scanf.c * stdio-common/vfscanf.c * stdio-common/vfwscanf.c * sysdeps/ieee754/ldbl-opt/nldbl-compat.c * sysdeps/ieee754/ldbl-opt/nldbl-fscanf.c * sysdeps/ieee754/ldbl-opt/nldbl-fwscanf.c * sysdeps/ieee754/ldbl-opt/nldbl-iovfscanf.c * sysdeps/ieee754/ldbl-opt/nldbl-scanf.c * sysdeps/ieee754/ldbl-opt/nldbl-sscanf.c * sysdeps/ieee754/ldbl-opt/nldbl-swscanf.c * sysdeps/ieee754/ldbl-opt/nldbl-vfscanf.c * sysdeps/ieee754/ldbl-opt/nldbl-vfwscanf.c * sysdeps/ieee754/ldbl-opt/nldbl-vscanf.c * sysdeps/ieee754/ldbl-opt/nldbl-vsscanf.c * sysdeps/ieee754/ldbl-opt/nldbl-vswscanf.c * sysdeps/ieee754/ldbl-opt/nldbl-vwscanf.c * sysdeps/ieee754/ldbl-opt/nldbl-wscanf.c: Override __GLIBC_USE_DEPRECATED_SCANF to 1. * stdio-common/sscanf.c: Likewise. Remove ldbl_hidden_def for __sscanf. * stdio-common/isoc99_sscanf.c: Add libc_hidden_def for __isoc99_sscanf. * include/stdio.h: Provide libc_hidden_proto for __isoc99_sscanf, not sscanf. [!__GLIBC_USE (DEPRECATED_SCANF)]: Define sscanf as __isoc99_scanf with a preprocessor macro. * stdio-common/bug21.c, stdio-common/scanf14.c: Use %ms instead of %as, %mS instead of %aS, %m[] instead of %a[]; remove DIAG_IGNORE_NEEDS_COMMENT for -Wformat. * stdio-common/scanf16.c: Likewise. Add __attribute__ ((format (scanf))) to xscanf, xfscanf, xsscanf. * stdio-common/scanf14a.c: New copy of scanf14.c which still uses %as, %aS, %a[]. Remove DIAG_IGNORE_NEEDS_COMMENT for -Wformat. * stdio-common/scanf16a.c: New copy of scanf16.c which still uses %as, %aS, %a[]. Add __attribute__ ((format (scanf))) to xscanf, xfscanf, xsscanf. * stdio-common/scanf15.c, stdio-common/scanf17.c: No need to override feature selection macros or provide definitions of u_char etc. * stdio-common/Makefile (tests): Add scanf14a and scanf16a. (CFLAGS-scanf15.c, CFLAGS-scanf17.c): Remove. (CFLAGS-scanf14a.c, CFLAGS-scanf16a.c): New. Compile these files with -std=gnu89.
-rw-r--r--ChangeLog65
-rw-r--r--NEWS17
-rw-r--r--include/features.h22
-rw-r--r--include/stdio.h11
-rw-r--r--libio/bits/stdio-ldbl.h7
-rw-r--r--libio/fwscanf.c5
-rw-r--r--libio/iovsscanf.c5
-rw-r--r--libio/iovswscanf.c5
-rw-r--r--libio/stdio.h22
-rw-r--r--libio/swscanf.c5
-rw-r--r--libio/vscanf.c5
-rw-r--r--libio/vwscanf.c5
-rw-r--r--libio/wscanf.c5
-rw-r--r--stdio-common/Makefile14
-rw-r--r--stdio-common/bug21.c11
-rw-r--r--stdio-common/fscanf.c5
-rw-r--r--stdio-common/isoc99_sscanf.c1
-rw-r--r--stdio-common/scanf.c5
-rw-r--r--stdio-common/scanf14.c52
-rw-r--r--stdio-common/scanf14a.c143
-rw-r--r--stdio-common/scanf15.c31
-rw-r--r--stdio-common/scanf16.c37
-rw-r--r--stdio-common/scanf16a.c173
-rw-r--r--stdio-common/scanf17.c31
-rw-r--r--stdio-common/sscanf.c6
-rw-r--r--stdio-common/vfscanf.c5
-rw-r--r--stdio-common/vfwscanf.c5
-rw-r--r--sysdeps/ieee754/ldbl-opt/nldbl-compat.c5
-rw-r--r--sysdeps/ieee754/ldbl-opt/nldbl-fscanf.c5
-rw-r--r--sysdeps/ieee754/ldbl-opt/nldbl-fwscanf.c5
-rw-r--r--sysdeps/ieee754/ldbl-opt/nldbl-iovfscanf.c5
-rw-r--r--sysdeps/ieee754/ldbl-opt/nldbl-scanf.c5
-rw-r--r--sysdeps/ieee754/ldbl-opt/nldbl-sscanf.c5
-rw-r--r--sysdeps/ieee754/ldbl-opt/nldbl-swscanf.c5
-rw-r--r--sysdeps/ieee754/ldbl-opt/nldbl-vfscanf.c5
-rw-r--r--sysdeps/ieee754/ldbl-opt/nldbl-vfwscanf.c5
-rw-r--r--sysdeps/ieee754/ldbl-opt/nldbl-vscanf.c5
-rw-r--r--sysdeps/ieee754/ldbl-opt/nldbl-vsscanf.c5
-rw-r--r--sysdeps/ieee754/ldbl-opt/nldbl-vswscanf.c5
-rw-r--r--sysdeps/ieee754/ldbl-opt/nldbl-vwscanf.c5
-rw-r--r--sysdeps/ieee754/ldbl-opt/nldbl-wscanf.c5
-rw-r--r--wcsmbs/bits/wchar-ldbl.h7
-rw-r--r--wcsmbs/wchar.h10
43 files changed, 682 insertions, 103 deletions
diff --git a/ChangeLog b/ChangeLog
index c446abcd4e..8121c71714 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,68 @@
+2019-01-03 Zack Weinberg <zackw@panix.com>
+
+ * include/features.h (__GLIBC_USE_DEPRECATED_SCANF): New __GLIBC_USE
+ parameter. Only use deprecated scanf when __USE_GNU is defined
+ and __STDC_VERSION__ is less than 199901L or __cplusplus is less
+ than 201103L, whichever is relevant for the language being compiled.
+
+ * libio/stdio.h, libio/bits/stdio-ldbl.h: Decide whether to redirect
+ scanf, fscanf, sscanf, vscanf, vfscanf, and vsscanf to their
+ __isoc99_ variants based only on __GLIBC_USE (DEPRECATED_SCANF).
+ * wcsmbs/wchar.h: wcsmbs/bits/wchar-ldbl.h: Likewise for
+ wscanf, fwscanf, swscanf, vwscanf, vfwscanf, and vswscanf.
+
+ * libio/iovsscanf.c
+ * libio/fwscanf.c
+ * libio/iovswscanf.c
+ * libio/swscanf.c
+ * libio/vscanf.c
+ * libio/vwscanf.c
+ * libio/wscanf.c
+ * stdio-common/fscanf.c
+ * stdio-common/scanf.c
+ * stdio-common/vfscanf.c
+ * stdio-common/vfwscanf.c
+ * sysdeps/ieee754/ldbl-opt/nldbl-compat.c
+ * sysdeps/ieee754/ldbl-opt/nldbl-fscanf.c
+ * sysdeps/ieee754/ldbl-opt/nldbl-fwscanf.c
+ * sysdeps/ieee754/ldbl-opt/nldbl-iovfscanf.c
+ * sysdeps/ieee754/ldbl-opt/nldbl-scanf.c
+ * sysdeps/ieee754/ldbl-opt/nldbl-sscanf.c
+ * sysdeps/ieee754/ldbl-opt/nldbl-swscanf.c
+ * sysdeps/ieee754/ldbl-opt/nldbl-vfscanf.c
+ * sysdeps/ieee754/ldbl-opt/nldbl-vfwscanf.c
+ * sysdeps/ieee754/ldbl-opt/nldbl-vscanf.c
+ * sysdeps/ieee754/ldbl-opt/nldbl-vsscanf.c
+ * sysdeps/ieee754/ldbl-opt/nldbl-vswscanf.c
+ * sysdeps/ieee754/ldbl-opt/nldbl-vwscanf.c
+ * sysdeps/ieee754/ldbl-opt/nldbl-wscanf.c:
+ Override __GLIBC_USE_DEPRECATED_SCANF to 1.
+
+ * stdio-common/sscanf.c: Likewise. Remove ldbl_hidden_def for __sscanf.
+ * stdio-common/isoc99_sscanf.c: Add libc_hidden_def for __isoc99_sscanf.
+ * include/stdio.h: Provide libc_hidden_proto for __isoc99_sscanf,
+ not sscanf.
+ [!__GLIBC_USE (DEPRECATED_SCANF)]: Define sscanf as __isoc99_scanf
+ with a preprocessor macro.
+
+ * stdio-common/bug21.c, stdio-common/scanf14.c:
+ Use %ms instead of %as, %mS instead of %aS, %m[] instead of %a[];
+ remove DIAG_IGNORE_NEEDS_COMMENT for -Wformat.
+ * stdio-common/scanf16.c: Likewise. Add __attribute__ ((format (scanf)))
+ to xscanf, xfscanf, xsscanf.
+
+ * stdio-common/scanf14a.c: New copy of scanf14.c which still uses
+ %as, %aS, %a[]. Remove DIAG_IGNORE_NEEDS_COMMENT for -Wformat.
+ * stdio-common/scanf16a.c: New copy of scanf16.c which still uses
+ %as, %aS, %a[]. Add __attribute__ ((format (scanf))) to xscanf,
+ xfscanf, xsscanf.
+ * stdio-common/scanf15.c, stdio-common/scanf17.c: No need to
+ override feature selection macros or provide definitions of u_char etc.
+ * stdio-common/Makefile (tests): Add scanf14a and scanf16a.
+ (CFLAGS-scanf15.c, CFLAGS-scanf17.c): Remove.
+ (CFLAGS-scanf14a.c, CFLAGS-scanf16a.c): New. Compile these files
+ with -std=gnu89.
+
2019-01-03 Adhemerval Zanella <adhemerval.zanella@linaro.org>
* sysdeps/unix/sysv/linux/Makefile (sysdep_headers): Add
diff --git a/NEWS b/NEWS
index 4c8bc924ce..cc20102fda 100644
--- a/NEWS
+++ b/NEWS
@@ -68,6 +68,23 @@ Deprecated and removed features, and other changes affecting compatibility:
used by the Linux kernel. This affects the size and layout of those
structures.
+* An archaic GNU extension to scanf, under which '%as', '%aS', and '%a[...]'
+ meant to scan a string and allocate space for it with malloc, is now
+ restricted to programs compiled in C89 or C++98 mode with _GNU_SOURCE
+ defined. This extension conflicts with C99's use of '%a' to scan a
+ hexadecimal floating-point number, which is now available to programs
+ compiled as C99 or C++11 or higher, regardless of _GNU_SOURCE.
+
+ POSIX.1-2008 includes the feature of allocating a buffer for string input
+ with malloc, using the modifier letter 'm' instead. Programs using
+ '%as', '%aS', or '%a[...]' with the old GNU meaning should change to
+ '%ms', '%mS', or '%m[...]' respectively. Programs that wish to use the
+ C99 '%a' no longer need to avoid _GNU_SOURCE.
+
+ GCC's -Wformat warnings can detect most uses of this extension, as long
+ as all functions that call vscanf, vfscanf, or vsscanf are annotated with
+ __attribute__ ((format (scanf, ...))).
+
Changes to build and runtime requirements:
* Python 3.4 or later is required to build the GNU C Library.
diff --git a/include/features.h b/include/features.h
index dc9f8fa9ac..c9bc534e27 100644
--- a/include/features.h
+++ b/include/features.h
@@ -140,6 +140,7 @@
#undef __USE_FORTIFY_LEVEL
#undef __KERNEL_STRICT_NAMES
#undef __GLIBC_USE_DEPRECATED_GETS
+#undef __GLIBC_USE_DEPRECATED_SCANF
/* Suppress kernel-name space pollution unless user expressedly asks
for it. */
@@ -401,6 +402,27 @@
# define __GLIBC_USE_DEPRECATED_GETS 1
#endif
+/* GNU formerly extended the scanf functions with modified format
+ specifiers %as, %aS, and %a[...] that allocate a buffer for the
+ input using malloc. This extension conflicts with ISO C99, which
+ defines %a as a standalone format specifier that reads a floating-
+ point number; moreover, POSIX.1-2008 provides the same feature
+ using the modifier letter 'm' instead (%ms, %mS, %m[...]).
+
+ We now follow C99 unless GNU extensions are active and the compiler
+ is specifically in C89 or C++98 mode (strict or not). For
+ instance, with GCC, -std=gnu11 will have C99-compliant scanf with
+ or without -D_GNU_SOURCE, but -std=c89 -D_GNU_SOURCE will have the
+ old extension. */
+#if defined __USE_GNU && \
+ (defined __cplusplus \
+ ? (__cplusplus < 201103L && !defined __GXX_EXPERIMENTAL_CXX0X__) \
+ : (!defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L))
+# define __GLIBC_USE_DEPRECATED_SCANF 1
+#else
+# define __GLIBC_USE_DEPRECATED_SCANF 0
+#endif
+
/* Get definitions of __STDC_* predefined macros, if the compiler has
not preincluded this header automatically. */
#include <stdc-predef.h>
diff --git a/include/stdio.h b/include/stdio.h
index 1b7da0f74d..65ccabbb05 100644
--- a/include/stdio.h
+++ b/include/stdio.h
@@ -64,9 +64,19 @@ extern int __isoc99_vscanf (const char *__restrict __format,
extern int __isoc99_vsscanf (const char *__restrict __s,
const char *__restrict __format,
__gnuc_va_list __arg) __THROW;
+libc_hidden_proto (__isoc99_sscanf)
libc_hidden_proto (__isoc99_vsscanf)
libc_hidden_proto (__isoc99_vfscanf)
+/* Internal uses of sscanf should call the C99-compliant version.
+ Unfortunately, symbol redirection is not transitive, so the
+ __REDIRECT in the public header does not link up with the above
+ libc_hidden_proto. Bridge the gap with a macro. */
+# if !__GLIBC_USE (DEPRECATED_SCANF)
+# undef sscanf
+# define sscanf __isoc99_sscanf
+# endif
+
/* Prototypes for compatibility functions. */
extern FILE *__new_tmpfile (void);
extern FILE *__old_tmpfile (void);
@@ -171,7 +181,6 @@ libc_hidden_proto (__dprintf)
libc_hidden_proto (fprintf)
libc_hidden_proto (vfprintf)
libc_hidden_proto (sprintf)
-libc_hidden_proto (sscanf)
libc_hidden_proto (fwrite)
libc_hidden_proto (perror)
libc_hidden_proto (remove)
diff --git a/libio/bits/stdio-ldbl.h b/libio/bits/stdio-ldbl.h
index 18289e6b86..97ad168a04 100644
--- a/libio/bits/stdio-ldbl.h
+++ b/libio/bits/stdio-ldbl.h
@@ -26,9 +26,7 @@ __LDBL_REDIR_DECL (sprintf)
__LDBL_REDIR_DECL (vfprintf)
__LDBL_REDIR_DECL (vprintf)
__LDBL_REDIR_DECL (vsprintf)
-#if defined __USE_ISOC99 && !defined __USE_GNU \
- && !defined __REDIRECT \
- && (defined __STRICT_ANSI__ || defined __USE_XOPEN2K)
+#if !__GLIBC_USE (DEPRECATED_SCANF)
__LDBL_REDIR1_DECL (fscanf, __nldbl___isoc99_fscanf)
__LDBL_REDIR1_DECL (scanf, __nldbl___isoc99_scanf)
__LDBL_REDIR1_DECL (sscanf, __nldbl___isoc99_sscanf)
@@ -44,8 +42,7 @@ __LDBL_REDIR_DECL (vsnprintf)
#endif
#ifdef __USE_ISOC99
-# if !defined __USE_GNU && !defined __REDIRECT \
- && (defined __STRICT_ANSI__ || defined __USE_XOPEN2K)
+# if !__GLIBC_USE (DEPRECATED_SCANF)
__LDBL_REDIR1_DECL (vfscanf, __nldbl___isoc99_vfscanf)
__LDBL_REDIR1_DECL (vscanf, __nldbl___isoc99_vscanf)
__LDBL_REDIR1_DECL (vsscanf, __nldbl___isoc99_vsscanf)
diff --git a/libio/fwscanf.c b/libio/fwscanf.c
index c316ef961d..24872f46ff 100644
--- a/libio/fwscanf.c
+++ b/libio/fwscanf.c
@@ -15,6 +15,11 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+/* This file defines one of the deprecated scanf variants. */
+#include <features.h>
+#undef __GLIBC_USE_DEPRECATED_SCANF
+#define __GLIBC_USE_DEPRECATED_SCANF 1
+
#include <libioP.h>
#include <stdarg.h>
#include <stdio.h>
diff --git a/libio/iovsscanf.c b/libio/iovsscanf.c
index 752eed96e3..a561eab87e 100644
--- a/libio/iovsscanf.c
+++ b/libio/iovsscanf.c
@@ -24,6 +24,11 @@
This exception applies to code released by its copyright holders
in files containing the exception. */
+/* This file defines one of the deprecated scanf variants. */
+#include <features.h>
+#undef __GLIBC_USE_DEPRECATED_SCANF
+#define __GLIBC_USE_DEPRECATED_SCANF 1
+
#include "strfile.h"
int
diff --git a/libio/iovswscanf.c b/libio/iovswscanf.c
index f584c963fa..669fdc12b6 100644
--- a/libio/iovswscanf.c
+++ b/libio/iovswscanf.c
@@ -24,6 +24,11 @@
This exception applies to code released by its copyright holders
in files containing the exception. */
+/* This file defines one of the deprecated scanf variants. */
+#include <features.h>
+#undef __GLIBC_USE_DEPRECATED_SCANF
+#define __GLIBC_USE_DEPRECATED_SCANF 1
+
#include <wchar.h>
#include "strfile.h"
diff --git a/libio/stdio.h b/libio/stdio.h
index 4cc5b24a31..b63ee88a77 100644
--- a/libio/stdio.h
+++ b/libio/stdio.h
@@ -399,13 +399,11 @@ extern int scanf (const char *__restrict __format, ...) __wur;
extern int sscanf (const char *__restrict __s,
const char *__restrict __format, ...) __THROW;
-#if defined __USE_ISOC99 && !defined __USE_GNU \
- && (!defined __LDBL_COMPAT || !defined __REDIRECT) \
- && (defined __STRICT_ANSI__ || defined __USE_XOPEN2K)
+/* For historical reasons, the C99-compliant versions of the scanf
+ functions are at alternative names. When __LDBL_COMPAT is in
+ effect, this is handled in bits/stdio-ldbl.h. */
+#if !__GLIBC_USE (DEPRECATED_SCANF) && !defined __LDBL_COMPAT
# ifdef __REDIRECT
-/* For strict ISO C99 or POSIX compliance disallow %as, %aS and %a[
- GNU extension which conflicts with valid %a followed by letter
- s, S or [. */
extern int __REDIRECT (fscanf, (FILE *__restrict __stream,
const char *__restrict __format, ...),
__isoc99_fscanf) __wur;
@@ -447,13 +445,9 @@ extern int vsscanf (const char *__restrict __s,
const char *__restrict __format, __gnuc_va_list __arg)
__THROW __attribute__ ((__format__ (__scanf__, 2, 0)));
-# if !defined __USE_GNU \
- && (!defined __LDBL_COMPAT || !defined __REDIRECT) \
- && (defined __STRICT_ANSI__ || defined __USE_XOPEN2K)
-# ifdef __REDIRECT
-/* For strict ISO C99 or POSIX compliance disallow %as, %aS and %a[
- GNU extension which conflicts with valid %a followed by letter
- s, S or [. */
+/* Same redirection as above for the v*scanf family. */
+# if !__GLIBC_USE (DEPRECATED_SCANF)
+# if defined __REDIRECT && !defined __LDBL_COMPAT
extern int __REDIRECT (vfscanf,
(FILE *__restrict __s,
const char *__restrict __format, __gnuc_va_list __arg),
@@ -467,7 +461,7 @@ extern int __REDIRECT_NTH (vsscanf,
const char *__restrict __format,
__gnuc_va_list __arg), __isoc99_vsscanf)
__attribute__ ((__format__ (__scanf__, 2, 0)));
-# else
+# elif !defined __REDIRECT
extern int __isoc99_vfscanf (FILE *__restrict __s,
const char *__restrict __format,
__gnuc_va_list __arg) __wur;
diff --git a/libio/swscanf.c b/libio/swscanf.c
index e38b938b0b..5f529ef630 100644
--- a/libio/swscanf.c
+++ b/libio/swscanf.c
@@ -15,6 +15,11 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+/* This file defines one of the deprecated scanf variants. */
+#include <features.h>
+#undef __GLIBC_USE_DEPRECATED_SCANF
+#define __GLIBC_USE_DEPRECATED_SCANF 1
+
#include <stdarg.h>
#include "strfile.h"
diff --git a/libio/vscanf.c b/libio/vscanf.c
index 936a2fdef8..342dc3effc 100644
--- a/libio/vscanf.c
+++ b/libio/vscanf.c
@@ -24,6 +24,11 @@
This exception applies to code released by its copyright holders
in files containing the exception. */
+/* This file defines one of the deprecated scanf variants. */
+#include <features.h>
+#undef __GLIBC_USE_DEPRECATED_SCANF
+#define __GLIBC_USE_DEPRECATED_SCANF 1
+
#include "libioP.h"
#include "stdio.h"
diff --git a/libio/vwscanf.c b/libio/vwscanf.c
index 0804175a81..696e4c5c99 100644
--- a/libio/vwscanf.c
+++ b/libio/vwscanf.c
@@ -24,6 +24,11 @@
This exception applies to code released by its copyright holders
in files containing the exception. */
+/* This file defines one of the deprecated scanf variants. */
+#include <features.h>
+#undef __GLIBC_USE_DEPRECATED_SCANF
+#define __GLIBC_USE_DEPRECATED_SCANF 1
+
#include "libioP.h"
#include <wchar.h>
diff --git a/libio/wscanf.c b/libio/wscanf.c
index ce8d3ed6b4..d4c7753e8e 100644
--- a/libio/wscanf.c
+++ b/libio/wscanf.c
@@ -15,6 +15,11 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+/* This file defines one of the deprecated scanf variants. */
+#include <features.h>
+#undef __GLIBC_USE_DEPRECATED_SCANF
+#define __GLIBC_USE_DEPRECATED_SCANF 1
+
#include <libioP.h>
#include <stdarg.h>
#include <stdio.h>
diff --git a/stdio-common/Makefile b/stdio-common/Makefile
index 11556f2177..c38299c864 100644
--- a/stdio-common/Makefile
+++ b/stdio-common/Makefile
@@ -65,6 +65,8 @@ tests := tstscanf test_rdwr test-popen tstgetln test-fseek \
tst-vfprintf-mbs-prec \
tst-scanf-round \
tst-renameat2 tst-bz11319 tst-bz11319-fortify2 \
+ scanf14a scanf16a \
+
test-srcs = tst-unbputc tst-printf tst-printfsz-islongdouble
@@ -146,13 +148,11 @@ CFLAGS-isoc99_scanf.c += -fexceptions
CFLAGS-errlist.c += $(fno-unit-at-a-time)
CFLAGS-siglist.c += $(fno-unit-at-a-time)
-# The following is a hack since we must compile scanf1{5,7}.c without any
-# GNU extension. The latter are needed, though, when internal headers
-# are used. So made sure we see the installed headers first.
-CFLAGS-scanf15.c += -I../libio -I../stdlib -I../wcsmbs -I../time -I../string \
- -I../wctype
-CFLAGS-scanf17.c += -I../libio -I../stdlib -I../wcsmbs -I../time -I../string \
- -I../wctype
+# scanf14a.c and scanf16a.c test a deprecated extension which is no
+# longer visible under most conformance levels; see the source files
+# for more detail.
+CFLAGS-scanf14a.c += -std=gnu89
+CFLAGS-scanf16a.c += -std=gnu89
CFLAGS-bug3.c += -DOBJPFX=\"$(objpfx)\"
CFLAGS-bug4.c += -DOBJPFX=\"$(objpfx)\"
diff --git a/stdio-common/bug21.c b/stdio-common/bug21.c
index 7a8c6a3542..1f06c0dab4 100644
--- a/stdio-common/bug21.c
+++ b/stdio-common/bug21.c
@@ -1,5 +1,4 @@
#include <stdio.h>
-#include <libc-diag.h>
static int
do_test (void)
@@ -7,15 +6,7 @@ do_test (void)
static const char buf[] = " ";
char *str;
- /* GCC in C99 mode treats %a as the C99 format expecting float *,
- but glibc with _GNU_SOURCE treats %as as the GNU allocation
- extension, so resulting in "warning: format '%a' expects argument
- of type 'float *', but argument 3 has type 'char **'". This
- applies to the other %as, %aS and %a[] formats below as well. */
- DIAG_PUSH_NEEDS_COMMENT;
- DIAG_IGNORE_NEEDS_COMMENT (4.9, "-Wformat");
- int r = sscanf (buf, "%as", &str);
- DIAG_POP_NEEDS_COMMENT;
+ int r = sscanf (buf, "%ms", &str);
printf ("%d %p\n", r, str);
return r != -1 || str != NULL;
diff --git a/stdio-common/fscanf.c b/stdio-common/fscanf.c
index 4b8b26ad54..a210eafcab 100644
--- a/stdio-common/fscanf.c
+++ b/stdio-common/fscanf.c
@@ -15,6 +15,11 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+/* This file defines one of the deprecated scanf variants. */
+#include <features.h>
+#undef __GLIBC_USE_DEPRECATED_SCANF
+#define __GLIBC_USE_DEPRECATED_SCANF 1
+
#include <libioP.h>
#include <stdarg.h>
#include <stdio.h>
diff --git a/stdio-common/isoc99_sscanf.c b/stdio-common/isoc99_sscanf.c
index a6bfc66e95..a70c0c3f2f 100644
--- a/stdio-common/isoc99_sscanf.c
+++ b/stdio-common/isoc99_sscanf.c
@@ -33,3 +33,4 @@ __isoc99_sscanf (const char *s, const char *format, ...)
return done;
}
+libc_hidden_def (__isoc99_sscanf)
diff --git a/stdio-common/scanf.c b/stdio-common/scanf.c
index 1b69a656ef..9008d2bf97 100644
--- a/stdio-common/scanf.c
+++ b/stdio-common/scanf.c
@@ -15,6 +15,11 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+/* This file defines one of the deprecated scanf variants. */
+#include <features.h>
+#undef __GLIBC_USE_DEPRECATED_SCANF
+#define __GLIBC_USE_DEPRECATED_SCANF 1
+
#include <stdarg.h>
#include <stdio.h>
diff --git a/stdio-common/scanf14.c b/stdio-common/scanf14.c
index 2bcd9c9893..8b271ae7cc 100644
--- a/stdio-common/scanf14.c
+++ b/stdio-common/scanf14.c
@@ -1,8 +1,28 @@
+/* Copyright (C) 2007-2019 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
+ <http://www.gnu.org/licenses/>. */
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
-#include <libc-diag.h>
+
+#if __GLIBC_USE_DEPRECATED_SCANF
+# error "This file should not be compiled with deprecated scanf"
+#endif
#define FAIL() \
do { \
@@ -24,14 +44,7 @@ main (void)
FAIL ();
else if (f != 0.25 || memcmp (c, "s x", 3) != 0)
FAIL ();
- /* GCC in C99 mode treats %a as the C99 format expecting float *,
- but glibc with _GNU_SOURCE treats %as as the GNU allocation
- extension, so resulting in "warning: format '%a' expects argument
- of type 'float *', but argument 3 has type 'char **'". This
- applies to the other %as, %aS and %a[] formats below as well. */
- DIAG_PUSH_NEEDS_COMMENT;
- DIAG_IGNORE_NEEDS_COMMENT (4.9, "-Wformat");
- if (sscanf (" 1.25s x", "%as%2c", &sp, c) != 2)
+ if (sscanf (" 1.25s x", "%ms%2c", &sp, c) != 2)
FAIL ();
else
{
@@ -40,15 +53,11 @@ main (void)
memset (sp, 'x', sizeof "1.25s");
free (sp);
}
- DIAG_POP_NEEDS_COMMENT;
if (sscanf (" 2.25s x", "%las%2c", &d, c) != 2)
FAIL ();
else if (d != 2.25 || memcmp (c, " x", 2) != 0)
FAIL ();
- /* See explanation above. */
- DIAG_PUSH_NEEDS_COMMENT;
- DIAG_IGNORE_NEEDS_COMMENT (4.9, "-Wformat");
- if (sscanf (" 3.25S x", "%4aS%3c", &lsp, c) != 2)
+ if (sscanf (" 3.25S x", "%4mS%3c", &lsp, c) != 2)
FAIL ();
else
{
@@ -57,7 +66,7 @@ main (void)
memset (lsp, 'x', sizeof L"3.25");
free (lsp);
}
- if (sscanf ("4.25[0-9.] x", "%a[0-9.]%8c", &sp, c) != 2)
+ if (sscanf ("4.25[0-9.] x", "%m[0-9.]%8c", &sp, c) != 2)
FAIL ();
else
{
@@ -66,7 +75,6 @@ main (void)
memset (sp, 'x', sizeof "4.25");
free (sp);
}
- DIAG_POP_NEEDS_COMMENT;
if (sscanf ("5.25[0-9.] x", "%la[0-9.]%2c", &d, c) != 2)
FAIL ();
else if (d != 5.25 || memcmp (c, " x", 2) != 0)
@@ -95,10 +103,7 @@ main (void)
FAIL ();
if (fseek (fp, 0, SEEK_SET) != 0)
FAIL ();
- /* See explanation above. */
- DIAG_PUSH_NEEDS_COMMENT;
- DIAG_IGNORE_NEEDS_COMMENT (4.9, "-Wformat");
- if (fscanf (fp, "%as%2c", &sp, c) != 2)
+ if (fscanf (fp, "%ms%2c", &sp, c) != 2)
FAIL ();
else
{
@@ -107,16 +112,12 @@ main (void)
memset (sp, 'x', sizeof "1.25s");
free (sp);
}
- DIAG_POP_NEEDS_COMMENT;
if (freopen (fname, "r", stdin) == NULL)
FAIL ();
else
{
- /* See explanation above. */
- DIAG_PUSH_NEEDS_COMMENT;
- DIAG_IGNORE_NEEDS_COMMENT (4.9, "-Wformat");
- if (scanf ("%as%2c", &sp, c) != 2)
+ if (scanf ("%ms%2c", &sp, c) != 2)
FAIL ();
else
{
@@ -125,7 +126,6 @@ main (void)
memset (sp, 'x', sizeof "1.25s");
free (sp);
}
- DIAG_POP_NEEDS_COMMENT;
}
fclose (fp);
diff --git a/stdio-common/scanf14a.c b/stdio-common/scanf14a.c
new file mode 100644
index 0000000000..5f95ecb693
--- /dev/null
+++ b/stdio-common/scanf14a.c
@@ -0,0 +1,143 @@
+/* Copyright (C) 2007-2019 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
+ <http://www.gnu.org/licenses/>. */
+
+/* This test exercises the deprecated GNU %as, %aS, and %a[...] scanf
+ modifiers, which are not available to programs compiled as C99
+ anymore; therefore, this file is compiled with -std=gnu89 and C99
+ syntax must not be used. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#if !__GLIBC_USE_DEPRECATED_SCANF
+# error "This file should be compiled with deprecated scanf"
+#endif
+
+
+#define FAIL() \
+ do { \
+ result = 1; \
+ printf ("test at line %d failed\n", __LINE__); \
+ } while (0)
+
+int
+main (void)
+{
+ wchar_t *lsp;
+ char *sp;
+ float f;
+ double d;
+ char c[8];
+ int result = 0;
+
+ if (sscanf (" 0.25s x", "%e%3c", &f, c) != 2)
+ FAIL ();
+ else if (f != 0.25 || memcmp (c, "s x", 3) != 0)
+ FAIL ();
+ if (sscanf (" 1.25s x", "%as%2c", &sp, c) != 2)
+ FAIL ();
+ else
+ {
+ if (strcmp (sp, "1.25s") != 0 || memcmp (c, " x", 2) != 0)
+ FAIL ();
+ memset (sp, 'x', sizeof "1.25s");
+ free (sp);
+ }
+ if (sscanf (" 2.25s x", "%las%2c", &d, c) != 2)
+ FAIL ();
+ else if (d != 2.25 || memcmp (c, " x", 2) != 0)
+ FAIL ();
+ if (sscanf (" 3.25S x", "%4aS%3c", &lsp, c) != 2)
+ FAIL ();
+ else
+ {
+ if (wcscmp (lsp, L"3.25") != 0 || memcmp (c, "S x", 3) != 0)
+ FAIL ();
+ memset (lsp, 'x', sizeof L"3.25");
+ free (lsp);
+ }
+ if (sscanf ("4.25[0-9.] x", "%a[0-9.]%8c", &sp, c) != 2)
+ FAIL ();
+ else
+ {
+ if (strcmp (sp, "4.25") != 0 || memcmp (c, "[0-9.] x", 8) != 0)
+ FAIL ();
+ memset (sp, 'x', sizeof "4.25");
+ free (sp);
+ }
+ if (sscanf ("5.25[0-9.] x", "%la[0-9.]%2c", &d, c) != 2)
+ FAIL ();
+ else if (d != 5.25 || memcmp (c, " x", 2) != 0)
+ FAIL ();
+
+ const char *tmpdir = getenv ("TMPDIR");
+ if (tmpdir == NULL || tmpdir[0] == '\0')
+ tmpdir = "/tmp";
+
+ char fname[strlen (tmpdir) + sizeof "/tst-scanf14.XXXXXX"];
+ sprintf (fname, "%s/tst-scanf14.XXXXXX", tmpdir);
+ if (fname == NULL)
+ FAIL ();
+
+ /* Create a temporary file. */
+ int fd = mkstemp (fname);
+ if (fd == -1)
+ FAIL ();
+
+ FILE *fp = fdopen (fd, "w+");
+ if (fp == NULL)
+ FAIL ();
+ else
+ {
+ if (fputs (" 1.25s x", fp) == EOF)
+ FAIL ();
+ if (fseek (fp, 0, SEEK_SET) != 0)
+ FAIL ();
+ if (fscanf (fp, "%as%2c", &sp, c) != 2)
+ FAIL ();
+ else
+ {
+ if (strcmp (sp, "1.25s") != 0 || memcmp (c, " x", 2) != 0)
+ FAIL ();
+ memset (sp, 'x', sizeof "1.25s");
+ free (sp);
+ }
+
+ if (freopen (fname, "r", stdin) == NULL)
+ FAIL ();
+ else
+ {
+ if (scanf ("%as%2c", &sp, c) != 2)
+ FAIL ();
+ else
+ {
+ if (strcmp (sp, "1.25s") != 0 || memcmp (c, " x", 2) != 0)
+ FAIL ();
+ memset (sp, 'x', sizeof "1.25s");
+ free (sp);
+ }
+ }
+
+ fclose (fp);
+ }
+
+ remove (fname);
+
+ return result;
+}
diff --git a/stdio-common/scanf15.c b/stdio-common/scanf15.c
index a3ab15dea2..e658e42a2f 100644
--- a/stdio-common/scanf15.c
+++ b/stdio-common/scanf15.c
@@ -1,18 +1,29 @@
-#undef _GNU_SOURCE
-#define _XOPEN_SOURCE 600
-#undef _LIBC
-#undef _IO_MTSAFE_IO
-/* The following macro definitions are a hack. They word around disabling
- the GNU extension while still using a few internal headers. */
-#define u_char unsigned char
-#define u_short unsigned short
-#define u_int unsigned int
-#define u_long unsigned long
+/* Copyright (C) 2007-2019 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
+ <http://www.gnu.org/licenses/>. */
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
+#if __GLIBC_USE_DEPRECATED_SCANF
+# error "This file should not be compiled with deprecated scanf"
+#endif
+
#define FAIL() \
do { \
result = 1; \
diff --git a/stdio-common/scanf16.c b/stdio-common/scanf16.c
index 3e3cb417f2..6e6f644e20 100644
--- a/stdio-common/scanf16.c
+++ b/stdio-common/scanf16.c
@@ -1,16 +1,37 @@
+/* Copyright (C) 2008-2019 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
+ <http://www.gnu.org/licenses/>. */
+
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
+#if __GLIBC_USE_DEPRECATED_SCANF
+# error "This file should not be compiled with deprecated scanf"
+#endif
+
#define FAIL() \
do { \
result = 1; \
printf ("test at line %d failed\n", __LINE__); \
} while (0)
-static int
+static int __attribute__ ((format (scanf, 2, 3)))
xsscanf (const char *str, const char *fmt, ...)
{
va_list ap;
@@ -20,7 +41,7 @@ xsscanf (const char *str, const char *fmt, ...)
return ret;
}
-static int
+static int __attribute__ ((format (scanf, 1, 2)))
xscanf (const char *fmt, ...)
{
va_list ap;
@@ -30,7 +51,7 @@ xscanf (const char *fmt, ...)
return ret;
}
-static int
+static int __attribute__ ((format (scanf, 2, 3)))
xfscanf (FILE *f, const char *fmt, ...)
{
va_list ap;
@@ -54,7 +75,7 @@ main (void)
FAIL ();
else if (f != 0.25 || memcmp (c, "s x", 3) != 0)
FAIL ();
- if (xsscanf (" 1.25s x", "%as%2c", &sp, c) != 2)
+ if (xsscanf (" 1.25s x", "%ms%2c", &sp, c) != 2)
FAIL ();
else
{
@@ -67,7 +88,7 @@ main (void)
FAIL ();
else if (d != 2.25 || memcmp (c, " x", 2) != 0)
FAIL ();
- if (xsscanf (" 3.25S x", "%4aS%3c", &lsp, c) != 2)
+ if (xsscanf (" 3.25S x", "%4mS%3c", &lsp, c) != 2)
FAIL ();
else
{
@@ -76,7 +97,7 @@ main (void)
memset (lsp, 'x', sizeof L"3.25");
free (lsp);
}
- if (xsscanf ("4.25[0-9.] x", "%a[0-9.]%8c", &sp, c) != 2)
+ if (xsscanf ("4.25[0-9.] x", "%m[0-9.]%8c", &sp, c) != 2)
FAIL ();
else
{
@@ -113,7 +134,7 @@ main (void)
FAIL ();
if (fseek (fp, 0, SEEK_SET) != 0)
FAIL ();
- if (xfscanf (fp, "%as%2c", &sp, c) != 2)
+ if (xfscanf (fp, "%ms%2c", &sp, c) != 2)
FAIL ();
else
{
@@ -127,7 +148,7 @@ main (void)
FAIL ();
else
{
- if (xscanf ("%as%2c", &sp, c) != 2)
+ if (xscanf ("%ms%2c", &sp, c) != 2)
FAIL ();
else
{
diff --git a/stdio-common/scanf16a.c b/stdio-common/scanf16a.c
new file mode 100644
index 0000000000..09dc6582ef
--- /dev/null
+++ b/stdio-common/scanf16a.c
@@ -0,0 +1,173 @@
+/* Copyright (C) 2008-2019 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
+ <http://www.gnu.org/licenses/>. */
+
+/* This test exercises the deprecated GNU %as, %aS, and %a[...] scanf
+ modifiers, which are not available to programs compiled as C99
+ anymore; therefore, this file is compiled with -std=gnu89 and C99
+ syntax must not be used. */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#if !__GLIBC_USE_DEPRECATED_SCANF
+# error "This file should be compiled with deprecated scanf"
+#endif
+
+#define FAIL() \
+ do { \
+ result = 1; \
+ printf ("test at line %d failed\n", __LINE__); \
+ } while (0)
+
+static int __attribute__ ((format (scanf, 2, 3)))
+xsscanf (const char *str, const char *fmt, ...)
+{
+ va_list ap;
+ va_start (ap, fmt);
+ int ret = vsscanf (str, fmt, ap);
+ va_end (ap);
+ return ret;
+}
+
+static int __attribute__ ((format (scanf, 1, 2)))
+xscanf (const char *fmt, ...)
+{
+ va_list ap;
+ va_start (ap, fmt);
+ int ret = vscanf (fmt, ap);
+ va_end (ap);
+ return ret;
+}
+
+static int __attribute__ ((format (scanf, 2, 3)))
+xfscanf (FILE *f, const char *fmt, ...)
+{
+ va_list ap;
+ va_start (ap, fmt);
+ int ret = vfscanf (f, fmt, ap);
+ va_end (ap);
+ return ret;
+}
+
+int
+main (void)
+{
+ wchar_t *lsp;
+ char *sp;
+ float f;
+ double d;
+ char c[8];
+ int result = 0;
+
+ if (xsscanf (" 0.25s x", "%e%3c", &f, c) != 2)
+ FAIL ();
+ else if (f != 0.25 || memcmp (c, "s x", 3) != 0)
+ FAIL ();
+ if (xsscanf (" 1.25s x", "%as%2c", &sp, c) != 2)
+ FAIL ();
+ else
+ {
+ if (strcmp (sp, "1.25s") != 0 || memcmp (c, " x", 2) != 0)
+ FAIL ();
+ memset (sp, 'x', sizeof "1.25s");
+ free (sp);
+ }
+ if (xsscanf (" 2.25s x", "%las%2c", &d, c) != 2)
+ FAIL ();
+ else if (d != 2.25 || memcmp (c, " x", 2) != 0)
+ FAIL ();
+ if (xsscanf (" 3.25S x", "%4aS%3c", &lsp, c) != 2)
+ FAIL ();
+ else
+ {
+ if (wcscmp (lsp, L"3.25") != 0 || memcmp (c, "S x", 3) != 0)
+ FAIL ();
+ memset (lsp, 'x', sizeof L"3.25");
+ free (lsp);
+ }
+ if (xsscanf ("4.25[0-9.] x", "%a[0-9.]%8c", &sp, c) != 2)
+ FAIL ();
+ else
+ {
+ if (strcmp (sp, "4.25") != 0 || memcmp (c, "[0-9.] x", 8) != 0)
+ FAIL ();
+ memset (sp, 'x', sizeof "4.25");
+ free (sp);
+ }
+ if (xsscanf ("5.25[0-9.] x", "%la[0-9.]%2c", &d, c) != 2)
+ FAIL ();
+ else if (d != 5.25 || memcmp (c, " x", 2) != 0)
+ FAIL ();
+
+ const char *tmpdir = getenv ("TMPDIR");
+ if (tmpdir == NULL || tmpdir[0] == '\0')
+ tmpdir = "/tmp";
+
+ char fname[strlen (tmpdir) + sizeof "/tst-scanf16.XXXXXX"];
+ sprintf (fname, "%s/tst-scanf16.XXXXXX", tmpdir);
+ if (fname == NULL)
+ FAIL ();
+
+ /* Create a temporary file. */
+ int fd = mkstemp (fname);
+ if (fd == -1)
+ FAIL ();
+
+ FILE *fp = fdopen (fd, "w+");
+ if (fp == NULL)
+ FAIL ();
+ else
+ {
+ if (fputs (" 1.25s x", fp) == EOF)
+ FAIL ();
+ if (fseek (fp, 0, SEEK_SET) != 0)
+ FAIL ();
+ if (xfscanf (fp, "%as%2c", &sp, c) != 2)
+ FAIL ();
+ else
+ {
+ if (strcmp (sp, "1.25s") != 0 || memcmp (c, " x", 2) != 0)
+ FAIL ();
+ memset (sp, 'x', sizeof "1.25s");
+ free (sp);
+ }
+
+ if (freopen (fname, "r", stdin) == NULL)
+ FAIL ();
+ else
+ {
+ if (xscanf ("%as%2c", &sp, c) != 2)
+ FAIL ();
+ else
+ {
+ if (strcmp (sp, "1.25s") != 0 || memcmp (c, " x", 2) != 0)
+ FAIL ();
+ memset (sp, 'x', sizeof "1.25s");
+ free (sp);
+ }
+ }
+
+ fclose (fp);
+ }
+
+ remove (fname);
+
+ return result;
+}
diff --git a/stdio-common/scanf17.c b/stdio-common/scanf17.c
index b6c0e63ab0..c17c1dab4d 100644
--- a/stdio-common/scanf17.c
+++ b/stdio-common/scanf17.c
@@ -1,19 +1,30 @@
-#undef _GNU_SOURCE
-#define _XOPEN_SOURCE 600
-#undef _LIBC
-#undef _IO_MTSAFE_IO
-/* The following macro definitions are a hack. They word around disabling
- the GNU extension while still using a few internal headers. */
-#define u_char unsigned char
-#define u_short unsigned short
-#define u_int unsigned int
-#define u_long unsigned long
+/* Copyright (C) 2008-2019 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
+ <http://www.gnu.org/licenses/>. */
+
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
+#if __GLIBC_USE_DEPRECATED_SCANF
+# error "This file should not be compiled with deprecated scanf"
+#endif
+
#define FAIL() \
do { \
result = 1; \
diff --git a/stdio-common/sscanf.c b/stdio-common/sscanf.c
index a630fba409..59caf8df38 100644
--- a/stdio-common/sscanf.c
+++ b/stdio-common/sscanf.c
@@ -15,6 +15,11 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+/* This file defines one of the deprecated scanf variants. */
+#include <features.h>
+#undef __GLIBC_USE_DEPRECATED_SCANF
+#define __GLIBC_USE_DEPRECATED_SCANF 1
+
#include <stdarg.h>
#include <libio/strfile.h>
@@ -34,6 +39,5 @@ __sscanf (const char *s, const char *format, ...)
return done;
}
-ldbl_hidden_def (__sscanf, sscanf)
ldbl_strong_alias (__sscanf, sscanf)
ldbl_strong_alias (__sscanf, _IO_sscanf)
diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c
index f479909351..b1ef0fc718 100644
--- a/stdio-common/vfscanf.c
+++ b/stdio-common/vfscanf.c
@@ -15,6 +15,11 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+/* This file defines one of the deprecated scanf variants. */
+#include <features.h>
+#undef __GLIBC_USE_DEPRECATED_SCANF
+#define __GLIBC_USE_DEPRECATED_SCANF 1
+
#include <libioP.h>
int
diff --git a/stdio-common/vfwscanf.c b/stdio-common/vfwscanf.c
index f8cfd81982..e75aafe39e 100644
--- a/stdio-common/vfwscanf.c
+++ b/stdio-common/vfwscanf.c
@@ -16,6 +16,11 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+/* This file defines one of the deprecated scanf variants. */
+#include <features.h>
+#undef __GLIBC_USE_DEPRECATED_SCANF
+#define __GLIBC_USE_DEPRECATED_SCANF 1
+
#include <libioP.h>
int
diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-compat.c b/sysdeps/ieee754/ldbl-opt/nldbl-compat.c
index 9c9646c4d2..76ef8a8f74 100644
--- a/sysdeps/ieee754/ldbl-opt/nldbl-compat.c
+++ b/sysdeps/ieee754/ldbl-opt/nldbl-compat.c
@@ -17,6 +17,11 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+/* This file may define some of the deprecated scanf variants. */
+#include <features.h>
+#undef __GLIBC_USE_DEPRECATED_SCANF
+#define __GLIBC_USE_DEPRECATED_SCANF 1
+
#include <stdarg.h>
#include <stdio.h>
#include <libio/strfile.h>
diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-fscanf.c b/sysdeps/ieee754/ldbl-opt/nldbl-fscanf.c
index 1b768e306f..00507187f3 100644
--- a/sysdeps/ieee754/ldbl-opt/nldbl-fscanf.c
+++ b/sysdeps/ieee754/ldbl-opt/nldbl-fscanf.c
@@ -1,3 +1,8 @@
+/* This file defines one of the deprecated scanf variants. */
+#include <features.h>
+#undef __GLIBC_USE_DEPRECATED_SCANF
+#define __GLIBC_USE_DEPRECATED_SCANF 1
+
#include "nldbl-compat.h"
int
diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-fwscanf.c b/sysdeps/ieee754/ldbl-opt/nldbl-fwscanf.c
index 27fc1a7271..65782894a2 100644
--- a/sysdeps/ieee754/ldbl-opt/nldbl-fwscanf.c
+++ b/sysdeps/ieee754/ldbl-opt/nldbl-fwscanf.c
@@ -1,3 +1,8 @@
+/* This file defines one of the deprecated scanf variants. */
+#include <features.h>
+#undef __GLIBC_USE_DEPRECATED_SCANF
+#define __GLIBC_USE_DEPRECATED_SCANF 1
+
#include "nldbl-compat.h"
int
diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-iovfscanf.c b/sysdeps/ieee754/ldbl-opt/nldbl-iovfscanf.c
index 442c11c203..6ed9b48624 100644
--- a/sysdeps/ieee754/ldbl-opt/nldbl-iovfscanf.c
+++ b/sysdeps/ieee754/ldbl-opt/nldbl-iovfscanf.c
@@ -1,3 +1,8 @@
+/* This file defines one of the deprecated scanf variants. */
+#include <features.h>
+#undef __GLIBC_USE_DEPRECATED_SCANF
+#define __GLIBC_USE_DEPRECATED_SCANF 1
+
#include "nldbl-compat.h"
int
diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-scanf.c b/sysdeps/ieee754/ldbl-opt/nldbl-scanf.c
index bbab371cbe..c10da284f2 100644
--- a/sysdeps/ieee754/ldbl-opt/nldbl-scanf.c
+++ b/sysdeps/ieee754/ldbl-opt/nldbl-scanf.c
@@ -1,3 +1,8 @@
+/* This file defines one of the deprecated scanf variants. */
+#include <features.h>
+#undef __GLIBC_USE_DEPRECATED_SCANF
+#define __GLIBC_USE_DEPRECATED_SCANF 1
+
#include "nldbl-compat.h"
int
diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-sscanf.c b/sysdeps/ieee754/ldbl-opt/nldbl-sscanf.c
index a771d49996..34e18be0a1 100644
--- a/sysdeps/ieee754/ldbl-opt/nldbl-sscanf.c
+++ b/sysdeps/ieee754/ldbl-opt/nldbl-sscanf.c
@@ -1,3 +1,8 @@
+/* This file defines one of the deprecated scanf variants. */
+#include <features.h>
+#undef __GLIBC_USE_DEPRECATED_SCANF
+#define __GLIBC_USE_DEPRECATED_SCANF 1
+
#include "nldbl-compat.h"
int
diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-swscanf.c b/sysdeps/ieee754/ldbl-opt/nldbl-swscanf.c
index dd058f47ab..4076debc4e 100644
--- a/sysdeps/ieee754/ldbl-opt/nldbl-swscanf.c
+++ b/sysdeps/ieee754/ldbl-opt/nldbl-swscanf.c
@@ -1,3 +1,8 @@
+/* This file defines one of the deprecated scanf variants. */
+#include <features.h>
+#undef __GLIBC_USE_DEPRECATED_SCANF
+#define __GLIBC_USE_DEPRECATED_SCANF 1
+
#include "nldbl-compat.h"
int
diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-vfscanf.c b/sysdeps/ieee754/ldbl-opt/nldbl-vfscanf.c
index f23465ee95..6f5ebc3045 100644
--- a/sysdeps/ieee754/ldbl-opt/nldbl-vfscanf.c
+++ b/sysdeps/ieee754/ldbl-opt/nldbl-vfscanf.c
@@ -1,3 +1,8 @@
+/* This file defines one of the deprecated scanf variants. */
+#include <features.h>
+#undef __GLIBC_USE_DEPRECATED_SCANF
+#define __GLIBC_USE_DEPRECATED_SCANF 1
+
#include "nldbl-compat.h"
int
diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-vfwscanf.c b/sysdeps/ieee754/ldbl-opt/nldbl-vfwscanf.c
index be9febc9a0..0bef274726 100644
--- a/sysdeps/ieee754/ldbl-opt/nldbl-vfwscanf.c
+++ b/sysdeps/ieee754/ldbl-opt/nldbl-vfwscanf.c
@@ -1,3 +1,8 @@
+/* This file defines one of the deprecated scanf variants. */
+#include <features.h>
+#undef __GLIBC_USE_DEPRECATED_SCANF
+#define __GLIBC_USE_DEPRECATED_SCANF 1
+
#include "nldbl-compat.h"
int
diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-vscanf.c b/sysdeps/ieee754/ldbl-opt/nldbl-vscanf.c
index e75907b905..38f654aa73 100644
--- a/sysdeps/ieee754/ldbl-opt/nldbl-vscanf.c
+++ b/sysdeps/ieee754/ldbl-opt/nldbl-vscanf.c
@@ -1,3 +1,8 @@
+/* This file defines one of the deprecated scanf variants. */
+#include <features.h>
+#undef __GLIBC_USE_DEPRECATED_SCANF
+#define __GLIBC_USE_DEPRECATED_SCANF 1
+
#include "nldbl-compat.h"
int
diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-vsscanf.c b/sysdeps/ieee754/ldbl-opt/nldbl-vsscanf.c
index f5594c122c..33e10e49a9 100644
--- a/sysdeps/ieee754/ldbl-opt/nldbl-vsscanf.c
+++ b/sysdeps/ieee754/ldbl-opt/nldbl-vsscanf.c
@@ -1,3 +1,8 @@
+/* This file defines one of the deprecated scanf variants. */
+#include <features.h>
+#undef __GLIBC_USE_DEPRECATED_SCANF
+#define __GLIBC_USE_DEPRECATED_SCANF 1
+
#include "nldbl-compat.h"
int
diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-vswscanf.c b/sysdeps/ieee754/ldbl-opt/nldbl-vswscanf.c
index bd4bb5131b..91c0d4cd4f 100644
--- a/sysdeps/ieee754/ldbl-opt/nldbl-vswscanf.c
+++ b/sysdeps/ieee754/ldbl-opt/nldbl-vswscanf.c
@@ -1,3 +1,8 @@
+/* This file defines one of the deprecated scanf variants. */
+#include <features.h>
+#undef __GLIBC_USE_DEPRECATED_SCANF
+#define __GLIBC_USE_DEPRECATED_SCANF 1
+
#include "nldbl-compat.h"
int
diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-vwscanf.c b/sysdeps/ieee754/ldbl-opt/nldbl-vwscanf.c
index d39578ca4e..b3d0f1be18 100644
--- a/sysdeps/ieee754/ldbl-opt/nldbl-vwscanf.c
+++ b/sysdeps/ieee754/ldbl-opt/nldbl-vwscanf.c
@@ -1,3 +1,8 @@
+/* This file defines one of the deprecated scanf variants. */
+#include <features.h>
+#undef __GLIBC_USE_DEPRECATED_SCANF
+#define __GLIBC_USE_DEPRECATED_SCANF 1
+
#include "nldbl-compat.h"
int
diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-wscanf.c b/sysdeps/ieee754/ldbl-opt/nldbl-wscanf.c
index 4ee3fdc15f..2689e27f06 100644
--- a/sysdeps/ieee754/ldbl-opt/nldbl-wscanf.c
+++ b/sysdeps/ieee754/ldbl-opt/nldbl-wscanf.c
@@ -1,3 +1,8 @@
+/* This file defines one of the deprecated scanf variants. */
+#include <features.h>
+#undef __GLIBC_USE_DEPRECATED_SCANF
+#define __GLIBC_USE_DEPRECATED_SCANF 1
+
#include "nldbl-compat.h"
int
diff --git a/wcsmbs/bits/wchar-ldbl.h b/wcsmbs/bits/wchar-ldbl.h
index c0b0c6e973..a3378014f3 100644
--- a/wcsmbs/bits/wchar-ldbl.h
+++ b/wcsmbs/bits/wchar-ldbl.h
@@ -27,9 +27,7 @@ __LDBL_REDIR_DECL (swprintf);
__LDBL_REDIR_DECL (vfwprintf);
__LDBL_REDIR_DECL (vwprintf);
__LDBL_REDIR_DECL (vswprintf);
-# if defined __USE_ISOC99 && !defined __USE_GNU \
- && !defined __REDIRECT \
- && (defined __STRICT_ANSI__ || defined __USE_XOPEN2K)
+# if !__GLIBC_USE (DEPRECATED_SCANF)
__LDBL_REDIR1_DECL (fwscanf, __nldbl___isoc99_fwscanf)
__LDBL_REDIR1_DECL (wscanf, __nldbl___isoc99_wscanf)
__LDBL_REDIR1_DECL (swscanf, __nldbl___isoc99_swscanf)
@@ -42,8 +40,7 @@ __LDBL_REDIR_DECL (swscanf);
#ifdef __USE_ISOC99
__LDBL_REDIR1_DECL (wcstold, wcstod);
-# if !defined __USE_GNU && !defined __REDIRECT \
- && (defined __STRICT_ANSI__ || defined __USE_XOPEN2K)
+# if !__GLIBC_USE (DEPRECATED_SCANF)
__LDBL_REDIR1_DECL (vfwscanf, __nldbl___isoc99_vfwscanf)
__LDBL_REDIR1_DECL (vwscanf, __nldbl___isoc99_vwscanf)
__LDBL_REDIR1_DECL (vswscanf, __nldbl___isoc99_vswscanf)
diff --git a/wcsmbs/wchar.h b/wcsmbs/wchar.h
index ddbe7100ee..20deca90bf 100644
--- a/wcsmbs/wchar.h
+++ b/wcsmbs/wchar.h
@@ -632,13 +632,11 @@ extern int swscanf (const wchar_t *__restrict __s,
const wchar_t *__restrict __format, ...)
__THROW /* __attribute__ ((__format__ (__wscanf__, 2, 3))) */;
-# if defined __USE_ISOC99 && !defined __USE_GNU \
- && (!defined __LDBL_COMPAT || !defined __REDIRECT) \
- && (defined __STRICT_ANSI__ || defined __USE_XOPEN2K)
+/* For historical reasons, the C99-compliant versions of the scanf
+ functions are at alternative names. When __LDBL_COMPAT is in
+ effect, this is handled in bits/wchar-ldbl.h. */
+#if !__GLIBC_USE (DEPRECATED_SCANF) && !defined __LDBL_COMPAT
# ifdef __REDIRECT
-/* For strict ISO C99 or POSIX compliance disallow %as, %aS and %a[
- GNU extension which conflicts with valid %a followed by letter
- s, S or [. */
extern int __REDIRECT (fwscanf, (__FILE *__restrict __stream,
const wchar_t *__restrict __format, ...),
__isoc99_fwscanf)