https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106284
Bug ID: 106284 Summary: False positives from -Wanalyzer-tainted-array-index with optimized conditionals Product: gcc Version: 12.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: analyzer Assignee: dmalcolm at gcc dot gnu.org Reporter: dmalcolm at gcc dot gnu.org Target Milestone: --- Consider: #define LOWER_LIMIT 5 #define UPPER_LIMIT 10 static int arr[UPPER_LIMIT]; static int called_by_test_1 (int iarg) { return arr[iarg]; /* { dg-warning "without bounds checking" } */ } int __attribute__((tainted_args)) test_1 (unsigned long ularg) { return called_by_test_1 (ularg); } static int called_by_test_2 (int iarg) { if (iarg < LOWER_LIMIT || iarg > UPPER_LIMIT) return 0; return arr[iarg]; /* { dg-bogus "bounds checking" "" { xfail *-*-* } } */ } int __attribute__((tainted_args)) test_2 (unsigned long ularg) { return called_by_test_2 (ularg); } int __attribute__((tainted_args)) test_3 (int iarg) { if (iarg < LOWER_LIMIT || iarg > UPPER_LIMIT) return 0; return arr[iarg]; /* { dg-bogus "bounds checking" "" { xfail *-*-* } } */ } int __attribute__((tainted_args)) test_4 (unsigned int uiarg) { if (uiarg > UPPER_LIMIT) return 0; return arr[uiarg]; /* { dg-bogus "bounds checking" } */ } This gives false positives from -Wanalyzer-tainted-array-index at -O1 and above at the xfails. See: https://godbolt.org/z/ahq7G6b4n Affects trunk and gcc 12.1; would possibly also affect 11 (but that reproducer uses __attribute__((tainted_args)) which gcc 12 added). Seen via false positive on Linux kernel in drivers/usb/class/usblp.c in function ‘usblp_set_protocol’ handling usblp_ioctl on IOCNR_SET_PROTOCOL, which has: | 1337 | if (protocol < USBLP_FIRST_PROTOCOL || protocol > USBLP_LAST_PROTOCOL) | | ~ | | | | | (15) following ‘false’ branch... |...... | 1341 | if (usblp->intf->num_altsetting > 1) { | | ~~~~~~~~~~~~ | | | | | | | (16) ...to here | | (17) following ‘true’ branch... | 1342 | alts = usblp->protocol[protocol].alt_setting; | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | | | | (18) ...to here | | (19) use of attacker-controlled value ‘arg’ in array lookup without bounds checking where "arg" is "protocol" (but from the caller frame), and is checked at (15).