[committed] analyzer: fix ICE in taint checker on unary ops [PR104029]
Commit Message
gcc/analyzer/ChangeLog:
PR analyzer/104029
* sm-taint.cc (taint_state_machine::alt_get_inherited_state):
Remove gcc_unreachable from default case for unary ops.
gcc/testsuite/ChangeLog:
PR analyzer/104029
* gcc.dg/analyzer/pr104029.c: New test.
* gcc.dg/analyzer/taint-ops.c: New test.
---
gcc/analyzer/sm-taint.cc | 1 -
gcc/testsuite/gcc.dg/analyzer/pr104029.c | 115 ++++++++++++++++++++++
gcc/testsuite/gcc.dg/analyzer/taint-ops.c | 106 ++++++++++++++++++++
3 files changed, 221 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/gcc.dg/analyzer/pr104029.c
create mode 100644 gcc/testsuite/gcc.dg/analyzer/taint-ops.c
Comments
On Fri, 2022-01-14 at 17:53 -0500, David Malcolm wrote:
> gcc/analyzer/ChangeLog:
> PR analyzer/104029
> * sm-taint.cc (taint_state_machine::alt_get_inherited_state):
> Remove gcc_unreachable from default case for unary ops.
>
> gcc/testsuite/ChangeLog:
> PR analyzer/104029
> * gcc.dg/analyzer/pr104029.c: New test.
> * gcc.dg/analyzer/taint-ops.c: New test.
Forgot to add:
Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Pushed to trunk as r12-6597-g8931adfa0530590d21e74e5c7a1f8d26df575775.
[...snip...]
@@ -649,7 +649,6 @@ taint_state_machine::alt_get_inherited_state (const sm_state_map &map,
return arg_state;
}
default:
- gcc_unreachable ();
break;
}
}
new file mode 100644
@@ -0,0 +1,115 @@
+// TODO: remove need for this option
+/* { dg-additional-options "-fanalyzer-checker=taint" } */
+
+typedef __SIZE_TYPE__ size_t;
+typedef const void *t_comptype;
+typedef int (*t_compfunc)(t_comptype, t_comptype);
+
+extern int *__errno_location(void)
+ __attribute__((__nothrow__, __leaf__,__const__));
+extern void free(void *__ptr)
+ __attribute__((__nothrow__, __leaf__));
+extern void *my_malloc1(const char *file, int line, size_t size);
+
+int heapsort(void *vbase, size_t nmemb, size_t size, t_compfunc compar) {
+ char tmp, *tmp1, *tmp2, *abase, *k, *p, *t;
+ size_t cnt, i, j, l;
+
+ if (nmemb <= 1)
+ return (0);
+
+ if (!size) {
+ (*__errno_location()) = 22;
+ return (-1);
+ }
+
+ k = my_malloc1(__FILE__, __LINE__, size);
+
+ abase = (char *)vbase - size;
+
+ for (l = nmemb / 2 + 1; --l;) {
+ for (i = l; (j = i * 2) <= nmemb; i = j) {
+ p = abase + j * size;
+ if (j < nmemb && compar(p, p + size) < 0) {
+ p += size;
+ ++j;
+ }
+ t = abase + i * size;
+ if (compar(p, t) <= 0)
+ break;
+ {
+ cnt = size;
+ do {
+ tmp = *t;
+ *t++ = *p;
+ *p++ = tmp;
+ } while (--cnt);
+ };
+ }
+ };
+
+ while (nmemb > 1) {
+ {
+ cnt = size;
+ tmp1 = k;
+ tmp2 = abase + nmemb * size;
+ do {
+ *tmp1++ = *tmp2++;
+ } while (--cnt);
+ };
+ {
+ cnt = size;
+ tmp1 = abase + nmemb * size;
+ tmp2 = abase + size;
+ do {
+ *tmp1++ = *tmp2++;
+ } while (--cnt);
+ };
+ --nmemb;
+ {
+ for (i = 1; (j = i * 2) <= nmemb; i = j) {
+ p = abase + j * size;
+ if (j < nmemb && compar(p, p + size) < 0) {
+ p += size;
+ ++j;
+ }
+ t = abase + i * size;
+ {
+ cnt = size;
+ tmp1 = t;
+ tmp2 = p;
+ do {
+ *tmp1++ = *tmp2++;
+ } while (--cnt);
+ };
+ }
+ for (;;) {
+ j = i;
+ i = j / 2;
+ p = abase + j * size;
+ t = abase + i * size;
+ if (j == 1 || compar(k, t) < 0) {
+ {
+ cnt = size;
+ tmp1 = p;
+ tmp2 = k;
+ do {
+ *tmp1++ = *tmp2++;
+ } while (--cnt);
+ };
+ break;
+ }
+ {
+ cnt = size;
+ tmp1 = p;
+ tmp2 = t;
+ do {
+ *tmp1++ = *tmp2++;
+ } while (--cnt);
+ };
+ }
+ };
+ }
+ free(k);
+ return (0);
+}
new file mode 100644
@@ -0,0 +1,106 @@
+/* { dg-additional-options "-fanalyzer-checker=taint" } */
+// TODO: remove need for this option
+/* This test can probably be removed when -fanalyzer enables
+ the taint checker by default. */
+
+#include "analyzer-decls.h"
+
+void
+test_1 (char a)
+{
+ char b = -a;
+}
+
+/* Copies of code from data-model-1.c. */
+
+void test_20 (int i, int j)
+{
+ __analyzer_eval (i + 1); /* { dg-warning "UNKNOWN" } */
+ __analyzer_eval (i + j); /* { dg-warning "UNKNOWN" } */
+
+ __analyzer_eval (i - 1); /* { dg-warning "UNKNOWN" } */
+ __analyzer_eval (i - j); /* { dg-warning "UNKNOWN" } */
+
+ __analyzer_eval (i * 2); /* { dg-warning "UNKNOWN" } */
+ __analyzer_eval (i * j); /* { dg-warning "UNKNOWN" } */
+
+ __analyzer_eval (i / 2); /* { dg-warning "UNKNOWN" } */
+ __analyzer_eval (i / j); /* { dg-warning "UNKNOWN" } */
+
+ __analyzer_eval (i % 2); /* { dg-warning "UNKNOWN" } */
+ __analyzer_eval (i % j); /* { dg-warning "UNKNOWN" } */
+
+ __analyzer_eval (i & 1); /* { dg-warning "UNKNOWN" } */
+ __analyzer_eval (i & j); /* { dg-warning "UNKNOWN" } */
+
+ __analyzer_eval (i | 1); /* { dg-warning "UNKNOWN" } */
+ __analyzer_eval (i | j); /* { dg-warning "UNKNOWN" } */
+
+ __analyzer_eval (i ^ 1); /* { dg-warning "UNKNOWN" } */
+ __analyzer_eval (i ^ j); /* { dg-warning "UNKNOWN" } */
+
+ __analyzer_eval (i >> 1); /* { dg-warning "UNKNOWN" } */
+ __analyzer_eval (i >> j); /* { dg-warning "UNKNOWN" } */
+
+ __analyzer_eval (i << 1); /* { dg-warning "UNKNOWN" } */
+ __analyzer_eval (i << j); /* { dg-warning "UNKNOWN" } */
+
+ __analyzer_eval (i && 0); /* { dg-warning "FALSE" } */
+ __analyzer_eval (i && 1); /* { dg-warning "UNKNOWN" } */
+ __analyzer_eval (i && j); /* { dg-warning "UNKNOWN" } */
+
+ __analyzer_eval (i || 0); /* { dg-warning "UNKNOWN" } */
+
+ __analyzer_eval (i || 1); /* { dg-warning "TRUE" } */
+ __analyzer_eval (i || j); /* { dg-warning "UNKNOWN" } */
+
+ __analyzer_eval (~i); /* { dg-warning "UNKNOWN" } */
+ __analyzer_eval (-i); /* { dg-warning "UNKNOWN" } */
+ __analyzer_eval (+i); /* { dg-warning "UNKNOWN" } */
+
+ /* Anything added above should be added to the next function also. */
+}
+
+void test_21 (void)
+{
+ int i, j, zero;
+ int *pi = &i;
+ int *pj = &j;
+ int *pzero = &zero;
+ *pi = 5;
+ *pj = 3;
+ *pzero = 0;
+
+ __analyzer_eval (i + j == 8); /* { dg-warning "TRUE" } */
+ __analyzer_eval (i - j == 2); /* { dg-warning "TRUE" } */
+ __analyzer_eval (i * j == 15); /* { dg-warning "TRUE" } */
+ __analyzer_eval (i / j == 1); /* { dg-warning "TRUE" } */
+ __analyzer_eval (i % j == 2); /* { dg-warning "TRUE" } */
+
+ /* Division by zero. */
+ // TODO: should we warn for this?
+ __analyzer_eval (i / zero); /* { dg-warning "UNKNOWN" } */
+ __analyzer_eval (i % zero); /* { dg-warning "UNKNOWN" } */
+
+ __analyzer_eval ((i & 1) == (5 & 1)); /* { dg-warning "TRUE" } */
+ __analyzer_eval ((i & j) == (5 & 3)); /* { dg-warning "TRUE" } */
+ __analyzer_eval ((i | 1) == (5 | 1)); /* { dg-warning "TRUE" } */
+ __analyzer_eval ((i | j) == (5 | 3)); /* { dg-warning "TRUE" } */
+ __analyzer_eval ((i ^ 1) == (5 ^ 1)); /* { dg-warning "TRUE" } */
+ __analyzer_eval ((i ^ j) == (5 ^ 3)); /* { dg-warning "TRUE" } */
+ __analyzer_eval ((i >> 1) == (5 >> 1)); /* { dg-warning "TRUE" } */
+ __analyzer_eval ((i >> j) == (5 >> 3)); /* { dg-warning "TRUE" } */
+ __analyzer_eval ((i << 1) == (5 << 1)); /* { dg-warning "TRUE" } */
+ __analyzer_eval ((i << j) == (5 << 3)); /* { dg-warning "TRUE" } */
+ __analyzer_eval (i && 0); /* { dg-warning "FALSE" } */
+ __analyzer_eval (i && 1); /* { dg-warning "TRUE" } */
+ __analyzer_eval (i && j); /* { dg-warning "TRUE" } */
+
+ __analyzer_eval (i || 0); /* { dg-warning "TRUE" } */
+ __analyzer_eval (i || 1); /* { dg-warning "TRUE" } */
+ __analyzer_eval (i || j); /* { dg-warning "TRUE" } */
+
+ __analyzer_eval (~i == ~5); /* { dg-warning "TRUE" } */
+ __analyzer_eval (-i == -5); /* { dg-warning "TRUE" } */
+ __analyzer_eval (+i == +5); /* { dg-warning "TRUE" } */
+}