]> git.draconx.ca Git - cdecl99.git/commitdiff
Fix use-after-free during parser error recovery.
authorNick Bowler <nbowler@draconx.ca>
Sat, 4 Jul 2020 17:28:53 +0000 (13:28 -0400)
committerNick Bowler <nbowler@draconx.ca>
Sat, 4 Jul 2020 17:38:23 +0000 (13:38 -0400)
When parsing a declaration containing more than one full declarator,
each such declarator references the same list of declaration specifiers.

While processing the declarators the specifier list is normalized and
each declarator needs to be updated to the new list.

However, if a syntax error is detected we break out of the processing
loop and end up with only some of these updates occurring.  When the
partially-updated declaration list is subsequently freed, this can
in some cases lead to a use after free when the stale pointers are
encountered.

Fix this by updating all the specifier references before doing any
further processing to avoid dealing with partially-updated lists.

src/parse-decl.c
tests/decl-bad.at

index e96efb7073362ba47eda7e8c6341362cc1246980..694f4ab32c3875458b8293f98d619ce3b1be707c 100644 (file)
@@ -1,20 +1,21 @@
 /*
- *  Parse and validate C declarations.
- *  Copyright © 2011-2012, 2020 Nick Bowler
+ * Parse and validate C declarations.
+ * Copyright © 2011-2012, 2020 Nick Bowler
  *
- *  This program is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, either version 3 of the License, or
- *  (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
  *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
+
 #include <config.h>
 #include <stdio.h>
 #include <assert.h>
@@ -446,10 +447,12 @@ struct cdecl *cdecl_parse_decl(const char *declstr)
         * new specifier list.
         */
        norm_specs = cdecl__normalize_specs(decl->specifiers);
-
        for (struct cdecl *i = decl; i; i = i->next) {
                i->specifiers = norm_specs;
+       }
 
+       /* Now perform checks and simplifications on each declarator. */
+       for (struct cdecl *i = decl; i; i = i->next) {
                if (!forall_declarators(i, reduce_parentheses))
                        goto err;
                if (!forall_declarators(i, simplify_functions))
index 369220631190fbdde0aef223dd4e1968ef7c8ae3..2d357c9f17931d9f7c5d64bdd815376b68393e7f 100644 (file)
@@ -16,7 +16,7 @@
 AT_BANNER([Invalid C declarations])
 
 m4_define([CHECK_BADDECL],
-  [AT_CHECK([if cdecl99 -e '$1'; then exit 1; fi], [0], [], [stderr])])
+  [AT_CHECK([cdecl99 -e '$1'], [1], [], [stderr])])
 
 m4_define([SIMPLE_BADDECL],
 [AT_SETUP([$1])
@@ -133,3 +133,6 @@ SIMPLE_BADDECL([Reject multiple declarators in type names],
   [explain int f, g((x))],
   [explain int x, (void)],
   [explain int [[5]], (void)])
+
+SIMPLE_BADDECL([Error recovery on multiple object declaration],
+  [explain int inline x, y])