]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Use C99-compliant scanf under _GNU_SOURCE with modern compilers.
authorZack Weinberg <zackw@panix.com>
Sat, 10 Feb 2018 16:58:35 +0000 (11:58 -0500)
committerZack Weinberg <zackw@panix.com>
Thu, 3 Jan 2019 16:12:39 +0000 (11:12 -0500)
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.

43 files changed:
ChangeLog
NEWS
include/features.h
include/stdio.h
libio/bits/stdio-ldbl.h
libio/fwscanf.c
libio/iovsscanf.c
libio/iovswscanf.c
libio/stdio.h
libio/swscanf.c
libio/vscanf.c
libio/vwscanf.c
libio/wscanf.c
stdio-common/Makefile
stdio-common/bug21.c
stdio-common/fscanf.c
stdio-common/isoc99_sscanf.c
stdio-common/scanf.c
stdio-common/scanf14.c
stdio-common/scanf14a.c [new file with mode: 0644]
stdio-common/scanf15.c
stdio-common/scanf16.c
stdio-common/scanf16a.c [new file with mode: 0644]
stdio-common/scanf17.c
stdio-common/sscanf.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
wcsmbs/bits/wchar-ldbl.h
wcsmbs/wchar.h

index c446abcd4e708a207201d6f0f71a9dc160b58131..8121c71714d649e0007f697c34fac14f0247e723 100644 (file)
--- 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 4c8bc924ce3293af63a50aee7ebb04d6847b9fdd..cc20102fda461d2f1a2989462342dcc0e6fa5fd3 100644 (file)
--- 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.
index dc9f8fa9accb29963ec366e83a97683d293cbbf6..c9bc534e27a9c5163db6c5b6e4e28c0339486954 100644 (file)
 #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.  */
 # 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>
index 1b7da0f74d85cd833af41a1f8c234fba157e6469..65ccabbb058f49934884eca81f497038edc16e06 100644 (file)
@@ -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)
index 18289e6b86dd39a70daf7a157e42ac93a139408f..97ad168a04a9cf5e32c8f8e4ac8db42b8b9d92be 100644 (file)
@@ -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)
index c316ef961d84a6829a36bbd3e8213b26ab8efe11..24872f46ffb00a2e26413b339f33b650df97a0b2 100644 (file)
    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>
index 752eed96e3a974a208da0cf0491efe02400f1bc9..a561eab87e49d6bad972de6493c0928e53665931 100644 (file)
    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
index f584c963fa6f2463632b5431200271cd4d111612..669fdc12b68a00281540c57fedcd3da6b976850d 100644 (file)
    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"
 
index 4cc5b24a31f4c89c2b212bf192a2b87c81969394..b63ee88a776aa12586f086ab49d05baadd12aeed 100644 (file)
@@ -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;
index e38b938b0b2509cfe37d86a51ee2081fb82b68cb..5f529ef630cb326215fe44d3eaced729389685cd 100644 (file)
    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"
 
index 936a2fdef8df72620ac0a94c39ffb579b395e805..342dc3effcb71c6698fa35212f1a7a7c4f9837e4 100644 (file)
    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"
 
index 0804175a8154d46293b67931e2958acff9edb924..696e4c5c99edfae60cb22bb283d23cf6ffcf3370 100644 (file)
    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>
 
index ce8d3ed6b460d1f9d8266245224e9f8c35c68554..d4c7753e8e2a5d88a24e16f5597cac367bfa7a3c 100644 (file)
    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>
index 11556f217781f8612ab1c781e382af20098dfbf4..c38299c8648fe02ad98fe4243fba28413a297234 100644 (file)
@@ -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)\"
index 7a8c6a354233ad4e918db595e99d748f5fa206cf..1f06c0dab4b50e4f52fb7c18b11a1fcd85d8dd4d 100644 (file)
@@ -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;
index 4b8b26ad54e63f5afa16666b77e287d50b53e4a0..a210eafcabba77876162c4dfa6e0ddd9c507ba0d 100644 (file)
    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>
index a6bfc66e952f7cd8fb21a5386d5508c3810bd678..a70c0c3f2f731d8b31b7e8851c8c1f171b86290b 100644 (file)
@@ -33,3 +33,4 @@ __isoc99_sscanf (const char *s, const char *format, ...)
 
   return done;
 }
+libc_hidden_def (__isoc99_sscanf)
index 1b69a656efccda8b54d983a53e1518fd93e63c8f..9008d2bf97822e8a513baeaff130557d8ff4f713 100644 (file)
    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>
 
index 2bcd9c9893db9727f89a4a50175ece7b8dfcb2a8..8b271ae7cc1dc18eaf44c6ef84948e7793768970 100644 (file)
@@ -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 (file)
index 0000000..5f95ecb
--- /dev/null
@@ -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;
+}
index a3ab15dea224d66e02eeb0306f6843d0b2117ae4..e658e42a2f0dfce24c2660300199c608a33ff85a 100644 (file)
@@ -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;                                                \
index 3e3cb417f2100d82eed970df51ddbc240aaba167..6e6f644e2088ab511e4adbca82b1099baaa16721 100644 (file)
@@ -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 (file)
index 0000000..09dc658
--- /dev/null
@@ -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;
+}
index b6c0e63ab0252ca627a74538d58294076984885a..c17c1dab4da4bcd669323a75caf54eeaa94f2c2f 100644 (file)
@@ -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;                                                \
index a630fba40939ac51ce7526899af686f1c08bc083..59caf8df38362797067bbd4b3d76f6c7e3d7b529 100644 (file)
    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)
index f479909351c19e31284e6f817254795783d7cd9d..b1ef0fc71867275c4bf7a42b8a75820fa44bec13 100644 (file)
    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
index f8cfd81982b0b2f96fb226d12f58253ac29b69da..e75aafe39e986a1ddaacefd1f187d2c6eb58d91b 100644 (file)
    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
index 9c9646c4d2bc61be65084c83a79726d63b5fd052..76ef8a8f7457c15eaad8a612e8917d791d833fdc 100644 (file)
    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>
index 1b768e306f76da6baf3dd626e64afe1ab492202c..00507187f3e80ce1da35ba895e22ebadae3a2094 100644 (file)
@@ -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
index 27fc1a72717d65934f9a8264caaf475880667b11..65782894a2084027bfb724a2ab10d7ce5f93be24 100644 (file)
@@ -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
index 442c11c20378f8694186ecfb3be234a2390f7f27..6ed9b486249af566b8635923f66db1bf4abdcfff 100644 (file)
@@ -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
index bbab371cbe006e9aac6773c4feaf6b2bb05f6b61..c10da284f2ec1719a064edd0dc6fb6125eb032e7 100644 (file)
@@ -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
index a771d499966c6220c482eb2130a383244c308120..34e18be0a16a8282c3a255d62c8f3e0d62f5016f 100644 (file)
@@ -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
index dd058f47ab9229afcd30cd14983e0f148ca72ca2..4076debc4e1d021c1f3ce95b4cd581668095fe8f 100644 (file)
@@ -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
index f23465ee95c7362dbdd00a3004ae794d9106e89e..6f5ebc3045447598873bc379e5b52c4b40d60cb3 100644 (file)
@@ -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
index be9febc9a0ec2a83c48f1ad14167d8aa10f1dbd6..0bef274726f787d505bb0d13892892b1a32dbd97 100644 (file)
@@ -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
index e75907b905627f8c5c93d74937741bd0b92e7a19..38f654aa7303e3b012e4e54a5d34615acd6b6818 100644 (file)
@@ -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
index f5594c122cec9599047b6c9e6149f8a4058cc1fa..33e10e49a91e5b1737f69c3bb33a3d0b252339ac 100644 (file)
@@ -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
index bd4bb5131b2fe793e9cb7811b169f99c4d354b71..91c0d4cd4f7a3f7bdb515f8b50203f0aa4f883c1 100644 (file)
@@ -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
index d39578ca4e4cec49b5128915dd42d19f93de60d0..b3d0f1be1883a5b10a696d5d0223f1ef835e4ed7 100644 (file)
@@ -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
index 4ee3fdc15f4ec2fa7338d6edade216c9ddd3993c..2689e27f06e274bf18c449d18f33a4b7eff1011f 100644 (file)
@@ -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
index c0b0c6e97346cf85fe3a8dd672389e66dd2b8c20..a3378014f3923cf948cb56f2d4d5d79ec47c0f0f 100644 (file)
@@ -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)
index ddbe7100ee6817646d9f0a570d82464fd3ebaa64..20deca90bf26042fe0e709b4607dee1ce72aa594 100644 (file)
@@ -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)