Hello,

[email protected] on 2015-02-13:
I have a question about how Klee goes about creating test cases at the end of 
its run.  It seems that it goes through the cexPreferences that are associated 
with each MemoryObject, adding on as many as it possibly can.  (as seen in 
lib/Core/Executor.cpp::getSymbolicSolution())

In many cases, however, it seems that not all of these additional constraints 
can be added to the state.  I assume this because when I just stick on all of 
the cexPreferences to the state and call getInitialValues(), I get a lot of 
errors in the test suite.

A Klee state can correspond to many different possible test cases. For example, in this program:

 int main(int argc, char **argv) {
   return argv[1][0] ? 1 : 0;
 }

Klee will have two states, one of which corresponds to the condition "argv[1][0] != 0". When Klee generates a test case for that state, there are 255 possible values for argv[1][0].

Without cexPreferences, Klee would just tell the solver to solve
"argv[1][0] != 0" and it might return "argv[1][0] = '\x01'". That could be hard to read, though, especially with a longer string. Klee uses cexPreferences to prefer "nicer" test cases when possible, so you get "argv[1][0] = 'A'" instead of "argv[1][0] = '\x01'".

My Questions are:
1) Where do the constraints in cexPrefences come from when Klee simulates 
running a command line program?  Are there different types of constraints on 
command line arguments and input files?

They are added by the klee_prefer_cex intrinsic, which you can call just like you call klee_make_symbolic. If you use the POSIX runtime, it already calls klee_prefer_cex in a few places to prefer printable characters in argv and so on.

2) What does not fully applying all of the constraints in cexPreferences mean 
about the testcase that is created?  Is it not fully representative of the path 
that was actually taken through the program or is their a possibility of two 
tests traversing equivalent paths?

Klee should always generate one representative test case per path. CexPreferences are only used to try to generate "nice" test cases, like an argument of "AA" instead of "\x01\x01". If they fail, it means only an "ugly" test case will follow the right path, so that's what Klee will produce.

3) What does it mean about a state when a constraint in cexPreferences can't be 
applied? (i.e. solver->mustBeTrue(tmp, Expr::createIsZero(*pi), mustBeTrue == 
false);

As above.

3) Are paths leading to states where all the constraints in cexPreferences 
aren't possible traversing impossible paths?

No.

4) Why are the constraints stored in the cexPreferences not simply added in the 
beginning of the run so that unused information isn't calculated?

Because that would rule out paths that require "ugly" inputs. For instance, if your program crashes only when you give it an argument of "\x01", forcing the cexPreferences to hold would prevent you from ever seeing the crash. That's why Klee allows the preferences to fail.

Sorry for the multitude of questions and thanks,
Eric Rizzi

_______________________________________________
klee-dev mailing list
[email protected]
https://mailman.ic.ac.uk/mailman/listinfo/klee-dev

_______________________________________________
klee-dev mailing list
[email protected]
https://mailman.ic.ac.uk/mailman/listinfo/klee-dev

Reply via email to