[PATCH 1/2] stdio-common: Use reallocarray for wide strings in vfscanf

Florian Weimer <[email protected]>
Newsgroups gmane.comp.lib.glibc.alpha
Message-ID <c0875b265621beda69b08080e3a9ed1f80c32894.1786961109.git.fweimer@redhat.com>
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.
---
 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;
 		    }

base-commit: 6144ef08960e1db191db2054abef02d361042018
-- 
2.55.0
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.