Quuxplusone / LLVMBugzillaTest

0 stars 0 forks source link

scan-build null dereference false positive #16129

Open Quuxplusone opened 11 years ago

Quuxplusone commented 11 years ago
Bugzilla Link PR16129
Status NEW
Importance P normal
Reported by Nick Bowler (nbowler@draconx.ca)
Reported on 2013-05-23 14:58:31 -0700
Last modified on 2013-06-07 12:22:00 -0700
Version 3.2
Hardware PC Linux
CC ganna@apple.com, jrose@belkadan.com, llvm-bugs@lists.llvm.org
Fixed by commit(s)
Attachments report-HKmf7s.html (6717 bytes, text/html)
Blocks
Blocked by
See also
Created attachment 10575
Annotated source file.

Consider the following C program (key locations marked in comments):

  #include <stdio.h>
  #include <stdlib.h>

  int main(int argc, char **argv)
  {
    int *x = NULL, n = argc;

    if (!x && !argv[n]) /* (A) */
        return EXIT_FAILURE;

    if (argv[n]) /* (B) */
        ;
    else
        printf("%d\n", *x); /* (C) */

    return EXIT_SUCCESS;
  }

The scan-build report suggests that a NULL pointer dereference is possible by
the following path:

  1: false branch at (A)
  2: false branch at (B)
  3: NULL dereference at (C).

This is clearly a false positive.  By taking the false branch at A, that
implies that at least one of x and argv[n] is non-zero (ignore the fact that
in this test case both values are always zero).  By taking the false branch at
B, this implies that argv[n] is zero.  So given the first 2 decisions, we can
conclude that x must be non-zero at (C), and thus there is no NULL
dereference.
Quuxplusone commented 11 years ago

Attached report-HKmf7s.html (6717 bytes, text/html): Annotated source file.

Quuxplusone commented 11 years ago
Simplified:

  int test(int n, char **args)
  {
    if (!args[n])
      return 0;

    if (!args[n])
      *(volatile int *)0 = 1;
    return 1;
  }

(I've taken argv and argc out of the equation since argv[argc] is guaranteed to
be NULL, even though the analyzer doesn't know that today.)

This does seem like a bug.
Quuxplusone commented 11 years ago

Cloned to rdar://problem/14087970

Quuxplusone commented 11 years ago

Nick, A workaround would be to use a boolean flag to store the value of !argv[n].