[PATCH] D88019: [analyzer][solver] Fix issue with symbol non-equality tracking

Balázs Benics via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 30 09:49:59 PDT 2020


steakhal added a comment.

In D88019#2303078 <https://reviews.llvm.org/D88019#2303078>, @martong wrote:

> I like the second approach, i.e. to have a debug checker. But I don't see, how would this checker validate all constraints at the moment when they are added to the State.

`ProgramStateRef evalAssume(ProgramStateRef State, SVal Cond, bool Assumption)` checker callback is called **after** any assume call.
So, we would have a `State` which has all? the constraints stored in the appropriate GDM. I'm not sure if we should aggregate all the constraints till this node - like we do for refutation. I think, in this case, we should just make sure that the **current** state does not have any contradiction.

---

Here is my proof-of-concept:

I've  dumped the state and args of evalAssume for the repro example, pretending that we don't reach a code-path on the infeasable path to crash:

  void avoidInfeasibleConstraintforGT(int a, int b) {
    int c = b - a;
    if (c <= 0)
      return;
    if (a != b) {
      clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
      return;
    }
    clang_analyzer_warnIfReached(); // eh, we will reach this..., #1
    // These are commented out, to pretend that we don't find out that we are on an infeasable path...
    // a == b
    // if (c < 0)
    //   ;
  }

We reach the `#1` line, but more importantly, we will have the following state dumps:

  evalAssume: assuming Cond: (reg_$1<int a>) != (reg_$0<int b>) to be true in state:
  "program_state": {
    "constraints": [
      { "symbol": "(reg_$0<int b>) - (reg_$1<int a>)", "range": "{ [1, 2147483647] }" },
      { "symbol": "(reg_$1<int a>) != (reg_$0<int b>)", "range": "{ [-2147483648, -1], [1, 2147483647] }" }
    ]
  }
  
  evalAssume: assuming Cond: (reg_$1<int a>) != (reg_$0<int b>) to be false in state:
  "program_state": {
    "constraints": [
      { "symbol": "(reg_$0<int b>) - (reg_$1<int a>)", "range": "{ [1, 2147483647] }" },
      { "symbol": "(reg_$1<int a>) != (reg_$0<int b>)", "range": "{ [0, 0] }" }
    ]
  }

As you can see, the **latter** is the //infeasable// path, and if we have had serialized the constraints and let the Z3 check it, we would have gotten that it's unfeasable.
At this point the checker can dump any useful data for debugging, and crash the analyzer to let us know that something really bad happened.

> [...] And that might be too slow, it would have the same speed as using z3 instead of the range based solver.

Yes, it will probably freaking slow, but at least we have something.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D88019/new/

https://reviews.llvm.org/D88019



More information about the cfe-commits mailing list