From: Jakub Jelinek Date: Tue, 2 Sep 2025 10:18:52 +0000 (+0200) Subject: tree-cfg: Fix up assign_discriminator ICE with too large #line [PR121663] X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5440f4ceee3152148c6c212f57b85da918b66abf;p=thirdparty%2Fgcc.git tree-cfg: Fix up assign_discriminator ICE with too large #line [PR121663] As mentioned in the PR, LOCATION_LINE is represented in an int, and while we have -pedantic diagnostics (and -pedantic-error error) for too large #line, we can still overflow into negative line numbers up to -2 and -1. We could overflow to that even with valid source if it says has #line 2147483640 and then just has 2G+ lines after it. Now, the ICE is because assign_discriminator{,s} uses a hash_map with int_hash , so values -2 and -1 are reserved for deleted and empty entries. We just need to make sure those aren't valid. One possible fix would be just that - discrim_entry &e = map.get_or_insert (LOCATION_LINE (loc), &existed); + discrim_entry &e + = map.get_or_insert ((unsigned) LOCATION_LINE (loc), &existed); by adding unsigned cast when the key is signed 64-bit, it will never be -1 or -2. But I think that is wasteful, discrim_entry is a struct with 2 unsigned non-static data members, so for lines which can only be 0 to 0xffffffff (sure, with wrap-around), I think just using a hash_map with 96bit elts is better than 128bit. So, the following patch just doesn't assign any discriminators for lines -1U and -2U, I think that is fine, normal programs never do that. Another possibility would be to handle lines -1U and -2U as if it was say -3U. 2025-09-02 Jakub Jelinek PR middle-end/121663 * tree-cfg.cc (assign_discriminator): Change map argument type from hash_map with int_hash to one with int_hash . Cast LOCATION_LINE to unsigned. Return early for (unsigned) LOCATION_LINE above -3U. (assign_discriminators): Change map type from hash_map with int_hash to one with int_hash . * gcc.dg/pr121663.c: New test. --- diff --git a/gcc/testsuite/gcc.dg/pr121663.c b/gcc/testsuite/gcc.dg/pr121663.c new file mode 100644 index 00000000000..b1dfa302c2a --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr121663.c @@ -0,0 +1,9 @@ +/* PR middle-end/121663 */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +void +foo (void) +{ +#line 4294967295 +} diff --git a/gcc/tree-cfg.cc b/gcc/tree-cfg.cc index 4c885637da3..c3883446de8 100644 --- a/gcc/tree-cfg.cc +++ b/gcc/tree-cfg.cc @@ -1095,10 +1095,14 @@ struct discrim_entry location_t assign_discriminator (location_t loc, unsigned int bb_id, - hash_map, discrim_entry> &map) + hash_map, + discrim_entry> &map) { bool existed; - discrim_entry &e = map.get_or_insert (LOCATION_LINE (loc), &existed); + if ((unsigned) LOCATION_LINE (loc) >= -2U) + return loc; + discrim_entry &e + = map.get_or_insert ((unsigned) LOCATION_LINE (loc), &existed); gcc_checking_assert (!has_discriminator (loc)); if (!existed) { @@ -1121,7 +1125,7 @@ assign_discriminator (location_t loc, unsigned int bb_id, static void assign_discriminators (void) { - hash_map, discrim_entry> map (13); + hash_map, discrim_entry> map (13); unsigned int bb_id = 0; basic_block bb; FOR_EACH_BB_FN (bb, cfun)