As commented in PR114541 here is a first patch that 1. replaces atoi() with strtoul() with ERANGE checking and 2. fixes the handling of misparsed gimple compounds to return early. 3. adds two new test cases.
There is more work to do for Andrews testcase to succeed, so PR114541 is not done yet. === Replace atoi() with strtoul() with ERANGE checking. The function c_parser_gimple_parse_bb_spec uses atoi, which can silently return valid numbers even for some too large numbers in the string. Furthermore in function c_parser_parse_gimple_body handle the case of gimple compound statement errors more generically. In the case of cdil != cdil_gimple now consider them as errors and return early. This avoids further processing with erroneous data. 2024-12-05 Heiko Eißfeldt <he...@hexco.de> PR c/114541 * gimple-parser.cc (c_parser_gimple_parse_bb_spec): Use strtoul with ERANGE check instead of atoi * gimple-parser.cc (c_parser_parse_gimple_body): separate check for errors in c_parser_gimple_compound_statement and special handling of cdil == cdil_gimple to allow a return in case of errors for cdil != cdil_gimple * gcc.dg/pr114541-else-BB#-and-garbagechar.c: New test. * gcc.dg/pr114541-then-BB#-and-garbagechar.c: New test. Signed-off-by: Heiko Eißfeldt <he...@hexco.de>
diff --git a/gcc/c/gimple-parser.cc b/gcc/c/gimple-parser.cc index 78e85d93487..21631fa02f5 100644 --- a/gcc/c/gimple-parser.cc +++ b/gcc/c/gimple-parser.cc @@ -133,11 +133,21 @@ c_parser_gimple_parse_bb_spec (tree val, int *index) { if (!startswith (IDENTIFIER_POINTER (val), "__BB")) return false; - for (const char *p = IDENTIFIER_POINTER (val) + 4; *p; ++p) - if (!ISDIGIT (*p)) - return false; - *index = atoi (IDENTIFIER_POINTER (val) + 4); - return *index > 0; + + const char *bb = IDENTIFIER_POINTER (val) + 4; + if (! ISDIGIT (*bb)) + return false; + + char *pend; + errno = 0; + const unsigned long number = strtoul (bb, &pend, 10); + if (errno == ERANGE + || *pend != '\0' + || number > INT_MAX) + return false; + + *index = number; + return true; } /* See if VAL is an identifier matching __BB<num> and return <num> @@ -250,11 +260,18 @@ c_parser_parse_gimple_body (c_parser *cparser, char *gimple_pass, } } - if (! c_parser_gimple_compound_statement (parser, &seq) - && cdil == cdil_gimple) + if (! c_parser_gimple_compound_statement (parser, &seq)) { - gimple *ret = gimple_build_return (NULL); - gimple_seq_add_stmt_without_update (&seq, ret); + if (cdil == cdil_gimple) + { + gimple *ret = gimple_build_return (NULL); + gimple_seq_add_stmt_without_update (&seq, ret); + } + else + { + /* in case of syntax errors abort early */ + return; + } } tree block = pop_scope (); diff --git a/gcc/testsuite/gcc.dg/pr114541-else-BB#-and-garbagechar.c b/gcc/testsuite/gcc.dg/pr114541-else-BB#-and-garbagechar.c new file mode 100644 index 00000000000..4cb990f4423 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr114541-else-BB#-and-garbagechar.c @@ -0,0 +1,29 @@ +/* PR middle-end/114541 */ +/* { dg-do compile } */ +/* { dg-options "-fgimple" } */ +/* { dg-bogus "internal compiler error" } */ + +void __GIMPLE (ssa,startwith ("dse2")) foo () +{ + int a; + +__BB(2): + if (a_5(D) > 4) + goto __BB3; + else + goto __BB4&; /* { dg-error "expected ';' before" } */ + +__BB(3): + a_2 = 10; + goto __BB5; + +__BB(4): + a_3 = 20; + goto __BB5; + +__BB(5): + a_1 = __PHI (__BB3: a_2, __BB4: a_3); + a_4 = a_1 + 4; + +return; +} diff --git a/gcc/testsuite/gcc.dg/pr114541-then-BB#-and-garbagechar.c b/gcc/testsuite/gcc.dg/pr114541-then-BB#-and-garbagechar.c new file mode 100644 index 00000000000..bcb6a937283 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr114541-then-BB#-and-garbagechar.c @@ -0,0 +1,29 @@ +/* PR middle-end/114541 */ +/* { dg-do compile } */ +/* { dg-options "-fgimple" } */ +/* { dg-bogus "internal compiler error" } */ + +void __GIMPLE (ssa,startwith ("dse2")) foo () +{ + int a; + +__BB(2): + if (a_5(D) > 4) + goto __BB3&; /* { dg-error "expected ';' before" } */ + else + goto __BB4; + +__BB(3): + a_2 = 10; + goto __BB5; + +__BB(4): + a_3 = 20; + goto __BB5; + +__BB(5): + a_1 = __PHI (__BB3: a_2, __BB4: a_3); + a_4 = a_1 + 4; + +return; +}