Fix for heap overflow in wscanf (BZ 16618)

Message ID CALoOobPyDepfTFp=_y50iKHxAhKV8W+ZkUiV6e-2O=kgpT_08g@mail.gmail.com
State Superseded
Headers

Commit Message

Paul Pluzhnikov Feb. 2, 2015, 4:57 p.m. UTC
  On Mon, Feb 2, 2015 at 2:03 AM, Andreas Schwab <schwab@suse.de> wrote:
> Paul Pluzhnikov <ppluzhnikov@google.com> writes:

> You should set errno here.

Done.

Thanks,
  

Comments

Andreas Schwab Feb. 2, 2015, 6:45 p.m. UTC | #1
Paul Pluzhnikov <ppluzhnikov@google.com> writes:

> diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c
> index cd129a8..fb0a601 100644
> --- a/stdio-common/vfscanf.c
> +++ b/stdio-common/vfscanf.c
> @@ -274,14 +274,24 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
>  	  CHAR_T *old = wp;						    \
>  	  size_t newsize = (UCHAR_MAX + 1 > 2 * wpmax			    \
>  			    ? UCHAR_MAX + 1 : 2 * wpmax);		    \
> -	  if (use_malloc || !__libc_use_alloca (newsize))		    \
> +	  if (__glibc_unlikely (wpmax > SIZE_MAX / 2)			    \
> +	      || __glibc_unlikely (newsize > SIZE_MAX / sizeof (CHAR_T)))   \
>  	    {								    \
> -	      wp = realloc (use_malloc ? wp : NULL, newsize);		    \
> +	      if (use_malloc)						    \
> +	    	free (old);						    \
> +	      done = EOF;						    \
> +	      __set_errno (ENOMEM);					    \
> +	      goto errout;						    \
> +	    }								    \
> +	  if (use_malloc || !__libc_use_alloca (newsize * sizeof (CHAR_T))) \
> +	    {								    \
> +	      wp = realloc (use_malloc ? wp : NULL, newsize * sizeof (CHAR_T));	\
>  	      if (wp == NULL)						    \
>  		{							    \
>  		  if (use_malloc)					    \
>  		    free (old);						    \
>  		  done = EOF;						    \
> +		  __set_errno (ENOMEM);					    \

You already have a meaningful errno from the failed realloc.

Andreas.
  

Patch

diff --git a/NEWS b/NEWS
index c91b9fc..85b2948 100644
--- a/NEWS
+++ b/NEWS
@@ -10,15 +10,16 @@  Version 2.21
 * The following bugs are resolved with this release:
 
   6652, 10672, 12674, 12847, 12926, 13862, 14132, 14138, 14171, 14498,
-  15215, 15378, 15884, 16009, 16418, 16191, 16469, 16576, 16617, 16619,
-  16657, 16740, 16857, 17192, 17266, 17273, 17344, 17363, 17370, 17371,
-  17411, 17460, 17475, 17485, 17501, 17506, 17508, 17522, 17555, 17570,
-  17571, 17572, 17573, 17574, 17582, 17583, 17584, 17585, 17589, 17594,
-  17601, 17608, 17616, 17625, 17630, 17633, 17634, 17635, 17647, 17653,
-  17657, 17658, 17664, 17665, 17668, 17682, 17702, 17717, 17719, 17722,
-  17723, 17724, 17725, 17732, 17733, 17744, 17745, 17746, 17747, 17748,
-  17775, 17777, 17780, 17781, 17782, 17791, 17793, 17796, 17797, 17801,
-  17803, 17806, 17834, 17844, 17848, 17868, 17869, 17870, 17885, 17892.
+  15215, 15378, 15884, 16009, 16418, 16191, 16469, 16576, 16617, 16618,
+  16619, 16657, 16740, 16857, 17192, 17266, 17273, 17344, 17363, 17370,
+  17371, 17411, 17460, 17475, 17485, 17501, 17506, 17508, 17522, 17555,
+  17570, 17571, 17572, 17573, 17574, 17582, 17583, 17584, 17585, 17589,
+  17594, 17601, 17608, 17616, 17625, 17630, 17633, 17634, 17635, 17647,
+  17653, 17657, 17658, 17664, 17665, 17668, 17682, 17702, 17717, 17719,
+  17722, 17723, 17724, 17725, 17732, 17733, 17744, 17745, 17746, 17747,
+  17748, 17775, 17777, 17780, 17781, 17782, 17791, 17793, 17796, 17797,
+  17801, 17803, 17806, 17834, 17844, 17848, 17868, 17869, 17870, 17885,
+  17892.
 
 * A new semaphore algorithm has been implemented in generic C code for all
   machines. Previous custom assembly implementations of semaphore were
diff --git a/stdio-common/tst-sscanf.c b/stdio-common/tst-sscanf.c
index aece3f2..a12333c 100644
--- a/stdio-common/tst-sscanf.c
+++ b/stdio-common/tst-sscanf.c
@@ -233,5 +233,23 @@  main (void)
 	}
     }
 
+  /* BZ 16618 */
+  {
+#define SIZE 131072
+    CHAR *s = malloc ((SIZE + 1) * sizeof (*s));
+    if (s == NULL)
+      abort ();
+    for (size_t i = 0; i < SIZE; i++)
+      s[i] = L('0');
+    s[SIZE] = L('\0');
+    int i = 42;
+    if (SSCANF (s, L("%d"), &i) != 1)
+      result = 1;
+    if (i != 0)
+      result = 1;
+    free (s);
+#undef SIZE
+  }
+
   return result;
 }
diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c
index cd129a8..fb0a601 100644
--- a/stdio-common/vfscanf.c
+++ b/stdio-common/vfscanf.c
@@ -274,14 +274,24 @@  _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
 	  CHAR_T *old = wp;						    \
 	  size_t newsize = (UCHAR_MAX + 1 > 2 * wpmax			    \
 			    ? UCHAR_MAX + 1 : 2 * wpmax);		    \
-	  if (use_malloc || !__libc_use_alloca (newsize))		    \
+	  if (__glibc_unlikely (wpmax > SIZE_MAX / 2)			    \
+	      || __glibc_unlikely (newsize > SIZE_MAX / sizeof (CHAR_T)))   \
 	    {								    \
-	      wp = realloc (use_malloc ? wp : NULL, newsize);		    \
+	      if (use_malloc)						    \
+	    	free (old);						    \
+	      done = EOF;						    \
+	      __set_errno (ENOMEM);					    \
+	      goto errout;						    \
+	    }								    \
+	  if (use_malloc || !__libc_use_alloca (newsize * sizeof (CHAR_T))) \
+	    {								    \
+	      wp = realloc (use_malloc ? wp : NULL, newsize * sizeof (CHAR_T));	\
 	      if (wp == NULL)						    \
 		{							    \
 		  if (use_malloc)					    \
 		    free (old);						    \
 		  done = EOF;						    \
+		  __set_errno (ENOMEM);					    \
 		  goto errout;						    \
 		}							    \
 	      if (! use_malloc)						    \