[Bug analyzer/106284] New: False positives from -Wanalyzer-tainted-array-index with optimized conditionals

dmalcolm at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Wed Jul 13 20:08:10 GMT 2022


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).


More information about the Gcc-bugs mailing list