summaryrefslogtreecommitdiff
path: root/gcc/testsuite
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2022-07-27 17:38:55 -0400
committerDavid Malcolm <dmalcolm@redhat.com>2022-07-27 17:54:44 -0400
commit71a4f739c218746df70612eeb844024d1fe206bb (patch)
tree67122c902f922136258bdbb8a332fa560788ada8 /gcc/testsuite
parent09cb9c88ef8e2c0c89ada9cde2caf1a960db7a77 (diff)
analyzer: fix false positives from -Wanalyzer-tainted-divisor [PR106225]
(cherry picked from r13-1562-g897b3b31f0a94b) gcc/analyzer/ChangeLog: PR analyzer/106225 * sm-taint.cc (taint_state_machine::on_stmt): Move handling of assignments from division to... (taint_state_machine::check_for_tainted_divisor): ...this new function. Reject warning when the divisor is known to be non-zero. * sm.cc: Include "analyzer/program-state.h". (sm_context::get_old_region_model): New. * sm.h (sm_context::get_old_region_model): New decl. gcc/testsuite/ChangeLog: PR analyzer/106225 * gcc.dg/analyzer/taint-divisor-1.c: Add test coverage for various correct and incorrect checks against zero. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
Diffstat (limited to 'gcc/testsuite')
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/taint-divisor-1.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/gcc/testsuite/gcc.dg/analyzer/taint-divisor-1.c b/gcc/testsuite/gcc.dg/analyzer/taint-divisor-1.c
index 5a5a0b93ce0..b7c1faef1c4 100644
--- a/gcc/testsuite/gcc.dg/analyzer/taint-divisor-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/taint-divisor-1.c
@@ -24,3 +24,69 @@ int test_2 (FILE *f)
fread (&s, sizeof (s), 1, f);
return s.a % s.b; /* { dg-warning "use of attacker-controlled value 's\\.b' as divisor without checking for zero" } */
}
+
+/* We shouldn't complain if the divisor has been checked for zero. */
+
+int test_checked_ne_zero (FILE *f)
+{
+ struct st1 s;
+ fread (&s, sizeof (s), 1, f);
+ if (s.b)
+ return s.a / s.b; /* { dg-bogus "divisor" } */
+ else
+ return 0;
+}
+
+int test_checked_gt_zero (FILE *f)
+{
+ struct st1 s;
+ fread (&s, sizeof (s), 1, f);
+ if (s.b > 0)
+ return s.a / s.b; /* { dg-bogus "divisor" } */
+ else
+ return 0;
+}
+
+int test_checked_lt_zero (FILE *f)
+{
+ struct st1 s;
+ fread (&s, sizeof (s), 1, f);
+ if (s.b < 0)
+ return s.a / s.b; /* { dg-bogus "divisor" } */
+ else
+ return 0;
+}
+
+/* We should complain if the check on the divisor still allows it to be
+ zero. */
+
+int test_checked_ge_zero (FILE *f)
+{
+ struct st1 s;
+ fread (&s, sizeof (s), 1, f);
+ if (s.b >= 0)
+ return s.a / s.b; /* { dg-warning "use of attacker-controlled value 's\\.b' as divisor without checking for zero" } */
+ else
+ return 0;
+}
+
+int test_checked_le_zero (FILE *f)
+{
+ struct st1 s;
+ fread (&s, sizeof (s), 1, f);
+ if (s.b <= 0)
+ return s.a / s.b; /* { dg-warning "use of attacker-controlled value 's\\.b' as divisor without checking for zero" } */
+ else
+ return 0;
+}
+
+int test_checked_eq_zero (FILE *f)
+{
+ struct st1 s;
+ fread (&s, sizeof (s), 1, f);
+ /* Wrong sense of test. */
+ if (s.b != 0)
+ return 0;
+ else
+ return s.a / s.b; /* { dg-warning "use of attacker-controlled value 's\\.b' as divisor without checking for zero" } */
+}