vfscanf: Avoid multiple reads of multi-byte character width
This avoids a race condition if the process-global locale is changed while vfscanf is running. MB_LEN_MAX is always larger than MB_CUR_MAX, so we might realloc earlier than necessary (but even MB_CUR_MAX could be larger than the minimum required space). The existing length was a bit questionable because str + MB_LEN_MAX might point past the end of the buffer.
This commit is contained in:
parent
326e288b1e
commit
9dd87afbf1
|
@ -1,3 +1,9 @@
|
||||||
|
2016-09-02 Florian Weimer <fweimer@redhat.com>
|
||||||
|
|
||||||
|
* stdio-common/vfscanf.c (_IO_vfwscanf): Use MB_LEN_MAX instead of
|
||||||
|
MB_CUR_MAX to avoid race condition. Avoid pointer arithmetic
|
||||||
|
outside of allocated array.
|
||||||
|
|
||||||
2016-09-02 Florian Weimer <fweimer@redhat.com>
|
2016-09-02 Florian Weimer <fweimer@redhat.com>
|
||||||
|
|
||||||
* stdio-common/vfprintf.c (process_string_arg): Use MB_LEN_MAX
|
* stdio-common/vfprintf.c (process_string_arg): Use MB_LEN_MAX
|
||||||
|
|
|
@ -757,7 +757,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
||||||
size_t n;
|
size_t n;
|
||||||
|
|
||||||
if (!(flags & SUPPRESS) && (flags & POSIX_MALLOC)
|
if (!(flags & SUPPRESS) && (flags & POSIX_MALLOC)
|
||||||
&& str + MB_CUR_MAX >= *strptr + strsize)
|
&& *strptr + strsize - str <= MB_LEN_MAX)
|
||||||
{
|
{
|
||||||
/* We have to enlarge the buffer if the `m' flag
|
/* We have to enlarge the buffer if the `m' flag
|
||||||
was given. */
|
was given. */
|
||||||
|
@ -769,7 +769,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
||||||
{
|
{
|
||||||
/* Can't allocate that much. Last-ditch effort. */
|
/* Can't allocate that much. Last-ditch effort. */
|
||||||
newstr = (char *) realloc (*strptr,
|
newstr = (char *) realloc (*strptr,
|
||||||
strleng + MB_CUR_MAX);
|
strleng + MB_LEN_MAX);
|
||||||
if (newstr == NULL)
|
if (newstr == NULL)
|
||||||
{
|
{
|
||||||
/* c can't have `a' flag, only `m'. */
|
/* c can't have `a' flag, only `m'. */
|
||||||
|
@ -780,7 +780,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
||||||
{
|
{
|
||||||
*strptr = newstr;
|
*strptr = newstr;
|
||||||
str = newstr + strleng;
|
str = newstr + strleng;
|
||||||
strsize = strleng + MB_CUR_MAX;
|
strsize = strleng + MB_LEN_MAX;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1048,7 +1048,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
||||||
size_t n;
|
size_t n;
|
||||||
|
|
||||||
if (!(flags & SUPPRESS) && (flags & MALLOC)
|
if (!(flags & SUPPRESS) && (flags & MALLOC)
|
||||||
&& str + MB_CUR_MAX >= *strptr + strsize)
|
&& *strptr + strsize - str <= MB_LEN_MAX)
|
||||||
{
|
{
|
||||||
/* We have to enlarge the buffer if the `a' or `m'
|
/* We have to enlarge the buffer if the `a' or `m'
|
||||||
flag was given. */
|
flag was given. */
|
||||||
|
@ -1061,7 +1061,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
||||||
/* Can't allocate that much. Last-ditch
|
/* Can't allocate that much. Last-ditch
|
||||||
effort. */
|
effort. */
|
||||||
newstr = (char *) realloc (*strptr,
|
newstr = (char *) realloc (*strptr,
|
||||||
strleng + MB_CUR_MAX);
|
strleng + MB_LEN_MAX);
|
||||||
if (newstr == NULL)
|
if (newstr == NULL)
|
||||||
{
|
{
|
||||||
if (flags & POSIX_MALLOC)
|
if (flags & POSIX_MALLOC)
|
||||||
|
@ -1081,7 +1081,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
||||||
{
|
{
|
||||||
*strptr = newstr;
|
*strptr = newstr;
|
||||||
str = newstr + strleng;
|
str = newstr + strleng;
|
||||||
strsize = strleng + MB_CUR_MAX;
|
strsize = strleng + MB_LEN_MAX;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1097,7 +1097,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
||||||
if (__glibc_unlikely (n == (size_t) -1))
|
if (__glibc_unlikely (n == (size_t) -1))
|
||||||
encode_error ();
|
encode_error ();
|
||||||
|
|
||||||
assert (n <= MB_CUR_MAX);
|
assert (n <= MB_LEN_MAX);
|
||||||
str += n;
|
str += n;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@ -2675,7 +2675,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
||||||
/* Possibly correct character, just not enough
|
/* Possibly correct character, just not enough
|
||||||
input. */
|
input. */
|
||||||
++cnt;
|
++cnt;
|
||||||
assert (cnt < MB_CUR_MAX);
|
assert (cnt < MB_LEN_MAX);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
cnt = 0;
|
cnt = 0;
|
||||||
|
@ -2827,7 +2827,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
||||||
if (!(flags & SUPPRESS))
|
if (!(flags & SUPPRESS))
|
||||||
{
|
{
|
||||||
if ((flags & MALLOC)
|
if ((flags & MALLOC)
|
||||||
&& str + MB_CUR_MAX >= *strptr + strsize)
|
&& *strptr + strsize - str <= MB_LEN_MAX)
|
||||||
{
|
{
|
||||||
/* Enlarge the buffer. */
|
/* Enlarge the buffer. */
|
||||||
size_t strleng = str - *strptr;
|
size_t strleng = str - *strptr;
|
||||||
|
@ -2839,7 +2839,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
||||||
/* Can't allocate that much. Last-ditch
|
/* Can't allocate that much. Last-ditch
|
||||||
effort. */
|
effort. */
|
||||||
newstr = (char *) realloc (*strptr,
|
newstr = (char *) realloc (*strptr,
|
||||||
strleng + MB_CUR_MAX);
|
strleng + MB_LEN_MAX);
|
||||||
if (newstr == NULL)
|
if (newstr == NULL)
|
||||||
{
|
{
|
||||||
if (flags & POSIX_MALLOC)
|
if (flags & POSIX_MALLOC)
|
||||||
|
@ -2859,7 +2859,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
||||||
{
|
{
|
||||||
*strptr = newstr;
|
*strptr = newstr;
|
||||||
str = newstr + strleng;
|
str = newstr + strleng;
|
||||||
strsize = strleng + MB_CUR_MAX;
|
strsize = strleng + MB_LEN_MAX;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -2875,7 +2875,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
|
||||||
if (__glibc_unlikely (n == (size_t) -1))
|
if (__glibc_unlikely (n == (size_t) -1))
|
||||||
encode_error ();
|
encode_error ();
|
||||||
|
|
||||||
assert (n <= MB_CUR_MAX);
|
assert (n <= MB_LEN_MAX);
|
||||||
str += n;
|
str += n;
|
||||||
}
|
}
|
||||||
while (--width > 0 && inchar () != WEOF);
|
while (--width > 0 && inchar () != WEOF);
|
||||||
|
|
Loading…
Reference in New Issue