analyzer: add support for GLib memory functions

Message ID 20261001151851.5807-1-dishusangwan04@gmail.com
State New
Headers
Series analyzer: add support for GLib memory functions |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_simplebootstrap_build--master-arm-bootstrap success Build passed
linaro-tcwg-bot/tcwg_simplebootstrap_build--master-aarch64-bootstrap success Build passed

Commit Message

dishu305 Oct. 1, 2026, 3:18 p.m. UTC
  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
  

Patch

diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc
index 72e6e28e2..ff8e19f0b 100644
--- a/gcc/analyzer/sm-malloc.cc
+++ b/gcc/analyzer/sm-malloc.cc
@@ -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);
diff --git a/gcc/testsuite/gcc.dg/analyzer/glib-malloc-leak.c b/gcc/testsuite/gcc.dg/analyzer/glib-malloc-leak.c
new file mode 100644
index 000000000..0a5622c1f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/glib-malloc-leak.c
@@ -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;
+}