Skip to content

fix-846: Viper encoding leads to insufficient permissions with interfaces #955

Description

@henriman
package tests

type HostAddr interface {
    pred Mem()

    ghost
    hyper
    requires Mem()
    decreases
    pure IsLow() bool
}

type HostNone int

pred (h HostNone) Mem() { true }

ghost
hyper
requires h.Mem()
decreases
pure func (h HostNone) IsLow() bool {
    return true
}

HostNone implements HostAddr

Trying to verify the above program using Gobra branch fix-846 and --hyperMode=on leads to the following verification error (line 6 is at ghost in the interface definition):

12:56:23.200 [pool-1-thread-1] ERROR viper.gobra.reporting.FileWriterReporter - Error at: <.\tests\test85-fix-846.gobra:6:5> Precondition of call might not hold.
Permission to Mem() might not suffice.
12:56:23.304 [pool-1-thread-1] ERROR viper.gobra.reporting.FileWriterReporter - Error at: <.\tests\test85-fix-846.gobra:6:5> Precondition of call might not hold.
Permission to Mem() might not suffice.

The reason can be found in the Viper encoding:

function IsLow_3eb53157_SY$ac11f519_3eb53157_(thisItf0: Tuple2[Ref, Types],
  thisItf1: Tuple2[Ref, Types]): Bool
  requires thisItf0 != (tuple2(null, nil_Types()): Tuple2[Ref, Types]) &&
    thisItf1 != (tuple2(null, nil_Types()): Tuple2[Ref, Types])
  requires acc(dynamic_pred_00(thisItf0), write) &&
    acc(dynamic_pred_01(thisItf1), write)
  ensures ((get1of2(thisItf0): Types) == HostNone_3eb53157_T_Types() ==>
    result ==
    DefinedHostNone_3eb53157_T$$$$_E_$$$_IsLow_3eb53157_MHostNone_IsLow_3eb53157_SY$ac11f519_3eb53157__proof((unbox_Poly((get0of2(thisItf0): Ref)): Int),
    (unbox_Poly((get0of2(thisItf1): Ref)): Int))) &&
    ((get1of2(thisItf1): Types) == HostNone_3eb53157_T_Types() ==>
    result ==
    DefinedHostNone_3eb53157_T$$$$_E_$$$_IsLow_3eb53157_MHostNone_IsLow_3eb53157_SY$ac11f519_3eb53157__proof((unbox_Poly((get0of2(thisItf0): Ref)): Int),
    (unbox_Poly((get0of2(thisItf1): Ref)): Int)))
  decreases ItfMethodMeasure(), ItfMethodMeasure()
{
  IsLow_3eb53157_SY$ac11f519_3eb53157_$itfcopy$fallback(thisItf0, thisItf1) &&
  IsLow_3eb53157_SY$ac11f519_3eb53157_$itfcopy$fallback(thisItf0, thisItf1)
}
Precondition of function DefinedHostNone_3eb53157_T$$$$_E_$$$_IsLow_3eb53157_MHostNone_IsLow_3eb53157_SY$ac11f519_3eb53157__proof might not hold. There might be insufficient permission to access dynamic_pred_01((tuple2((box_Poly((unbox_Poly((get0of2(thisItf1): Ref)): Int)): Ref), HostNone_3eb53157_T_Types()): Tuple2[Ref, Types]))

The problem: DefinedhostNone_... requires (get1of2(thisItf1): Types) == HostNone_3eb53157_T_Types() as well. Thus, a potential fix could be to replace

ensures ((get1of2(thisItf0): Types) == HostNone_3eb53157_T_Types() ==>

by

ensures ((get1of2(thisItf0): Types) == HostNone_3eb53157_T_Types() && (get1of2(thisItf1): Types) == HostNone_3eb53157_T_Types() ==>

(and analogously for the second call, where it is the other way around), which makes the file verify successfully.


This bug only occurs when the function is annotated with hyper, and when the interface has at least one type implementing it.

(@jcp19)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions