public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r14-6239] analyzer: fix taint false positives with UNKNOWN [PR112850]
@ 2023-12-07  0:26 David Malcolm
  0 siblings, 0 replies; only message in thread
From: David Malcolm @ 2023-12-07  0:26 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:08b7462d3ad8e5acd941b7c777c5b26b4064d686

commit r14-6239-g08b7462d3ad8e5acd941b7c777c5b26b4064d686
Author: David Malcolm <dmalcolm@redhat.com>
Date:   Wed Dec 6 19:25:26 2023 -0500

    analyzer: fix taint false positives with UNKNOWN [PR112850]
    
    PR analyzer/112850 reports a false positive from
    -Wanalyzer-tainted-allocation-size on the Linux kernel [1] where
    -fanalyzer complains that an allocation size is attacker-controlled
    despite the value being correctly sanitized against upper and lower
    limits.
    
    The root cause is that the expression is sufficiently complex
    to exceed the -param=analyzer-max-svalue-depth= threshold,
    currently at 12, with depth 13, and so it is treated as UNKNOWN.
    Hence the sanitizations are seen as comparisons of an UNKNOWN
    symbolic value against constants, and these were being ignored
    by the taint state machine.
    
    The expression in question is relatively typical for those seen in
    Linux kernel ioctl handlers, and I was surprised that it had exceeded
    the analyzer's default expression complexity limit.
    
    This patch addresses this problem in three ways:
    (a) the default value of the threshold parameter is increased, from 12
    to 18, so that such expressions are precisely handled
    (b) adding a new -Wanalyzer-symbol-too-complex to warn when the symbol
    complexity limit is reached.  This is off by default for users, and
    on by default in the test suite.
    (c) the taint state machine handles comparisons against UNKNOWN svalues
    by dropping all taint information on that execution path, so that if
    the complexity limit has been exceeded we don't generate false positives
    
    As well as fixing the taint false positive (PR analyzer/112850), the
    patch also fixes a couple of leak false positives seen on flex-generated
    scanners (PR analyzer/103546).
    
    [1] specifically, in sound/core/rawmidi.c's handler for
    SNDRV_RAWMIDI_STREAM_OUTPUT.
    
    gcc/ChangeLog:
            PR analyzer/103546
            PR analyzer/112850
            * doc/invoke.texi: Add -Wanalyzer-symbol-too-complex.
    
    gcc/analyzer/ChangeLog:
            PR analyzer/103546
            PR analyzer/112850
            * analyzer.opt (-param=analyzer-max-svalue-depth=): Increase from
            12 to 18.
            (Wanalyzer-symbol-too-complex): New.
            * diagnostic-manager.cc
            (null_assignment_sm_context::clear_all_per_svalue_state): New.
            * engine.cc (impl_sm_context::clear_all_per_svalue_state): New.
            * program-state.cc (sm_state_map::clear_all_per_svalue_state):
            New.
            * program-state.h (sm_state_map::clear_all_per_svalue_state): New
            decl.
            * region-model-manager.cc
            (region_model_manager::reject_if_too_complex): Add
            -Wanalyzer-symbol-too-complex.
            * sm-taint.cc (taint_state_machine::on_condition): Handle
            comparisons against UNKNOWN.
            * sm.h (sm_context::clear_all_per_svalue_state): New.
    
    gcc/testsuite/ChangeLog:
            PR analyzer/103546
            PR analyzer/112850
            * c-c++-common/analyzer/call-summaries-pr107158-2.c: Add
            -Wno-analyzer-symbol-too-complex.
            * c-c++-common/analyzer/call-summaries-pr107158.c: Likewise.
            * c-c++-common/analyzer/deref-before-check-pr109060-haproxy-cfgparse.c:
            Likewise.
            * c-c++-common/analyzer/feasibility-3.c: Add
            -Wno-analyzer-too-complex and -Wno-analyzer-symbol-too-complex.
            * c-c++-common/analyzer/flex-with-call-summaries.c: Add
            -Wno-analyzer-symbol-too-complex.  Remove fail for
            PR analyzer/103546 leak false positive.
            * c-c++-common/analyzer/flex-without-call-summaries.c: Remove
            xfail for PR analyzer/103546 leak false positive.
            * c-c++-common/analyzer/infinite-recursion-3.c: Add
            -Wno-analyzer-symbol-too-complex.
            * c-c++-common/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early-O2.c:
            Likewise.
            * c-c++-common/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early.c:
            Likewise.
            * c-c++-common/analyzer/null-deref-pr108400-SoftEtherVPN-WebUi.c:
            Likewise.
            * c-c++-common/analyzer/null-deref-pr108806-qemu.c: Likewise.
            * c-c++-common/analyzer/null-deref-pr108830.c: Likewise.
            * c-c++-common/analyzer/pr94596.c: Likewise.
            * c-c++-common/analyzer/strtok-2.c: Likewise.
            * c-c++-common/analyzer/strtok-4.c: Add -Wno-analyzer-too-complex
            and -Wno-analyzer-symbol-too-complex.
            * c-c++-common/analyzer/strtok-cppreference.c: Likewise.
            * gcc.dg/analyzer/analyzer.exp: Add -Wanalyzer-symbol-too-complex
            to DEFAULT_CFLAGS.
            * gcc.dg/analyzer/attr-const-3.c: Add
            -Wno-analyzer-symbol-too-complex.
            * gcc.dg/analyzer/call-summaries-pr107072.c: Likewise.
            * gcc.dg/analyzer/doom-s_sound-pr108867.c: Likewise.
            * gcc.dg/analyzer/explode-4.c: Likewise.
            * gcc.dg/analyzer/null-deref-pr102671-1.c: Likewise.
            * gcc.dg/analyzer/null-deref-pr105755.c: Likewise.
            * gcc.dg/analyzer/out-of-bounds-curl.c: Likewise.
            * gcc.dg/analyzer/pr101503.c: Likewise.
            * gcc.dg/analyzer/pr103892.c: Add -Wno-analyzer-too-complex and
            -Wno-analyzer-symbol-too-complex.
            * gcc.dg/analyzer/pr94851-4.c: Add
            -Wno-analyzer-symbol-too-complex.
            * gcc.dg/analyzer/pr96860-1.c: Likewise.
            * gcc.dg/analyzer/pr96860-2.c: Likewise.
            * gcc.dg/analyzer/pr98918.c: Likewise.
            * gcc.dg/analyzer/pr99044-2.c: Likewise.
            * gcc.dg/analyzer/uninit-pr108806-qemu.c: Likewise.
            * gcc.dg/analyzer/use-after-free.c: Add -Wno-analyzer-too-complex
            and -Wno-analyzer-symbol-too-complex.
            * gcc.dg/plugin/plugin.exp: Add new tests for
            analyzer_kernel_plugin.c.
            * gcc.dg/plugin/taint-CVE-2011-0521-4.c: Update expected results.
            * gcc.dg/plugin/taint-CVE-2011-0521-5.c: Likewise.
            * gcc.dg/plugin/taint-CVE-2011-0521-6.c: Likewise.
            * gcc.dg/plugin/taint-CVE-2011-0521-5-fixed.c: Remove xfail.
            * gcc.dg/plugin/taint-pr112850-precise.c: New test.
            * gcc.dg/plugin/taint-pr112850-too-complex.c: New test.
            * gcc.dg/plugin/taint-pr112850-unsanitized.c: New test.
            * gcc.dg/plugin/taint-pr112850.c: New test.
    
    Signed-off-by: David Malcolm <dmalcolm@redhat.com>

Diff:
---
 gcc/analyzer/analyzer.opt                          |  6 ++-
 gcc/analyzer/diagnostic-manager.cc                 |  5 +++
 gcc/analyzer/engine.cc                             |  5 +++
 gcc/analyzer/program-state.cc                      |  8 ++++
 gcc/analyzer/program-state.h                       |  1 +
 gcc/analyzer/region-model-manager.cc               | 10 +++++
 gcc/analyzer/sm-taint.cc                           | 14 ++++++
 gcc/analyzer/sm.h                                  |  2 +
 gcc/doc/invoke.texi                                | 14 ++++++
 .../analyzer/call-summaries-pr107158-2.c           |  2 +-
 .../analyzer/call-summaries-pr107158.c             |  2 +-
 .../deref-before-check-pr109060-haproxy-cfgparse.c |  2 +
 .../c-c++-common/analyzer/feasibility-3.c          |  2 +
 .../analyzer/flex-with-call-summaries.c            |  4 +-
 .../analyzer/flex-without-call-summaries.c         |  3 +-
 .../c-c++-common/analyzer/infinite-recursion-3.c   |  2 +-
 ...-deref-pr108251-smp_fetch_ssl_fc_has_early-O2.c |  2 +-
 ...ull-deref-pr108251-smp_fetch_ssl_fc_has_early.c |  1 +
 .../null-deref-pr108400-SoftEtherVPN-WebUi.c       |  2 +
 .../analyzer/null-deref-pr108806-qemu.c            |  2 +
 .../c-c++-common/analyzer/null-deref-pr108830.c    |  2 +-
 gcc/testsuite/c-c++-common/analyzer/pr94596.c      |  3 ++
 gcc/testsuite/c-c++-common/analyzer/strtok-2.c     |  2 +
 gcc/testsuite/c-c++-common/analyzer/strtok-4.c     |  2 +
 .../c-c++-common/analyzer/strtok-cppreference.c    |  2 +
 gcc/testsuite/gcc.dg/analyzer/analyzer.exp         |  2 +-
 gcc/testsuite/gcc.dg/analyzer/attr-const-3.c       |  2 +-
 .../gcc.dg/analyzer/call-summaries-pr107072.c      |  2 +-
 .../gcc.dg/analyzer/doom-s_sound-pr108867.c        |  2 +-
 gcc/testsuite/gcc.dg/analyzer/explode-4.c          |  2 +-
 .../gcc.dg/analyzer/null-deref-pr102671-1.c        |  2 +-
 .../gcc.dg/analyzer/null-deref-pr105755.c          |  2 +-
 gcc/testsuite/gcc.dg/analyzer/out-of-bounds-curl.c |  2 +-
 gcc/testsuite/gcc.dg/analyzer/pr101503.c           |  2 +-
 gcc/testsuite/gcc.dg/analyzer/pr103892.c           |  2 +-
 gcc/testsuite/gcc.dg/analyzer/pr94851-4.c          |  2 +-
 gcc/testsuite/gcc.dg/analyzer/pr96860-1.c          |  2 +-
 gcc/testsuite/gcc.dg/analyzer/pr96860-2.c          |  2 +-
 gcc/testsuite/gcc.dg/analyzer/pr98918.c            |  2 +
 gcc/testsuite/gcc.dg/analyzer/pr99044-2.c          |  2 +
 .../gcc.dg/analyzer/uninit-pr108806-qemu.c         |  2 +
 gcc/testsuite/gcc.dg/analyzer/use-after-free.c     |  2 +
 gcc/testsuite/gcc.dg/plugin/plugin.exp             |  6 ++-
 .../gcc.dg/plugin/taint-CVE-2011-0521-4.c          |  4 +-
 .../gcc.dg/plugin/taint-CVE-2011-0521-5-fixed.c    |  3 +-
 .../gcc.dg/plugin/taint-CVE-2011-0521-5.c          |  4 +-
 .../gcc.dg/plugin/taint-CVE-2011-0521-6.c          |  4 +-
 .../gcc.dg/plugin/taint-pr112850-precise.c         | 50 +++++++++++++++++++++
 .../gcc.dg/plugin/taint-pr112850-too-complex.c     | 51 ++++++++++++++++++++++
 .../gcc.dg/plugin/taint-pr112850-unsanitized.c     | 50 +++++++++++++++++++++
 gcc/testsuite/gcc.dg/plugin/taint-pr112850.c       | 47 ++++++++++++++++++++
 51 files changed, 321 insertions(+), 32 deletions(-)

diff --git a/gcc/analyzer/analyzer.opt b/gcc/analyzer/analyzer.opt
index a3c30caf2ab..d0fe5a43788 100644
--- a/gcc/analyzer/analyzer.opt
+++ b/gcc/analyzer/analyzer.opt
@@ -43,7 +43,7 @@ Common Joined UInteger Var(param_analyzer_max_recursion_depth) Init(2) Param
 The maximum number of times a callsite can appear in a call stack within the analyzer, before terminating analysis of a call that would recurse deeper.
 
 -param=analyzer-max-svalue-depth=
-Common Joined UInteger Var(param_analyzer_max_svalue_depth) Init(12) Param
+Common Joined UInteger Var(param_analyzer_max_svalue_depth) Init(18) Param
 The maximum depth of a symbolic value, before approximating the value as unknown.
 
 -param=analyzer-min-snodes-for-call-summary=
@@ -262,6 +262,10 @@ Wanalyzer-use-of-uninitialized-value
 Common Var(warn_analyzer_use_of_uninitialized_value) Init(1) Warning
 Warn about code paths in which an uninitialized value is used.
 
+Wanalyzer-symbol-too-complex
+Common Var(warn_analyzer_symbol_too_complex) Init(0) Warning
+Warn if expressions are too complicated for the analyzer to fully track.
+
 Wanalyzer-too-complex
 Common Var(warn_analyzer_too_complex) Init(0) Warning
 Warn if the code is too complicated for the analyzer to fully explore.
diff --git a/gcc/analyzer/diagnostic-manager.cc b/gcc/analyzer/diagnostic-manager.cc
index ecd57376b54..38bd308a9a4 100644
--- a/gcc/analyzer/diagnostic-manager.cc
+++ b/gcc/analyzer/diagnostic-manager.cc
@@ -2043,6 +2043,11 @@ struct null_assignment_sm_context : public sm_context
     /* No-op.  */
   }
 
+  void clear_all_per_svalue_state () final override
+  {
+    /* No-op.  */
+  }
+
   void on_custom_transition (custom_transition *) final override
   {
   }
diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index 825b3af43fc..d2524e34f58 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -474,6 +474,11 @@ public:
     m_new_state->m_checker_states[m_sm_idx]->set_global_state (state);
   }
 
+  void clear_all_per_svalue_state () final override
+  {
+    m_new_state->m_checker_states[m_sm_idx]->clear_all_per_svalue_state ();
+  }
+
   void on_custom_transition (custom_transition *transition) final override
   {
     transition->impl_transition (&m_eg,
diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc
index 9bb81e6dddd..78f739ef5ef 100644
--- a/gcc/analyzer/program-state.cc
+++ b/gcc/analyzer/program-state.cc
@@ -526,6 +526,14 @@ sm_state_map::clear_any_state (const svalue *sval)
   m_map.remove (sval);
 }
 
+/* Clear all per-svalue state within this state map.  */
+
+void
+sm_state_map::clear_all_per_svalue_state ()
+{
+  m_map.empty ();
+}
+
 /* Set the "global" state within this state map to STATE.  */
 
 void
diff --git a/gcc/analyzer/program-state.h b/gcc/analyzer/program-state.h
index c9b3aa0cbfc..ef1a2ad54a9 100644
--- a/gcc/analyzer/program-state.h
+++ b/gcc/analyzer/program-state.h
@@ -146,6 +146,7 @@ public:
 		       const svalue *origin,
 		       const extrinsic_state &ext_state);
   void clear_any_state (const svalue *sval);
+  void clear_all_per_svalue_state ();
 
   void set_global_state (state_machine::state_t state);
   state_machine::state_t get_global_state () const;
diff --git a/gcc/analyzer/region-model-manager.cc b/gcc/analyzer/region-model-manager.cc
index 921edc55868..b631bcb04d0 100644
--- a/gcc/analyzer/region-model-manager.cc
+++ b/gcc/analyzer/region-model-manager.cc
@@ -185,6 +185,16 @@ region_model_manager::reject_if_too_complex (svalue *sval)
       return false;
     }
 
+  pretty_printer pp;
+  pp_format_decoder (&pp) = default_tree_printer;
+  sval->dump_to_pp (&pp, true);
+  if (warning_at (input_location, OPT_Wanalyzer_symbol_too_complex,
+		  "symbol too complicated: %qs",
+		  pp_formatted_text (&pp)))
+    inform (input_location,
+	    "max_depth %i exceeds --param=analyzer-max-svalue-depth=%i",
+	    c.m_max_depth, param_analyzer_max_svalue_depth);
+
   delete sval;
   return true;
 }
diff --git a/gcc/analyzer/sm-taint.cc b/gcc/analyzer/sm-taint.cc
index d01e3f03951..6b5d51c62af 100644
--- a/gcc/analyzer/sm-taint.cc
+++ b/gcc/analyzer/sm-taint.cc
@@ -1038,6 +1038,20 @@ taint_state_machine::on_condition (sm_context *sm_ctxt,
   if (stmt == NULL)
     return;
 
+  if (lhs->get_kind () == SK_UNKNOWN
+      || rhs->get_kind () == SK_UNKNOWN)
+    {
+      /* If we have a comparison against UNKNOWN, then
+	 we've presumably hit the svalue complexity limit,
+	 and we don't know what is being sanitized.
+	 Give up on any taint already found on this execution path.  */
+      // TODO: warn about this
+      if (get_logger ())
+	get_logger ()->log ("comparison against UNKNOWN; removing all taint");
+      sm_ctxt->clear_all_per_svalue_state ();
+      return;
+    }
+
   // TODO
   switch (op)
     {
diff --git a/gcc/analyzer/sm.h b/gcc/analyzer/sm.h
index 3ff9c260780..ef63d73a541 100644
--- a/gcc/analyzer/sm.h
+++ b/gcc/analyzer/sm.h
@@ -299,6 +299,8 @@ public:
   virtual state_machine::state_t get_global_state () const = 0;
   virtual void set_global_state (state_machine::state_t) = 0;
 
+  virtual void clear_all_per_svalue_state () = 0;
+
   /* A vfunc for handling custom transitions, such as when registering
      a signal handler.  */
   virtual void on_custom_transition (custom_transition *transition) = 0;
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index bff3645eedc..f8d6f799e11 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -491,6 +491,7 @@ Objective-C and Objective-C++ Dialects}.
 -Wno-analyzer-tainted-divisor
 -Wno-analyzer-tainted-offset
 -Wno-analyzer-tainted-size
+-Wanalyzer-symbol-too-complex
 -Wanalyzer-too-complex
 -Wno-analyzer-undefined-behavior-strtok
 -Wno-analyzer-unsafe-call-within-signal-handler
@@ -10562,6 +10563,19 @@ Enabling this option effectively enables the following warnings:
 This option is only available if GCC was configured with analyzer
 support enabled.
 
+@opindex Wanalyzer-symbol-too-complex
+@opindex Wno-analyzer-symbol-too-complex
+@item -Wanalyzer-symbol-too-complex
+If @option{-fanalyzer} is enabled, the analyzer uses various heuristics
+to attempt to track the state of memory, but these can be defeated by
+sufficiently complicated code.
+
+By default, the analysis silently stops tracking values of expressions
+if they exceed the threshold defined by
+@option{--param analyzer-max-svalue-depth=@var{value}}, and falls back
+to an imprecise representation for such expressions.
+The @option{-Wanalyzer-symbol-too-complex} option warns if this occurs.
+
 @opindex Wanalyzer-too-complex
 @opindex Wno-analyzer-too-complex
 @item -Wanalyzer-too-complex
diff --git a/gcc/testsuite/c-c++-common/analyzer/call-summaries-pr107158-2.c b/gcc/testsuite/c-c++-common/analyzer/call-summaries-pr107158-2.c
index 4561e10cafd..b395623ccca 100644
--- a/gcc/testsuite/c-c++-common/analyzer/call-summaries-pr107158-2.c
+++ b/gcc/testsuite/c-c++-common/analyzer/call-summaries-pr107158-2.c
@@ -1,4 +1,4 @@
-/* { dg-additional-options "-fanalyzer-call-summaries -Wno-analyzer-too-complex" } */
+/* { dg-additional-options "-fanalyzer-call-summaries -Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */
 /* { dg-skip-if "c++98 has no noreturn attribute" { c++98_only } } */
 
 #ifdef __cplusplus
diff --git a/gcc/testsuite/c-c++-common/analyzer/call-summaries-pr107158.c b/gcc/testsuite/c-c++-common/analyzer/call-summaries-pr107158.c
index d4cf079cef8..de705836249 100644
--- a/gcc/testsuite/c-c++-common/analyzer/call-summaries-pr107158.c
+++ b/gcc/testsuite/c-c++-common/analyzer/call-summaries-pr107158.c
@@ -1,4 +1,4 @@
-/* { dg-additional-options "-fanalyzer-call-summaries" } */
+/* { dg-additional-options "-fanalyzer-call-summaries -Wno-analyzer-symbol-too-complex" } */
 
 typedef __SIZE_TYPE__ size_t;
 enum { _ISspace = ((5) < 8 ? ((1 << (5)) << 8) : ((1 << (5)) >> 8)) };
diff --git a/gcc/testsuite/c-c++-common/analyzer/deref-before-check-pr109060-haproxy-cfgparse.c b/gcc/testsuite/c-c++-common/analyzer/deref-before-check-pr109060-haproxy-cfgparse.c
index 1d28e10747c..c4561fcd8a7 100644
--- a/gcc/testsuite/c-c++-common/analyzer/deref-before-check-pr109060-haproxy-cfgparse.c
+++ b/gcc/testsuite/c-c++-common/analyzer/deref-before-check-pr109060-haproxy-cfgparse.c
@@ -1,5 +1,7 @@
 /* Reduced from haproxy-2.7.1's cfgparse.c.  */
 
+/* { dg-additional-options "-Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */
+
 typedef __SIZE_TYPE__ size_t;
 
 extern int
diff --git a/gcc/testsuite/c-c++-common/analyzer/feasibility-3.c b/gcc/testsuite/c-c++-common/analyzer/feasibility-3.c
index 2fcd064e801..06194f85069 100644
--- a/gcc/testsuite/c-c++-common/analyzer/feasibility-3.c
+++ b/gcc/testsuite/c-c++-common/analyzer/feasibility-3.c
@@ -1,6 +1,8 @@
 /* Reduced and adapted from Linux: fs/proc/inode.c: proc_reg_open
    (GPL v2.0).  */
 
+/* { dg-additional-options "-Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */
+
 /* Types.  */
 
 typedef unsigned char u8;
diff --git a/gcc/testsuite/c-c++-common/analyzer/flex-with-call-summaries.c b/gcc/testsuite/c-c++-common/analyzer/flex-with-call-summaries.c
index 45edacf0e53..963a84bc9ab 100644
--- a/gcc/testsuite/c-c++-common/analyzer/flex-with-call-summaries.c
+++ b/gcc/testsuite/c-c++-common/analyzer/flex-with-call-summaries.c
@@ -5,6 +5,7 @@
 /* { dg-skip-if "" { "avr-*-*" } } */
 /* { dg-additional-options "-fanalyzer-call-summaries" } */
 /* { dg-additional-options "-Wno-analyzer-too-complex" } */
+/* { dg-additional-options "-Wno-analyzer-symbol-too-complex" } */
 
 /* A lexical scanner generated by flex */
 
@@ -885,8 +886,7 @@ static int yy_get_next_buffer (void)
 				}
 			else
 				/* Can't grow it, we don't own it. */
-				b->yy_ch_buf = NULL;  /* { dg-bogus "leak" "" { xfail *-*-* } } */
-				/* TODO: leak false positive: PR analyzer/103546.  */
+				b->yy_ch_buf = NULL;  /* { dg-bogus "leak" "PR analyzer/103546" } */
 
 			if ( ! b->yy_ch_buf )
 				YY_FATAL_ERROR(
diff --git a/gcc/testsuite/c-c++-common/analyzer/flex-without-call-summaries.c b/gcc/testsuite/c-c++-common/analyzer/flex-without-call-summaries.c
index 5369f7685c2..b1c23312137 100644
--- a/gcc/testsuite/c-c++-common/analyzer/flex-without-call-summaries.c
+++ b/gcc/testsuite/c-c++-common/analyzer/flex-without-call-summaries.c
@@ -886,8 +886,7 @@ static int yy_get_next_buffer (void)
 				}
 			else
 				/* Can't grow it, we don't own it. */
-				b->yy_ch_buf = NULL;  /* { dg-bogus "leak" "" { xfail *-*-* } } */
-				/* TODO: leak false positive: PR analyzer/103546.  */
+				b->yy_ch_buf = NULL;  /* { dg-bogus "leak" "PR analyzer/103546"  */
 
 			if ( ! b->yy_ch_buf )
 				YY_FATAL_ERROR(
diff --git a/gcc/testsuite/c-c++-common/analyzer/infinite-recursion-3.c b/gcc/testsuite/c-c++-common/analyzer/infinite-recursion-3.c
index 68c4fa396ca..2ae20a1108a 100644
--- a/gcc/testsuite/c-c++-common/analyzer/infinite-recursion-3.c
+++ b/gcc/testsuite/c-c++-common/analyzer/infinite-recursion-3.c
@@ -1,4 +1,4 @@
-/* { dg-additional-options "-fno-analyzer-call-summaries -Wno-analyzer-too-complex" } */
+/* { dg-additional-options "-fno-analyzer-call-summaries -Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */
 
 struct node
 {
diff --git a/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early-O2.c b/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early-O2.c
index c46ffe91a6b..c1c8e6f6a39 100644
--- a/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early-O2.c
+++ b/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early-O2.c
@@ -1,7 +1,7 @@
 /* Reduced from haproxy's src/ssl_sample.c  */
 
 /* { dg-require-effective-target ptr_eq_long } */
-/* { dg-additional-options "-O2" } */
+/* { dg-additional-options "-O2 -Wno-analyzer-symbol-too-complex" } */
 
 union sample_value {
   long long int sint;
diff --git a/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early.c b/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early.c
index ef34a76c50d..c5f1fa42e6f 100644
--- a/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early.c
+++ b/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early.c
@@ -1,6 +1,7 @@
 /* Reduced from haproxy's src/ssl_sample.c  */
 
 /* { dg-require-effective-target ptr_eq_long } */
+/* { dg-additional-options "-Wno-analyzer-symbol-too-complex" } */
 
 union sample_value {
   long long int sint;
diff --git a/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108400-SoftEtherVPN-WebUi.c b/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108400-SoftEtherVPN-WebUi.c
index 1151d622519..9dcf7aa31f1 100644
--- a/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108400-SoftEtherVPN-WebUi.c
+++ b/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108400-SoftEtherVPN-WebUi.c
@@ -1,4 +1,6 @@
 /* Reduced from SoftEtherVPN's src/Cedar/WebUI.c.   */
+/* { dg-additional-options "-Wno-analyzer-symbol-too-complex" } */
+
 #include "../../gcc.dg/analyzer/analyzer-decls.h"
 typedef int (COMPARE)(void *p1, void *p2);
 typedef unsigned int UINT;
diff --git a/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108806-qemu.c b/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108806-qemu.c
index f7f6923927f..16ef6574d2f 100644
--- a/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108806-qemu.c
+++ b/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108806-qemu.c
@@ -1,5 +1,7 @@
 /* Reduced from qemu-7.2.0's hw/intc/omap_intc.c */
 
+/* { dg-additional-options "-Wno-analyzer-symbol-too-complex" } */
+
 #include "../../gcc.dg/analyzer/analyzer-decls.h"
 
 typedef unsigned char __uint8_t;
diff --git a/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108830.c b/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108830.c
index 0c95148ebd5..1cb1ebe65f9 100644
--- a/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108830.c
+++ b/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108830.c
@@ -1,6 +1,6 @@
 /* Reduced from apr-1.7.0/tables/apr_hash.c: 'apr_hash_merge' */
 
-/* { dg-additional-options "-Wno-analyzer-too-complex" } */
+/* { dg-additional-options "-Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */
 
 #include "../../gcc.dg/analyzer/analyzer-decls.h"
 
diff --git a/gcc/testsuite/c-c++-common/analyzer/pr94596.c b/gcc/testsuite/c-c++-common/analyzer/pr94596.c
index 10ea549924e..0d6240941d7 100644
--- a/gcc/testsuite/c-c++-common/analyzer/pr94596.c
+++ b/gcc/testsuite/c-c++-common/analyzer/pr94596.c
@@ -17,6 +17,9 @@
  */
 
 #include "../../gcc.dg/analyzer/analyzer-decls.h"
+
+/* { dg-additional-options "-Wno-analyzer-symbol-too-complex" } */
+
 typedef __SIZE_TYPE__ size_t;
 
 #ifndef __cplusplus
diff --git a/gcc/testsuite/c-c++-common/analyzer/strtok-2.c b/gcc/testsuite/c-c++-common/analyzer/strtok-2.c
index 0336bf0cfe9..f34b4a7198a 100644
--- a/gcc/testsuite/c-c++-common/analyzer/strtok-2.c
+++ b/gcc/testsuite/c-c++-common/analyzer/strtok-2.c
@@ -1,3 +1,5 @@
+/* { dg-additional-options "-Wno-analyzer-symbol-too-complex" } */
+
 #include "../../gcc.dg/analyzer/analyzer-decls.h"
 
 extern char *strtok (char *str, const char *delim)
diff --git a/gcc/testsuite/c-c++-common/analyzer/strtok-4.c b/gcc/testsuite/c-c++-common/analyzer/strtok-4.c
index b6b7d49e3c3..793c7fcb7f4 100644
--- a/gcc/testsuite/c-c++-common/analyzer/strtok-4.c
+++ b/gcc/testsuite/c-c++-common/analyzer/strtok-4.c
@@ -1,3 +1,5 @@
+/* { dg-additional-options "-Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */
+
 #include "../../gcc.dg/analyzer/analyzer-decls.h"
 
 extern char *strtok (char *str, const char *delim);
diff --git a/gcc/testsuite/c-c++-common/analyzer/strtok-cppreference.c b/gcc/testsuite/c-c++-common/analyzer/strtok-cppreference.c
index a2e912341d6..a396c643f11 100644
--- a/gcc/testsuite/c-c++-common/analyzer/strtok-cppreference.c
+++ b/gcc/testsuite/c-c++-common/analyzer/strtok-cppreference.c
@@ -11,6 +11,8 @@
      should be released under an equivalent license so that everyone could
      benefit from the modified versions. "  */
 
+/* { dg-additional-options " -Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */
+
 #define __STDC_WANT_LIB_EXT1__ 0
 #include <string.h>
 #include <stdio.h>
diff --git a/gcc/testsuite/gcc.dg/analyzer/analyzer.exp b/gcc/testsuite/gcc.dg/analyzer/analyzer.exp
index cedf3c0466f..ba5aa680fc7 100644
--- a/gcc/testsuite/gcc.dg/analyzer/analyzer.exp
+++ b/gcc/testsuite/gcc.dg/analyzer/analyzer.exp
@@ -30,7 +30,7 @@ if [info exists DEFAULT_CFLAGS] then {
 }
 
 # If a testcase doesn't have special options, use these.
-set DEFAULT_CFLAGS "-fanalyzer -Wanalyzer-too-complex -fanalyzer-call-summaries"
+set DEFAULT_CFLAGS "-fanalyzer -Wanalyzer-too-complex -Wanalyzer-symbol-too-complex -fanalyzer-call-summaries"
 
 if { [istarget "*-*-darwin*" ] } {
   # On macOS, system headers redefine by default some macros (memcpy,
diff --git a/gcc/testsuite/gcc.dg/analyzer/attr-const-3.c b/gcc/testsuite/gcc.dg/analyzer/attr-const-3.c
index fc8527a5d0e..11238a77a65 100644
--- a/gcc/testsuite/gcc.dg/analyzer/attr-const-3.c
+++ b/gcc/testsuite/gcc.dg/analyzer/attr-const-3.c
@@ -1,7 +1,7 @@
 /* Verify that we handle unknown values passed to  __attribute__ ((const))
    (by imposing a complexity limit).  */
 
-/* { dg-additional-options "--param analyzer-max-svalue-depth=4" } */
+/* { dg-additional-options "--param analyzer-max-svalue-depth=4 -Wno-analyzer-symbol-too-complex" } */
 
 #include "analyzer-decls.h"
 
diff --git a/gcc/testsuite/gcc.dg/analyzer/call-summaries-pr107072.c b/gcc/testsuite/gcc.dg/analyzer/call-summaries-pr107072.c
index 6e583d0228f..f59318b428f 100644
--- a/gcc/testsuite/gcc.dg/analyzer/call-summaries-pr107072.c
+++ b/gcc/testsuite/gcc.dg/analyzer/call-summaries-pr107072.c
@@ -1,5 +1,5 @@
 /* { dg-require-effective-target int32plus } */
-/* { dg-additional-options "-fanalyzer-call-summaries --param analyzer-min-snodes-for-call-summary=0" } */
+/* { dg-additional-options "-fanalyzer-call-summaries --param analyzer-min-snodes-for-call-summary=0 -Wno-analyzer-symbol-too-complex" } */
 
 /* There need to be at least two calls to a function for the
    call-summarization code to be used.
diff --git a/gcc/testsuite/gcc.dg/analyzer/doom-s_sound-pr108867.c b/gcc/testsuite/gcc.dg/analyzer/doom-s_sound-pr108867.c
index ae58f03d3b3..fdc21a2bec3 100644
--- a/gcc/testsuite/gcc.dg/analyzer/doom-s_sound-pr108867.c
+++ b/gcc/testsuite/gcc.dg/analyzer/doom-s_sound-pr108867.c
@@ -1,6 +1,6 @@
 /* Reduced from Doom's linuxdoom-1.10/s_sound.c, which is GPLv2 or later.  */
 
-/* { dg-additional-options "-fno-analyzer-call-summaries -Wno-analyzer-too-complex" } */
+/* { dg-additional-options "-fno-analyzer-call-summaries -Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */
 /* { dg-require-effective-target size32plus } */
 
 typedef struct _IO_FILE FILE;
diff --git a/gcc/testsuite/gcc.dg/analyzer/explode-4.c b/gcc/testsuite/gcc.dg/analyzer/explode-4.c
index 874b1e9c300..a98dfb56bf5 100644
--- a/gcc/testsuite/gcc.dg/analyzer/explode-4.c
+++ b/gcc/testsuite/gcc.dg/analyzer/explode-4.c
@@ -3,7 +3,7 @@
    conjured_svalues whilst handling a long chain of external
    function calls.  */
 
-/* { dg-additional-options "-Wno-implicit-function-declaration -Wno-int-conversion -Wno-analyzer-too-complex" } */
+/* { dg-additional-options "-Wno-implicit-function-declaration -Wno-int-conversion -Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */
 
 #define NULL ((void *)0)
 typedef unsigned char uint8_t;
diff --git a/gcc/testsuite/gcc.dg/analyzer/null-deref-pr102671-1.c b/gcc/testsuite/gcc.dg/analyzer/null-deref-pr102671-1.c
index 3fe061bdbd8..65c7bac1f7e 100644
--- a/gcc/testsuite/gcc.dg/analyzer/null-deref-pr102671-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/null-deref-pr102671-1.c
@@ -1,5 +1,5 @@
 /* { dg-require-effective-target ptr_eq_long } */
-/* { dg-additional-options "-O2 -Wno-shift-count-overflow" } */
+/* { dg-additional-options "-O2 -Wno-shift-count-overflow -Wno-analyzer-symbol-too-complex" } */
 
 struct lisp;
 union vectorlike_header { long size; };
diff --git a/gcc/testsuite/gcc.dg/analyzer/null-deref-pr105755.c b/gcc/testsuite/gcc.dg/analyzer/null-deref-pr105755.c
index 2b0ba292e00..5375b4dd6f6 100644
--- a/gcc/testsuite/gcc.dg/analyzer/null-deref-pr105755.c
+++ b/gcc/testsuite/gcc.dg/analyzer/null-deref-pr105755.c
@@ -1,5 +1,5 @@
 /* { dg-require-effective-target int32plus } */
-/* { dg-additional-options "-Wno-analyzer-too-complex -O2" } */
+/* { dg-additional-options "-Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex -O2" } */
 
 typedef long int ptrdiff_t;
 typedef long int EMACS_INT;
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-curl.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-curl.c
index e34b572966e..d14661cbc6a 100644
--- a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-curl.c
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-curl.c
@@ -1,4 +1,4 @@
-/* { dg-additional-options "-O2" } */
+/* { dg-additional-options "-O2 -Wno-analyzer-symbol-too-complex" } */
 #include <string.h>
 
 /* Reduced from curl lib/smb.c.  */
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr101503.c b/gcc/testsuite/gcc.dg/analyzer/pr101503.c
index 16faf6eac2f..cc4d801d8a6 100644
--- a/gcc/testsuite/gcc.dg/analyzer/pr101503.c
+++ b/gcc/testsuite/gcc.dg/analyzer/pr101503.c
@@ -1,4 +1,4 @@
-/* { dg-additional-options "--param analyzer-max-svalue-depth=0" } */
+/* { dg-additional-options "--param analyzer-max-svalue-depth=0 -Wno-analyzer-symbol-too-complex" } */
 
 int val;
 
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr103892.c b/gcc/testsuite/gcc.dg/analyzer/pr103892.c
index d16cd83c472..a17c3b7e119 100644
--- a/gcc/testsuite/gcc.dg/analyzer/pr103892.c
+++ b/gcc/testsuite/gcc.dg/analyzer/pr103892.c
@@ -1,4 +1,4 @@
-/* { dg-additional-options "-O2" } */
+/* { dg-additional-options "-O2 -Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */
 
 /* C only: C++ FE optimizes argstr_get_word completely away
    and therefore the number of SN diminishes compared to C,
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr94851-4.c b/gcc/testsuite/gcc.dg/analyzer/pr94851-4.c
index 2a15a5d7f5b..a5130c59cb0 100644
--- a/gcc/testsuite/gcc.dg/analyzer/pr94851-4.c
+++ b/gcc/testsuite/gcc.dg/analyzer/pr94851-4.c
@@ -1,4 +1,4 @@
-/* { dg-additional-options "-O2" } */
+/* { dg-additional-options "-O2 -Wno-analyzer-symbol-too-complex" } */
 
 #include <stdlib.h>
 
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96860-1.c b/gcc/testsuite/gcc.dg/analyzer/pr96860-1.c
index 8f298ec04e7..8be30b3a6da 100644
--- a/gcc/testsuite/gcc.dg/analyzer/pr96860-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/pr96860-1.c
@@ -1,5 +1,5 @@
 /* { dg-require-effective-target int128 } */
-/* { dg-additional-options "--param analyzer-max-svalue-depth=0" } */
+/* { dg-additional-options "--param analyzer-max-svalue-depth=0 -Wno-analyzer-symbol-too-complex" } */
 
 void x7 (void)
 {
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96860-2.c b/gcc/testsuite/gcc.dg/analyzer/pr96860-2.c
index 90a818cb283..d12b9a1e1fa 100644
--- a/gcc/testsuite/gcc.dg/analyzer/pr96860-2.c
+++ b/gcc/testsuite/gcc.dg/analyzer/pr96860-2.c
@@ -1,4 +1,4 @@
-/* { dg-additional-options "--param analyzer-max-svalue-depth=0" } */
+/* { dg-additional-options "--param analyzer-max-svalue-depth=0 -Wno-analyzer-symbol-too-complex" } */
 
 void x7 (void)
 {
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr98918.c b/gcc/testsuite/gcc.dg/analyzer/pr98918.c
index ac626ba1f30..c3bbce3e6ec 100644
--- a/gcc/testsuite/gcc.dg/analyzer/pr98918.c
+++ b/gcc/testsuite/gcc.dg/analyzer/pr98918.c
@@ -1,3 +1,5 @@
+/* { dg-additional-options "-Wno-analyzer-symbol-too-complex" } */
+
 #include <stdlib.h>
 
 struct marker {
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr99044-2.c b/gcc/testsuite/gcc.dg/analyzer/pr99044-2.c
index fd71d35d7e4..f7badb92f44 100644
--- a/gcc/testsuite/gcc.dg/analyzer/pr99044-2.c
+++ b/gcc/testsuite/gcc.dg/analyzer/pr99044-2.c
@@ -1,3 +1,5 @@
+/* { dg-additional-options "-Wno-analyzer-symbol-too-complex" } */
+
 struct node
 {
   struct node *next;
diff --git a/gcc/testsuite/gcc.dg/analyzer/uninit-pr108806-qemu.c b/gcc/testsuite/gcc.dg/analyzer/uninit-pr108806-qemu.c
index 34fe802f495..09272011128 100644
--- a/gcc/testsuite/gcc.dg/analyzer/uninit-pr108806-qemu.c
+++ b/gcc/testsuite/gcc.dg/analyzer/uninit-pr108806-qemu.c
@@ -5,6 +5,8 @@
      struct omap_intr_handler_bank_s* bank;
  */
 
+/* { dg-additional-options "-Wno-analyzer-symbol-too-complex" } */
+
 typedef unsigned char __uint8_t;
 typedef unsigned int __uint32_t;
 typedef unsigned long int __uint64_t;
diff --git a/gcc/testsuite/gcc.dg/analyzer/use-after-free.c b/gcc/testsuite/gcc.dg/analyzer/use-after-free.c
index d7e4bc2c6ca..76a85f56335 100644
--- a/gcc/testsuite/gcc.dg/analyzer/use-after-free.c
+++ b/gcc/testsuite/gcc.dg/analyzer/use-after-free.c
@@ -1,3 +1,5 @@
+/* { dg-additional-options "-Wno-analyzer-too-complex -Wno-analyzer-symbol-too-complex" } */
+
 #include <stdlib.h>
 #include "analyzer-decls.h"
 
diff --git a/gcc/testsuite/gcc.dg/plugin/plugin.exp b/gcc/testsuite/gcc.dg/plugin/plugin.exp
index f098a327d31..f0b4bb7a051 100644
--- a/gcc/testsuite/gcc.dg/plugin/plugin.exp
+++ b/gcc/testsuite/gcc.dg/plugin/plugin.exp
@@ -162,7 +162,11 @@ set plugin_test_list [list \
 	  taint-CVE-2011-0521-5.c \
 	  taint-CVE-2011-0521-5-fixed.c \
 	  taint-CVE-2011-0521-6.c \
-	  taint-antipatterns-1.c } \
+	  taint-antipatterns-1.c \
+	  taint-pr112850.c \
+	  taint-pr112850-precise.c \
+	  taint-pr112850-too-complex.c \
+	  taint-pr112850-unsanitized.c } \
     { analyzer_cpython_plugin.c \
 	  cpython-plugin-test-no-Python-h.c \
 	  cpython-plugin-test-PyList_Append.c \
diff --git a/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-4.c b/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-4.c
index 06b3468fca5..e268a8eab8f 100644
--- a/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-4.c
+++ b/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-4.c
@@ -32,9 +32,9 @@ int test_1(struct file *file, unsigned int cmd, unsigned long arg)
 		if (info->num > 1)
 			return -EINVAL;
 		av7110->ci_slot[info->num].num = info->num; /* { dg-warning "attacker-controlled value" } */
-		av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ? /* { dg-warning "attacker-controlled value" } */
+		av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ?
 							CA_CI_LINK : CA_CI;
-		memcpy(info, &av7110->ci_slot[info->num], sizeof(ca_slot_info_t));  /* { dg-warning "attacker-controlled value" } */
+		memcpy(info, &av7110->ci_slot[info->num], sizeof(ca_slot_info_t));
 	}
 
 	copy_to_user((void __user *)arg, parg, sizeof(sbuf));
diff --git a/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-5-fixed.c b/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-5-fixed.c
index 076ada3a20a..b39e693da63 100644
--- a/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-5-fixed.c
+++ b/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-5-fixed.c
@@ -39,8 +39,7 @@ int test_1(struct file *file, unsigned int cmd, unsigned long arg)
 		av7110->ci_slot[info->num].num = info->num;
 		av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ?
 							CA_CI_LINK : CA_CI;
-		memcpy(info, &av7110->ci_slot[info->num], sizeof(ca_slot_info_t)); /* { dg-bogus "use of attacker-controlled value in array lookup without bounds checking" "" { xfail *-*-* } } */
-		// FIXME: why the above false +ve?
+		memcpy(info, &av7110->ci_slot[info->num], sizeof(ca_slot_info_t)); /* { dg-bogus "use of attacker-controlled value in array lookup without bounds checking" } */
 	}
 
 	copy_to_user((void __user *)arg, &sbuf, sizeof(sbuf));
diff --git a/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-5.c b/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-5.c
index e27ee469df8..fe216c0a3c4 100644
--- a/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-5.c
+++ b/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-5.c
@@ -37,9 +37,9 @@ int test_1(struct file *file, unsigned int cmd, unsigned long arg)
 		__analyzer_dump_state ("taint", info->num); /* { dg-warning "has_ub" } */
 
 		av7110->ci_slot[info->num].num = info->num; /* { dg-warning "use of attacker-controlled value '\\*info\\.num' in array lookup without checking for negative" } */
-		av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ? /* { dg-warning "use of attacker-controlled value '\\*info\\.num' in array lookup without checking for negative" } */
+		av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ?
 							CA_CI_LINK : CA_CI;
-		memcpy(info, &av7110->ci_slot[info->num], sizeof(ca_slot_info_t)); /* { dg-warning "use of attacker-controlled value in array lookup without bounds checking" } */
+		memcpy(info, &av7110->ci_slot[info->num], sizeof(ca_slot_info_t));
 	}
 
 	copy_to_user((void __user *)arg, &sbuf, sizeof(sbuf));
diff --git a/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-6.c b/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-6.c
index fea70ee5761..5b68de32470 100644
--- a/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-6.c
+++ b/gcc/testsuite/gcc.dg/plugin/taint-CVE-2011-0521-6.c
@@ -34,9 +34,9 @@ int test_1(struct file *file, unsigned int cmd, unsigned long arg)
 		//__analyzer_break ();
 
 		av7110->ci_slot[info->num].num = info->num; /* { dg-warning "use of attacker-controlled value '\\*info\\.num' in array lookup without bounds checking" } */
-		av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ?  /* { dg-warning "use of attacker-controlled value '\\*info\\.num' in array lookup without bounds checking" } */
+		av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ?
 							CA_CI_LINK : CA_CI;
-		memcpy(info, &av7110->ci_slot[info->num], sizeof(ca_slot_info_t));  /* { dg-warning "use of attacker-controlled value in array lookup without bounds checking" } */
+		memcpy(info, &av7110->ci_slot[info->num], sizeof(ca_slot_info_t));
 	}
 
 	copy_to_user((void __user *)arg, &sbuf, sizeof(sbuf));
diff --git a/gcc/testsuite/gcc.dg/plugin/taint-pr112850-precise.c b/gcc/testsuite/gcc.dg/plugin/taint-pr112850-precise.c
new file mode 100644
index 00000000000..558f0fb1a8a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/taint-pr112850-precise.c
@@ -0,0 +1,50 @@
+/* Reduced from false positive in Linux kernel in sound/core/rawmidi.c.
+
+   Use a value of --param=analyzer-max-svalue-depth= high enough to avoid
+   UNKNOWN svalues; make sure we don't get false positives with this case.  */
+
+/* { dg-do compile } */
+/* { dg-options "-fanalyzer -O2 -Wanalyzer-symbol-too-complex --param=analyzer-max-svalue-depth=13" } */
+/* { dg-require-effective-target analyzer } */
+
+typedef unsigned long __kernel_ulong_t;
+typedef __kernel_ulong_t __kernel_size_t;
+typedef __kernel_size_t size_t;
+typedef unsigned int gfp_t;
+
+extern unsigned long copy_from_user(void* to, const void* from, unsigned long n);
+
+extern
+__attribute__((__alloc_size__(1)))
+__attribute__((__malloc__)) void*
+kvzalloc(size_t size, gfp_t flags);
+
+struct snd_rawmidi_params
+{
+  int stream;
+  size_t buffer_size;
+};
+
+char *newbuf;
+
+static int
+resize_runtime_buffer(struct snd_rawmidi_params* params)
+{
+  if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) /* { dg-bogus "symbol too complicated" } */
+    return -22;
+  newbuf = kvzalloc(params->buffer_size, /* { dg-bogus "use of attacker-controlled value '\\*params.buffer_size' as allocation size without upper-bounds checking" "PR analyzer/112850" } */
+		    (((gfp_t)(0x400u | 0x800u)) | ((gfp_t)0x40u) | ((gfp_t)0x80u)));
+  if (!newbuf)
+    return -12;
+  return 0;
+}
+
+long
+snd_rawmidi_ioctl(unsigned long arg)
+{
+  void* argp = (void*)arg;
+  struct snd_rawmidi_params params;
+  if (copy_from_user(&params, argp, sizeof(struct snd_rawmidi_params)))
+    return -14;
+  return resize_runtime_buffer(&params);
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/taint-pr112850-too-complex.c b/gcc/testsuite/gcc.dg/plugin/taint-pr112850-too-complex.c
new file mode 100644
index 00000000000..2a4ee8197c3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/taint-pr112850-too-complex.c
@@ -0,0 +1,51 @@
+/* Reduced from false positive in Linux kernel in sound/core/rawmidi.c.
+
+   With --param=analyzer-max-svalue-depth=12, the value being compared
+   at the sanitization is too complex and becomes UNKNOWN; make sure
+   this doesn't lead to a false positive.  */
+
+/* { dg-do compile } */
+/* { dg-options "-fanalyzer -O2 -Wanalyzer-symbol-too-complex --param=analyzer-max-svalue-depth=12" } */
+/* { dg-require-effective-target analyzer } */
+
+typedef unsigned long __kernel_ulong_t;
+typedef __kernel_ulong_t __kernel_size_t;
+typedef __kernel_size_t size_t;
+typedef unsigned int gfp_t;
+
+extern unsigned long copy_from_user(void* to, const void* from, unsigned long n);
+
+extern
+__attribute__((__alloc_size__(1)))
+__attribute__((__malloc__)) void*
+kvzalloc(size_t size, gfp_t flags);
+
+struct snd_rawmidi_params
+{
+  int stream;
+  size_t buffer_size;
+};
+
+char *newbuf;
+
+static int
+resize_runtime_buffer(struct snd_rawmidi_params* params)
+{
+  if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) /* { dg-warning "symbol too complicated" } */
+    return -22;
+  newbuf = kvzalloc(params->buffer_size, /* { dg-bogus "use of attacker-controlled value '\\*params.buffer_size' as allocation size without upper-bounds checking" "PR analyzer/112850" } */
+		    (((gfp_t)(0x400u | 0x800u)) | ((gfp_t)0x40u) | ((gfp_t)0x80u)));
+  if (!newbuf)
+    return -12;
+  return 0;
+}
+
+long
+snd_rawmidi_ioctl(unsigned long arg)
+{
+  void* argp = (void*)arg;
+  struct snd_rawmidi_params params;
+  if (copy_from_user(&params, argp, sizeof(struct snd_rawmidi_params)))
+    return -14;
+  return resize_runtime_buffer(&params);
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/taint-pr112850-unsanitized.c b/gcc/testsuite/gcc.dg/plugin/taint-pr112850-unsanitized.c
new file mode 100644
index 00000000000..e46fcb6c8a1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/taint-pr112850-unsanitized.c
@@ -0,0 +1,50 @@
+/* Reduced from false positive in Linux kernel in sound/core/rawmidi.c,
+   with sanitization removed to make it a true positive.
+
+   Verify that we detect this (with default params).  */
+
+/* { dg-do compile } */
+/* { dg-options "-fanalyzer -O2 -Wanalyzer-too-complex" } */
+/* { dg-require-effective-target analyzer } */
+
+typedef unsigned long __kernel_ulong_t;
+typedef __kernel_ulong_t __kernel_size_t;
+typedef __kernel_size_t size_t;
+typedef unsigned int gfp_t;
+
+extern unsigned long copy_from_user(void* to, const void* from, unsigned long n);
+
+extern
+__attribute__((__alloc_size__(1)))
+__attribute__((__malloc__)) void*
+kvzalloc(size_t size, gfp_t flags);
+
+struct snd_rawmidi_params
+{
+  int stream;
+  size_t buffer_size;
+};
+
+char *newbuf;
+
+static int
+resize_runtime_buffer(struct snd_rawmidi_params* params)
+{
+  /* No sanitization, so we should complain.  */
+  
+  newbuf = kvzalloc(params->buffer_size, /* { dg-warning "use of attacker-controlled value '\\*params.buffer_size' as allocation size without upper-bounds checking" "PR analyzer/112850" } */
+		    (((gfp_t)(0x400u | 0x800u)) | ((gfp_t)0x40u) | ((gfp_t)0x80u)));
+  if (!newbuf)
+    return -12;
+  return 0;
+}
+
+long
+snd_rawmidi_ioctl(unsigned long arg)
+{
+  void* argp = (void*)arg;
+  struct snd_rawmidi_params params;
+  if (copy_from_user(&params, argp, sizeof(struct snd_rawmidi_params)))
+    return -14;
+  return resize_runtime_buffer(&params);
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/taint-pr112850.c b/gcc/testsuite/gcc.dg/plugin/taint-pr112850.c
new file mode 100644
index 00000000000..6fa1d0f9bd4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/taint-pr112850.c
@@ -0,0 +1,47 @@
+/* Reduced from false positive in Linux kernel in sound/core/rawmidi.c.  */
+
+/* { dg-do compile } */
+/* { dg-options "-fanalyzer -O2 -Wanalyzer-symbol-too-complex" } */
+/* { dg-require-effective-target analyzer } */
+
+typedef unsigned long __kernel_ulong_t;
+typedef __kernel_ulong_t __kernel_size_t;
+typedef __kernel_size_t size_t;
+typedef unsigned int gfp_t;
+
+extern unsigned long copy_from_user(void* to, const void* from, unsigned long n);
+
+extern
+__attribute__((__alloc_size__(1)))
+__attribute__((__malloc__)) void*
+kvzalloc(size_t size, gfp_t flags);
+
+struct snd_rawmidi_params
+{
+  int stream;
+  size_t buffer_size;
+};
+
+char *newbuf;
+
+static int
+resize_runtime_buffer(struct snd_rawmidi_params* params)
+{
+  if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) /* { dg-bogus "symbol too complicated" } */
+    return -22;
+  newbuf = kvzalloc(params->buffer_size, /* { dg-bogus "use of attacker-controlled value '\\*params.buffer_size' as allocation size without upper-bounds checking" "PR analyzer/112850" } */
+		    (((gfp_t)(0x400u | 0x800u)) | ((gfp_t)0x40u) | ((gfp_t)0x80u)));
+  if (!newbuf)
+    return -12;
+  return 0;
+}
+
+long
+snd_rawmidi_ioctl(unsigned long arg)
+{
+  void* argp = (void*)arg;
+  struct snd_rawmidi_params params;
+  if (copy_from_user(&params, argp, sizeof(struct snd_rawmidi_params)))
+    return -14;
+  return resize_runtime_buffer(&params);
+}

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-12-07  0:26 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-12-07  0:26 [gcc r14-6239] analyzer: fix taint false positives with UNKNOWN [PR112850] David Malcolm

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).