[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;
 		    }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.