Heya!
I'm currently teaching myself how to prove programs memory safe. In that pursuit, I wrote a little struct and tried to phrase a predicate expressing general memory-safety for a pointer to that struct. While testing, I noticed that I could prove the pointer to be non-nil from that predicate, which contradicted my intuition. After digging a bit further, I managed to create the following little example where I can prove both s == nil and s != nil when assuming the invariant. I would expect to not be able to prove either as I wanted my predicate to apply to both pointers that are nil and that are non-nil.
Either, there is a soundness error or (I guess?) my predicate is contradictory. I don't think, though, that my specification is contradictory, because h() does not verify and raises an error as expected.
Here the example:
type S struct {
arr *[1]int
}
/*@
pred (s *S) Inv() {
(s != nil ==> acc(&s.arr)) &&
(s != nil && s.arr != nil ==> acc(s.arr))
}
@*/
func mk() (s *S) {
return nil
}
// verifies (unexpected)
func f() {
s := mk()
// @ assume s.Inv()
// @ unfold s.Inv()
// @ assert s != nil
return
}
// verifies (unexpected)
func g() {
s := mk()
// @ assume s.Inv()
// @ unfold s.Inv()
// @ assert s == nil
return
}
// does not verify (expected)
func h() {
var s *S = nil
// @ assert s == nil
// @ fold s.Inv()
// @ unfold s.Inv()
// @ assert s != nil
return
}
Heya!
I'm currently teaching myself how to prove programs memory safe. In that pursuit, I wrote a little struct and tried to phrase a predicate expressing general memory-safety for a pointer to that struct. While testing, I noticed that I could prove the pointer to be non-nil from that predicate, which contradicted my intuition. After digging a bit further, I managed to create the following little example where I can prove both
s == nilands != nilwhen assuming the invariant. I would expect to not be able to prove either as I wanted my predicate to apply to both pointers that are nil and that are non-nil.Either, there is a soundness error or (I guess?) my predicate is contradictory. I don't think, though, that my specification is contradictory, because
h()does not verify and raises an error as expected.Here the example: