public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] vfscanf: Avoid multiple reads of multi-byte character width
@ 2016-09-02 13:19 Florian Weimer
  2016-09-02 13:56 ` Andreas Schwab
  0 siblings, 1 reply; 3+ messages in thread
From: Florian Weimer @ 2016-09-02 13:19 UTC (permalink / raw)
  To: libc-alpha

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.

2016-09-02  Florian Weimer  <fweimer@redhat.com>

	* stdio-common/vfscanf.c (_IO_vfwscanf): Use MB_LEN_MAX instead of
	MB_CUR_MAX to avoid race condition.  Avoid pointer arithmetic
	outside of allocated array.

diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c
index 8cd5955..2b7093e 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)
+		      && MB_LEN_MAX >= *strptr + strsize - str)
 		    {
 		      /* 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)
+			&& MB_LEN_MAX >= *strptr + strsize - str)
 		      {
 			/* 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)
+			  && MB_LEN_MAX >= *strptr + strsize - str)
 			{
 			  /* 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);

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] vfscanf: Avoid multiple reads of multi-byte character width
  2016-09-02 13:19 [PATCH] vfscanf: Avoid multiple reads of multi-byte character width Florian Weimer
@ 2016-09-02 13:56 ` Andreas Schwab
  2016-09-02 14:15   ` Florian Weimer
  0 siblings, 1 reply; 3+ messages in thread
From: Andreas Schwab @ 2016-09-02 13:56 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha

On Sep 02 2016, fweimer@redhat.com (Florian Weimer) wrote:

> diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c
> index 8cd5955..2b7093e 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)
> +		      && MB_LEN_MAX >= *strptr + strsize - str)

Please reorder the condition to put the constant part on the right hand
side (also below).

Ok with that change.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] vfscanf: Avoid multiple reads of multi-byte character width
  2016-09-02 13:56 ` Andreas Schwab
@ 2016-09-02 14:15   ` Florian Weimer
  0 siblings, 0 replies; 3+ messages in thread
From: Florian Weimer @ 2016-09-02 14:15 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: libc-alpha

On 09/02/2016 03:56 PM, Andreas Schwab wrote:
> On Sep 02 2016, fweimer@redhat.com (Florian Weimer) wrote:
>
>> diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c
>> index 8cd5955..2b7093e 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)
>> +		      && MB_LEN_MAX >= *strptr + strsize - str)
>
> Please reorder the condition to put the constant part on the right hand
> side (also below).

Thanks, committed with that change.

Florian

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2016-09-02 14:15 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-02 13:19 [PATCH] vfscanf: Avoid multiple reads of multi-byte character width Florian Weimer
2016-09-02 13:56 ` Andreas Schwab
2016-09-02 14:15   ` Florian Weimer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).