<html>
    <head>
      <base href="https://llvm.org/bugs/" />
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW --- - ArrayBoundCheckerV2 false positive due to dead symbol remove."
   href="https://llvm.org/bugs/show_bug.cgi?id=27820">27820</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>ArrayBoundCheckerV2 false positive due to dead symbol remove.
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>clang
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>3.6
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Windows NT
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>Static Analyzer
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>kremenek@apple.com
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>ioripolo@foxmail.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr>

        <tr>
          <th>Classification</th>
          <td>Unclassified
          </td>
        </tr></table>
      <p>
        <div>
        <pre>I got a simple test case as below:

  typedef struct _FILE FILE;
  extern FILE *stdin;

  void foo() {
    int pos = 1;
    int table[] = {1, 2};
    char inputBuffer[2] = "";
    fgets(inputBuffer, 2, stdin);
    pos = atoi(inputBuffer);
    if (pos > 0 && pos <=2) {
      table[pos] = 10;
    }
  }

And with the command line "clang -cc1 -analyze -w
-analyzer-checker=alpha.security.ArrayBoundV2
-analyzer-checker=alpha.security.taint test.c"

Then i got a warning like this:

  test.c:15:16: warning: Out of bound memory access (index is tainted)
    table[pos] = 10;
    ~~~~~~~~~~~^~~~
  1 warning generated.

But we have a validation "if (pos > 0 && pos <=2)", so the extent of pos should
be OK.



After took a look inside this false positive, i think i found the reason:

In the 'PreStmtPurgeDeadSymbols' process of the assign binaryoperator
'table[pos] = 10', the 'pos' is not live any more, so the conjured symbol and
it's constraint were removed.

Later when we check the location for ArrayBoundV2, because the removement of
the conjured symbol, both 'state_exceedsUpperBound'and 'state_withinUpperBound'
are not null. Finally got the warning according the logic below.

    // If we are under constrained and the index variables are tainted, report.
    if (state_exceedsUpperBound && state_withinUpperBound) {
      if (state->isTainted(rawOffset.getByteOffset()))
        reportOOB(checkerContext, state_exceedsUpperBound, OOB_Tainted);
        return;
    }</pre>
        </div>
      </p>
      <hr>
      <span>You are receiving this mail because:</span>
      
      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>