[glibc] stdio-common: Use reallocarray for wide strings in vfscanf (bug 34531)
Florian Weimer via Glibc-cvs <[email protected]>
| Newsgroups | gmane.comp.lib.glibc.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=b2d944913a6454ca3d30f4c5b57fa8130cc090ce commit b2d944913a6454ca3d30f4c5b57fa8130cc090ce Author: Florian Weimer <[email protected]> Date: Thu Aug 20 09:20:55 2026 +0200 stdio-common: Use reallocarray for wide strings in vfscanf (bug 34531) This avoids theoretical integer overflow issues on 32-bit architectures. The overflow is not reachable since glibc 2.30 because doubling reaches a size larger than PTRDIFF_MAX, at which point realloc fails due to commit 9bf8e29ca136094f73f6 ("malloc: make malloc fail with requests larger than PTRDIFF_MAX (BZ#23741)"). The non-doubling path is used instead. Eventually, the size increments also pass PTRDIFF_MAX, so the fallback realloc fails, too. This means that in current glibc, there is no crash. Reviewed-by: Collin Funk <[email protected]> Diff: --- stdio-common/vfscanf-internal.c | 77 +++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 38 deletions(-) diff --git a/stdio-common/vfscanf-internal.c b/stdio-common/vfscanf-internal.c index 5f548f709f..e2e08c0eab 100644 --- a/stdio-common/vfscanf-internal.c +++ b/stdio-common/vfscanf-internal.c @@ -944,14 +944,15 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr, size_t newsize = strsize + (strsize >= width ? width : strsize); /* Enlarge the buffer. */ - wstr = (wchar_t *) realloc (*strptr, - newsize * sizeof (wchar_t)); + wstr = (wchar_t *) + __libc_reallocarray (*strptr, newsize, + sizeof (wchar_t)); if (wstr == NULL) { /* Can't allocate that much. Last-ditch effort. */ - wstr = (wchar_t *) realloc (*strptr, - (strsize + 1) - * sizeof (wchar_t)); + wstr = (wchar_t *) + __libc_reallocarray (*strptr, strsize + 1, + sizeof (wchar_t)); if (wstr == NULL) { /* C or lc can't have `a' flag, only `m' @@ -999,14 +1000,14 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr, size_t newsize = strsize + (strsize >= width ? width : strsize); /* Enlarge the buffer. */ - wstr = (wchar_t *) realloc (*strptr, - newsize * sizeof (wchar_t)); + wstr = (wchar_t *) __libc_reallocarray (*strptr, newsize, + sizeof (wchar_t)); if (wstr == NULL) { /* Can't allocate that much. Last-ditch effort. */ - wstr = (wchar_t *) realloc (*strptr, - ((strsize + 1) - * sizeof (wchar_t))); + wstr = (wchar_t *) + __libc_reallocarray (*strptr, strsize + 1, + sizeof (wchar_t)); if (wstr == NULL) { /* C or lc can't have `a' flag, only `m' flag. */ @@ -1066,10 +1067,9 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr, { if ((flags & MALLOC) && wstr - (wchar_t *) *strptr != strsize) { - wchar_t *cp = (wchar_t *) realloc (*strptr, - ((wstr - - (wchar_t *) *strptr) - * sizeof (wchar_t))); + wchar_t *cp = (wchar_t *) + __libc_reallocarray (*strptr, wstr - (wchar_t *) *strptr, + sizeof (wchar_t)); if (cp != NULL) *strptr = (char *) cp; } @@ -1305,15 +1305,15 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr, /* Enlarge the buffer. */ size_t newsize = grow_to_fit (strsize, width); - wstr = (wchar_t *) realloc ( - *strptr, newsize * sizeof (wchar_t)); + wstr = (wchar_t *) __libc_reallocarray + (*strptr, newsize, sizeof (wchar_t)); if (wstr == NULL) { /* Can't allocate that much. Last-ditch effort. */ - wstr = (wchar_t *) realloc (*strptr, - (strsize + 1) - * sizeof (wchar_t)); + wstr = (wchar_t *) + __libc_reallocarray (*strptr, strsize + 1, + sizeof (wchar_t)); if (wstr == NULL) { if (flags & POSIX_MALLOC) @@ -1382,14 +1382,15 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr, /* Enlarge the buffer. */ size_t newsize = grow_to_fit (strsize, width); - wstr = (wchar_t *) realloc (*strptr, - newsize * sizeof (wchar_t)); + wstr = (wchar_t *) + __libc_reallocarray (*strptr, newsize, + sizeof (wchar_t)); if (wstr == NULL) { /* Can't allocate that much. Last-ditch effort. */ - wstr = (wchar_t *) realloc (*strptr, - ((strsize + 1) - * sizeof (wchar_t))); + wstr = (wchar_t *) + __libc_reallocarray (*strptr, strsize + 1, + sizeof (wchar_t)); if (wstr == NULL) { if (flags & POSIX_MALLOC) @@ -1430,10 +1431,9 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr, if ((flags & MALLOC) && wstr - (wchar_t *) *strptr != strsize) { - wchar_t *cp = (wchar_t *) realloc (*strptr, - ((wstr - - (wchar_t *) *strptr) - * sizeof (wchar_t))); + wchar_t *cp = (wchar_t *) + __libc_reallocarray (*strptr, wstr - (wchar_t *) *strptr, + sizeof (wchar_t)); if (cp != NULL) *strptr = (char *) cp; } @@ -2800,15 +2800,15 @@ digits_extended_fail: /* Enlarge the buffer. */ size_t newsize = grow_to_fit (strsize, width); - wstr = (wchar_t *) realloc ( - *strptr, newsize * sizeof (wchar_t)); + wstr = (wchar_t *) __libc_reallocarray + (*strptr, newsize, sizeof (wchar_t)); if (wstr == NULL) { /* Can't allocate that much. Last-ditch effort. */ wstr = (wchar_t *) - realloc (*strptr, (strsize + 1) - * sizeof (wchar_t)); + __libc_reallocarray (*strptr, strsize + 1, + sizeof (wchar_t)); if (wstr == NULL) { if (flags & POSIX_MALLOC) @@ -2886,15 +2886,15 @@ digits_extended_fail: /* Enlarge the buffer. */ size_t newsize = grow_to_fit (strsize, width); - wstr = (wchar_t *) realloc ( - *strptr, newsize * sizeof (wchar_t)); + wstr = (wchar_t *) __libc_reallocarray + (*strptr, newsize, sizeof (wchar_t)); if (wstr == NULL) { /* Can't allocate that much. Last-ditch effort. */ wstr = (wchar_t *) - realloc (*strptr, ((strsize + 1) - * sizeof (wchar_t))); + __libc_reallocarray (*strptr, strsize + 1, + sizeof (wchar_t)); if (wstr == NULL) { if (flags & POSIX_MALLOC) @@ -2949,8 +2949,9 @@ digits_extended_fail: && wstr - (wchar_t *) *strptr != strsize) { wchar_t *cp = (wchar_t *) - realloc (*strptr, ((wstr - (wchar_t *) *strptr) - * sizeof (wchar_t))); + __libc_reallocarray (*strptr, + wstr - (wchar_t *) *strptr, + sizeof (wchar_t)); if (cp != NULL) *strptr = (char *) cp; }