Project

General

Profile

Actions

Bug #1970

closed

Nondetermined variable intitialization is not performed

Added by Pavel Shved almost 13 years ago. Updated over 12 years ago.

Status:
Closed
Priority:
High
Assignee:
Category:
-
Target version:
Start date:
11/06/2011
Due date:
% Done:

0%

Estimated time:
Detected in build:
svn
Platform:
Published in build:

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

bad_s3.c (69.5 KB) bad_s3.c ssh test as in competition Pavel Shved, 12/28/2011 12:57 AM
good_bad_s3.c (69.5 KB) good_bad_s3.c "fixed" ssh test that should pass if the reason is nondet functon Pavel Shved, 12/28/2011 12:57 AM

Related issues 1 (0 open1 closed)

Related to BLAST - Bug #1684: BLAST incorrectly updates lvalue indexes when converting to SSA with recursion enabled!ClosedPavel Shved08/24/2011

Actions
Actions #1

Updated by Alexey Khoroshilov almost 13 years ago

May be more correct solution is to add explicit initialization by nondet value to all uninitialized local variables?

Actions #2

Updated by Pavel Shved almost 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? :-)

Actions #3

Updated by Pavel Shved almost 13 years ago

  • Status changed from Open to New

I gave this a thought today. This bug (and bug #1684) is a bit more profound than I thought.

I guess that reverting the fix to #1684 would be the correct way to resolve this bug, and fixing #1684 will require to revamp recursion handling instead of discarding the variable map update.

Actions #4

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.

Actions #5

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

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.

Actions #7

Updated by Pavel Shved over 12 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.

Actions

Also available in: Atom PDF