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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions