Fix boundary conditions in scanf

Allocate large buffers with realloc.  When returning error make sure
the stream is unlocked.
This commit is contained in:
Ulrich Drepper 2011-09-09 21:26:05 -04:00
parent e4899e7b9a
commit 3f8cc204fd
3 changed files with 104 additions and 28 deletions

View File

@ -1,5 +1,11 @@
2011-09-09 Ulrich Drepper <drepper@gmail.com>
[BZ #13138]
* stdio-common/vfscanf.c (ADDW): Allocate large memory block with
realloc.
(_IO_vfscanf_internal): Remove reteof. Use errout after setting done.
Free memory block if necessary.
[BZ #12847]
* libio/genops.c (INTDEF): For string streams the _lock pointer can
be NULL. Don't lock in this case.

2
NEWS
View File

@ -10,7 +10,7 @@ Version 2.15
* The following bugs are resolved with this release:
9696, 12403, 12847, 12868, 12852, 12874, 12885, 12907, 12922, 12935,
13007, 13021, 13068, 13092, 13114, 13118, 13123, 13134, 13150
13007, 13021, 13068, 13092, 13114, 13118, 13123, 13134, 13138, 13150
* New program pldd to list loaded object of a process
Implemented by Ulrich Drepper.

View File

@ -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))
{