diff options
author | David Malcolm <dmalcolm@redhat.com> | 2019-12-13 19:48:06 -0500 |
---|---|---|
committer | David Malcolm <dmalcolm@redhat.com> | 2020-01-14 18:47:22 -0500 |
commit | ef7827b0bd7cd980da625fcd12e6c56f51a166c2 (patch) | |
tree | 7b501f4af72a1259ff2454de2b4569a221c6bbc4 /gcc/analyzer/region-model.h | |
parent | 14f9d7b9a708ebca57257059bda40986bb1e82a7 (diff) |
analyzer: purge state for unknown function calls
Whilst analyzing the reproducer for detecting CVE-2005-1689
(krb5-1.4.1's src/lib/krb5/krb/recvauth.c), the analyzer reports
a false double-free of the form:
krb5_xfree(inbuf.data);
krb5_read_message(..., &inbuf);
krb5_xfree(inbuf.data); /* false diagnostic here. */
where the call to krb5_read_message overwrites inbuf.data with
a freshly-malloced buffer.
This patch fixes the issue by purging state more thorougly when
handling a call with unknown behavior, by walking the graph of
memory regions that are reachable from the call.
gcc/analyzer/ChangeLog:
* analyzer.h (fndecl_has_gimple_body_p): New decl.
* engine.cc (impl_region_model_context::on_unknown_change): New
function.
(fndecl_has_gimple_body_p): Make non-static.
(exploded_node::on_stmt): Treat __analyzer_dump_exploded_nodes as
known. Track whether we have a call with unknown side-effects and
pass it to on_call_post.
* exploded-graph.h (impl_region_model_context::on_unknown_change):
New decl.
* program-state.cc (sm_state_map::on_unknown_change): New function.
* program-state.h (sm_state_map::on_unknown_change): New decl.
* region-model.cc: Include "bitmap.h".
(region_model::on_call_pre): Return a bool, capturing whether the
call has unknown side effects.
(region_model::on_call_post): Add arg "bool unknown_side_effects"
and if true, call handle_unrecognized_call.
(class reachable_regions): New class.
(region_model::handle_unrecognized_call): New function.
* region-model.h (region_model::on_call_pre): Return a bool.
(region_model::on_call_post): Add arg "bool unknown_side_effects".
(region_model::handle_unrecognized_call): New decl.
(region_model_context::on_unknown_change): New vfunc.
(test_region_model_context::on_unknown_change): New function.
gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/data-model-1.c: Remove xfail.
* gcc.dg/analyzer/data-model-5b.c: Likewise.
* gcc.dg/analyzer/data-model-5c.c: Likewise.
* gcc.dg/analyzer/setjmp-3.c: Mark "foo" as pure.
* gcc.dg/analyzer/setjmp-4.c: Likewise.
* gcc.dg/analyzer/setjmp-6.c: Likewise.
* gcc.dg/analyzer/setjmp-7.c: Likewise.
* gcc.dg/analyzer/setjmp-7a.c: Likewise.
* gcc.dg/analyzer/setjmp-8.c: Likewise.
* gcc.dg/analyzer/setjmp-9.c: Likewise.
* gcc.dg/analyzer/unknown-fns.c: New test.
Diffstat (limited to 'gcc/analyzer/region-model.h')
-rw-r--r-- | gcc/analyzer/region-model.h | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/gcc/analyzer/region-model.h b/gcc/analyzer/region-model.h index ec5282f6956..2d0c0618bd0 100644 --- a/gcc/analyzer/region-model.h +++ b/gcc/analyzer/region-model.h @@ -1578,8 +1578,12 @@ class region_model void check_for_poison (tree expr, region_model_context *ctxt); void on_assignment (const gassign *stmt, region_model_context *ctxt); - void on_call_pre (const gcall *stmt, region_model_context *ctxt); - void on_call_post (const gcall *stmt, region_model_context *ctxt); + bool on_call_pre (const gcall *stmt, region_model_context *ctxt); + void on_call_post (const gcall *stmt, + bool unknown_side_effects, + region_model_context *ctxt); + void handle_unrecognized_call (const gcall *call, + region_model_context *ctxt); void on_return (const greturn *stmt, region_model_context *ctxt); void on_setjmp (const gcall *stmt, const exploded_node *enode, region_model_context *ctxt); @@ -1827,6 +1831,10 @@ class region_model_context to ptrs becoming known to be NULL or non-NULL, rather than just "unchecked") */ virtual void on_condition (tree lhs, enum tree_code op, tree rhs) = 0; + + /* Hooks for clients to be notified when an unknown change happens + to SID (in response to a call to an unknown function). */ + virtual void on_unknown_change (svalue_id sid) = 0; }; /* A bundle of data for use when attempting to merge two region_model @@ -1993,6 +2001,10 @@ public: { } + void on_unknown_change (svalue_id sid ATTRIBUTE_UNUSED) FINAL OVERRIDE + { + } + private: /* Implicitly delete any diagnostics in the dtor. */ auto_delete_vec<pending_diagnostic> m_diagnostics; |