diff options
-rw-r--r-- | gcc/analyzer/engine.cc | 4 | ||||
-rw-r--r-- | gcc/analyzer/region-model.cc | 50 | ||||
-rw-r--r-- | gcc/analyzer/region-model.h | 7 | ||||
-rw-r--r-- | gcc/analyzer/region.cc | 50 | ||||
-rw-r--r-- | gcc/analyzer/region.h | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/analyzer/boxed-malloc-1-29.c | 36 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/analyzer/boxed-malloc-1.c | 9 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/analyzer/stale-frame-1.c | 29 |
8 files changed, 120 insertions, 71 deletions
diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index caa8796..0f40e06 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -5717,11 +5717,11 @@ impl_run_checkers (logger *logger) FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) node->get_untransformed_body (); - engine eng (logger); - /* Create the supergraph. */ supergraph sg (logger); + engine eng (&sg, logger); + state_purge_map *purge_map = NULL; if (flag_analyzer_state_purge) diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc index 29d3122..44bd802 100644 --- a/gcc/analyzer/region-model.cc +++ b/gcc/analyzer/region-model.cc @@ -2081,7 +2081,7 @@ region_model::get_lvalue_1 (path_var pv, region_model_context *ctxt) const int stack_index = pv.m_stack_depth; const frame_region *frame = get_frame_at_index (stack_index); gcc_assert (frame); - return frame->get_region_for_local (m_mgr, expr); + return frame->get_region_for_local (m_mgr, expr, ctxt); } case COMPONENT_REF: @@ -3696,20 +3696,11 @@ void region_model::update_for_return_gcall (const gcall *call_stmt, region_model_context *ctxt) { - /* Get the region for the result of the call, within the caller frame. */ - const region *result_dst_reg = NULL; + /* Get the lvalue for the result of the call, passing it to pop_frame, + so that pop_frame can determine the region with respect to the + *caller* frame. */ tree lhs = gimple_call_lhs (call_stmt); - if (lhs) - { - /* Normally we access the top-level frame, which is: - path_var (expr, get_stack_depth () - 1) - whereas here we need the caller frame, hence "- 2" here. */ - gcc_assert (get_stack_depth () >= 2); - result_dst_reg = get_lvalue (path_var (lhs, get_stack_depth () - 2), - ctxt); - } - - pop_frame (result_dst_reg, NULL, ctxt); + pop_frame (lhs, NULL, ctxt); } /* Extract calling information from the superedge and update the model for the @@ -3928,8 +3919,9 @@ region_model::get_current_function () const /* Pop the topmost frame_region from this region_model's stack; - If RESULT_DST_REG is non-null, copy any return value from the frame - into RESULT_DST_REG's region. + If RESULT_LVALUE is non-null, copy any return value from the frame + into the corresponding region (evaluated with respect to the *caller* + frame, rather than the called frame). If OUT_RESULT is non-null, copy any return value from the frame into *OUT_RESULT. @@ -3938,7 +3930,7 @@ region_model::get_current_function () const POISON_KIND_POPPED_STACK svalues. */ void -region_model::pop_frame (const region *result_dst_reg, +region_model::pop_frame (tree result_lvalue, const svalue **out_result, region_model_context *ctxt) { @@ -3948,11 +3940,10 @@ region_model::pop_frame (const region *result_dst_reg, const frame_region *frame_reg = m_current_frame; tree fndecl = m_current_frame->get_function ()->decl; tree result = DECL_RESULT (fndecl); + const svalue *retval = NULL; if (result && TREE_TYPE (result) != void_type_node) { - const svalue *retval = get_rvalue (result, ctxt); - if (result_dst_reg) - set_value (result_dst_reg, retval, ctxt); + retval = get_rvalue (result, ctxt); if (out_result) *out_result = retval; } @@ -3960,6 +3951,14 @@ region_model::pop_frame (const region *result_dst_reg, /* Pop the frame. */ m_current_frame = m_current_frame->get_calling_frame (); + if (result_lvalue && retval) + { + /* Compute result_dst_reg using RESULT_LVALUE *after* popping + the frame, but before poisoning pointers into the old frame. */ + const region *result_dst_reg = get_lvalue (result_lvalue, ctxt); + set_value (result_dst_reg, retval, ctxt); + } + unbind_region_and_descendents (frame_reg,POISON_KIND_POPPED_STACK); } @@ -4366,8 +4365,8 @@ rejected_ranges_constraint::dump_to_pp (pretty_printer *pp) const /* engine's ctor. */ -engine::engine (logger *logger) -: m_mgr (logger) +engine::engine (const supergraph *sg, logger *logger) +: m_sg (sg), m_mgr (logger) { } @@ -5138,16 +5137,20 @@ test_stack_frames () tree a = build_decl (UNKNOWN_LOCATION, PARM_DECL, get_identifier ("a"), integer_type_node); + DECL_CONTEXT (a) = parent_fndecl; tree b = build_decl (UNKNOWN_LOCATION, PARM_DECL, get_identifier ("b"), integer_type_node); + DECL_CONTEXT (b) = parent_fndecl; /* "x" and "y" in a child frame. */ tree x = build_decl (UNKNOWN_LOCATION, PARM_DECL, get_identifier ("x"), integer_type_node); + DECL_CONTEXT (x) = child_fndecl; tree y = build_decl (UNKNOWN_LOCATION, PARM_DECL, get_identifier ("y"), integer_type_node); + DECL_CONTEXT (y) = child_fndecl; /* "p" global. */ tree p = build_global_decl ("p", ptr_type_node); @@ -5258,6 +5261,7 @@ test_get_representative_path_var () tree n = build_decl (UNKNOWN_LOCATION, PARM_DECL, get_identifier ("n"), integer_type_node); + DECL_CONTEXT (n) = fndecl; region_model_manager mgr; test_region_model_context ctxt; @@ -5470,12 +5474,14 @@ test_state_merging () tree a = build_decl (UNKNOWN_LOCATION, PARM_DECL, get_identifier ("a"), integer_type_node); + DECL_CONTEXT (a) = test_fndecl; tree addr_of_a = build1 (ADDR_EXPR, ptr_type_node, a); /* Param "q", a pointer. */ tree q = build_decl (UNKNOWN_LOCATION, PARM_DECL, get_identifier ("q"), ptr_type_node); + DECL_CONTEXT (q) = test_fndecl; program_point point (program_point::origin ()); region_model_manager mgr; diff --git a/gcc/analyzer/region-model.h b/gcc/analyzer/region-model.h index 8d92d7c..d9e2143 100644 --- a/gcc/analyzer/region-model.h +++ b/gcc/analyzer/region-model.h @@ -658,7 +658,7 @@ class region_model region_model_context *ctxt); const frame_region *get_current_frame () const { return m_current_frame; } function * get_current_function () const; - void pop_frame (const region *result_dst, + void pop_frame (tree result_lvalue, const svalue **out_result, region_model_context *ctxt); int get_stack_depth () const; @@ -1262,14 +1262,15 @@ private: class engine { public: - engine (logger *logger = NULL); + engine (const supergraph *sg = NULL, logger *logger = NULL); + const supergraph *get_supergraph () { return m_sg; } region_model_manager *get_model_manager () { return &m_mgr; } void log_stats (logger *logger) const; private: + const supergraph *m_sg; region_model_manager m_mgr; - }; } // namespace ana diff --git a/gcc/analyzer/region.cc b/gcc/analyzer/region.cc index 5ac24fb..2020ef4 100644 --- a/gcc/analyzer/region.cc +++ b/gcc/analyzer/region.cc @@ -59,6 +59,8 @@ along with GCC; see the file COPYING3. If not see #include "analyzer/store.h" #include "analyzer/region.h" #include "analyzer/region-model.h" +#include "analyzer/sm.h" +#include "analyzer/program-state.h" #if ENABLE_ANALYZER @@ -842,13 +844,49 @@ frame_region::dump_to_pp (pretty_printer *pp, bool simple) const const decl_region * frame_region::get_region_for_local (region_model_manager *mgr, - tree expr) const + tree expr, + const region_model_context *ctxt) const { - // TODO: could also check that VAR_DECLs are locals - gcc_assert (TREE_CODE (expr) == PARM_DECL - || TREE_CODE (expr) == VAR_DECL - || TREE_CODE (expr) == SSA_NAME - || TREE_CODE (expr) == RESULT_DECL); + if (CHECKING_P) + { + /* Verify that EXPR is a local or SSA name, and that it's for the + correct function for this stack frame. */ + gcc_assert (TREE_CODE (expr) == PARM_DECL + || TREE_CODE (expr) == VAR_DECL + || TREE_CODE (expr) == SSA_NAME + || TREE_CODE (expr) == RESULT_DECL); + switch (TREE_CODE (expr)) + { + default: + gcc_unreachable (); + case VAR_DECL: + gcc_assert (!is_global_var (expr)); + /* Fall through. */ + case PARM_DECL: + case RESULT_DECL: + gcc_assert (DECL_CONTEXT (expr) == m_fun->decl); + break; + case SSA_NAME: + { + if (tree var = SSA_NAME_VAR (expr)) + { + if (DECL_P (var)) + gcc_assert (DECL_CONTEXT (var) == m_fun->decl); + } + else if (ctxt) + if (const extrinsic_state *ext_state = ctxt->get_ext_state ()) + if (const supergraph *sg + = ext_state->get_engine ()->get_supergraph ()) + { + const gimple *def_stmt = SSA_NAME_DEF_STMT (expr); + const supernode *snode + = sg->get_supernode_for_stmt (def_stmt); + gcc_assert (snode->get_function () == m_fun); + } + } + break; + } + } /* Ideally we'd use mutable here. */ map_t &mutable_locals = const_cast <map_t &> (m_locals); diff --git a/gcc/analyzer/region.h b/gcc/analyzer/region.h index 2f987e4..dbeb485 100644 --- a/gcc/analyzer/region.h +++ b/gcc/analyzer/region.h @@ -312,8 +312,10 @@ public: int get_index () const { return m_index; } int get_stack_depth () const { return m_index + 1; } - const decl_region *get_region_for_local (region_model_manager *mgr, - tree expr) const; + const decl_region * + get_region_for_local (region_model_manager *mgr, + tree expr, + const region_model_context *ctxt) const; unsigned get_num_locals () const { return m_locals.elements (); } diff --git a/gcc/testsuite/gcc.dg/analyzer/boxed-malloc-1-29.c b/gcc/testsuite/gcc.dg/analyzer/boxed-malloc-1-29.c deleted file mode 100644 index 9e38f97..0000000 --- a/gcc/testsuite/gcc.dg/analyzer/boxed-malloc-1-29.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Isolating this false positive from boxed-malloc-1.c since it's - reported within boxed_malloc. */ - -#include <stdlib.h> - -typedef struct boxed_ptr { void *value; } boxed_ptr; - -boxed_ptr -boxed_malloc (size_t sz) -{ - boxed_ptr result; - result.value = malloc (sz); - return result; /* { dg-bogus "leak" "leak false +ve (PR analyzer/104979)" { xfail *-*-* } } */ -} - -boxed_ptr -boxed_free (boxed_ptr ptr) -{ - free (ptr.value); -} - -const boxed_ptr boxed_null = {NULL}; - -struct link -{ - boxed_ptr m_ptr; -}; - -boxed_ptr test_29 (void) -{ - boxed_ptr res = boxed_malloc (sizeof (struct link)); - if (!res.value) - return boxed_null; - ((struct link *)res.value)->m_ptr = boxed_malloc (sizeof (struct link)); - return res; -} diff --git a/gcc/testsuite/gcc.dg/analyzer/boxed-malloc-1.c b/gcc/testsuite/gcc.dg/analyzer/boxed-malloc-1.c index 5428f2b..435fb4f 100644 --- a/gcc/testsuite/gcc.dg/analyzer/boxed-malloc-1.c +++ b/gcc/testsuite/gcc.dg/analyzer/boxed-malloc-1.c @@ -334,6 +334,15 @@ struct link boxed_ptr m_ptr; }; +boxed_ptr test_29 (void) +{ + boxed_ptr res = boxed_malloc (sizeof (struct link)); + if (!res.value) + return boxed_null; + ((struct link *)res.value)->m_ptr = boxed_malloc (sizeof (struct link)); + return res; +} + void test_31 (void) { struct link tmp; diff --git a/gcc/testsuite/gcc.dg/analyzer/stale-frame-1.c b/gcc/testsuite/gcc.dg/analyzer/stale-frame-1.c index 0422147..c3b7186 100644 --- a/gcc/testsuite/gcc.dg/analyzer/stale-frame-1.c +++ b/gcc/testsuite/gcc.dg/analyzer/stale-frame-1.c @@ -13,3 +13,32 @@ int test_1 (void) called_by_test_1 (); return *global_ptr; /* { dg-warning "dereferencing pointer 'global_ptr' to within stale stack frame" } */ } + +static void __attribute__((noinline)) +called_by_test_2 (int **out) +{ + int i = 42; + *out = &i; +} + +int test_2 (void) +{ + int *ptr; + called_by_test_2 (&ptr); + return *ptr; /* { dg-warning "dereferencing pointer 'ptr' to within stale stack frame" } */ +} + +static int __attribute__((noinline)) +called_by_test_3 (int **out) +{ + int i = 42; + *out = &i; + return i; +} + +int test_3 (void) +{ + int *lhs_ptr; + *lhs_ptr = called_by_test_3 (&lhs_ptr); /* { dg-warning "use of uninitialized value 'lhs_ptr'" } */ + return *lhs_ptr; +} |