Skip to content
Snippets Groups Projects
Commit a61aaee6 authored by David Malcolm's avatar David Malcolm
Browse files

analyzer: fixes to free of non-heap detection [PR104560]


PR analyzer/104560 reports various false positives from
-Wanalyzer-free-of-non-heap seen with rdma-core, on what's
effectively:

  free (&ptr->field)

where in this case "field" is the first element of its struct, and thus
&ptr->field == ptr, and could be on the heap.

The root cause is due to malloc_state_machine::on_stmt making
  "LHS = &EXPR;"
transition LHS from start to non_heap when EXPR is not a MEM_REF;
this assumption doesn't hold for the above case.

This patch eliminates that state transition, instead relying on
malloc_state_machine::get_default_state to detect regions known to
not be on the heap.
Doing so fixes the false positive, but eliminates some events relating
to free-of-alloca identifying the alloca, so the patch also reworks
free_of_non_heap to capture which region has been freed, adding
region creation events to diagnostic paths, so that the alloca calls
can be identified, and using the memory space of the region for more
precise wording of the diagnostic.
The improvement to malloc_state_machine::get_default_state also
means we now detect attempts to free VLAs, functions and code labels.

In doing so I spotted that I wasn't adding region creation events for
regions for global variables, and for cases where an allocation is the
last stmt within its basic block, so the patch also fixes these issues.

gcc/analyzer/ChangeLog:
	PR analyzer/104560
	* diagnostic-manager.cc (diagnostic_manager::build_emission_path):
	Add region creation events for globals of interest.
	(null_assignment_sm_context::get_old_program_state): New.
	(diagnostic_manager::add_events_for_eedge): Move check for
	changing dynamic extents from PK_BEFORE_STMT case to after the
	switch on the dst_point's kind so that we can emit them for the
	final stmt in a basic block.
	* engine.cc (impl_sm_context::get_old_program_state): New.
	* sm-malloc.cc (malloc_state_machine::get_default_state): Rewrite
	detection of m_non_heap to use get_memory_space.
	(free_of_non_heap::free_of_non_heap): Add freed_reg param.
	(free_of_non_heap::subclass_equal_p): Update for changes to
	fields.
	(free_of_non_heap::emit): Drop m_kind in favor of
	get_memory_space.
	(free_of_non_heap::describe_state_change): Remove logic for
	detecting alloca.
	(free_of_non_heap::mark_interesting_stuff): Add region-creation of
	m_freed_reg.
	(free_of_non_heap::get_memory_space): New.
	(free_of_non_heap::kind): Drop enum.
	(free_of_non_heap::m_freed_reg): New field.
	(free_of_non_heap::m_kind): Drop field.
	(malloc_state_machine::on_stmt): Drop transition to m_non_heap.
	(malloc_state_machine::handle_free_of_non_heap): New function,
	split out from on_deallocator_call and on_realloc_call, adding
	detection of the freed region.
	(malloc_state_machine::on_deallocator_call): Use it.
	(malloc_state_machine::on_realloc_call): Likewise.
	* sm.h (sm_context::get_old_program_state): New vfunc.

gcc/testsuite/ChangeLog:
	PR analyzer/104560
	* g++.dg/analyzer/placement-new.C: Update expected wording.
	* g++.dg/analyzer/pr100244.C: Likewise.
	* gcc.dg/analyzer/attr-malloc-1.c (test_7): Likewise.
	* gcc.dg/analyzer/malloc-1.c (test_24): Likewise.
	(test_25): Likewise.
	(test_26): Likewise.
	(test_50a, test_50b, test_50c): New.
	* gcc.dg/analyzer/malloc-callbacks.c (test_5): Update expected
	wording.
	* gcc.dg/analyzer/malloc-paths-8.c: Likewise.
	* gcc.dg/analyzer/pr104560-1.c: New test.
	* gcc.dg/analyzer/pr104560-2.c: New test.
	* gcc.dg/analyzer/realloc-1.c (test_7): Updated expected wording.
	* gcc.dg/analyzer/vla-1.c (test_2): New.  Prune output from
	-Wfree-nonheap-object.

Signed-off-by: default avatarDavid Malcolm <dmalcolm@redhat.com>
parent 24ca9732
No related branches found
No related tags found
Loading
Showing
with 262 additions and 117 deletions
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment