From 76252467a9696b3d649083e7a8325fd1e14e3d87 Mon Sep 17 00:00:00 2001 From: Nick Bowler Date: Sat, 4 Jul 2020 13:28:53 -0400 Subject: [PATCH] Fix use-after-free during parser error recovery. 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 | 29 ++++++++++++++++------------- tests/decl-bad.at | 5 ++++- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/parse-decl.c b/src/parse-decl.c index e96efb7..694f4ab 100644 --- a/src/parse-decl.c +++ b/src/parse-decl.c @@ -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 . + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ + #include #include #include @@ -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)) diff --git a/tests/decl-bad.at b/tests/decl-bad.at index 3692206..2d357c9 100644 --- a/tests/decl-bad.at +++ b/tests/decl-bad.at @@ -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]) -- 2.43.2