https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97111

--- Comment #4 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by David Malcolm <dmalc...@gcc.gnu.org>:

https://gcc.gnu.org/g:7a39e0ca0652ff84a31efa3c7d4c7a78d9bb95ae

commit r16-264-g7a39e0ca0652ff84a31efa3c7d4c7a78d9bb95ae
Author: David Malcolm <dmalc...@redhat.com>
Date:   Mon Apr 28 18:21:24 2025 -0400

    analyzer: initial implementation of exception handling [PR97111]

    This patch adds initial support for exception-handling to -fanalyzer,
    handling eh_dispatch for regions of type ERT_TRY and
    ERT_ALLOWED_EXCEPTIONS.   I haven't managed yet seen eh_dispatch for
    regions of type ERT_CLEANUP and ERT_MUST_NOT_THROW in the analyzer; with
    this patch it will ICE if it sees those.

    Additionally, this patch only checks for exact matches of exception
    types, rather than supporting subclasses and references.  I'm deferring
    fixing this for now whilst figuring out how best to interact with the C++
    type system; I'm tracking it as PR analyzer/119697.

    The patch adds event classes for throwing and catching exceptions, and
    seems to generate readable warnings for the kinds of leak that might
    occur due to trying to manage resources manually and forgetting about
    exceptions; for example:

    exception-leak-1.C: In function âint test()â:
    exception-leak-1.C:7:9: warning: leak of âptrâ [CWE-401]
[-Wanalyzer-malloc-leak]
        7 |   throw 42;
          |         ^~
      âint test()â: events 1-3
        5 |   void *ptr = __builtin_malloc (1024);
          |               ~~~~~~~~~~~~~~~~~^~~~~~
          |                                |
          |                                (1) allocated here
        6 |
        7 |   throw 42;
          |         ~~
          |         |
          |         (2) throwing exception of type âintâ here...
          |         (3) â ï¸  âptrâ leaks here; was allocated at (1)

    Although dynamic exception specifications are only available in C++14
    and earlier, the need to support them meant it seemed relatively easy to
    add a warning to check them, hence the patch adds a new warning
    for code paths that throw an exception that doesn't match a dynamic
    exception specification:  -Wanalyzer-throw-of-unexpected-type.

    gcc/analyzer/ChangeLog:
            PR analyzer/97111
            * analyzer.cc (is_cxa_throw_p): New.
            (is_cxa_rethrow_p): New.
            * analyzer.opt (Wanalyzer-throw-of-unexpected-type): New.
            * analyzer.opt.urls: Regenerate.
            * call-info.cc (custom_edge_info::create_enode): New.
            * call-info.h (call_info::print): Drop "final".
            (call_info::add_events_to_path): Likewise.
            * checker-event.cc (event_kind_to_string): Add cases for
            event_kind::catch_, event_kind::throw_, and event_kind::unwind.
            (explicit_throw_event::print_desc): New.
            (throw_from_call_to_external_fn_event::print_desc): New.
            (unwind_event::print_desc): New.
            * checker-event.h (enum class event_kind): Add catch_, throw_,
            and unwind.
            (class catch_cfg_edge_event): New.
            (class throw_event): New.
            (class explicit_throw_event): New.
            (class throw_from_call_to_external_fn_event): New.
            (class unwind_event): New.
            * common.h (class eh_dispatch_cfg_superedge): New forward decl.
            (class eh_dispatch_try_cfg_superedge): New forward decl.
            (class eh_dispatch_allowed_cfg_superedge): New forward decl.
            (custom_edge_info::create_enode): New vfunc decl.
            (is_cxa_throw_p): New decl.
            (is_cxa_rethrow_p): New decl.
            * diagnostic-manager.cc
            (diagnostic_manager::add_events_for_superedge): Special-case edges
            for eh_dispach_try.
            (diagnostic_manager::prune_path): Call consolidate_unwind_events.
            (diagnostic_manager::prune_for_sm_diagnostic): Don't filter the new
            event_kinds.
            (diagnostic_manager::consolidate_unwind_events): New.
            * diagnostic-manager.h
            (diagnostic_manager::consolidate_unwind_events): New decl.
            * engine.cc (exploded_node::on_stmt_pre): Handle "__cxa_throw",
            "__cxa_rethrow", and resx statements.
            (class throw_custom_edge): New.
            (class unwind_custom_edge): New.
            (get_eh_outedge): New.
            (exploded_graph::unwind_from_exception): New.
            (exploded_node::on_throw): New.
            (exploded_node::on_resx): New.
            (exploded_graph::get_or_create_node): Add "add_to_worklist" param
            and use it.
            (exploded_graph::process_node): Use edge_info's create_enode vfunc
            to create enodes, rather than calling get_or_create_node directly.
            Ignore CFG edges in the sgraph flagged with EH whilst we're
            exploring the egraph.
            (exploded_graph_annotator::print_enode): Handle case
            exploded_node::status::special.
            * exploded-graph.h (exploded_node::status): Add value "special".
            (exploded_node::on_throw): New decl.
            (exploded_node::on_resx): New decl.
            (exploded_graph::get_or_create_node): Add optional
            "add_to_worklist" param.
            (exploded_graph::unwind_from_exception): New decl.
            * kf-lang-cp.cc (class kf_cxa_allocate_exception): New.
            (class kf_cxa_begin_catch): New.
            (class kf_cxa_end_catch): New.
            (class throw_of_unexpected_type): New.
            (class kf_cxa_call_unexpected): New.
            (register_known_functions_lang_cp): Register known functions
            "__cxa_allocate_exception", "__cxa_begin_catch",
            "__cxa_end_catch", and "__cxa_call_unexpected".
            * kf.cc (class kf_eh_pointer): New.
            (register_known_functions): Register it for BUILT_IN_EH_POINTER.
            * region-model.cc: Include "analyzer/function-set.h".
            (exception_node::operator==): New.
            (exception_node::dump_to_pp): New.
            (exception_node::dump): New.
            (exception_node::to_json): New.
            (exception_node::make_dump_widget): New.
            (exception_node::maybe_get_type): New.
            (exception_node::add_to_reachable_regions): New.
            (region_model::region_model): Initialize
            m_thrown_exceptions_stack and m_caught_exceptions_stack.
            (region_model::operator=): Likewise.
            (region_model::operator==): Compare them.
            (region_model::dump_to_pp): Dump exception stacks.
            (region_model::to_json): Add exception stacks.
            (region_model::make_dump_widget): Likewise.
            (class exception_thrown_from_unrecognized_call): New.
            (get_fns_assumed_not_to_throw): New.
            (can_throw_p): New.
            (region_model::check_for_throw_inside_call): New.
            (region_model::on_call_pre): Call check_for_throw_inside_call
            on unknown fns or those we don't have a body for.
            (region_model::maybe_update_for_edge): Handle eh_dispatch_stmt
            statements.  Drop old code that called
            apply_constraints_for_exception on EDGE_EH edges.
            (class rejected_eh_dispatch): New.
            (exception_matches_type_p): New.
            (matches_any_exception_type_p): New.
            (region_model::apply_constraints_for_eh_dispatch): New.
            (region_model::apply_constraints_for_eh_dispatch_try): New.
            (region_model::apply_constraints_for_eh_dispatch_allowed): New.
            (region_model::apply_constraints_for_exception): Delete.
            (region_model::can_merge_with_p): Don't merge models with
            non-equal exception stacks.
            (region_model::get_referenced_base_regions): Add regions from
            exception stacks.
            * region-model.h (struct exception_node): New.
            (region_model::push_thrown_exception): New.
            (region_model::get_current_thrown_exception): New.
            (region_model::pop_thrown_exception): New.
            (region_model::push_caught_exception): New.
            (region_model::get_current_caught_exception): New.
            (region_model::pop_caught_exception): New.
            (region_model::apply_constraints_for_eh_dispatch_try): New decl.
            (region_model::apply_constraints_for_eh_dispatch_allowed) New decl.
            (region_model::apply_constraints_for_exception): Delete.
            (region_model::apply_constraints_for_eh_dispatch): New decl.
            (region_model::check_for_throw_inside_call): New decl.
            (region_model::m_thrown_exceptions_stack): New field.
            (region_model::m_caught_exceptions_stack): New field.
            * supergraph.cc: Include "except.h" and "analyzer/region-model.h".
            (supergraph::add_cfg_edge): Special-case eh_dispatch edges.
            (superedge::get_description): Use default_tree_printer.
            (get_catch): New.
            (eh_dispatch_cfg_superedge::make): New.
            (eh_dispatch_cfg_superedge::eh_dispatch_cfg_superedge): New.
            (eh_dispatch_cfg_superedge::get_eh_status): New.
            (eh_dispatch_try_cfg_superedge::dump_label_to_pp): New.
            (eh_dispatch_try_cfg_superedge::apply_constraints): New.
           
(eh_dispatch_allowed_cfg_superedge::eh_dispatch_allowed_cfg_superedge):
            New.
            (eh_dispatch_allowed_cfg_superedge::dump_label_to_pp): New.
            (eh_dispatch_allowed_cfg_superedge::apply_constraints): New.
            * supergraph.h: Include "except.h".
            (superedge::dyn_cast_eh_dispatch_cfg_superedge): New vfunc.
            (superedge::dyn_cast_eh_dispatch_try_cfg_superedge): New vfunc.
            (superedge::dyn_cast_eh_dispatch_allowed_cfg_superedge): New
            vfunc.
            (class eh_dispatch_cfg_superedge): New.
            (is_a_helper <const eh_dispatch_cfg_superedge *>::test): New.
            (class eh_dispatch_try_cfg_superedge): New.
            (is_a_helper <const eh_dispatch_try_cfg_superedge *>::test): New.
            (class eh_dispatch_allowed_cfg_superedge): New.
            (is_a_helper <const eh_dispatch_allowed_cfg_superedge *>::test):
            New.
            * svalue.cc (svalue::maybe_get_type_from_typeinfo): New.
            * svalue.h (svalue::maybe_get_type_from_typeinfo): New decl.

    gcc/ChangeLog:
            PR analyzer/97111
            * doc/invoke.texi: Add -Wanalyzer-throw-of-unexpected-type.
            * gimple.h (gimple_call_nothrow_p): Make arg const.

    gcc/testsuite/ChangeLog:
            PR analyzer/97111
            * c-c++-common/analyzer/analyzer-verbosity-2a.c: Add
            -fno-exceptions.
            * c-c++-common/analyzer/analyzer-verbosity-3a.c: Likewise.
            * c-c++-common/analyzer/attr-const-2.c: Add
            __attribute__((nothrow)).
            * c-c++-common/analyzer/attr-malloc-4.c: Likewise.
            * c-c++-common/analyzer/attr-malloc-5.c: Likewise.
            * c-c++-common/analyzer/attr-malloc-6.c: Add -fno-exceptions.
            * c-c++-common/analyzer/attr-malloc-CVE-2019-19078-usb-leak.c:
            Likewise.
            * c-c++-common/analyzer/attr-malloc-exception.c: New test.
            * c-c++-common/analyzer/call-summaries-pr107158-2.c: Add
            -fno-exceptions.
            * c-c++-common/analyzer/call-summaries-pr107158.c: Likewise.
            * c-c++-common/analyzer/capacity-2.c: Likewise.
            * c-c++-common/analyzer/coreutils-sum-pr108666.c: Likewise.
            * c-c++-common/analyzer/data-model-22.c: Likewise.
            * c-c++-common/analyzer/data-model-5d.c: Likewise.
            *
c-c++-common/analyzer/deref-before-check-pr108455-git-pack-revindex.c:
            Likewise.
            *
c-c++-common/analyzer/deref-before-check-pr108475-haproxy-tcpcheck.c:
            Likewise.
            * c-c++-common/analyzer/edges-2.c: Likewise.
            * c-c++-common/analyzer/fd-2.c: Likewise.
            * c-c++-common/analyzer/fd-3.c: Likewise.
            * c-c++-common/analyzer/fd-meaning.c: Likewise.
            * c-c++-common/analyzer/file-1.c: Likewise.
            * c-c++-common/analyzer/file-3.c: Likewise.
            * c-c++-common/analyzer/file-meaning-1.c: Likewise.
            * c-c++-common/analyzer/infinite-recursion.c: Likewise.
            * c-c++-common/analyzer/leak-3.c: Likewise.
            * c-c++-common/analyzer/malloc-dedupe-1.c: Likewise.
            * c-c++-common/analyzer/malloc-in-loop.c: Likewise.
            * c-c++-common/analyzer/malloc-many-paths-3.c: Likewise.
            * c-c++-common/analyzer/malloc-paths-5.c: Likewise.
            * c-c++-common/analyzer/malloc-paths-7.c: Likewise.
            * c-c++-common/analyzer/malloc-paths-8.c: Likewise.
            * c-c++-common/analyzer/malloc-vs-local-1a.c: Likewise.
            * c-c++-common/analyzer/malloc-vs-local-2.c: Likewise.
            * c-c++-common/analyzer/malloc-vs-local-3.c: Likewise.
            * c-c++-common/analyzer/paths-7.c: Likewise.
            * c-c++-common/analyzer/pr110830.c: Likewise.
            * c-c++-common/analyzer/pr93032-mztools-simplified.c: Likewise.
            * c-c++-common/analyzer/pr93355-localealias-feasibility-3.c:
            Likewise.
            * c-c++-common/analyzer/pr93355-localealias-simplified.c:
            Likewise.
            * c-c++-common/analyzer/pr96650-1-trans.c: Likewise.
            * c-c++-common/analyzer/pr97072.c: Add __attribute__((nothrow)).
            * c-c++-common/analyzer/pr98575-1.c: Likewise.
            * c-c++-common/analyzer/pr99716-1.c: Add -fno-exceptions.
            * c-c++-common/analyzer/pr99716-2.c: Likewise.
            * c-c++-common/analyzer/pr99716-3.c: Likewise.
            * c-c++-common/analyzer/pragma-2.c: Likewise.
            * c-c++-common/analyzer/rhbz1878600.c: Likewise.
            * c-c++-common/analyzer/strndup-1.c: Likewise.
            * c-c++-common/analyzer/write-to-string-literal-4-disabled.c:
            Likewise.
            * c-c++-common/analyzer/write-to-string-literal-4.c: Likewise.
            * c-c++-common/analyzer/write-to-string-literal-5.c: Likewise.
            * c-c++-common/analyzer/zlib-5.c: Likewise.
            * g++.dg/analyzer/exception-could-throw-1.C: New test.
            * g++.dg/analyzer/exception-could-throw-2.C: New test.
            * g++.dg/analyzer/exception-dynamic-spec.C: New test.
            * g++.dg/analyzer/exception-leak-1.C: New test.
            * g++.dg/analyzer/exception-leak-2.C: New test.
            * g++.dg/analyzer/exception-leak-3.C: New test.
            * g++.dg/analyzer/exception-leak-4.C: New test.
            * g++.dg/analyzer/exception-leak-5.C: New test.
            * g++.dg/analyzer/exception-leak-6.C: New test.
            * g++.dg/analyzer/exception-nothrow.C: New test.
            * g++.dg/analyzer/exception-path-1.C: New test.
            * g++.dg/analyzer/exception-path-catch-all-1.C: New test.
            * g++.dg/analyzer/exception-path-catch-all-2.C: New test.
            * g++.dg/analyzer/exception-path-unwind-multiple-2.C: New test.
            * g++.dg/analyzer/exception-path-unwind-multiple.C: New test.
            * g++.dg/analyzer/exception-path-unwind-single.C: New test.
            * g++.dg/analyzer/exception-path-with-cleanups.C: New test.
            * g++.dg/analyzer/exception-rethrow-1.C: New test.
            * g++.dg/analyzer/exception-rethrow-2.C: New test.
            * g++.dg/analyzer/exception-stack-1.C: New test.
            * g++.dg/analyzer/exception-stack-2.C: New test.
            * g++.dg/analyzer/exception-subclass-1.C: New test.
            * g++.dg/analyzer/exception-subclass-2.C: New test.
            * g++.dg/analyzer/exception-value-1.C: New test.
            * g++.dg/analyzer/exception-value-2.C: New test.
            * g++.dg/analyzer/fno-exception.C: New test.
            * g++.dg/analyzer/pr94028.C: Drop xfail.
            * g++.dg/analyzer/std-unexpected.C: New test.
            * g++.dg/coroutines/pr105287.C: Drop dg-excess-errors.

    Signed-off-by: David Malcolm <dmalc...@redhat.com>
  • [Bug analyzer/97111] Support fo... cvs-commit at gcc dot gnu.org via Gcc-bugs

Reply via email to