diff options
author | David Malcolm <dmalcolm@redhat.com> | 2023-12-06 19:25:26 -0500 |
---|---|---|
committer | David Malcolm <dmalcolm@redhat.com> | 2023-12-06 19:25:26 -0500 |
commit | 08b7462d3ad8e5acd941b7c777c5b26b4064d686 (patch) | |
tree | 9d418e45863ed55b22f8fc4cb5422a1efe906ee2 /gcc/testsuite/c-c++-common | |
parent | ae9e48e5c0acaecf181117bdf3632b6eabf907ec (diff) | |
download | gcc-08b7462d3ad8e5acd941b7c777c5b26b4064d686.zip gcc-08b7462d3ad8e5acd941b7c777c5b26b4064d686.tar.gz gcc-08b7462d3ad8e5acd941b7c777c5b26b4064d686.tar.bz2 |
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>
Diffstat (limited to 'gcc/testsuite/c-c++-common')
16 files changed, 26 insertions, 9 deletions
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 4561e10..b395623 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 d4cf079..de70583 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 1d28e10..c4561fc 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 2fcd064..06194f8 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 45edacf..963a84b 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 5369f76..b1c2331 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 68c4fa3..2ae20a1 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 c46ffe9..c1c8e6f 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 ef34a76..c5f1fa4 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 1151d62..9dcf7aa 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 f7f6923..16ef657 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 0c95148..1cb1ebe 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 10ea549..0d62409 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 0336bf0..f34b4a7 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 b6b7d49..793c7fc 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 a2e9123..a396c64 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> |