aboutsummaryrefslogtreecommitdiff
path: root/gcc/analyzer/program-state.cc
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2021-05-26 15:47:23 -0400
committerDavid Malcolm <dmalcolm@redhat.com>2021-11-13 09:27:26 -0500
commitb9365b93212041f14a7f71ba8da5af4d82240dc6 (patch)
tree3cc3fcc1a454a25b03b7bd62dcfb6d5e9add0058 /gcc/analyzer/program-state.cc
parente2dd12ab66d14ac76a92b4538af81f8361132ba0 (diff)
downloadgcc-b9365b93212041f14a7f71ba8da5af4d82240dc6.zip
gcc-b9365b93212041f14a7f71ba8da5af4d82240dc6.tar.gz
gcc-b9365b93212041f14a7f71ba8da5af4d82240dc6.tar.bz2
analyzer: add four new taint-based warnings
The initial commit of the analyzer in GCC 10 had a single warning, -Wanalyzer-tainted-array-index and required manually enabling the taint checker with -fanalyzer-checker=taint (due to scaling issues). This patch extends the taint detection to add four new taint-based warnings: -Wanalyzer-tainted-allocation-size for e.g. attacker-controlled malloc/alloca -Wanalyzer-tainted-divisor for detecting where an attacker can inject a divide-by-zero -Wanalyzer-tainted-offset for attacker-controlled pointer offsets -Wanalyzer-tainted-size for e.g. attacker-controlled memset and rewords all the warnings to talk about "attacker-controlled" values rather than "tainted" values. Unfortunately I haven't yet addressed the scaling issues, so all of these still require -fanalyzer-checker=taint (in addition to -fanalyzer). gcc/analyzer/ChangeLog: * analyzer.opt (Wanalyzer-tainted-allocation-size): New. (Wanalyzer-tainted-divisor): New. (Wanalyzer-tainted-offset): New. (Wanalyzer-tainted-size): New. * engine.cc (impl_region_model_context::get_taint_map): New. * exploded-graph.h (impl_region_model_context::get_taint_map): New decl. * program-state.cc (sm_state_map::get_state): Call alt_get_inherited_state. (sm_state_map::impl_set_state): Modify states within compound svalues. (program_state::impl_call_analyzer_dump_state): Undo casts. (selftest::test_program_state_1): Update for new context param of create_region_for_heap_alloc. (selftest::test_program_state_merging): Likewise. * region-model-impl-calls.cc (region_model::impl_call_alloca): Likewise. (region_model::impl_call_calloc): Likewise. (region_model::impl_call_malloc): Likewise. (region_model::impl_call_operator_new): Likewise. (region_model::impl_call_realloc): Likewise. * region-model.cc (region_model::check_region_access): Call check_region_for_taint. (region_model::get_representative_path_var_1): Handle binops. (region_model::create_region_for_heap_alloc): Add "ctxt" param and pass it to set_dynamic_extents. (region_model::create_region_for_alloca): Likewise. (region_model::set_dynamic_extents): Add "ctxt" param and use it to call check_dynamic_size_for_taint. (selftest::test_state_merging): Update for new context param of create_region_for_heap_alloc. (selftest::test_malloc_constraints): Likewise. (selftest::test_malloc): Likewise. (selftest::test_alloca): Likewise for create_region_for_alloca. * region-model.h (region_model::create_region_for_heap_alloc): Add "ctxt" param. (region_model::create_region_for_alloca): Likewise. (region_model::set_dynamic_extents): Likewise. (region_model::check_dynamic_size_for_taint): New decl. (region_model::check_region_for_taint): New decl. (region_model_context::get_taint_map): New vfunc. (noop_region_model_context::get_taint_map): New. * sm-taint.cc: Remove include of "diagnostic-event-id.h"; add includes of "gimple-iterator.h", "tristate.h", "selftest.h", "ordered-hash-map.h", "cgraph.h", "cfg.h", "digraph.h", "analyzer/supergraph.h", "analyzer/call-string.h", "analyzer/program-point.h", "analyzer/store.h", "analyzer/region-model.h", and "analyzer/program-state.h". (enum bounds): Move to top of file. (class taint_diagnostic): New. (class tainted_array_index): Convert to subclass of taint_diagnostic. (tainted_array_index::emit): Add CWE-129. Reword warning to use "attacker-controlled" rather than "tainted". (tainted_array_index::describe_state_change): Move to taint_diagnostic::describe_state_change. (tainted_array_index::describe_final_event): Reword to use "attacker-controlled" rather than "tainted". (class tainted_offset): New. (class tainted_size): New. (class tainted_divisor): New. (class tainted_allocation_size): New. (taint_state_machine::alt_get_inherited_state): New. (taint_state_machine::on_stmt): In assignment handling, remove ARRAY_REF handling in favor of check_region_for_taint. Add detection of tainted divisors. (taint_state_machine::get_taint): New. (taint_state_machine::combine_states): New. (region_model::check_region_for_taint): New. (region_model::check_dynamic_size_for_taint): New. * sm.h (state_machine::alt_get_inherited_state): New. gcc/ChangeLog: * doc/invoke.texi (Static Analyzer Options): Add -Wno-analyzer-tainted-allocation-size, -Wno-analyzer-tainted-divisor, -Wno-analyzer-tainted-offset, and -Wno-analyzer-tainted-size to list. Add -Wanalyzer-tainted-allocation-size, -Wanalyzer-tainted-divisor, -Wanalyzer-tainted-offset, and -Wanalyzer-tainted-size to list of options effectively enabled by -fanalyzer. (-Wanalyzer-tainted-allocation-size): New. (-Wanalyzer-tainted-array-index): Tweak wording; add link to CWE. (-Wanalyzer-tainted-divisor): New. (-Wanalyzer-tainted-offset): New. (-Wanalyzer-tainted-size): New. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/pr93382.c: Tweak expected wording. * gcc.dg/analyzer/taint-alloc-1.c: New test. * gcc.dg/analyzer/taint-alloc-2.c: New test. * gcc.dg/analyzer/taint-divisor-1.c: New test. * gcc.dg/analyzer/taint-1.c: Rename to... * gcc.dg/analyzer/taint-read-index-1.c: ...this. Tweak expected wording. Mark some events as xfail. * gcc.dg/analyzer/taint-read-offset-1.c: New test. * gcc.dg/analyzer/taint-size-1.c: New test. * gcc.dg/analyzer/taint-write-index-1.c: New test. * gcc.dg/analyzer/taint-write-offset-1.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
Diffstat (limited to 'gcc/analyzer/program-state.cc')
-rw-r--r--gcc/analyzer/program-state.cc26
1 files changed, 24 insertions, 2 deletions
diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc
index 8230140..1c87af0 100644
--- a/gcc/analyzer/program-state.cc
+++ b/gcc/analyzer/program-state.cc
@@ -420,6 +420,10 @@ sm_state_map::get_state (const svalue *sval,
}
}
+ if (state_machine::state_t state
+ = m_sm.alt_get_inherited_state (*this, sval, ext_state))
+ return state;
+
return m_sm.get_default_state (sval);
}
@@ -495,6 +499,18 @@ sm_state_map::impl_set_state (const svalue *sval,
gcc_assert (sval->can_have_associated_state_p ());
+ if (m_sm.inherited_state_p ())
+ {
+ if (const compound_svalue *compound_sval
+ = sval->dyn_cast_compound_svalue ())
+ for (auto iter : *compound_sval)
+ {
+ const svalue *inner_sval = iter.second;
+ if (inner_sval->can_have_associated_state_p ())
+ impl_set_state (inner_sval, state, origin, ext_state);
+ }
+ }
+
/* Special-case state 0 as the default value. */
if (state == 0)
{
@@ -1384,6 +1400,10 @@ program_state::impl_call_analyzer_dump_state (const gcall *call,
const svalue *sval = cd.get_arg_svalue (1);
+ /* Strip off cast to int (due to variadic args). */
+ if (const svalue *cast = sval->maybe_undo_cast ())
+ sval = cast;
+
state_machine::state_t state = smap->get_state (sval, ext_state);
warning_at (call->location, 0, "state: %qs", state->get_name ());
}
@@ -1543,7 +1563,8 @@ test_program_state_1 ()
region_model *model = s.m_region_model;
const svalue *size_in_bytes
= mgr->get_or_create_unknown_svalue (size_type_node);
- const region *new_reg = model->create_region_for_heap_alloc (size_in_bytes);
+ const region *new_reg
+ = model->create_region_for_heap_alloc (size_in_bytes, NULL);
const svalue *ptr_sval = mgr->get_ptr_svalue (ptr_type_node, new_reg);
model->set_value (model->get_lvalue (p, NULL),
ptr_sval, NULL);
@@ -1599,7 +1620,8 @@ test_program_state_merging ()
region_model *model0 = s0.m_region_model;
const svalue *size_in_bytes
= mgr->get_or_create_unknown_svalue (size_type_node);
- const region *new_reg = model0->create_region_for_heap_alloc (size_in_bytes);
+ const region *new_reg
+ = model0->create_region_for_heap_alloc (size_in_bytes, NULL);
const svalue *ptr_sval = mgr->get_ptr_svalue (ptr_type_node, new_reg);
model0->set_value (model0->get_lvalue (p, &ctxt),
ptr_sval, &ctxt);