Fix for heap overflow in wscanf (BZ 16618)
Commit Message
On 02/02/2015 08:57 AM, Paul Pluzhnikov wrote:
> + if (__glibc_unlikely (wpmax > SIZE_MAX / 2) \
> + || __glibc_unlikely (newsize > SIZE_MAX / sizeof (CHAR_T))) \
"if (__glibc_unlikely (wpmax > SIZE_MAX / sizeof (CHAR_T) / 2)" is
shorter and faster. Also, the proposed patch duplicates the use_malloc
/ free / done code, which is messy. And there's an existing use of
'use_malloc' which makes sense only if the code ignores overflow, which
it no longer does.
So, how about the attached (untested) patch to vfscanf.c instead? It's
simpler. It does rely on realloc (wp, SIZE_MAX) returning NULL, but
that's safe in glibc.
@@ -272,9 +272,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
if (__glibc_unlikely (wpsize == wpmax)) \
{ \
CHAR_T *old = wp; \
- size_t newsize = (UCHAR_MAX + 1 > 2 * wpmax \
- ? UCHAR_MAX + 1 : 2 * wpmax); \
- if (use_malloc || !__libc_use_alloca (newsize)) \
+ bool fits = __glibc_likely (wpmax <= SIZE_MAX / sizeof (CHAR_T) / 2); \
+ size_t wpneed = MAX (UCHAR_MAX + 1, 2 * wpmax); \
+ size_t newsize = fits ? wpneed * sizeof (CHAR_T) : SIZE_MAX; \
+ if (!__libc_use_alloca (newsize)) \
{ \
wp = realloc (use_malloc ? wp : NULL, newsize); \
if (wp == NULL) \
@@ -286,14 +287,13 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
} \
if (! use_malloc) \
MEMCPY (wp, old, wpsize); \
- wpmax = newsize; \
+ wpmax = wpneed; \
use_malloc = true; \
} \
else \
{ \
size_t s = wpmax * sizeof (CHAR_T); \
- wp = (CHAR_T *) extend_alloca (wp, s, \
- newsize * sizeof (CHAR_T)); \
+ wp = (CHAR_T *) extend_alloca (wp, s, newsize); \
wpmax = s / sizeof (CHAR_T); \
if (old != NULL) \
MEMCPY (wp, old, wpsize); \