summaryrefslogtreecommitdiff
path: root/stdio-common/vfscanf.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@gmail.com>2011-09-09 21:26:05 -0400
committerUlrich Drepper <drepper@gmail.com>2011-09-09 21:26:05 -0400
commit3f8cc204fdd077da66ffc8e9595158b469e2b8e5 (patch)
tree0e882e37b9a69ef19c40c06d57bbedf1c5792ea7 /stdio-common/vfscanf.c
parente4899e7b9adbf74145f6530f6f57517f773e330c (diff)
downloadglibc-3f8cc204fdd077da66ffc8e9595158b469e2b8e5.tar.gz
Fix boundary conditions in scanf
Allocate large buffers with realloc. When returning error make sure the stream is unlocked.
Diffstat (limited to 'stdio-common/vfscanf.c')
-rw-r--r--stdio-common/vfscanf.c124
1 files changed, 97 insertions, 27 deletions
diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c
index 9d312d55aa..0e71deba22 100644
--- a/stdio-common/vfscanf.c
+++ b/stdio-common/vfscanf.c
@@ -265,16 +265,39 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
CHAR_T *wp = NULL; /* Workspace. */
size_t wpmax = 0; /* Maximal size of workspace. */
size_t wpsize; /* Currently used bytes in workspace. */
+ bool use_malloc = false;
#define ADDW(Ch) \
do \
{ \
- if (wpsize == wpmax) \
+ if (__builtin_expect (wpsize == wpmax, 0)) \
{ \
CHAR_T *old = wp; \
- wpmax = (UCHAR_MAX + 1 > 2 * wpmax ? UCHAR_MAX + 1 : 2 * wpmax); \
- wp = (CHAR_T *) alloca (wpmax * sizeof (CHAR_T)); \
- if (old != NULL) \
- MEMCPY (wp, old, wpsize); \
+ size_t newsize = (UCHAR_MAX + 1 > 2 * wpmax \
+ ? UCHAR_MAX + 1 : 2 * wpmax); \
+ if (use_malloc || __libc_use_alloca (newsize)) \
+ { \
+ wp = realloc (use_malloc ? wp : NULL, newsize); \
+ if (wp == NULL) \
+ { \
+ if (use_malloc) \
+ free (old); \
+ done = EOF; \
+ goto errout; \
+ } \
+ if (! use_malloc) \
+ MEMCPY (wp, old, wpsize); \
+ wpmax = newsize; \
+ use_malloc = true; \
+ } \
+ else \
+ { \
+ size_t s = wpmax * sizeof (CHAR_T); \
+ wp = (CHAR_T *) extend_alloca (wp, s, \
+ newsize * sizeof (CHAR_T)); \
+ wpmax = s / sizeof (CHAR_T); \
+ if (old != NULL) \
+ MEMCPY (wp, old, wpsize); \
+ } \
} \
wp[wpsize++] = (Ch); \
} \
@@ -670,7 +693,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
if (Str != NULL) \
add_ptr_to_free (strptr); \
else if (flags & POSIX_MALLOC) \
- goto reteof; \
+ { \
+ done = EOF; \
+ goto errout; \
+ } \
} \
else \
Str = ARG (Type *); \
@@ -711,8 +737,11 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
newstr = (char *) realloc (*strptr,
strleng + MB_CUR_MAX);
if (newstr == NULL)
- /* c can't have `a' flag, only `m'. */
- goto reteof;
+ {
+ /* c can't have `a' flag, only `m'. */
+ done = EOF;
+ goto errout;
+ }
else
{
*strptr = newstr;
@@ -758,8 +787,11 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
effort. */
str = (char *) realloc (*strptr, strsize + 1);
if (str == NULL)
- /* c can't have `a' flag, only `m'. */
- goto reteof;
+ {
+ /* c can't have `a' flag, only `m'. */
+ done = EOF;
+ goto errout;
+ }
else
{
*strptr = (char *) str;
@@ -828,8 +860,12 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
(strsize + 1)
* sizeof (wchar_t));
if (wstr == NULL)
- /* C or lc can't have `a' flag, only `m' flag. */
- goto reteof;
+ {
+ /* C or lc can't have `a' flag, only `m'
+ flag. */
+ done = EOF;
+ goto errout;
+ }
else
{
*strptr = (char *) wstr;
@@ -879,8 +915,11 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
((strsize + 1)
* sizeof (wchar_t)));
if (wstr == NULL)
- /* C or lc can't have `a' flag, only `m' flag. */
- goto reteof;
+ {
+ /* C or lc can't have `a' flag, only `m' flag. */
+ done = EOF;
+ goto errout;
+ }
else
{
*strptr = (char *) wstr;
@@ -992,7 +1031,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
if (newstr == NULL)
{
if (flags & POSIX_MALLOC)
- goto reteof;
+ {
+ done = EOF;
+ goto errout;
+ }
/* We lose. Oh well. Terminate the
string and stop converting,
so at least we don't skip any input. */
@@ -1042,7 +1084,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
if (str == NULL)
{
if (flags & POSIX_MALLOC)
- goto reteof;
+ {
+ done = EOF;
+ goto errout;
+ }
/* We lose. Oh well. Terminate the
string and stop converting,
so at least we don't skip any input. */
@@ -1088,7 +1133,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
if (newstr == NULL)
{
if (flags & POSIX_MALLOC)
- goto reteof;
+ {
+ done = EOF;
+ goto errout;
+ }
/* We lose. Oh well. Terminate the string
and stop converting, so at least we don't
skip any input. */
@@ -1170,7 +1218,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
if (wstr == NULL)
{
if (flags & POSIX_MALLOC)
- goto reteof;
+ {
+ done = EOF;
+ goto errout;
+ }
/* We lose. Oh well. Terminate the string
and stop converting, so at least we don't
skip any input. */
@@ -1242,7 +1293,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
if (wstr == NULL)
{
if (flags & POSIX_MALLOC)
- goto reteof;
+ {
+ done = EOF;
+ goto errout;
+ }
/* We lose. Oh well. Terminate the
string and stop converting, so at
least we don't skip any input. */
@@ -2433,7 +2487,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
if (wstr == NULL)
{
if (flags & POSIX_MALLOC)
- goto reteof;
+ {
+ done = EOF;
+ goto errout;
+ }
/* We lose. Oh well. Terminate the string
and stop converting, so at least we don't
skip any input. */
@@ -2515,7 +2572,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
if (wstr == NULL)
{
if (flags & POSIX_MALLOC)
- goto reteof;
+ {
+ done = EOF;
+ goto errout;
+ }
/* We lose. Oh well. Terminate the
string and stop converting,
so at least we don't skip any input. */
@@ -2657,7 +2717,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
if (newstr == NULL)
{
if (flags & POSIX_MALLOC)
- goto reteof;
+ {
+ done = EOF;
+ goto errout;
+ }
/* We lose. Oh well. Terminate the string
and stop converting, so at least we don't
skip any input. */
@@ -2722,7 +2785,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
goto allocagain;
}
if (flags & POSIX_MALLOC)
- goto reteof;
+ {
+ done = EOF;
+ goto errout;
+ }
/* We lose. Oh well. Terminate the
string and stop converting,
so at least we don't skip any input. */
@@ -2765,7 +2831,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
if (newstr == NULL)
{
if (flags & POSIX_MALLOC)
- goto reteof;
+ {
+ done = EOF;
+ goto errout;
+ }
/* We lose. Oh well. Terminate the string
and stop converting, so at least we don't
skip any input. */
@@ -2828,12 +2897,14 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
/* Unlock stream. */
UNLOCK_STREAM (s);
+ if (use_malloc)
+ free (wp);
+
if (errp != NULL)
*errp |= errval;
- if (done == EOF)
+ if (__builtin_expect (done == EOF, 0))
{
- reteof:
if (__builtin_expect (ptrs_to_free != NULL, 0))
{
struct ptrs_to_free *p = ptrs_to_free;
@@ -2848,7 +2919,6 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
ptrs_to_free = p;
}
}
- return EOF;
}
else if (__builtin_expect (strptr != NULL, 0))
{