In this PR, canonicalize_move_range walked off the end of a list and triggered a null dereference. There are multiple ways of fixing that, but I think the approach taken in the patch should be relatively efficient.
Tested on aarch64-linux-gnu & x86_64-linux-gnu. OK to install? Richard gcc/ PR rtl-optimization/115929 * rtl-ssa/movement.h (canonicalize_move_range): Check for null prev and next insns and create an invalid move range for them. gcc/testsuite/ PR rtl-optimization/115929 * gcc.dg/torture/pr115929-2.c: New test. --- gcc/rtl-ssa/movement.h | 20 ++++++++++++++++++-- gcc/testsuite/gcc.dg/torture/pr115929-2.c | 22 ++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr115929-2.c diff --git a/gcc/rtl-ssa/movement.h b/gcc/rtl-ssa/movement.h index 17d31e0b5cb..ea1f788df49 100644 --- a/gcc/rtl-ssa/movement.h +++ b/gcc/rtl-ssa/movement.h @@ -76,9 +76,25 @@ inline bool canonicalize_move_range (insn_range_info &move_range, insn_info *insn) { while (move_range.first != insn && !can_insert_after (move_range.first)) - move_range.first = move_range.first->next_nondebug_insn (); + if (auto *next = move_range.first->next_nondebug_insn ()) + move_range.first = next; + else + { + // Invalidate the range. prev_nondebug_insn is always nonnull + // if next_nondebug_insn is null. + move_range.last = move_range.first->prev_nondebug_insn (); + return false; + } while (move_range.last != insn && !can_insert_after (move_range.last)) - move_range.last = move_range.last->prev_nondebug_insn (); + if (auto *prev = move_range.last->prev_nondebug_insn ()) + move_range.last = prev; + else + { + // Invalidate the range. next_nondebug_insn is always nonnull + // if prev_nondebug_insn is null. + move_range.first = move_range.last->next_nondebug_insn (); + return false; + } return bool (move_range); } diff --git a/gcc/testsuite/gcc.dg/torture/pr115929-2.c b/gcc/testsuite/gcc.dg/torture/pr115929-2.c new file mode 100644 index 00000000000..c8473a74da6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr115929-2.c @@ -0,0 +1,22 @@ +/* { dg-additional-options "-fschedule-insns" } */ + +int a, b, c, d, e, f; +int main() { + if (e && f) + while (1) + while (a) + a = 0; + if (c) { + if (b) + goto g; + int h = a; + i: + b = ~((b ^ h) | 1 % b); + if (a) + g: + b = 0; + } + if (d) + goto i; + return 0; +} -- 2.25.1