[Top][All Lists]
[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;
}