aboutsummaryrefslogtreecommitdiff
path: root/gcc/attribs.h
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2021-01-18 09:24:46 -0500
committerDavid Malcolm <dmalcolm@redhat.com>2021-01-18 09:24:46 -0500
commitc7e276b869bdeb4a95735c1f037ee1a5f629de3d (patch)
tree04c4f55a4275afaf736344d1824aeccb4cbe195e /gcc/attribs.h
parentec153f96f8943f1d2418d2248ed219358990bb5f (diff)
downloadgcc-c7e276b869bdeb4a95735c1f037ee1a5f629de3d.zip
gcc-c7e276b869bdeb4a95735c1f037ee1a5f629de3d.tar.gz
gcc-c7e276b869bdeb4a95735c1f037ee1a5f629de3d.tar.bz2
analyzer: use "malloc" attribute
In dce6c58db87ebf7f4477bd3126228e73e4eeee97 msebor extended the "malloc" attribute to support user-defined allocator/deallocator pairs. This patch extends the "malloc" checker within -fanalyzer to use these attributes. It is based on an earlier patch: 'RFC: add "deallocated_by" attribute for use by analyzer' https://gcc.gnu.org/pipermail/gcc-patches/2020-October/555544.html which added a different attribute. The patch needed a lot of reworking to support multiple deallocators per allocator. My hope was that this would provide a minimal level of markup that would support library-checking without requiring lots of further markup. I attempted to use this to detect a memory leak within a Linux driver (CVE-2019-19078), by adding the attribute to mark these fns: extern struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags); extern void usb_free_urb(struct urb *urb); where there is a leak of a "urb" on an error-handling path. Unfortunately I ran into the problem that there are various other fns that take "struct urb *" and the analyzer conservatively assumes that a urb passed to them might or might not be freed and thus stops tracking state for them. Hence this will only detect issues for the simplest cases (without adding another attribute). gcc/analyzer/ChangeLog: * analyzer.h (is_std_named_call_p): New decl. * diagnostic-manager.cc (path_builder::get_sm): New. (state_change_event_creator::state_change_event_creator): Add "pb" param. (state_change_event_creator::on_global_state_change): Don't consider state changes affecting other state_machines. (state_change_event_creator::on_state_change): Likewise. (state_change_event_creator::m_pb): New field. (diagnostic_manager::add_events_for_eedge): Pass pb to visitor ctor. * region-model-impl-calls.cc (region_model::impl_deallocation_call): New. * region-model.cc: Include "attribs.h". (region_model::on_call_post): Handle fndecls referenced by __attribute__((deallocated_by(FOO))). * region-model.h (region_model::impl_deallocation_call): New decl. * sm-malloc.cc: Include "stringpool.h" and "attribs.h". Add leading comment. (class api): Delete. (enum resource_state): Update comment for change from api to deallocator and deallocator_set. (allocation_state::allocation_state): Drop api param. Add "deallocators" and "deallocator". (allocation_state::m_api): Drop field in favor of... (allocation_state::m_deallocators): New field. (allocation_state::m_deallocator): New field. (enum wording): Add WORDING_DEALLOCATED. (struct deallocator): New. (struct standard_deallocator): New. (struct custom_deallocator): New. (struct deallocator_set): New. (struct custom_deallocator_set): New. (struct standard_deallocator_set): New. (struct deallocator_set_map_traits): New. (malloc_state_machine::m_malloc): Drop field (malloc_state_machine::m_scalar_new): Likewise. (malloc_state_machine::m_vector_new): Likewise. (malloc_state_machine::m_free): New field (malloc_state_machine::m_scalar_delete): Likewise. (malloc_state_machine::m_vector_delete): Likewise. (malloc_state_machine::deallocator_map_t): New typedef. (malloc_state_machine::m_deallocator_map): New field. (malloc_state_machine::deallocator_set_cache_t): New typedef. (malloc_state_machine::m_custom_deallocator_set_cache): New field. (malloc_state_machine::custom_deallocator_set_map_t): New typedef. (malloc_state_machine::m_custom_deallocator_set_map): New field. (malloc_state_machine::m_dynamic_sets): New field. (malloc_state_machine::m_dynamic_deallocators): New field. (api::api): Delete. (deallocator::deallocator): New ctor. (deallocator::hash): New. (deallocator::dump_to_pp): New. (deallocator::cmp): New. (deallocator::cmp_ptr_ptr): New. (standard_deallocator::standard_deallocator): New ctor. (deallocator_set::deallocator_set): New ctor. (deallocator_set::dump): New. (custom_deallocator_set::custom_deallocator_set): New ctor. (custom_deallocator_set::contains_p): New. (custom_deallocator_set::maybe_get_single): New. (custom_deallocator_set::dump_to_pp): New. (standard_deallocator_set::standard_deallocator_set): New ctor. (standard_deallocator_set::contains_p): New. (standard_deallocator_set::maybe_get_single): New. (standard_deallocator_set::dump_to_pp): New. (start_p): New. (class mismatching_deallocation): Update for conversion from api to deallocator_set and deallocator. (double_free::emit): Use %qs. (class use_after_free): Update for conversion from api to deallocator_set and deallocator. (malloc_leak::describe_state_change): Only emit "allocated here" on a start->nonnull transition, rather than on other transitions to nonnull. (allocation_state::dump_to_pp): Update for conversion from api to deallocator_set. (allocation_state::get_nonnull): Likewise. (malloc_state_machine::malloc_state_machine): Likewise. (malloc_state_machine::~malloc_state_machine): New. (malloc_state_machine::add_state): Update for conversion from api to deallocator_set. (malloc_state_machine::get_or_create_custom_deallocator_set): New. (malloc_state_machine::maybe_create_custom_deallocator_set): New. (malloc_state_machine::get_or_create_deallocator): New. (malloc_state_machine::on_stmt): Update for conversion from api to deallocator_set. Handle "__attribute__((malloc(FOO)))", and the special attribute set on FOO. (malloc_state_machine::on_allocator_call): Update for conversion from api to deallocator_set. Add "returns_nonnull" param and use it to affect which state to transition to. (malloc_state_machine::on_deallocator_call): Update for conversion from api to deallocator_set. gcc/ChangeLog: * attribs.h (fndecl_dealloc_argno): New decl. * builtins.c (call_dealloc_argno): Split out second half of function into... (fndecl_dealloc_argno): New. * doc/extend.texi (Common Function Attributes): Document the interaction between the analyzer and the malloc attribute. * doc/invoke.texi (Static Analyzer Options): Likewise. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/attr-malloc-1.c: New test. * gcc.dg/analyzer/attr-malloc-2.c: New test. * gcc.dg/analyzer/attr-malloc-4.c: New test. * gcc.dg/analyzer/attr-malloc-5.c: New test. * gcc.dg/analyzer/attr-malloc-6.c: New test. * gcc.dg/analyzer/attr-malloc-CVE-2019-19078-usb-leak.c: New test. * gcc.dg/analyzer/attr-malloc-misuses.c: New test.
Diffstat (limited to 'gcc/attribs.h')
-rw-r--r--gcc/attribs.h2
1 files changed, 2 insertions, 0 deletions
diff --git a/gcc/attribs.h b/gcc/attribs.h
index 9e3e56a..21d28a4 100644
--- a/gcc/attribs.h
+++ b/gcc/attribs.h
@@ -310,4 +310,6 @@ extern void init_attr_rdwr_indices (rdwr_map *, tree);
extern attr_access *get_parm_access (rdwr_map &, tree,
tree = current_function_decl);
+extern unsigned fndecl_dealloc_argno (tree fndecl);
+
#endif // GCC_ATTRIBS_H