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
