Skip to content

Jumps from outside of the loop into loop body will fail the loop contracts #7517

Closed
@qinheping

Description

@qinheping

Currently, to apply loop contracts, we instrument

... preamble ...
... eval guard ...
if (!guard)
  goto EXIT;
... loop body ...
goto HEAD;
EXIT:
... postamble ...

to

... preamble ...
PREHEAD: 
    skip;
    /// loop begin
    loop_entry_vars = ...;
    entered_loop = false;
    I_base = <I>;
    in_base_case = true;
    goto HEAD;
STEP:
    assert(I_base);
    in_base_case = false;
    in_loop_havoc_block = true;
    loop_i_havoc_write_set(&w_loop_i);
    in_loop_havoc_block = false;
    assume (invariant_expr);
    D_before = <D>;
HEAD:
    ... eval guard ... // instrument against w_loop_i
    if(!guard)
        GOTO EXIT;
    ... body ...       // instrument against w_loop_i
    entered_loop = true;
    if(in_base_case)
        goto STEP;
    assert(I);
    D_after = <D>;
    assert(D_after < D_before);
    DEAD D_after, D_before;
    assume(false);
EXIT:
    // did we actually do the step
    assert(entered_loop ==> !in_base_case);
    DEAD w_loop_i

... postamble ...

The havocing, all initialization of temporary variables, the snapshotting of the loop invariants all happends in the PREHEAD block or the STEP block. If there are some jumps from out side of the loop into the loop body, they will skip the PREHEAD block and the STEP block; and hence fail the loop contracts.

For example, after the instrumentation, the jump GOTO 2 in the following GOTO program will skip the PREHEAD and the STEP of the loop.

    GOTO 2;
... preamble ...
1:  IF x == 0 THEN GOTO 3;
2:  ASSIGN x := x - 1;
    GOTO 1;
3:
... postamble ...

After instrumentation

    GOTO 2;
... preamble ...

PREHEAD: 
... pre-head block ...
STEP:
... step block ...
HEAD:
1:  IF x == 0 THEN GOTO EXIT;
2:  ASSIGN x := x - 1;
    assert(loop_invariants);
... remaining part of the head block ...
    assume(false);
EXIT:
    ASSERT(entered_loop ==> !in_base_case);

... postamble ...

So, we should apply loop contracts only when there is no jumps from outside into the body of the loop, and error out otherwise.

Metadata

Metadata

Assignees

Labels

Code ContractsFunction and loop contractsawsBugs or features of importance to AWS CBMC users

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions