This patch teaches the GCC static analyzer to recognize GLib's memory
allocation and deallocation functions, preventing false negatives for
memory leaks in GTK/GNOME applications.
gcc/analyzer/ChangeLog:
* sm-malloc.cc (known_allocator_p): Add checks for g_malloc,
g_malloc0, g_realloc, g_new, and g_new0.
(get_deallocator): Add check for g_free.
(malloc_state_machine::on_call): Add check for g_free.
gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/glib-malloc-leak.c: New test.
Signed-off-by: dishu305 <dishusangwan04@gmail.com>
---
gcc/analyzer/sm-malloc.cc | 13 +++++++---
.../gcc.dg/analyzer/glib-malloc-leak.c | 26 +++++++++++++++++++
2 files changed, 36 insertions(+), 3 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/analyzer/glib-malloc-leak.c
@@ -1964,7 +1964,8 @@ malloc_state_machine::get_or_create_deallocator (tree deallocator_fndecl)
deallocator *d;
if (is_named_call_p (deallocator_fndecl, "free")
|| is_std_named_call_p (deallocator_fndecl, "free")
- || is_named_call_p (deallocator_fndecl, "__builtin_free"))
+ || is_named_call_p (deallocator_fndecl, "__builtin_free")
+ || is_named_call_p (deallocator_fndecl, "g_free"))
d = &m_free.m_deallocator;
else
{
@@ -2006,7 +2007,12 @@ known_allocator_p (const_tree fndecl, const gcall &call)
|| is_std_named_call_p (fndecl, "malloc", call, 1)
|| is_std_named_call_p (fndecl, "calloc", call, 2)
|| is_named_call_p (fndecl, "strdup", call, 1)
- || is_named_call_p (fndecl, "strndup", call, 2))
+ || is_named_call_p (fndecl, "strndup", call, 2)
+ || is_named_call_p (fndecl, "g_malloc", call, 1)
+ || is_named_call_p (fndecl, "g_malloc0", call, 1)
+ || is_named_call_p (fndecl, "g_realloc", call, 2)
+ || is_named_call_p (fndecl, "g_new", call, 2)
+ || is_named_call_p (fndecl, "g_new0", call, 2))
return true;
/* ... or it is a builtin allocator that allocates objects freed with
@@ -2161,7 +2167,8 @@ malloc_state_machine::on_stmt (sm_context &sm_ctxt,
if (is_named_call_p (callee_fndecl, "free", call, 1)
|| is_std_named_call_p (callee_fndecl, "free", call, 1)
- || is_named_call_p (callee_fndecl, "__builtin_free", call, 1))
+ || is_named_call_p (callee_fndecl, "__builtin_free", call, 1)
+ || is_named_call_p (callee_fndecl, "g_free", call, 1))
{
on_deallocator_call (sm_ctxt, call,
&m_free.m_deallocator, 0);
new file mode 100644
@@ -0,0 +1,26 @@
+/* { dg-do run } */
+/* { dg-options "-fanalyzer" } */
+
+/* Test that the analyzer recognizes g_malloc and g_free.
+ It should report a leak for ptr1, but not for ptr2. */
+
+extern void *g_malloc (unsigned long);
+extern void g_free (void *);
+
+void test_leak (void)
+{
+ void *ptr1 = g_malloc (100); /* { dg-warning "leak of 'ptr1'" } */
+}
+
+void test_no_leak (void)
+{
+ void *ptr2 = g_malloc (200);
+ g_free (ptr2);
+}
+
+int main (void)
+{
+ test_leak ();
+ test_no_leak ();
+ return 0;
+}