bug-gnu-utils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Bison 1.30e parser can dump core if malloc or alloca fails, etc.


From: Paul Eggert
Subject: Bison 1.30e parser can dump core if malloc or alloca fails, etc.
Date: Wed, 28 Nov 2001 12:39:51 -0800 (PST)

Here is a fix for some more memory allocation problems with the parser
generated by Bison 1.30e.  Sorry, I haven't had time to tease out
these into separate patches, but if you don't like part of this patch
please let me know and I'll reformulate it.

Here are the problems:

* If malloc fails, the Bison 1.30e parser dereferences the null
  pointer and this can cause a core dump.  The parser should instead
  report a stack overflow.

* On non-GCC hosts where size_t is wider than unsigned int
  (e.g. 64-bit Solaris 8 cc), Bison mishandles reallocation of stacks
  that are larger than UINT_MAX bytes.

  (I realize that there are other problems with Bison on many 64-bit
  hosts, but I haven't have time to address the others.)

* Bison calls malloc 3 times each time it grows the stack.  It's
  typically faster and less fragmentation-prone to call malloc just
  once.

2001-11-28  Paul Eggert  <address@hidden>

        * src/bison.simple (YYSTACK_REALLOC): Remove.
        (YYSTACK_ALLOC): Resurrect this macro, with its old meaning.
        (YYSTACK_FREE, YYSTACK_GAP_MAX, YYSTACK_BYTES, YYSTACK_RELOCATE):
        New macros.
        (union yyalloc): New type.
        (__yy_memcpy): Last arg is size_t, not unsigned int, to remove
        an arbitrary restriction on hosts where size_t is wider than int.

        (yyparse): Don't dump core if alloca or malloc fails; instead, report
        a parser stack overflow.  Allocate just one block of memory for all
        three stacks, instead of allocating three blocks; this typically is
        faster and reduces fragmentation.

===================================================================
RCS file: src/bison.simple,v
retrieving revision 1.30.5.2
retrieving revision 1.30.5.3
diff -pu -r1.30.5.2 -r1.30.5.3
--- src/bison.simple    2001/11/27 23:31:47     1.30.5.2
+++ src/bison.simple    2001/11/28 20:22:52     1.30.5.3
@@ -76,28 +76,55 @@
 # define YYSTACK_USE_ALLOCA 0
 #endif
 
-/* Realloc WHAT from SIZE to YYSTACKSIZE elements of TYPE.
-   If WHAT was malloc'ed (not the original automatic ARRAY), free it. */
 #if YYSTACK_USE_ALLOCA
-# define YYSTACK_REALLOC(Type, What, Array)                            \
-do {                                                                   \
-  Type *old = What;                                                    \
-  What = (Type *) alloca (yystacksize * sizeof (Type));                        
\
-  __yy_memcpy ((char *) What, (char *) old,                            \
-              (size) * (unsigned int) sizeof (Type));                  \
-} while (0)
+# define YYSTACK_ALLOC alloca
+# define YYSTACK_FREE(Ptr) /* empty */
 #else
-# define YYSTACK_REALLOC(Type, What, Array)                            \
-do {                                                                   \
-  Type *old = What;                                                    \
-  What = (Type *) malloc (yystacksize * sizeof (Type));                        
\
-  __yy_memcpy ((char *) What, (char *) old,                            \
-              (size) * (unsigned int) sizeof (Type));                  \
-  yyfree_stacks = 1;                                                   \
-  if (old != Array)                                                    \
-    free (old);                                                                
\
-} while (0)
+# define YYSTACK_ALLOC malloc
+# define YYSTACK_FREE(Ptr) free (Ptr)
+#endif
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  short yys;
+  YYSTYPE yyv;
+#if YYLSP_NEEDED
+  YYLTYPE yyl;
 #endif
+};
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+#define YYSTACK_GAP_MAX (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+#if YYLSP_NEEDED
+# define YYSTACK_BYTES(N) \
+    ((N) * (sizeof (short) + sizeof (YYSTYPE) + sizeof (YYLTYPE))      \
+     + 2 * YYSTACK_GAP_MAX)
+#else
+# define YYSTACK_BYTES(N) \
+    ((N) * (sizeof (short) + sizeof (YYSTYPE))                         \
+     + YYSTACK_GAP_MAX)
+#endif
+
+/* Relocate the TYPE STACK from its old location to the new one.  The
+   local variables SIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+#define YYSTACK_RELOCATE(Type, Stack)                                  \
+do                                                                     \
+  {                                                                    \
+    size_t yynewbytes;                                                 \
+    __yy_memcpy (yyptr, (char *) (Stack), size * sizeof (Type));       \
+    (Stack) = (Type *) yyptr;                                          \
+    yynewbytes = yystacksize * sizeof (Type) + YYSTACK_GAP_MAX;                
\
+    yynewbytes -= yynewbytes % sizeof (union yyalloc);                 \
+    yyptr += yynewbytes;                                               \
+  }                                                                    \
+while (0)
 
 #define yyerrok                (yyerrstatus = 0)
 #define yyclearin      (yychar = YYEMPTY)
@@ -198,11 +225,6 @@ int yydebug;
 # define YYMAXDEPTH 10000
 #endif
 
-/* Define __yy_memcpy.  Note that the size argument
-   should be passed with type unsigned int, because that is what the non-GCC
-   definitions require.  With GCC, __builtin_memcpy takes an arg
-   of type size_t, but it can handle unsigned int.  */
-
 #if __GNUC__ > 1               /* GNU C and GNU C++ define this.  */
 # define __yy_memcpy(To, From, Count)  __builtin_memcpy (To, From, Count)
 #else                          /* not GNU C or C++ */
@@ -214,16 +236,16 @@ static void
 __yy_memcpy (to, from, count)
      char *to;
      const char *from;
-     unsigned int count;
+     size_t count;
 # else /* __cplusplus */
-__yy_memcpy (char *to, const char *from, unsigned int count)
+__yy_memcpy (char *to, const char *from, size_t count)
 # endif
 {
   register const char *f = from;
   register char *t = to;
-  register int i = count;
+  register size_t i = count;
 
-  while (i-- > 0)
+  while (i-- != 0)
     *t++ = *f++;
 }
 
@@ -301,6 +323,7 @@ yyparse (YYPARSE_PARAM_ARG)
 
   register int yystate;
   register int yyn;
+  int yyresult;
   /* Number of tokens to shift before error messages enabled.  */
   int yyerrstatus;
   /* Lookahead token as an internal (translated) token number.  */
@@ -338,7 +361,6 @@ yyparse (YYPARSE_PARAM_ARG)
 #endif
 
   int yystacksize = YYINITDEPTH;
-  int yyfree_stacks = 0;
 
 
   /* The variables used to return semantic value and location from the
@@ -420,27 +442,25 @@ yyparse (YYPARSE_PARAM_ARG)
 #else /* no yyoverflow */
       /* Extend the stack our own way.  */
       if (yystacksize >= YYMAXDEPTH)
-       {
-         yyerror ("parser stack overflow");
-         if (yyfree_stacks)
-           {
-             free (yyss);
-             free (yyvs);
-# if YYLSP_NEEDED
-             free (yyls);
-# endif
-           }
-         return 2;
-       }
+       goto yyoverflowlab;
       yystacksize *= 2;
       if (yystacksize > YYMAXDEPTH)
        yystacksize = YYMAXDEPTH;
 
-      YYSTACK_REALLOC (short, yyss, yyssa);
-      YYSTACK_REALLOC (YYSTYPE, yyvs, yyvsa);
+      {
+       short *yyss1 = yyss;
+       char *yyptr = (char *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+       if (! yyptr)
+         goto yyoverflowlab;
+       YYSTACK_RELOCATE (short, yyss);
+       YYSTACK_RELOCATE (YYSTYPE, yyvs);
 # if YYLSP_NEEDED
-      YYSTACK_REALLOC (YYLTYPE, yyls, yylsa);
+       YYSTACK_RELOCATE (YYLTYPE, yyls);
 # endif
+# undef YYSTACK_RELOCATE
+       if (yyss1 != yyssa)
+         YYSTACK_FREE (yyss1);
+      }
 #endif /* no yyoverflow */
 
       yyssp = yyss + size - 1;
@@ -816,28 +836,28 @@ yyerrhandle:
 | yyacceptlab -- YYACCEPT comes here.  |
 `-------------------------------------*/
 yyacceptlab:
-  if (yyfree_stacks)
-    {
-      free (yyss);
-      free (yyvs);
-#if YYLSP_NEEDED
-      free (yyls);
-#endif
-    }
-  return 0;
-
+  yyresult = 0;
+  goto yyreturn;
 
 /*-----------------------------------.
 | yyabortlab -- YYABORT comes here.  |
 `-----------------------------------*/
 yyabortlab:
-  if (yyfree_stacks)
-    {
-      free (yyss);
-      free (yyvs);
-#if YYLSP_NEEDED
-      free (yyls);
+  yyresult = 1;
+  goto yyreturn;
+
+/*---------------------------------------------.
+| yyoverflowab -- parser overflow comes here.  |
+`---------------------------------------------*/
+yyoverflowlab:
+  yyerror ("parser stack overflow");
+  yyresult = 2;
+  /* Fall through.  */
+
+yyreturn:
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
 #endif
-    }
-  return 1;
+  return yyresult;
 }



reply via email to

[Prev in Thread] Current Thread [Next in Thread]