Concretize values based on seeds when available, remove --zero-seed-extension and improve/fix seeding code#1663
Conversation
Codecov Report
Additional details and impacted files@@ Coverage Diff @@
## master #1663 +/- ##
==========================================
+ Coverage 70.48% 70.61% +0.12%
==========================================
Files 154 154
Lines 18870 18875 +5
Branches 4424 4426 +2
==========================================
+ Hits 13301 13328 +27
+ Misses 3654 3630 -24
- Partials 1915 1917 +2
|
MartinNowack
left a comment
There was a problem hiding this comment.
@ccadar Thanks for reviving @hoangmle's PR and adding support for better seed handling.
I've added a more thorough comment to the first change.
Follow-up changes have similar issues.
In a nutshell, not every seed might lead to a constant expression, especially with changing pointers across runs plus patching up seeds.
|
@MartinNowack thanks for the thorough review. My understanding was that @hoangmle 's contribution handled the most common case of a single seed -- see also the test cases. I was fine with that, and I think it's strictly better than what we have now. But let me think if the more complex cases could be easily handled as well. |
35b638b to
760b500
Compare
|
@MartinNowack thanks for the excellent review. |
danielschemmel
left a comment
There was a problem hiding this comment.
I only went over the code, but did not try to semantically review the PR.
While some of the comments are stylistic choices, I also found a few instances of objects being copied as the loop variables of range-based for loops.
| auto found = seedMap.find(&state); | ||
| if (found != seedMap.end()) { |
There was a problem hiding this comment.
| auto found = seedMap.find(&state); | |
| if (found != seedMap.end()) { | |
| if (auto found = seedMap.find(&state); found != seedMap.end()) { |
| auto a = assignment.bindings.find(array); | ||
| if (a != assignment.bindings.end()) { |
There was a problem hiding this comment.
| auto a = assignment.bindings.find(array); | |
| if (a != assignment.bindings.end()) { | |
| if (auto a = assignment.bindings.find(array); a != assignment.bindings.end()) { |
f5e6cc2 to
dde390b
Compare
…ts (w/ and w/o seed extension) based on FP concretization.
…able. Added a test case.
dde390b to
345d4b1
Compare
…on. This reworked logic also fixes a buffer overflow which could be triggered during seed extension.
345d4b1 to
1f9944b
Compare
|
@danielschemmel thanks for the additional suggestions; I have applied most of them. @MartinNowack can you merge this, unless you have additional concerns? |
| ref<Expr> value; | ||
| if (auto found = seedMap.find(&state); found != seedMap.end()) | ||
| value = getValueFromSeeds(found->second, e); | ||
| /* If no seed evaluation results in a constant, call the solver */ |
There was a problem hiding this comment.
Is there are reason for using C-style comments? It makes it harder to comment out blocks (due to nesting) and is not recommended by the LLVM coding standard:
There was a problem hiding this comment.
No particular reason, and I think we can live with both. I guess I could change it, but I'm not convinced it matters. And looking at the code, we seem to use both types of comments.
To comment out code, I recommend #if 0 / #endif which should work with both types of comments.
There was a problem hiding this comment.
To comment out code, I recommend #if 0 / #endif which should work with both types of comments.
Common IDEs only support the traditional line/block comment via shortcuts but ok.
MartinNowack
left a comment
There was a problem hiding this comment.
@ccadar Thanks a lot for the changes. I'm mostly happy with it.
The only major issue I found is the newly introduced function getValueFromSeeds.
I would recommend changing it to simplify the code on the call side.
lib/Core/Executor.h
Outdated
| /// first one that results in a constant, if such a seed exist. Otherwise, | ||
| /// return the non-constant evaluation of the expression under one of the | ||
| /// seeds. | ||
| ref<klee::Expr> getValueFromSeeds(std::vector<SeedInfo> &seeds, |
There was a problem hiding this comment.
I would suggest to change the API of this call to use the current state as an argument and return a constant expression.
ref<klee::ConstantExpr> getValueFromSeeds(ExecutionState& state, const ref<Expr> &e);
As it stands now, all of the calls togetValueFromSeeds are guarded by a look-up of the seed vector with a subsequent check if the returned value is a constant expr.
Moving that lookup into the function itself makes that function easier to use.
This would simplify the code around quite a lot.
lib/Core/Executor.cpp
Outdated
| assert(success && "FIXME: Unhandled solver failure"); | ||
| (void) success; | ||
| ce->toMemory(&args[wordIndex]); | ||
| ref<ConstantExpr> cvalue; |
There was a problem hiding this comment.
This would become
ref<ConstantExpr> value = getValueFromSeeds(state, *ai);
if (!value) {
// do solver call
}
|
Thanks for the extra feedback, @MartinNowack , I have refactored that function now. |
Summary:
Concretize values based on seeds when available. The three commits handle the cases of concretizing an expression via toConstant, performing an external call with symbolic arguments and calling malloc with a symbolic argument, respectively.
Each case is accompanied by a test.
The PR is based on #1117 by @hoangmle
Checklist: