Skip to content

Can prove nil-ness and non-nilness from struct predicate #1025

Description

@felixlinker

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
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentation

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions