diff options
author | Florian Weimer <fweimer@redhat.com> | 2016-09-02 15:59:34 +0200 |
---|---|---|
committer | Florian Weimer <fweimer@redhat.com> | 2016-09-02 15:59:34 +0200 |
commit | 9dd87afbf1a2f7991a733609bbda6f26cadaa6ce (patch) | |
tree | 92f2635fe04cf52d11e3eaf91dab849c7ef1bdba /stdio-common | |
parent | 326e288b1e43832c138e5eb4521157d8aacef5b7 (diff) | |
download | glibc-9dd87afbf1a2f7991a733609bbda6f26cadaa6ce.tar.gz glibc-9dd87afbf1a2f7991a733609bbda6f26cadaa6ce.tar.xz glibc-9dd87afbf1a2f7991a733609bbda6f26cadaa6ce.zip |
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.
Diffstat (limited to 'stdio-common')
-rw-r--r-- | stdio-common/vfscanf.c | 24 |
1 files changed, 12 insertions, 12 deletions
diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c index 8cd59557a6..fe3677ba10 100644 --- a/stdio-common/vfscanf.c +++ b/stdio-common/vfscanf.c @@ -757,7 +757,7 @@ _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) + && *strptr + strsize - str <= MB_LEN_MAX) { /* We have to enlarge the buffer if the `m' flag 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. */ newstr = (char *) realloc (*strptr, - strleng + MB_CUR_MAX); + strleng + MB_LEN_MAX); if (newstr == NULL) { /* 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; str = newstr + strleng; - strsize = strleng + MB_CUR_MAX; + strsize = strleng + MB_LEN_MAX; } } else @@ -1048,7 +1048,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, size_t n; 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' 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 effort. */ newstr = (char *) realloc (*strptr, - strleng + MB_CUR_MAX); + strleng + MB_LEN_MAX); if (newstr == NULL) { if (flags & POSIX_MALLOC) @@ -1081,7 +1081,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, { *strptr = newstr; str = newstr + strleng; - strsize = strleng + MB_CUR_MAX; + strsize = strleng + MB_LEN_MAX; } } 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)) encode_error (); - assert (n <= MB_CUR_MAX); + assert (n <= MB_LEN_MAX); str += n; } #else @@ -2675,7 +2675,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, /* Possibly correct character, just not enough input. */ ++cnt; - assert (cnt < MB_CUR_MAX); + assert (cnt < MB_LEN_MAX); continue; } cnt = 0; @@ -2827,7 +2827,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, if (!(flags & SUPPRESS)) { if ((flags & MALLOC) - && str + MB_CUR_MAX >= *strptr + strsize) + && *strptr + strsize - str <= MB_LEN_MAX) { /* Enlarge the buffer. */ 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 effort. */ newstr = (char *) realloc (*strptr, - strleng + MB_CUR_MAX); + strleng + MB_LEN_MAX); if (newstr == NULL) { if (flags & POSIX_MALLOC) @@ -2859,7 +2859,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, { *strptr = newstr; str = newstr + strleng; - strsize = strleng + MB_CUR_MAX; + strsize = strleng + MB_LEN_MAX; } } 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)) encode_error (); - assert (n <= MB_CUR_MAX); + assert (n <= MB_LEN_MAX); str += n; } while (--width > 0 && inchar () != WEOF); |