This is an archive of the discontinued LLVM Phabricator instance.

[analyzer][solver] Fix CmpOpTable handling bug
ClosedPublic

Authored by martong on Oct 1 2021, 1:34 AM.

Details

Summary

There is an error in the implementation of the logic of reaching the Unknonw tristate in CmpOpTable.

void cmp_op_table_unknownX2(int x, int y, int z) {
  if (x >= y) {
                    // x >= y    [1, 1]
    if (x + z < y)
      return;
                    // x + z < y [0, 0]
    if (z != 0)
      return;
                    // x < y     [0, 0]
    clang_analyzer_eval(x > y);  // expected-warning{{TRUE}} expected-warning{{FALSE}}
  }
}

We miss the FALSE warning because the false branch is infeasible.

We have to exploit simplification to discover the bug. If we had x < y
as the second condition then the analyzer would return the parent state
on the false path and the new constraint would not be part of the State.
But adding z to the condition makes both paths feasible.

The root cause of the bug is that we reach the Unknown tristate
twice, but in both occasions we reach the same Op that is >= in the
test case. So, we reached >= twice, but we never reached !=, thus
querying the Unknonw2x column with getCmpOpStateForUnknownX2 is
wrong.

The solution is to ensure that we reached both different Ops once.

Diff Detail

Event Timeline

martong created this revision.Oct 1 2021, 1:34 AM
martong requested review of this revision.Oct 1 2021, 1:34 AM
Herald added a project: Restricted Project. · View Herald TranscriptOct 1 2021, 1:34 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript

Thanks for mentioning me. I'll make a review of this tomorrow.

ASDenysPetrov accepted this revision.EditedOct 6 2021, 7:01 AM

I see the problem. It appears when you meet, say, > in a true branch and <= in a false branch which then turns into > again and trigger the flag, but shouldn't. Your solution is correct and looks clear.
Here I propose you one more to not use additional abstruction in a favor of performance. See inlines.

clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
1129–1134
1170–1173
1179–1182
This revision is now accepted and ready to land.Oct 6 2021, 7:01 AM
martong updated this revision to Diff 377564.Oct 6 2021, 9:00 AM
  • Update to use a single variable to track the state
  • Make CurrentOP const

Thanks for the review Denys!

I've updated accordingly to your suggestion, it is certainly more efficient. However, I've found your solution more difficult to follow, thus I've added some more explanatory comments.

This revision was landed with ongoing or failed builds.Oct 6 2021, 9:28 AM
This revision was automatically updated to reflect the committed changes.

LGTM

clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
1129–1135

Perfect explanation. This is really worth to be here.

P.S. My nit. Disregard if you think it is unnecessary.