From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id CA73F3844012; Wed, 9 Sep 2020 21:24:35 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org CA73F3844012 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1599686675; bh=z2UwOHEFWU+6mJPzYyugFRZ9nVphXMc/BGttm1ERoxw=; h=From:To:Subject:Date:In-Reply-To:References:From; b=kmVHI0iAq1Z6yjsyUwEcQqXZUy6RvlMZ9hfDQnmNzqecTpRNI+pHaqCgt/MdkNUU4 MsdCBqvnel5+rGiIJZP98Eajfv+QC+LSCTWoD6XTqxr9yCN4X2Ai9JC0Own2fhjocy 7ueVMxldkslMEwuq0PWbjedVGOsOlORnZuMJez/A= From: "cvs-commit at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug analyzer/94355] support for C++ new expression Date: Wed, 09 Sep 2020 21:24:35 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: analyzer X-Bugzilla-Version: 10.0 X-Bugzilla-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: cvs-commit at gcc dot gnu.org X-Bugzilla-Status: UNCONFIRMED X-Bugzilla-Resolution: X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: dmalcolm at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: Message-ID: In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-BeenThere: gcc-bugs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-bugs mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 09 Sep 2020 21:24:36 -0000 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D94355 --- Comment #2 from CVS Commits --- The master branch has been updated by David Malcolm : https://gcc.gnu.org/g:1690a839cff2e0276017a013419d81d675bbf69d commit r11-3090-g1690a839cff2e0276017a013419d81d675bbf69d Author: David Malcolm Date: Fri Aug 28 13:43:56 2020 -0400 analyzer: generalize sm-malloc to new/delete [PR94355] This patch generalizes the state machine in sm-malloc.c to support multiple allocator APIs, and adds just enough support for C++ new and delete to demonstrate the feature, allowing for detection of code paths where the result of new in C++ can leak - for some crude examples, at least (bearing in mind that the analyzer doesn't yet know about e.g. vfuncs, exceptions, inheritance, RTTI, etc) It also implements a new warning: -Wanalyzer-mismatching-deallocation. For example: demo.cc: In function 'void test()': demo.cc:8:8: warning: 'f' should have been deallocated with 'delete' but was deallocated with 'free' [CWE-762] [-Wanalyzer-mismatching-deallocation] 8 | free (f); | ~~~~~^~~ 'void test()': events 1-2 | | 7 | foo *f =3D new foo; | | ^~~ | | | | | (1) allocated here (expects deallocation wi= th 'delete') | 8 | free (f); | | ~~~~~~~~ | | | | | (2) deallocated with 'free' here; allocation at (1) expects deallocation with 'delete' | The patch also adds just enough knowledge of exception-handling to suppress a false positive from -Wanalyzer-malloc-leak on g++.dg/analyzer/pr96723.C on the exception-handling CFG edge after operator new. It does this by adding a constraint that the result is NULL if an exception was thrown from operator new, since the result from operator new is lost when following that exception-handling CFG edge. gcc/analyzer/ChangeLog: PR analyzer/94355 * analyzer.opt (Wanalyzer-mismatching-deallocation): New warnin= g. * region-model-impl-calls.cc (region_model::impl_call_operator_new): New. (region_model::impl_call_operator_delete): New. * region-model.cc (region_model::on_call_pre): Detect operator = new and operator delete. (region_model::on_call_post): Likewise. (region_model::maybe_update_for_edge): Detect EH edges and call= ... (region_model::apply_constraints_for_exception): New function. * region-model.h (region_model::impl_call_operator_new): New de= cl. (region_model::impl_call_operator_delete): New decl. (region_model::apply_constraints_for_exception): New decl. * sm-malloc.cc (enum resource_state): New. (struct allocation_state): New state subclass. (enum wording): New. (struct api): New. (malloc_state_machine::custom_data_t): New typedef. (malloc_state_machine::add_state): New decl. (malloc_state_machine::m_unchecked) (malloc_state_machine::m_nonnull) (malloc_state_machine::m_freed): Delete these states in favor of... (malloc_state_machine::m_malloc) (malloc_state_machine::m_scalar_new) (malloc_state_machine::m_vector_new): ...this new api instances, which own their own versions of these states. (malloc_state_machine::on_allocator_call): New decl. (malloc_state_machine::on_deallocator_call): New decl. (api::api): New ctor. (dyn_cast_allocation_state): New. (as_a_allocation_state): New. (get_rs): New. (unchecked_p): New. (nonnull_p): New. (freed_p): New. (malloc_diagnostic::describe_state_change): Use unchecked_p and nonnull_p. (class mismatching_deallocation): New. (double_free::double_free): Add funcname param for initializing m_funcname. (double_free::emit): Use m_funcname in warning message rather than hardcoding "free". (double_free::describe_state_change): Likewise. Use freed_p. (double_free::describe_call_with_state): Use freed_p. (double_free::describe_final_event): Use m_funcname in message rather than hardcoding "free". (double_free::m_funcname): New field. (possible_null::describe_state_change): Use unchecked_p. (possible_null::describe_return_of_state): Likewise. (use_after_free::use_after_free): Add param for initializing m_= api. (use_after_free::emit): Use m_api->m_dealloc_funcname in message rather than hardcoding "free". (use_after_free::describe_state_change): Use freed_p. Change t= he wording of the message based on the API. (use_after_free::describe_final_event): Use m_api->m_dealloc_funcname in message rather than hardcoding "free". Change the wording of the message based on the API. (use_after_free::m_api): New field. (malloc_leak::describe_state_change): Use unchecked_p. Update for renaming of m_malloc_event to m_alloc_event. (malloc_leak::describe_final_event): Update for renaming of m_malloc_event to m_alloc_event. (malloc_leak::m_malloc_event): Rename... (malloc_leak::m_alloc_event): ...to this. (free_of_non_heap::free_of_non_heap): Add param for initializing m_funcname. (free_of_non_heap::emit): Use m_funcname in message rather than hardcoding "free". (free_of_non_heap::describe_final_event): Likewise. (free_of_non_heap::m_funcname): New field. (allocation_state::dump_to_pp): New. (allocation_state::get_nonnull): New. (malloc_state_machine::malloc_state_machine): Update for changes to state fields and new api fields. (malloc_state_machine::add_state): New. (malloc_state_machine::on_stmt): Move malloc/calloc handling to on_allocator_call and call it, passing in the API pointer. Likewise for free, moving it to on_deallocator_call. Handle ca= lls to operator new and delete in an analogous way. Use unchecked_p when testing for possibly-null-arg and possibly-null-deref, and transition to the non-null for the correct API. Remove redunda= nt node param from call to on_zero_assignment. Use freed_p for use-after-free check, and pass in API. (malloc_state_machine::on_allocator_call): New, based on code in on_stmt. (malloc_state_machine::on_deallocator_call): Likewise. (malloc_state_machine::on_phi): Mark node param with ATTRIBUTE_UNUSED; don't pass it to on_zero_assignment. (malloc_state_machine::on_condition): Mark node param with ATTRIBUTE_UNUSED. Replace on_transition calls with get_state a= nd set_next_state pairs, transitioning to the non-null state for t= he appropriate API. (malloc_state_machine::can_purge_p): Port to new state approach. (malloc_state_machine::on_zero_assignment): Replace on_transiti= on calls with get_state and set_next_state pairs. Drop redundant node param. * sm.h (state_machine::add_custom_state): New. gcc/ChangeLog: PR analyzer/94355 * doc/invoke.texi: Document -Wanalyzer-mismatching-deallocation. gcc/testsuite/ChangeLog: PR analyzer/94355 * g++.dg/analyzer/new-1.C: New test. * g++.dg/analyzer/new-vs-malloc.C: New test.=