aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2023-12-11 21:29:39 -0500
committerDavid Malcolm <dmalcolm@redhat.com>2023-12-11 21:29:39 -0500
commit2900a77fe4e7d2211a785d427794544fe3d01960 (patch)
tree1a84eb3197d8db825e7ce4163b8890da86cda965 /gcc
parent3e93a3f09dc9af7155cc4760bc65d5be4571addf (diff)
downloadgcc-2900a77fe4e7d2211a785d427794544fe3d01960.zip
gcc-2900a77fe4e7d2211a785d427794544fe3d01960.tar.gz
gcc-2900a77fe4e7d2211a785d427794544fe3d01960.tar.bz2
analyzer: add more test coverage for tainted modulus
Add more test coverage for r14-6349-g0bef72539e585d. gcc/testsuite/ChangeLog: * gcc.dg/plugin/plugin.exp: Add taint-modulus.c to analyzer_kernel_plugin.c tests. * gcc.dg/plugin/taint-modulus.c: New test. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/testsuite/gcc.dg/plugin/plugin.exp1
-rw-r--r--gcc/testsuite/gcc.dg/plugin/taint-modulus.c75
2 files changed, 76 insertions, 0 deletions
diff --git a/gcc/testsuite/gcc.dg/plugin/plugin.exp b/gcc/testsuite/gcc.dg/plugin/plugin.exp
index d6cccb2..eebf961 100644
--- a/gcc/testsuite/gcc.dg/plugin/plugin.exp
+++ b/gcc/testsuite/gcc.dg/plugin/plugin.exp
@@ -165,6 +165,7 @@ set plugin_test_list [list \
taint-CVE-2011-0521-5-fixed.c \
taint-CVE-2011-0521-6.c \
taint-antipatterns-1.c \
+ taint-modulus.c \
taint-pr112850.c \
taint-pr112850-precise.c \
taint-pr112850-too-complex.c \
diff --git a/gcc/testsuite/gcc.dg/plugin/taint-modulus.c b/gcc/testsuite/gcc.dg/plugin/taint-modulus.c
new file mode 100644
index 0000000..81d9688
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/taint-modulus.c
@@ -0,0 +1,75 @@
+/* { dg-do compile } */
+/* { dg-options "-fanalyzer" } */
+/* { dg-require-effective-target analyzer } */
+
+/* Reduced from a -Wanalyzer-tainted-array-index false +ve
+ seen in the Linux kernel's sound/drivers/opl3/opl3_synth.c. */
+
+extern unsigned long
+copy_from_user(void* to, const void* from, unsigned long n);
+
+struct sbi_patch
+{
+ unsigned char prog;
+ unsigned char bank;
+};
+struct fm_patch
+{
+ unsigned char prog;
+ unsigned char bank;
+ struct fm_patch* next;
+};
+struct snd_opl3
+{
+ struct fm_patch* patch_table[32];
+};
+int
+snd_opl3_load_patch(struct snd_opl3* opl3,
+ int prog,
+ int bank);
+struct fm_patch*
+snd_opl3_find_patch(struct snd_opl3* opl3,
+ int prog,
+ int bank,
+ int create_patch);
+long
+snd_opl3_write(struct snd_opl3* opl3,
+ const char* buf,
+ long count)
+{
+ long result = 0;
+ int err = 0;
+ struct sbi_patch inst;
+ while (count >= sizeof(inst)) {
+ if (copy_from_user(&inst, buf, sizeof(inst)))
+ return -14;
+ err = snd_opl3_load_patch(opl3, inst.prog, inst.bank);
+ if (err < 0)
+ break;
+ result += sizeof(inst);
+ count -= sizeof(inst);
+ }
+ return result > 0 ? result : err;
+}
+int
+snd_opl3_load_patch(struct snd_opl3* opl3,
+ int prog,
+ int bank)
+{
+ struct fm_patch* patch;
+ patch = snd_opl3_find_patch(opl3, prog, bank, 1);
+ if (!patch)
+ return -12;
+ return 0;
+}
+struct fm_patch*
+snd_opl3_find_patch(struct snd_opl3* opl3, int prog, int bank, int create_patch)
+{
+ unsigned int key = (prog + bank) % 32;
+ struct fm_patch* patch;
+ for (patch = opl3->patch_table[key]; patch; patch = patch->next) { /* { dg-bogus "use of attacker-controlled value in array lookup" } */
+ if (patch->prog == prog && patch->bank == bank)
+ return patch;
+ }
+ return ((void*)0);
+}