Bug #1970
closedNondetermined variable intitialization is not performed
0%
Description
At the Competition on Software Verification 2012, the functions that return a nondetermined value at each call are assumed to have the same behavior as this function:
X __VERIFIER_nondet_X() { X val; return val; }
However, if this definition is actually in the source code, BLAST doesn't think it's undetermined. Instead, it thinks that all invocations of such a function return the same value!
This bug leads to false safes, so it should be fixed. In competition setup we lose 10 points because of this, and could have lost 30 points more if the presence of this definition hadn't made several ssh* tests time out instead of failing with a wrong verdict.
To check for this behavior, I added a test: source:tests/files/nondet_definition.c
How to fix it?¶
According to C standards (as per this StackOverflow answer), a variable inside a function that is uninitialized at declaration gets an undetermined value. However, the function listed above is transformed by CIL to a CFG with one edge with a Return() operation on it. Return operation, by definition, works with Expressions rather than with Lvalues, so it can't be used for updating the Lvalue it returns in our case.
I guess, the proper solution is to update local variable maps at function calls.
And I suddenly recalled that I've already "fixed" something about variable maps at function calls. In bug #1684, there was a functionality that cleared these maps at each function call, but I removed it because it interfered with alias analysis badly.
So, we need to revamp the fix of #1684, and create a consistent approach to local variable mappings that suits both aliases and such cases as in the test linked above. Maybe, we may implement port something from "non-flat" algorithms described in "Abstractions from Proofs"...
Files
Updated by Alexey Khoroshilov about 13 years ago
May be more correct solution is to add explicit initialization by nondet value to all uninitialized local variables?
Updated by Pavel Shved about 13 years ago
Alexey Khoroshilov wrote:
May be more correct solution is to add explicit initialization by nondet value to all uninitialized local variables?
I wouldn't call it "a solution", I'd rather use the word "idea". Because this "idea" may be implemented in the multitude of ways.
If you propose to initialize each uninitialized variable with a nondetermined function call at declarations, then I don't like this, and here's why. Adding a separate function call at each variable declaration would increase the number of nodes in CFGs dramatically (each function adds 3 spurious nodes, which means 3 more steps in the big model checker loop). Though linear, this increase would just make debugging harder, add a lot of function call nodes and edges, and make the overall verification slower.
I would prefer just to assign different indexes at SSA conversion phase. That's what I meant by "update local variable maps at function calls". Besides, we may be sure that there's no possible connection between different instances of x
in two calls to such functions, and this is expressed via SSA conversion better than via nondetermined function calls.
And last, but not least, we would be trying to implement a nondetermined function via... another nondetermined function! Doesn't it look ridiculous? :-)
Updated by Pavel Shved almost 13 years ago
- Status changed from Open to New
Updated by Pavel Shved almost 13 years ago
- Status changed from New to Open
- Assignee set to Pavel Shved
I fixed lvalue mapping for non-recursive calls in adbcb02d.
It passes small tests (such as source:tests/files/nondet_definition.c or competition's stateful_check.c), and I'm currently running SSH tests BLAST made a wrong answer to.
Updated by Pavel Shved almost 13 years ago
Surprisingly, this didn't fix the problems in SSH tests.
This means, I've made a mistake, which I should fix.
Updated by Pavel Shved almost 13 years ago
- File bad_s3.c bad_s3.c added
- File good_bad_s3.c good_bad_s3.c added
- Status changed from Open to Resolved
I checked the test results, and found out that it's not undetermined function what prevents SSH tests from finishing O_O.
If it was a regular function, not an undetermined one, the tests would also fail. If we replace in bad_s3 (times out: the original SSH test should finish in less than 20000 iterations) the undetermined function
int __VERIFIER_nondet_int() { int val; return val; }
with good ol'
extern int nondet(); int __VERIFIER_nondet_int() { return nondet(); }
then the test fails as well.
So, I guess, I've fixed the undetermined function bug. The real issue with SSH's tests with __VERIFIER_nondet_int() is discussed in bug #2154.
Updated by Pavel Shved almost 13 years ago
- Status changed from Resolved to Closed
I think we can close this now.
Tomorrow I'll upload BLAST's binary files, and announce the next release with a note about our competition participation.