From aef703cf982072427e74034f4c460a11c5e04b8e Mon Sep 17 00:00:00 2001 From: Ankur Saini Date: Thu, 29 Jul 2021 15:48:07 +0530 Subject: analyzer: detect and analyze calls via function pointer 2021-07-29 Ankur Saini gcc/analyzer/ChangeLog: PR analyzer/100546 * analysis-plan.cc (analysis_plan::use_summary_p): Don't use call summaries if there is no callgraph edge * checker-path.cc (call_event::call_event): Handle calls events that are not represented by a supergraph call edge (return_event::return_event): Likewise. (call_event::get_desc): Work with new call_event structure. (return_event::get_desc): Likeise. * checker-path.h (call_event::m_src_snode): New field. (call_event::m_dest_snode): New field. (return_event::m_src_snode): New field. (return_event::m_dest_snode): New field. * diagnostic-manager.cc (diagnostic_manager::prune_for_sm_diagnostic): Refactor to work with edges without callgraph edge. (diagnostic_manager::prune_for_sm_diagnostic): Likewise. * engine.cc (dynamic_call_info_t::update_model): New function. (dynamic_call_info_t::add_events_to_path): New function. (exploded_graph::create_dynamic_call): New function. (exploded_graph::process_node): Work with dynamically discovered calls. * exploded-graph.h (class dynamic_call_info_t): New class. (exploded_graph::create_dynamic_call): New decl. * program-point.cc (program_point::push_to_call_stack): New function. (program_point::pop_from_call_stack): New function. * program-point.h (program_point::push_to_call_stack): New decl. (program_point::pop_from_call_stack): New decl. * program-state.cc (program_state::push_call): New function. (program_state::returning_call): New function. * program-state.h (program_state::push_call): New decl. (program_state::returning_call): New decl. * region-model.cc (region_model::update_for_gcall) New function. (region_model::update_for_return_gcall): New function. (egion_model::update_for_call_superedge): Get the underlying gcall and update for gcall. (region_model::update_for_return_superedge): Likewise. * region-model.h (region_model::update_for_gcall): New decl. (region_model::update_for_return_gcall): New decl. * state-purge.cc (state_purge_per_ssa_name::process_point): Update to work with calls without underlying cgraph edge. * supergraph.cc (supergraph::supergraph) Split snodes at every callsite. * supergraph.h (supernode::get_returning_call) New accessor. gcc/testsuite/ChangeLog: PR analyzer/100546 * gcc.dg/analyzer/function-ptr-4.c: New test. * gcc.dg/analyzer/pr100546.c: New test. --- gcc/testsuite/gcc.dg/analyzer/function-ptr-4.c | 24 ++++++++++++++++++++++++ gcc/testsuite/gcc.dg/analyzer/pr100546.c | 17 +++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/analyzer/function-ptr-4.c create mode 100644 gcc/testsuite/gcc.dg/analyzer/pr100546.c (limited to 'gcc/testsuite/gcc.dg') diff --git a/gcc/testsuite/gcc.dg/analyzer/function-ptr-4.c b/gcc/testsuite/gcc.dg/analyzer/function-ptr-4.c new file mode 100644 index 0000000..016351a --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/function-ptr-4.c @@ -0,0 +1,24 @@ +/* Test to see if the analyzer detect and analyze calls via + function pointers or not. */ + +#include + +void fun(int *int_ptr) +{ + free(int_ptr); /* { dg-warning "double-'free' of 'int_ptr'" } */ +} + +void single_call() +{ + int *int_ptr = (int*)malloc(sizeof(int)); + void (*fun_ptr)(int *) = &fun; + (*fun_ptr)(int_ptr); +} + +void double_call() +{ + int *int_ptr = (int*)malloc(sizeof(int)); + void (*fun_ptr)(int *) = &fun; + (*fun_ptr)(int_ptr); /* { dg-message "calling 'fun' from 'double_call'" } */ + (*fun_ptr)(int_ptr); +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr100546.c b/gcc/testsuite/gcc.dg/analyzer/pr100546.c new file mode 100644 index 0000000..3349d40 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr100546.c @@ -0,0 +1,17 @@ +#include +#include + +static void noReturn(const char *str) __attribute__((noreturn)); +static void noReturn(const char *str) { + printf("%s\n", str); + exit(1); +} + +void (*noReturnPtr)(const char *str) = &noReturn; + +int main(int argc, char **argv) { + char *str = 0; + if (!str) + noReturnPtr(__FILE__); + return printf("%c\n", *str); +} -- cgit v1.1