summaryrefslogtreecommitdiff
path: root/gcc/analyzer/region-model.h
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2019-12-13 19:48:06 -0500
committerDavid Malcolm <dmalcolm@redhat.com>2020-01-14 18:47:22 -0500
commitef7827b0bd7cd980da625fcd12e6c56f51a166c2 (patch)
tree7b501f4af72a1259ff2454de2b4569a221c6bbc4 /gcc/analyzer/region-model.h
parent14f9d7b9a708ebca57257059bda40986bb1e82a7 (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.h16
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;