On Sat, 2026-02-07 at 00:37 +0100, Federico Angelilli wrote:

Hi Federico

> Previously the analyzer emitted a -Wanalyzer-null-dereference even
> when
> the target pointer's address space allowed accesses at address 0.
> 
> This patch uses the targetm.addr_space.zero_address_valid hook to
> correctly ignore such cases.
> 
> Tested on x86_64-pc-linux-gnu.

Thanks for filing the bug and creating the patch.

As it happens, I also wrote a patch for this yesterday which survived
my overnight testing, and I was about to push it when I saw your email
:-)

I'm attaching my patch for reference.

I think I prefer the logic from my patch (having a subroutine for the
test and using it in two places), but it looks like the testsuite
coverage from your patch is better than mine.

Would you be able to have a go at merging the best parts of the two
patches and posting an updated version?  Or would you prefer me to do
that?  (I don't mind either way, I just want to avoid more duplicated
work)

Thanks again for working on this.
Dave

> 
> gcc/analyzer/ChangeLog:
>       PR analyzer/123981
> 
>       * sm-malloc.cc (malloc_state_machine::on_stmt): Check
>       if zero access is valid for the pointer's address space.
> 
> gcc/testsuite/ChangeLog:
>       PR analyzer/123981
> 
>       * gcc.dg/analyzer/null-deref-pr123981-1.c: New test.
>       * gcc.dg/analyzer/null-deref-pr123981-2.c: New test.
> 
> Signed-off-by: Federico Angelilli <[email protected]>
> ---
>  gcc/analyzer/sm-malloc.cc                            |  5 +++++
>  .../gcc.dg/analyzer/null-deref-pr123981-1.c          | 12
> ++++++++++++
>  .../gcc.dg/analyzer/null-deref-pr123981-2.c          |  8 ++++++++
>  3 files changed, 25 insertions(+)
>  create mode 100644 gcc/testsuite/gcc.dg/analyzer/null-deref-
> pr123981-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/analyzer/null-deref-
> pr123981-2.c
> 
> diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc
> index 6972a55d7fd..fb12b64d4be 100644
> --- a/gcc/analyzer/sm-malloc.cc
> +++ b/gcc/analyzer/sm-malloc.cc
> @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "system.h"
>  #include "coretypes.h"
>  #include "make-unique.h"
> +#include "target.h"
>  #include "tree.h"
>  #include "function.h"
>  #include "basic-block.h"
> @@ -2267,6 +2268,10 @@ malloc_state_machine::on_stmt (sm_context
> &sm_ctxt,
>           }
>         else if (state == m_null)
>           {
> +           addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (op));
> +           if (targetm.addr_space.zero_address_valid (as))
> +             continue;
> +
>             tree diag_arg = sm_ctxt.get_diagnostic_tree (arg);
>             sm_ctxt.warn (node, stmt, arg,
>                           make_unique<null_deref> (*this,
> diag_arg));
> diff --git a/gcc/testsuite/gcc.dg/analyzer/null-deref-pr123981-1.c
> b/gcc/testsuite/gcc.dg/analyzer/null-deref-pr123981-1.c
> new file mode 100644
> index 00000000000..2df9d7813d6
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/analyzer/null-deref-pr123981-1.c
> @@ -0,0 +1,12 @@
> +/* { dg-do compile { target x86_64-*-* } } */
> +/* { dg-additional-options "-mfsgsbase" } */
> +
> +#include <immintrin.h>
> +#define getgs() ((int __seg_gs *)0)
> +
> +int main()
> +{
> +  static int gsval = 42;
> +  _writegsbase_u64((unsigned long long)&gsval);
> +  return *getgs(); /* { dg-bogus "-Wanalyzer-null-dereference" } */
> +}
> diff --git a/gcc/testsuite/gcc.dg/analyzer/null-deref-pr123981-2.c
> b/gcc/testsuite/gcc.dg/analyzer/null-deref-pr123981-2.c
> new file mode 100644
> index 00000000000..03a48349244
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/analyzer/null-deref-pr123981-2.c
> @@ -0,0 +1,8 @@
> +/* { dg-do compile { target { i?86-*-* x86_64-*-* } } } */
> +
> +#define getfs() ((int __seg_fs *)0)
> +
> +int main()
> +{
> +  return *getfs(); /* { dg-bogus "-Wanalyzer-null-dereference" } */
> +}

From f3fb275b53096ba113bf032538c56ec97f18ace9 Mon Sep 17 00:00:00 2001
From: David Malcolm <[email protected]>
Date: Fri, 6 Feb 2026 14:53:37 -0500
Subject: [PATCH 6/7] Suppress -Wanalyzer-{possible}-null-deref in some address
 spaces [PR123981]

gcc/analyzer/ChangeLog:
	PR analyzer/123981
	* sm-malloc.cc: Include "target.h".
	(zero_address_valid_p): New.
	(malloc_state_machine::on_stmt): Guard possible_null_deref and
	null_deref with !zero_address_valid_p.

gcc/testsuite/ChangeLog:
	PR analyzer/123981
	* gcc.dg/analyzer/null-deref-address-space-pr123981.c: New test.

Signed-off-by: David Malcolm <[email protected]>
---
 gcc/analyzer/sm-malloc.cc                     | 46 +++++++++++++++----
 .../null-deref-address-space-pr123981.c       |  9 ++++
 2 files changed, 45 insertions(+), 10 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/null-deref-address-space-pr123981.c

diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc
index 657ebd3aff7a..2c036fc7d8bc 100644
--- a/gcc/analyzer/sm-malloc.cc
+++ b/gcc/analyzer/sm-malloc.cc
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "stringpool.h"
 #include "attribs.h"
 #include "xml-printer.h"
+#include "target.h"
 
 #include "analyzer/analyzer-logging.h"
 #include "analyzer/sm.h"
@@ -2087,6 +2088,25 @@ malloc_state_machine::handle_nonnull (sm_context &sm_ctxt,
     maybe_assume_non_null (sm_ctxt, arg);
 }
 
+/* Return true if it's valid to dereference the zero value of PTR_TYPE,
+   or false if we should warn on it.  */
+
+static bool
+zero_address_valid_p (const_tree ptr_type)
+{
+  gcc_assert (POINTER_TYPE_P (ptr_type));
+
+  /* Some targets have address spaces in which it's valid
+     to dereference zero.  */
+  addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (ptr_type));
+  if (!ADDR_SPACE_GENERIC_P (as)
+      && targetm.addr_space.zero_address_valid (as))
+    return true;
+
+  /* Invalid.  */
+  return false;
+}
+
 /* Implementation of state_machine::on_stmt vfunc for malloc_state_machine.  */
 
 bool
@@ -2250,19 +2270,25 @@ malloc_state_machine::on_stmt (sm_context &sm_ctxt,
 	    maybe_assume_non_null (sm_ctxt, arg);
 	  else if (unchecked_p (state))
 	    {
-	      tree diag_arg = sm_ctxt.get_diagnostic_tree (arg);
-	      sm_ctxt.warn (arg,
-			    std::make_unique<possible_null_deref> (*this,
-								   diag_arg));
-	      const allocation_state *astate = as_a_allocation_state (state);
-	      sm_ctxt.set_next_state (arg, astate->get_nonnull ());
+	      if (!zero_address_valid_p (TREE_TYPE (arg)))
+		{
+		  tree diag_arg = sm_ctxt.get_diagnostic_tree (arg);
+		  sm_ctxt.warn (arg,
+				std::make_unique<possible_null_deref> (*this,
+								       diag_arg));
+		  const allocation_state *astate = as_a_allocation_state (state);
+		  sm_ctxt.set_next_state (arg, astate->get_nonnull ());
+		}
 	    }
 	  else if (state == m_null)
 	    {
-	      tree diag_arg = sm_ctxt.get_diagnostic_tree (arg);
-	      sm_ctxt.warn (arg,
-			    std::make_unique<null_deref> (*this, diag_arg));
-	      sm_ctxt.set_next_state (arg, m_stop);
+	      if (!zero_address_valid_p (TREE_TYPE (arg)))
+		{
+		  tree diag_arg = sm_ctxt.get_diagnostic_tree (arg);
+		  sm_ctxt.warn (arg,
+				std::make_unique<null_deref> (*this, diag_arg));
+		  sm_ctxt.set_next_state (arg, m_stop);
+		}
 	    }
 	  else if (freed_p (state))
 	    {
diff --git a/gcc/testsuite/gcc.dg/analyzer/null-deref-address-space-pr123981.c b/gcc/testsuite/gcc.dg/analyzer/null-deref-address-space-pr123981.c
new file mode 100644
index 000000000000..0a7b2a4b45d6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/null-deref-address-space-pr123981.c
@@ -0,0 +1,9 @@
+/* Verify that we don't warn for address spaces in which
+   zero is a valid address.  */
+
+/* { dg-do compile { target x86_64-*-* } } */
+
+int test_1 ()
+{
+  return *((int __seg_gs *)0); /* { dg-bogus "dereference of NULL" } */
+}
-- 
2.26.3

Reply via email to