From: David Malcolm Date: Sat, 31 Jan 2026 04:27:40 +0000 (-0500) Subject: analyzer: fix ICE on rethrow without throw [PR123880] X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b5d5cab8e4b8077386b820a5b6c25b5fe632fa6d;p=thirdparty%2Fgcc.git analyzer: fix ICE on rethrow without throw [PR123880] gcc/analyzer/ChangeLog: PR analyzer/123880 * engine.cc (throw_custom_edge::update_model): Gracefully handle not knowing the current exception in a rethrow. (exploded_node::on_throw): Likewise. gcc/testsuite/ChangeLog: PR analyzer/123880 * g++.dg/analyzer/exception-rethrow-3.C: New test. Signed-off-by: David Malcolm --- diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index 2d22abf0530..8dc9a8b78ce 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -1575,9 +1575,14 @@ public: { if (m_is_rethrow) { - auto eh_node = model->get_current_caught_exception (); - gcc_assert (eh_node); - model->push_thrown_exception (*eh_node); + if (auto eh_node = model->get_current_caught_exception ()) + model->push_thrown_exception (*eh_node); + else + { + /* We have a rethrow of some unknown exception. + We don't have a good way of representing this; + leave the exception stack empty. */ + } } else { @@ -1811,8 +1816,15 @@ exploded_node::on_throw (exploded_graph &eg, if (is_rethrow) { const exception_node *eh_node = model->get_current_caught_exception (); - gcc_assert (eh_node); - type = eh_node->maybe_get_type (); + if (eh_node) + type = eh_node->maybe_get_type (); + else + { + /* We have a "throw;" but no exception to rethrow. + Presumably the top-level of the analysis is an + entrypoint for handling exceptions, so we will + simulate fully unwinding. */ + } } else { diff --git a/gcc/testsuite/g++.dg/analyzer/exception-rethrow-3.C b/gcc/testsuite/g++.dg/analyzer/exception-rethrow-3.C new file mode 100644 index 00000000000..652020c705b --- /dev/null +++ b/gcc/testsuite/g++.dg/analyzer/exception-rethrow-3.C @@ -0,0 +1,46 @@ +#include "../../gcc.dg/analyzer/analyzer-decls.h" + +/* Top-level rethrow (PR analyzer/123880). */ + +void test_1 () +{ + throw; +} + +/* Intraprocedural leak involving a rethrow. */ + +void test_2 () +{ + void *p = __builtin_malloc (1024); + throw; // { dg-warning "leak of 'p'" } + // { dg-message "rethrowing exception here\.\.\." "rethrow event" { target *-*-* } .-1 } +} + +/* Interprocedural leak involving a rethrow. */ + +static void called_by_test_3 () +{ + throw; // { dg-warning "leak of 'p'" } + // { dg-message "rethrowing exception here\.\.\." "rethrow event" { target *-*-* } .-1 } +} + +void test_3 () +{ + void *p = __builtin_malloc (1024); // { dg-message "allocated here" } + called_by_test_3 (); +} + +/* Rethrow of a rethrow. */ + +void test_4 () +{ + try + { + throw; + } + catch (...) + { + __analyzer_dump_path (); // { dg-message "path" "" { xfail *-*-* } } + throw; + } +}