summaryrefslogtreecommitdiff
path: root/stdio-common/vfscanf.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2007-09-18 19:04:01 +0000
committerUlrich Drepper <drepper@redhat.com>2007-09-18 19:04:01 +0000
commit874aa52349cc111d1f6ea5dff24bb14c306714e0 (patch)
tree40cc28100e18b8b9d8311038b0d3f9dd38bcfe0f /stdio-common/vfscanf.c
parent883f7943f242c174c49bc82d51fe8332ad50d573 (diff)
* include/stdio.h (__isoc99_fscanf, __isoc99_scanf,
__isoc99_sscanf, __isoc99_vscanf): New prototypes. (__isoc99_vsscanf, __isoc99_vfscanf): New prototypes, add libc_hidden_proto. * include/wchar.h (__isoc99_fwscanf, __isoc99_wscanf, __isoc99_swscanf, __isoc99_vwscanf): New prototypes. (__isoc99_vswscanf, __isoc99_vfwscanf): New prototypes, add libc_hidden_proto. * libio/stdio.h (fscanf, scanf, sscanf, vfscanf, vscanf, vsscanf): Redirect to __isoc99_* if strict ISO C99 or POSIX conformance requested. * wcsmbs/wchar.h (fwscanf, wscanf, swscanf, vfwscanf, vwscanf, vswscanf): Redirect to __isoc99_* if strict ISO C99 or POSIX conformance requested. * libio/bits/stdio-ldbl.h (fscanf, scanf, sscanf, vfscanf, vscanf, vsscanf): Redirect to __nldbl___isoc99_* if strict ISO C99 or POSIX conformance requested. * wcsmbs/bits/wchar-ldbl.h (fwscanf, wscanf, swscanf, vfwscanf, vwscanf, vswscanf): Redirect to __nldbl___isoc99_* if strict ISO C99 or POSIX conformance requested. * stdio-common/Versions (libc): Export __isoc99_scanf@@GLIBC_2.7, __isoc99_vscanf@@GLIBC_2.7, __isoc99_fscanf@@GLIBC_2.7, __isoc99_vfscanf@@GLIBC_2.7, __isoc99_sscanf@@GLIBC_2.7 and __isoc99_vsscanf@@GLIBC_2.7. * stdio-common/Makefile (routines): Add isoc99_scanf, isoc99_vscanf, isoc99_fscanf, isoc99_vfscanf, isoc99_sscanf and isoc99_vsscanf. (tests): Add scanf14. (CFLAGS-vfprintf.c, CFLAGS-fprintf.c, CFLAGS-printf.c, CFLAGS-vfwprintf.c, CFLAGS-vfscanf.c, CFLAGS-vfwscanf.c, CFLAGS-fscanf.c, CFLAGS-scanf.c, CFLAGS-isoc99_vfscanf.c, CFLAGS-isoc99_vscanf.c, CFLAGS-isoc99_fscanf.c, CFLAGS-isoc99_scanf.c): Add $(exceptions). (CFLAGS-scanf15.c): Add various -I paths to prevent the compiler from using internal headers. * wcsmbs/Versions (libc): Export __isoc99_wscanf@@GLIBC_2.7, __isoc99_vwscanf@@GLIBC_2.7, __isoc99_fwscanf@@GLIBC_2.7, __isoc99_vfwscanf@@GLIBC_2.7, __isoc99_swscanf@@GLIBC_2.7 and __isoc99_vswscanf@@GLIBC_2.7. * wcsmbs/Makefile (routines): Add isoc99_wscanf, isoc99_vwscanf, isoc99_fwscanf, isoc99_vfwscanf, isoc99_swscanf and isoc99_vswscanf. (CFLAGS-isoc99_wscanf.c, CFLAGS-isoc99_fwscanf.c, CFLAGS-isoc99_vwscanf.c, CFLAGS-isoc99_vfwscanf.c): Add $(exceptions). (CPPFLAGS): Add -D_IO_MTSAFE_IO if needed. * stdio-common/isoc99_scanf.c: New file. * stdio-common/isoc99_vsscanf.c: New file. * stdio-common/isoc99_vscanf.c: New file. * stdio-common/isoc99_vfscanf.c: New file. * stdio-common/isoc99_fscanf.c: New file. * stdio-common/isoc99_sscanf.c: New file. * wcsmbs/isoc99_fwscanf.c: New file. * wcsmbs/isoc99_vswscanf.c: New file. * wcsmbs/isoc99_swscanf.c: New file. * wcsmbs/isoc99_wscanf.c: New file. * wcsmbs/isoc99_vwscanf.c: New file. * wcsmbs/isoc99_vfwscanf.c: New file. * libio/libio.h (_IO_FLAGS2_SCANF_STD): Define. * libio/libioP.h (_IO_acquire_lock_clear_flags2_fct): Also clear _IO_FLAGS2_SCANF_STD bit from _flags2. * stdio-common/vfscanf.c (_IO_vfscanf_internal): Don't handle %as, %aS and %a[ if _IO_FLAGS2_SCANF_STD is set in _flags2. * stdio-common/scanf14.c: New test. * stdio-common/scanf15.c: New test. * sysdeps/ieee754/ldbl-opt/Makefile (libnldbl-calls): Add isoc99_scanf, isoc99_fscanf, isoc99_sscanf, isoc99_vscanf, isoc99_vfscanf, isoc99_vsscanf, isoc99_wscanf, isoc99_fwscanf, isoc99_swscanf, isoc99_vwscanf, isoc99_vfwscanf and isoc99_vswscanf. * sysdeps/ieee754/ldbl-opt/Versions (libc): Export __nldbl___isoc99_scanf@@GLIBC_2.7, __nldbl___isoc99_fscanf@@GLIBC_2.7, __nldbl___isoc99_sscanf@@GLIBC_2.7, __nldbl___isoc99_vscanf@@GLIBC_2.7, __nldbl___isoc99_vfscanf@@GLIBC_2.7, __nldbl___isoc99_vsscanf@@GLIBC_2.7, __nldbl___isoc99_wscanf@@GLIBC_2.7, __nldbl___isoc99_fwscanf@@GLIBC_2.7, __nldbl___isoc99_swscanf@@GLIBC_2.7, __nldbl___isoc99_vwscanf@@GLIBC_2.7, __nldbl___isoc99_vfwscanf@@GLIBC_2.7 and __nldbl___isoc99_vswscanf@@GLIBC_2.7. * sysdeps/ieee754/ldbl-opt/nldbl-compat.h (__isoc99_scanf, __isoc99_fscanf, __isoc99_sscanf, __isoc99_vscanf, __isoc99_vfscanf, __isoc99_vsscanf, __isoc99_wscanf, __isoc99_fwscanf, __isoc99_swscanf, __isoc99_vwscanf, __isoc99_vfwscanf, __isoc99_vswscanf): Add NLDBL_DECL. * sysdeps/ieee754/ldbl-opt/nldbl-compat.c (__nldbl___isoc99_scanf, __nldbl___isoc99_fscanf, __nldbl___isoc99_sscanf, __nldbl___isoc99_vscanf, __nldbl___isoc99_vfscanf, __nldbl___isoc99_vsscanf, __nldbl___isoc99_wscanf, __nldbl___isoc99_fwscanf, __nldbl___isoc99_swscanf, __nldbl___isoc99_vwscanf, __nldbl___isoc99_vfwscanf, __nldbl___isoc99_vswscanf): New functions. * sysdeps/ieee754/ldbl-opt/nldbl-isoc99_vfscanf.c: New file. * sysdeps/ieee754/ldbl-opt/nldbl-isoc99_swscanf.c: New file. * sysdeps/ieee754/ldbl-opt/nldbl-isoc99_vwscanf.c: New file. * sysdeps/ieee754/ldbl-opt/nldbl-isoc99_wscanf.c: New file. * sysdeps/ieee754/ldbl-opt/nldbl-isoc99_scanf.c: New file. * sysdeps/ieee754/ldbl-opt/nldbl-isoc99_sscanf.c: New file. * sysdeps/ieee754/ldbl-opt/nldbl-isoc99_vsscanf.c: New file. * sysdeps/ieee754/ldbl-opt/nldbl-isoc99_fwscanf.c: New file. * sysdeps/ieee754/ldbl-opt/nldbl-isoc99_vfwscanf.c: New file. * sysdeps/ieee754/ldbl-opt/nldbl-isoc99_vswscanf.c: New file. * sysdeps/ieee754/ldbl-opt/nldbl-isoc99_vscanf.c: New file. * sysdeps/ieee754/ldbl-opt/nldbl-isoc99_fscanf.c: New file. * stdio-common/Makefile (tests): Add scanf13. (scanf13-ENV): New. * stdio-common/vfscanf.c (_IO_vfscanf_internal): Handle m modifier followed by l. (STRING_ARG): Add width argument. (_IO_vfscanf_internal) <case L_('c')>: Handle %mc. <case L_('C')>: Handle %mlc and %mC. <case L_('s'), case L_('S'), case L_('[')>: Adjust STRING_ARG arguments. * stdio-common/scanf13.c: New test. * libio/libioP.h (_IO_acquire_lock_clear_flags2_fct): Clear the _IO_FLAGS2_FORTIFY bit from _flags2 rather than _flags. type and __THROW marker of splice, vmsplice, and tee.
Diffstat (limited to 'stdio-common/vfscanf.c')
-rw-r--r--stdio-common/vfscanf.c273
1 files changed, 217 insertions, 56 deletions
diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c
index ddf9a5ea31..e4728d00c9 100644
--- a/stdio-common/vfscanf.c
+++ b/stdio-common/vfscanf.c
@@ -514,13 +514,25 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
--f;
break;
}
+ /* In __isoc99_*scanf %as, %aS and %a[ extension is not
+ supported at all. */
+ if (s->_flags2 & _IO_FLAGS2_SCANF_STD)
+ {
+ --f;
+ break;
+ }
/* String conversions (%s, %[) take a `char **'
arg and fill it in with a malloc'd pointer. */
flags |= GNU_MALLOC;
break;
- case L_('m'):
- flags |= POSIX_MALLOC;
- break;
+ case L_('m'):
+ flags |= POSIX_MALLOC;
+ if (*f == L_('l'))
+ {
+ ++f;
+ flags |= LONG;
+ }
+ break;
case L_('z'):
if (need_longlong && sizeof (size_t) > sizeof (unsigned long int))
flags |= LONGDBL;
@@ -635,20 +647,46 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
case L_('c'): /* Match characters. */
if ((flags & LONG) == 0)
{
- if (!(flags & SUPPRESS))
- {
- str = ARG (char *);
- if (str == NULL)
- conv_error ();
- }
+ if (width == -1)
+ width = 1;
+
+#define STRING_ARG(Str, Type, Width) \
+ do if (!(flags & SUPPRESS)) \
+ { \
+ if (flags & MALLOC) \
+ { \
+ /* The string is to be stored in a malloc'd buffer. */ \
+ /* For %mS using char ** is actually wrong, but \
+ shouldn't make a difference on any arch glibc \
+ supports and would unnecessarily complicate \
+ things. */ \
+ strptr = ARG (char **); \
+ if (strptr == NULL) \
+ conv_error (); \
+ /* Allocate an initial buffer. */ \
+ strsize = Width; \
+ *strptr = (char *) malloc (strsize * sizeof (Type)); \
+ Str = (Type *) *strptr; \
+ if (Str != NULL) \
+ add_ptr_to_free (strptr); \
+ else if (flags & POSIX_MALLOC) \
+ goto reteof; \
+ } \
+ else \
+ Str = ARG (Type *); \
+ if (Str == NULL) \
+ conv_error (); \
+ } while (0)
+#ifdef COMPILE_WSCANF
+ STRING_ARG (str, char, 100);
+#else
+ STRING_ARG (str, char, (width > 1024 ? 1024 : width));
+#endif
c = inchar ();
if (__builtin_expect (c == EOF, 0))
input_error ();
- if (width == -1)
- width = 1;
-
#ifdef COMPILE_WSCANF
/* We have to convert the wide character(s) into multibyte
characters and store the result. */
@@ -658,6 +696,38 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
{
size_t n;
+ if (!(flags & SUPPRESS) && (flags & POSIX_MALLOC)
+ && str + MB_CUR_MAX >= *strptr + strsize)
+ {
+ /* We have to enlarge the buffer if the `m' flag
+ was given. */
+ size_t strleng = str - *strptr;
+ char *newstr;
+
+ newstr = (char *) realloc (*strptr, strsize * 2);
+ if (newstr == NULL)
+ {
+ /* Can't allocate that much. Last-ditch effort. */
+ newstr = (char *) realloc (*strptr,
+ strleng + MB_CUR_MAX);
+ if (newstr == NULL)
+ /* c can't have `a' flag, only `m'. */
+ goto reteof;
+ else
+ {
+ *strptr = newstr;
+ str = newstr + strleng;
+ strsize = strleng + MB_CUR_MAX;
+ }
+ }
+ else
+ {
+ *strptr = newstr;
+ str = newstr + strleng;
+ strsize *= 2;
+ }
+ }
+
n = __wcrtomb (!(flags & SUPPRESS) ? str : NULL, c, &state);
if (__builtin_expect (n == (size_t) -1, 0))
/* No valid wide character. */
@@ -672,7 +742,40 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
if (!(flags & SUPPRESS))
{
do
- *str++ = c;
+ {
+ if ((flags & MALLOC)
+ && (char *) str == *strptr + strsize)
+ {
+ /* Enlarge the buffer. */
+ size_t newsize
+ = strsize
+ + (strsize >= width ? width - 1 : strsize);
+
+ str = (char *) realloc (*strptr, newsize);
+ if (str == NULL)
+ {
+ /* Can't allocate that much. Last-ditch
+ effort. */
+ str = (char *) realloc (*strptr, strsize + 1);
+ if (str == NULL)
+ /* c can't have `a' flag, only `m'. */
+ goto reteof;
+ else
+ {
+ *strptr = (char *) str;
+ str += strsize;
+ ++strsize;
+ }
+ }
+ else
+ {
+ *strptr = (char *) str;
+ str += strsize;
+ strsize = newsize;
+ }
+ }
+ *str++ = c;
+ }
while (--width > 0 && inchar () != EOF);
}
else
@@ -680,18 +783,25 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
#endif
if (!(flags & SUPPRESS))
- ++done;
+ {
+ if ((flags & MALLOC) && str - *strptr != strsize)
+ {
+ char *cp = (char *) realloc (*strptr, str - *strptr);
+ if (cp != NULL)
+ *strptr = cp;
+ }
+ strptr = NULL;
+ ++done;
+ }
break;
}
/* FALLTHROUGH */
case L_('C'):
- if (!(flags & SUPPRESS))
- {
- wstr = ARG (wchar_t *);
- if (wstr == NULL)
- conv_error ();
- }
+ if (width == -1)
+ width = 1;
+
+ STRING_ARG (wstr, wchar_t, (width > 1024 ? 1024 : width));
c = inchar ();
if (__builtin_expect (c == EOF, 0))
@@ -702,7 +812,40 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
if (!(flags & SUPPRESS))
{
do
- *wstr++ = c;
+ {
+ if ((flags & MALLOC)
+ && wstr == (wchar_t *) *strptr + strsize)
+ {
+ size_t newsize
+ = strsize + (strsize > width ? width - 1 : strsize);
+ /* Enlarge the buffer. */
+ wstr = (wchar_t *) realloc (*strptr,
+ newsize * sizeof (wchar_t));
+ if (wstr == NULL)
+ {
+ /* Can't allocate that much. Last-ditch effort. */
+ wstr = (wchar_t *) realloc (*strptr,
+ (strsize + 1)
+ * sizeof (wchar_t));
+ if (wstr == NULL)
+ /* C or lc can't have `a' flag, only `m' flag. */
+ goto reteof;
+ else
+ {
+ *strptr = (char *) wstr;
+ wstr += strsize;
+ ++strsize;
+ }
+ }
+ else
+ {
+ *strptr = (char *) wstr;
+ wstr += strsize;
+ strsize = newsize;
+ }
+ }
+ *wstr++ = c;
+ }
while (--width > 0 && inchar () != EOF);
}
else
@@ -721,6 +864,38 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
/* This is what we present the mbrtowc function first. */
buf[0] = c;
+ if (!(flags & SUPPRESS) && (flags & MALLOC)
+ && wstr == (wchar_t *) *strptr + strsize)
+ {
+ size_t newsize
+ = strsize + (strsize > width ? width - 1 : strsize);
+ /* Enlarge the buffer. */
+ wstr = (wchar_t *) realloc (*strptr,
+ newsize * sizeof (wchar_t));
+ if (wstr == NULL)
+ {
+ /* Can't allocate that much. Last-ditch effort. */
+ wstr = (wchar_t *) realloc (*strptr,
+ ((strsize + 1)
+ * sizeof (wchar_t)));
+ if (wstr == NULL)
+ /* C or lc can't have `a' flag, only `m' flag. */
+ goto reteof;
+ else
+ {
+ *strptr = (char *) wstr;
+ wstr += strsize;
+ ++strsize;
+ }
+ }
+ else
+ {
+ *strptr = (char *) wstr;
+ wstr += strsize;
+ strsize = newsize;
+ }
+ }
+
while (1)
{
size_t n;
@@ -754,41 +929,27 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
#endif
if (!(flags & SUPPRESS))
- ++done;
+ {
+ if ((flags & MALLOC) && wstr - (wchar_t *) *strptr != strsize)
+ {
+ wchar_t *cp = (wchar_t *) realloc (*strptr,
+ ((wstr
+ - (wchar_t *) *strptr)
+ * sizeof (wchar_t)));
+ if (cp != NULL)
+ *strptr = (char *) cp;
+ }
+ strptr = NULL;
+
+ ++done;
+ }
break;
case L_('s'): /* Read a string. */
if (!(flags & LONG))
{
-#define STRING_ARG(Str, Type) \
- do if (!(flags & SUPPRESS)) \
- { \
- if (flags & MALLOC) \
- { \
- /* The string is to be stored in a malloc'd buffer. */ \
- /* For %mS using char ** is actually wrong, but \
- shouldn't make a difference on any arch glibc \
- supports and would unnecessarily complicate \
- things. */ \
- strptr = ARG (char **); \
- if (strptr == NULL) \
- conv_error (); \
- /* Allocate an initial buffer. */ \
- strsize = 100; \
- *strptr = (char *) malloc (strsize * sizeof (Type)); \
- Str = (Type *) *strptr; \
- if (Str != NULL) \
- add_ptr_to_free (strptr); \
- else if (flags & POSIX_MALLOC) \
- goto reteof; \
- } \
- else \
- Str = ARG (Type *); \
- if (Str == NULL) \
- conv_error (); \
- } while (0)
- STRING_ARG (str, char);
+ STRING_ARG (str, char, 100);
c = inchar ();
if (__builtin_expect (c == EOF, 0))
@@ -816,8 +977,8 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
if (!(flags & SUPPRESS) && (flags & MALLOC)
&& str + MB_CUR_MAX >= *strptr + strsize)
{
- /* We have to enlarge the buffer if the `a' flag
- was given. */
+ /* We have to enlarge the buffer if the `a' or `m'
+ flag was given. */
size_t strleng = str - *strptr;
char *newstr;
@@ -969,7 +1130,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
#endif
/* Wide character string. */
- STRING_ARG (wstr, wchar_t);
+ STRING_ARG (wstr, wchar_t, 100);
c = inchar ();
if (__builtin_expect (c == EOF, 0))
@@ -1002,7 +1163,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
if (wstr == NULL)
{
/* Can't allocate that much. Last-ditch
- effort. */
+ effort. */
wstr = (wchar_t *) realloc (*strptr,
(strsize + 1)
* sizeof (wchar_t));
@@ -2120,9 +2281,9 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
case L_('['): /* Character class. */
if (flags & LONG)
- STRING_ARG (wstr, wchar_t);
+ STRING_ARG (wstr, wchar_t, 100);
else
- STRING_ARG (str, char);
+ STRING_ARG (str, char, 100);
if (*f == L_('^'))
{