Page MenuHomePhabricator

[analyzer] Pass the correct loc Expr from VisitIncDecOp to evalStore
ClosedPublic

Authored by r.stahl on Dec 14 2018, 3:42 AM.

Details

Summary

The LocationE parameter of evalStore is documented as "The location expression that is stored to". When storing from an increment / decrement operator this was not satisfied. In user code this causes an inconsistency between the SVal and Stmt parameters of checkLocation.

Diff Detail

Repository
rC Clang

Event Timeline

r.stahl created this revision.Dec 14 2018, 3:42 AM
NoQ accepted this revision.Dec 14 2018, 2:23 PM

Thanks! Neat test.

Can we now assert(LocationE->isGLValue()) in evalStore()? What about evalLoad()?

Also, were no other checkers affected? Like, will null pointer dereference checker now warn upon something like (*0)++ or ++(*0)?

You can commit the patch, but i would also love to see these questions investigated.

This revision is now accepted and ready to land.Dec 14 2018, 2:23 PM
This revision was automatically updated to reflect the committed changes.

I tried adding isGLValue to evalStore and the test suite didn't complain. For evalLoad (on BoundEx) it failed in pretty much every test. Should the evalStore assert also go into trunk?

Since the analyzer behavior itself remains unchanged, I don't believe any other checker should be affected.

For myself it was pretty obvious that there is something weird going on when I didn't get the expected Stmt in my checker callback. So I added the following workaround. With this patch, the workaround is safely skipped.

The only change that this patch might cause "in the wild" is when someone used the Stmt as location, but didn't test with IncDecOps. However, as far as I can tell this should only have positive outcome.

Do I have any other means to check if other checkers were affected than to run the test suite?

// Workaround for an inconsistency with IncDecOps: The statement is not the location expr.
if (auto unaryE = dyn_cast<UnaryOperator>(S))
{
  if (unaryE->isIncrementDecrementOp())
  {
    S = unaryE->getSubExpr();
  }
}