diff options
author | David Malcolm <dmalcolm@redhat.com> | 2020-02-13 21:17:11 -0500 |
---|---|---|
committer | David Malcolm <dmalcolm@redhat.com> | 2020-02-17 02:20:36 -0500 |
commit | f76a88ebf089871dcce215aa0cb1956ccc060895 (patch) | |
tree | 4f8cb05de7bf355d548dc7ce2e8504730058c6bf /gcc/analyzer/program-state.cc | |
parent | 0993ad65cc4e462223e9337d9b2d3b82a887c6c8 (diff) | |
download | gcc-f76a88ebf089871dcce215aa0cb1956ccc060895.zip gcc-f76a88ebf089871dcce215aa0cb1956ccc060895.tar.gz gcc-f76a88ebf089871dcce215aa0cb1956ccc060895.tar.bz2 |
analyzer: fix ICEs in region_model::get_lvalue_1 [PR 93388]
There have been various ICEs with -fanalyzer involving unhandled tree
codes in region_model::get_lvalue_1; PR analyzer/93388 reports various
others e.g. for IMAGPART_EXPR, REALPART_EXPR, and VIEW_CONVERT_EXPR seen
when running the testsuite with -fanalyzer forcibly enabled.
Whilst we could implement lvalue-handling in the region model for every
tree code, for some of these we're straying far from my primary goal for
GCC 10 of implementing a double-free checker for C.
This patch implements a fallback for unimplemented tree codes: create a
dummy region, but mark the new state as being invalid, and stop
exploring state along this path. It also implements VIEW_CONVERT_EXPR.
Doing so fixes the ICEs, whilst effectively turning off the analyzer
along code paths that use such tree codes. Hopefully this compromise
is sensible for GCC 10.
gcc/analyzer/ChangeLog:
PR analyzer/93388
* engine.cc (impl_region_model_context::on_unknown_tree_code):
New.
(exploded_graph::get_or_create_node): Reject invalid states.
* exploded-graph.h
(impl_region_model_context::on_unknown_tree_code): New decl.
(point_and_state::point_and_state): Assert that the state is
valid.
* program-state.cc (program_state::program_state): Initialize
m_valid to true.
(program_state::operator=): Copy m_valid.
(program_state::program_state): Likewise for move constructor.
(program_state::print): Print m_valid.
(program_state::dump_to_pp): Likewise.
* program-state.h (program_state::m_valid): New field.
* region-model.cc (region_model::get_lvalue_1): Implement the
default case by returning a new symbolic region and calling
the context's on_unknown_tree_code, rather than issuing an
internal_error. Implement VIEW_CONVERT_EXPR.
* region-model.h (region_model_context::on_unknown_tree_code): New
vfunc.
(test_region_model_context::on_unknown_tree_code): New.
gcc/testsuite/ChangeLog:
PR analyzer/93388
* gcc.dg/analyzer/torture/20060625-1.c: New test.
* gcc.dg/analyzer/torture/pr51628-30.c: New test.
* gcc.dg/analyzer/torture/pr59037.c: New test.
Diffstat (limited to 'gcc/analyzer/program-state.cc')
-rw-r--r-- | gcc/analyzer/program-state.cc | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc index 82b921e..fb96e3c 100644 --- a/gcc/analyzer/program-state.cc +++ b/gcc/analyzer/program-state.cc @@ -573,7 +573,8 @@ sm_state_map::validate (const state_machine &sm, program_state::program_state (const extrinsic_state &ext_state) : m_region_model (new region_model ()), - m_checker_states (ext_state.get_num_checkers ()) + m_checker_states (ext_state.get_num_checkers ()), + m_valid (true) { int num_states = ext_state.get_num_checkers (); for (int i = 0; i < num_states; i++) @@ -584,7 +585,8 @@ program_state::program_state (const extrinsic_state &ext_state) program_state::program_state (const program_state &other) : m_region_model (new region_model (*other.m_region_model)), - m_checker_states (other.m_checker_states.length ()) + m_checker_states (other.m_checker_states.length ()), + m_valid (true) { int i; sm_state_map *smap; @@ -610,6 +612,8 @@ program_state::operator= (const program_state &other) FOR_EACH_VEC_ELT (other.m_checker_states, i, smap) m_checker_states.quick_push (smap->clone ()); + m_valid = other.m_valid; + return *this; } @@ -626,6 +630,8 @@ program_state::program_state (program_state &&other) FOR_EACH_VEC_ELT (other.m_checker_states, i, smap) m_checker_states.quick_push (smap); other.m_checker_states.truncate (0); + + m_valid = other.m_valid; } #endif @@ -693,6 +699,11 @@ program_state::print (const extrinsic_state &ext_state, pp_newline (pp); } } + if (!m_valid) + { + pp_printf (pp, "invalid state"); + pp_newline (pp); + } } /* Dump a multiline representation of this state to PP. */ @@ -716,6 +727,12 @@ program_state::dump_to_pp (const extrinsic_state &ext_state, pp_newline (pp); } } + + if (!m_valid) + { + pp_printf (pp, "invalid state"); + pp_newline (pp); + } } /* Dump a multiline representation of this state to OUTF. */ |