Fix boundary conditions in scanf
authorUlrich Drepper <drepper@gmail.com>
Sat, 10 Sep 2011 01:26:05 +0000 (21:26 -0400)
committerUlrich Drepper <drepper@gmail.com>
Sat, 10 Sep 2011 01:26:05 +0000 (21:26 -0400)
Allocate large buffers with realloc.  When returning error make sure
the stream is unlocked.

ChangeLog
NEWS
stdio-common/vfscanf.c

index 01d8905..7cc7ab0 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2011-09-09  Ulrich Drepper  <drepper@gmail.com>
 
+       [BZ #13138]
+       * stdio-common/vfscanf.c (ADDW): Allocate large memory block with
+       realloc.
+       (_IO_vfscanf_internal): Remove reteof.  Use errout after setting done.
+       Free memory block if necessary.
+
        [BZ #12847]
        * libio/genops.c (INTDEF): For string streams the _lock pointer can
        be NULL.  Don't lock in this case.
diff --git a/NEWS b/NEWS
index 9fa55ca..f431c9d 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -10,7 +10,7 @@ Version 2.15
 * The following bugs are resolved with this release:
 
   9696, 12403, 12847, 12868, 12852, 12874, 12885, 12907, 12922, 12935,
-  13007, 13021, 13068, 13092, 13114, 13118, 13123, 13134, 13150
+  13007, 13021, 13068, 13092, 13114, 13118, 13123, 13134, 13138, 13150
 
 * New program pldd to list loaded object of a process
   Implemented by Ulrich Drepper.
index 9d312d5..0e71deb 100644 (file)
@@ -265,16 +265,39 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
   CHAR_T *wp = NULL;           /* Workspace.  */
   size_t wpmax = 0;            /* Maximal size of workspace.  */
   size_t wpsize;               /* Currently used bytes in workspace.  */
+  bool use_malloc = false;
 #define ADDW(Ch)                                                           \
   do                                                                       \
     {                                                                      \
-      if (wpsize == wpmax)                                                 \
+      if (__builtin_expect (wpsize == wpmax, 0))                           \
        {                                                                   \
          CHAR_T *old = wp;                                                 \
-         wpmax = (UCHAR_MAX + 1 > 2 * wpmax ? UCHAR_MAX + 1 : 2 * wpmax);  \
-         wp = (CHAR_T *) alloca (wpmax * sizeof (CHAR_T));                 \
-         if (old != NULL)                                                  \
-           MEMCPY (wp, old, wpsize);                                       \
+         size_t newsize = (UCHAR_MAX + 1 > 2 * wpmax                       \
+                           ? UCHAR_MAX + 1 : 2 * wpmax);                   \
+         if (use_malloc || __libc_use_alloca (newsize))                    \
+           {                                                               \
+             wp = realloc (use_malloc ? wp : NULL, newsize);               \
+             if (wp == NULL)                                               \
+               {                                                           \
+                 if (use_malloc)                                           \
+                   free (old);                                             \
+                 done = EOF;                                               \
+                 goto errout;                                              \
+               }                                                           \
+             if (! use_malloc)                                             \
+               MEMCPY (wp, old, wpsize);                                   \
+             wpmax = newsize;                                              \
+             use_malloc = true;                                            \
+           }                                                               \
+         else                                                              \
+           {                                                               \
+             size_t s = wpmax * sizeof (CHAR_T);                           \
+             wp = (CHAR_T *) extend_alloca (wp, s,                         \
+                                            newsize * sizeof (CHAR_T));    \
+             wpmax = s / sizeof (CHAR_T);                                  \
+             if (old != NULL)                                              \
+               MEMCPY (wp, old, wpsize);                                   \
+           }                                                               \
        }                                                                   \
       wp[wpsize++] = (Ch);                                                 \
     }                                                                      \
@@ -670,7 +693,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
                      if (Str != NULL)                                        \
                        add_ptr_to_free (strptr);                             \
                      else if (flags & POSIX_MALLOC)                          \
-                       goto reteof;                                          \
+                       {                                                     \
+                         done = EOF;                                         \
+                         goto errout;                                        \
+                       }                                                     \
                    }                                                         \
                  else                                                        \
                    Str = ARG (Type *);                                       \
@@ -711,8 +737,11 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
                          newstr = (char *) realloc (*strptr,
                                                     strleng + MB_CUR_MAX);
                          if (newstr == NULL)
-                           /* c can't have `a' flag, only `m'.  */
-                           goto reteof;
+                           {
+                             /* c can't have `a' flag, only `m'.  */
+                             done = EOF;
+                             goto errout;
+                           }
                          else
                            {
                              *strptr = newstr;
@@ -758,8 +787,11 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
                                 effort.  */
                              str = (char *) realloc (*strptr, strsize + 1);
                              if (str == NULL)
-                               /* c can't have `a' flag, only `m'.  */
-                               goto reteof;
+                               {
+                                 /* c can't have `a' flag, only `m'.  */
+                                 done = EOF;
+                                 goto errout;
+                               }
                              else
                                {
                                  *strptr = (char *) str;
@@ -828,8 +860,12 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
                                                      (strsize + 1)
                                                      * sizeof (wchar_t));
                          if (wstr == NULL)
-                           /* C or lc can't have `a' flag, only `m' flag.  */
-                           goto reteof;
+                           {
+                             /* C or lc can't have `a' flag, only `m'
+                                flag.  */
+                             done = EOF;
+                             goto errout;
+                           }
                          else
                            {
                              *strptr = (char *) wstr;
@@ -879,8 +915,11 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
                                                    ((strsize + 1)
                                                     * sizeof (wchar_t)));
                        if (wstr == NULL)
-                         /* C or lc can't have `a' flag, only `m' flag.  */
-                         goto reteof;
+                         {
+                           /* C or lc can't have `a' flag, only `m' flag.  */
+                           done = EOF;
+                           goto errout;
+                         }
                        else
                          {
                            *strptr = (char *) wstr;
@@ -992,7 +1031,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
                            if (newstr == NULL)
                              {
                                if (flags & POSIX_MALLOC)
-                                 goto reteof;
+                                 {
+                                   done = EOF;
+                                   goto errout;
+                                 }
                                /* We lose.  Oh well.  Terminate the
                                   string and stop converting,
                                   so at least we don't skip any input.  */
@@ -1042,7 +1084,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
                              if (str == NULL)
                                {
                                  if (flags & POSIX_MALLOC)
-                                   goto reteof;
+                                   {
+                                     done = EOF;
+                                     goto errout;
+                                   }
                                  /* We lose.  Oh well.  Terminate the
                                     string and stop converting,
                                     so at least we don't skip any input.  */
@@ -1088,7 +1133,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
                      if (newstr == NULL)
                        {
                          if (flags & POSIX_MALLOC)
-                           goto reteof;
+                           {
+                             done = EOF;
+                             goto errout;
+                           }
                          /* We lose.  Oh well.  Terminate the string
                             and stop converting, so at least we don't
                             skip any input.  */
@@ -1170,7 +1218,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
                            if (wstr == NULL)
                              {
                                if (flags & POSIX_MALLOC)
-                                 goto reteof;
+                                 {
+                                   done = EOF;
+                                   goto errout;
+                                 }
                                /* We lose.  Oh well.  Terminate the string
                                   and stop converting, so at least we don't
                                   skip any input.  */
@@ -1242,7 +1293,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
                          if (wstr == NULL)
                            {
                              if (flags & POSIX_MALLOC)
-                               goto reteof;
+                               {
+                                 done = EOF;
+                                 goto errout;
+                               }
                              /* We lose.  Oh well.  Terminate the
                                 string and stop converting, so at
                                 least we don't skip any input.  */
@@ -2433,7 +2487,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
                              if (wstr == NULL)
                                {
                                  if (flags & POSIX_MALLOC)
-                                   goto reteof;
+                                   {
+                                     done = EOF;
+                                     goto errout;
+                                   }
                                  /* We lose.  Oh well.  Terminate the string
                                     and stop converting, so at least we don't
                                     skip any input.  */
@@ -2515,7 +2572,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
                              if (wstr == NULL)
                                {
                                  if (flags & POSIX_MALLOC)
-                                   goto reteof;
+                                   {
+                                     done = EOF;
+                                     goto errout;
+                                   }
                                  /* We lose.  Oh well.  Terminate the
                                     string and stop converting,
                                     so at least we don't skip any input.  */
@@ -2657,7 +2717,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
                              if (newstr == NULL)
                                {
                                  if (flags & POSIX_MALLOC)
-                                   goto reteof;
+                                   {
+                                     done = EOF;
+                                     goto errout;
+                                   }
                                  /* We lose.  Oh well.  Terminate the string
                                     and stop converting, so at least we don't
                                     skip any input.  */
@@ -2722,7 +2785,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
                                  goto allocagain;
                                }
                              if (flags & POSIX_MALLOC)
-                               goto reteof;
+                               {
+                                 done = EOF;
+                                 goto errout;
+                               }
                              /* We lose.  Oh well.  Terminate the
                                 string and stop converting,
                                 so at least we don't skip any input.  */
@@ -2765,7 +2831,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
                      if (newstr == NULL)
                        {
                          if (flags & POSIX_MALLOC)
-                           goto reteof;
+                           {
+                             done = EOF;
+                             goto errout;
+                           }
                          /* We lose.  Oh well.  Terminate the string
                             and stop converting, so at least we don't
                             skip any input.  */
@@ -2828,12 +2897,14 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
   /* Unlock stream.  */
   UNLOCK_STREAM (s);
 
+  if (use_malloc)
+    free (wp);
+
   if (errp != NULL)
     *errp |= errval;
 
-  if (done == EOF)
+  if (__builtin_expect (done == EOF, 0))
     {
-  reteof:
       if (__builtin_expect (ptrs_to_free != NULL, 0))
        {
          struct ptrs_to_free *p = ptrs_to_free;
@@ -2848,7 +2919,6 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
              ptrs_to_free = p;
            }
        }
-      return EOF;
     }
   else if (__builtin_expect (strptr != NULL, 0))
     {