Skip to content
Draft
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pkg/addr/fmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ func FormatAS(as_ AS, opts ...FormatOption) string {
return s
}

// @ requires as_.inRange()
// @ requires as_.InRange()
// @ decreases
func fmtAS(as_ AS, sep string) string {
if !as_.inRange() {
Expand Down
8 changes: 4 additions & 4 deletions pkg/addr/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const (
HostTypeSVC
)

// @ requires isValidHostAddrType(t)
// @ requires IsValidHostAddrType(t)
// @ decreases
func (t HostAddrType) String() string {
switch t {
Expand Down Expand Up @@ -433,8 +433,8 @@ func (h HostSVC) Network() string {
}

// @ requires acc(b)
// @ requires isValidHostAddrType(htype)
// @ requires len(b) == sizeOfHostAddrType(htype)
// @ requires IsValidHostAddrType(htype)
// @ requires len(b) == SizeOfHostAddrType(htype)
// @ ensures err == nil ==> res.Mem()
// @ decreases
func HostFromRaw(b []byte, htype HostAddrType) (res HostAddr, err error) {
Expand Down Expand Up @@ -502,7 +502,7 @@ func HostFromIPStr(s string) (res HostAddr) {
return HostFromIP(ip)
}

// @ requires isValidHostAddrType(htype)
// @ requires IsValidHostAddrType(htype)
// @ decreases
func HostLen(htype HostAddrType) (uint8, error) {
var length uint8
Expand Down
6 changes: 3 additions & 3 deletions pkg/addr/host_spec.gobra
Original file line number Diff line number Diff line change
Expand Up @@ -51,21 +51,21 @@ pred (h *HostSVC) Mem() { acc(h) }

ghost
decreases
pure func isValidHostAddrType(htype HostAddrType) bool {
pure func IsValidHostAddrType(htype HostAddrType) bool {
return htype == HostTypeNone ||
htype == HostTypeIPv4 ||
htype == HostTypeIPv6 ||
htype == HostTypeSVC
}

ghost
requires isValidHostAddrType(htype)
requires IsValidHostAddrType(htype)
ensures htype == HostTypeNone ==> res == HostLenNone
ensures htype == HostTypeIPv4 ==> res == HostLenIPv4
ensures htype == HostTypeIPv6 ==> res == HostLenIPv6
ensures htype == HostTypeSVC ==> res == HostLenSVC
decreases
pure func sizeOfHostAddrType(htype HostAddrType) (res int) {
pure func SizeOfHostAddrType(htype HostAddrType) (res int) {
return htype == HostTypeNone ?
HostLenNone : htype == HostTypeIPv4 ?
HostLenIPv4 : htype == HostTypeIPv6 ?
Expand Down
14 changes: 7 additions & 7 deletions pkg/addr/isdas.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,13 @@ type AS uint64

// ParseAS parses an AS from a decimal (in the case of the 32bit BGP AS number
// space) or ipv6-style hex (in the case of SCION-only AS numbers) string.
// @ ensures retErr == nil ==> retAs.inRange()
// @ ensures retErr == nil ==> retAs.InRange()
// @ decreases
func ParseAS(_as string) (retAs AS, retErr error) {
return parseAS(_as, ":")
}

// @ ensures retErr == nil ==> retAs.inRange()
// @ ensures retErr == nil ==> retAs.InRange()
// @ decreases
func parseAS(_as string, sep string) (retAs AS, retErr error) {
parts := strings.Split(_as, sep)
Expand Down Expand Up @@ -110,15 +110,15 @@ func parseAS(_as string, sep string) (retAs AS, retErr error) {
return parsed, nil
}

// @ ensures retErr == nil ==> retAs.inRange()
// @ ensures retErr == nil ==> retAs.InRange()
// @ decreases
func asParseBGP(s string) (retAs AS, retErr error) {
_as, err := strconv.ParseUint(s, 10, BGPASBits)
if err != nil {
return 0, serrors.WrapStr("parsing BGP AS", err)
}
// (VerifiedSCION)
// The following assertions are needed to prove retAs.inRange().
// The following assertions are needed to prove retAs.InRange().
// Gobra is not able to infer this automatically from the definition
// of strconv.Exp, unless we put a postcondition saying that the
// result is equal to the body.
Expand All @@ -131,7 +131,7 @@ func asParseBGP(s string) (retAs AS, retErr error) {
return AS(_as), nil
}

// @ requires _as.inRange()
// @ requires _as.InRange()
// @ decreases
func (_as AS) String() string {
return fmtAS(_as, ":")
Expand Down Expand Up @@ -175,7 +175,7 @@ type IA uint64
// MustIAFrom creates an IA from the ISD and AS number. It panics if any error
// is encountered. Callers must ensure that the values passed to this function
// are valid.
// @ requires _as.inRange()
// @ requires _as.InRange()
// @ decreases
func MustIAFrom(isd ISD, _as AS) IA {
ia, err := IAFrom(isd, _as)
Expand All @@ -186,7 +186,7 @@ func MustIAFrom(isd ISD, _as AS) IA {
}

// IAFrom creates an IA from the ISD and AS number.
// @ requires _as.inRange()
// @ requires _as.InRange()
// @ ensures err == nil
// @ decreases
func IAFrom(isd ISD, _as AS) (ia IA, err error) {
Expand Down
9 changes: 9 additions & 0 deletions pkg/addr/isdas_spec.gobra
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,12 @@ pred (_as *AS) Mem() { acc(_as) }
fold ia.Mem()
}
}

// InRange is the ghost counterpart of the (non-exported) method AS.inRange. It is
// part of the contracts of exported members of this package, which may not
// mention non-exported members.
ghost
decreases
pure func (_as AS) InRange() bool {
return _as <= MaxAS
}
36 changes: 14 additions & 22 deletions pkg/slayers/extn.go
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ func (h *HopByHopExtn) CanDecode() (res gopacket.LayerClass) {
// @ preserves acc(h.Mem(ubuf), R20)
// @ decreases
func (h *HopByHopExtn) NextLayerType( /*@ ghost ubuf []byte @*/ ) gopacket.LayerType {
return scionNextLayerTypeAfterHBH( /*@ unfolding acc(h.Mem(ubuf), R20) in (unfolding acc(h.extnBase.Mem(ubuf), R20) in @*/ h.NextHdr /*@ ) @*/)
return scionNextLayerTypeAfterHBH( /*@ unfolding acc(h.Mem(ubuf), R20) in @*/ h.NextHdr)
}

// @ preserves acc(h.Mem(ub), R20)
Expand All @@ -313,14 +313,12 @@ func (h *HopByHopExtn) NextLayerType( /*@ ghost ubuf []byte @*/ ) gopacket.Layer
// @ decreases
func (h *HopByHopExtn) LayerPayload( /*@ ghost ub []byte @*/ ) (res []byte /*@ , ghost start int, ghost end int @*/) {
// @ unfold acc(h.Mem(ub), R20)
// @ unfold acc(h.extnBase.Mem(ub), R20)
// @ ghost base := &h.extnBase.BaseLayer
// @ ghost base := &h.BaseLayer
// @ unfold acc(base.Mem(ub, h.ActualLen), R20)
tmp := h.Payload
// @ start = h.ActualLen
// @ end = len(ub)
// @ fold acc(base.Mem(ub, h.ActualLen), R20)
// @ fold acc(h.extnBase.Mem(ub), R20)
// @ fold acc(h.Mem(ub), R20)
return tmp /*@ , start, end @*/
}
Expand Down Expand Up @@ -392,8 +390,7 @@ func (h *HopByHopExtn) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback)
// @ fold tmp.Mem(lenOptions)
// @ lenOptions += 1
}
// @ fold h.extnBase.BaseLayer.Mem(data, h.extnBase.ActualLen)
// @ fold h.extnBase.Mem(data)
// @ fold h.BaseLayer.Mem(data, h.ActualLen)
// @ fold h.Mem(data)
return nil
}
Expand All @@ -411,7 +408,7 @@ func decodeHopByHopExtn(data []byte, p gopacket.PacketBuilder) (res error) {
if err != nil {
return err
}
nextTmp := scionNextLayerTypeAfterHBH(( /*@ unfolding h.Mem(data) in (unfolding h.extnBase.Mem(data) in @*/ h.NextHdr /*@ ) @*/))
nextTmp := scionNextLayerTypeAfterHBH(( /*@ unfolding h.Mem(data) in @*/ h.NextHdr))
// @ fold nextTmp.Mem()
return p.NextDecoder(nextTmp)
}
Expand Down Expand Up @@ -452,7 +449,7 @@ func (e *EndToEndExtn) CanDecode() (res gopacket.LayerClass) {
// @ preserves acc(e.Mem(ubuf), R20)
// @ decreases
func (e *EndToEndExtn) NextLayerType( /*@ ghost ubuf []byte @*/ ) gopacket.LayerType {
return scionNextLayerTypeAfterE2E( /*@ unfolding acc(e.Mem(ubuf), R20) in (unfolding acc(e.extnBase.Mem(ubuf), R20) in @*/ e.NextHdr /*@ ) @*/)
return scionNextLayerTypeAfterE2E( /*@ unfolding acc(e.Mem(ubuf), R20) in @*/ e.NextHdr)
}

// @ preserves acc(e.Mem(ub), R20)
Expand All @@ -462,14 +459,12 @@ func (e *EndToEndExtn) NextLayerType( /*@ ghost ubuf []byte @*/ ) gopacket.Layer
// @ decreases
func (e *EndToEndExtn) LayerPayload( /*@ ghost ub []byte @*/ ) (res []byte /*@ , ghost start int, ghost end int @*/) {
// @ unfold acc(e.Mem(ub), R20)
// @ unfold acc(e.extnBase.Mem(ub), R20)
// @ ghost base := &e.extnBase.BaseLayer
// @ ghost base := &e.BaseLayer
// @ unfold acc(base.Mem(ub, e.ActualLen), R20)
tmp := e.Payload
// @ start = e.ActualLen
// @ end = len(ub)
// @ fold acc(base.Mem(ub, e.ActualLen), R20)
// @ fold acc(e.extnBase.Mem(ub), R20)
// @ fold acc(e.Mem(ub), R20)
return tmp /*@ , start, end @*/
}
Expand Down Expand Up @@ -524,8 +519,7 @@ func (e *EndToEndExtn) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback)
// @ fold tmp.Mem(lenOptions)
// @ lenOptions += 1
}
// @ fold e.extnBase.BaseLayer.Mem(data, e.ActualLen)
// @ fold e.extnBase.Mem(data)
// @ fold e.BaseLayer.Mem(data, e.ActualLen)
// @ fold e.Mem(data)
return nil
}
Expand All @@ -543,7 +537,7 @@ func decodeEndToEndExtn(data []byte, p gopacket.PacketBuilder) (res error) {
if err != nil {
return err
}
nextTmp := scionNextLayerTypeAfterE2E( /*@ unfolding e.Mem(data) in (unfolding e.extnBase.Mem(data) in @*/ e.NextHdr /*@ ) @*/)
nextTmp := scionNextLayerTypeAfterE2E( /*@ unfolding e.Mem(data) in @*/ e.NextHdr)
// @ fold nextTmp.Mem()
return p.NextDecoder(nextTmp)
}
Expand Down Expand Up @@ -617,9 +611,8 @@ func (s *HopByHopExtnSkipper) DecodeFromBytes(data []byte, df gopacket.DecodeFee
// @ fold s.NonInitMem()
return err
}
// @ ghost contentsLen := s.extnBase.ActualLen
// @ fold s.extnBase.BaseLayer.Mem(data, s.ActualLen)
// @ fold s.extnBase.Mem(data)
// @ ghost contentsLen := s.ActualLen
// @ fold s.BaseLayer.Mem(data, s.ActualLen)
// @ fold s.Mem(data)
return nil
}
Expand All @@ -641,7 +634,7 @@ func (s *HopByHopExtnSkipper) CanDecode() (res gopacket.LayerClass) {
// @ preserves acc(h.Mem(ubuf), R20)
// @ decreases
func (h *HopByHopExtnSkipper) NextLayerType( /*@ ghost ubuf []byte @*/ ) gopacket.LayerType {
return scionNextLayerTypeAfterHBH( /*@ unfolding acc(h.Mem(ubuf), R20) in (unfolding acc(h.extnBase.Mem(ubuf), R20) in @*/ h.NextHdr /*@ ) @*/)
return scionNextLayerTypeAfterHBH( /*@ unfolding acc(h.Mem(ubuf), R20) in @*/ h.NextHdr)
}

// EndToEndExtnSkipper is a DecodingLayer which decodes an EndToEnd extension
Expand Down Expand Up @@ -672,9 +665,8 @@ func (s *EndToEndExtnSkipper) DecodeFromBytes(data []byte, df gopacket.DecodeFee
// @ fold s.NonInitMem()
return err
}
// @ ghost contentsLen := s.extnBase.ActualLen
// @ fold s.extnBase.BaseLayer.Mem(data, s.ActualLen)
// @ fold s.extnBase.Mem(data)
// @ ghost contentsLen := s.ActualLen
// @ fold s.BaseLayer.Mem(data, s.ActualLen)
// @ fold s.Mem(data)
return nil
}
Expand All @@ -696,5 +688,5 @@ func (s *EndToEndExtnSkipper) CanDecode() (res gopacket.LayerClass) {
// @ preserves acc(e.Mem(ubuf), R20)
// @ decreases
func (e *EndToEndExtnSkipper) NextLayerType( /*@ ghost ubuf []byte @*/ ) gopacket.LayerType {
return scionNextLayerTypeAfterE2E( /*@ unfolding acc(e.Mem(ubuf), R20) in (unfolding acc(e.extnBase.Mem(ubuf), R20) in @*/ e.NextHdr /*@ ) @*/)
return scionNextLayerTypeAfterE2E( /*@ unfolding acc(e.Mem(ubuf), R20) in @*/ e.NextHdr)
}
51 changes: 23 additions & 28 deletions pkg/slayers/extn_spec.gobra
Original file line number Diff line number Diff line change
Expand Up @@ -23,28 +23,22 @@ import (
// sl "github.com/scionproto/scion/verification/utils/slices"
)

/** start of extnBase **/

pred (e *extnBase) NonInitMem() {
acc(e)
}

pred (e *extnBase) Mem(ubuf []byte) {
acc(&e.NextHdr) &&
acc(&e.ExtLen) &&
acc(&e.ActualLen) &&
e.BaseLayer.Mem(ubuf, e.ActualLen)
}

/** end of extnBase **/
// The memory of the (non-exported) extnBase embedded in every extension header.
// It is spelled out in the predicates below instead of being factored out into a
// predicate of extnBase: the bodies of the fully-public predicates of the
// exported extension headers may only mention exported members, and importing
// packages must be able to unfold them to reach the promoted fields.

/** start of HopByHopExtn **/
pred (h *HopByHopExtn) NonInitMem() {
acc(h)
}

pred (h *HopByHopExtn) Mem(ubuf []byte) {
h.extnBase.Mem(ubuf) &&
acc(&h.NextHdr) &&
acc(&h.ExtLen) &&
acc(&h.ActualLen) &&
h.BaseLayer.Mem(ubuf, h.ActualLen) &&
acc(&h.Options) &&
forall i int :: { &h.Options[i] } 0 <= i && i < len(h.Options) ==>
(acc(&h.Options[i]) && h.Options[i].Mem(i))
Expand All @@ -64,7 +58,6 @@ ensures s.NonInitMem()
decreases
func (s *HopByHopExtn) DowngradePerm(ghost ub []byte) {
unfold s.Mem(ub)
unfold s.extnBase.Mem(ub)
unfold s.BaseLayer.Mem(ub, s.ActualLen)
fold s.NonInitMem()
}
Expand All @@ -80,7 +73,10 @@ pred (h *HopByHopExtnSkipper) NonInitMem() {
}

pred (h *HopByHopExtnSkipper) Mem(ubuf []byte) {
h.extnBase.Mem(ubuf)
acc(&h.NextHdr) &&
acc(&h.ExtLen) &&
acc(&h.ActualLen) &&
h.BaseLayer.Mem(ubuf, h.ActualLen)
}

// Gobra is not able to infer that HopByHopExtnSkipper is "inheriting"
Expand All @@ -100,12 +96,10 @@ ensures res === ub[start:end]
decreases
func (h *HopByHopExtnSkipper) LayerPayload(ghost ub []byte) (res []byte, ghost start int, ghost end int) {
unfold acc(h.Mem(ub), R20)
unfold acc(h.extnBase.Mem(ub), R20)
ghost base := &h.extnBase.BaseLayer
ghost base := &h.BaseLayer
res = base.LayerPayload(ub, h.ActualLen)
start = h.ActualLen
end = len(ub)
fold acc(h.extnBase.Mem(ub), R20)
fold acc(h.Mem(ub), R20)
return res, start, end
}
Expand All @@ -116,7 +110,6 @@ ensures s.NonInitMem()
decreases
func (s *HopByHopExtnSkipper) DowngradePerm(ghost ub []byte) {
unfold s.Mem(ub)
unfold s.extnBase.Mem(ub)
unfold s.BaseLayer.Mem(ub, s.ActualLen)
fold s.NonInitMem()
}
Expand All @@ -132,7 +125,10 @@ pred (e *EndToEndExtn) NonInitMem() {
}

pred (e *EndToEndExtn) Mem(ubuf []byte) {
e.extnBase.Mem(ubuf) &&
acc(&e.NextHdr) &&
acc(&e.ExtLen) &&
acc(&e.ActualLen) &&
e.BaseLayer.Mem(ubuf, e.ActualLen) &&
acc(&e.Options) &&
forall i int :: { &e.Options[i] } 0 <= i && i < len(e.Options) ==>
(acc(&e.Options[i]) && e.Options[i].Mem(i))
Expand All @@ -152,7 +148,6 @@ ensures s.NonInitMem()
decreases
func (s *EndToEndExtn) DowngradePerm(ghost ub []byte) {
unfold s.Mem(ub)
unfold s.extnBase.Mem(ub)
unfold s.BaseLayer.Mem(ub, s.ActualLen)
fold s.NonInitMem()
}
Expand All @@ -170,7 +165,10 @@ pred (e *EndToEndExtnSkipper) NonInitMem() {
}

pred (e *EndToEndExtnSkipper) Mem(ubuf []byte) {
e.extnBase.Mem(ubuf)
acc(&e.NextHdr) &&
acc(&e.ExtLen) &&
acc(&e.ActualLen) &&
e.BaseLayer.Mem(ubuf, e.ActualLen)
}

// Gobra is not able to infer that EndToEndExtnSkipper is "inheriting"
Expand All @@ -190,12 +188,10 @@ ensures res === ub[start:end]
decreases
func (e *EndToEndExtnSkipper) LayerPayload(ghost ub []byte) (res []byte, ghost start int, ghost end int) {
unfold acc(e.Mem(ub), R20)
unfold acc(e.extnBase.Mem(ub), R20)
ghost base := &e.extnBase.BaseLayer
ghost base := &e.BaseLayer
res = base.LayerPayload(ub, e.ActualLen)
start = e.ActualLen
end = len(ub)
fold acc(e.extnBase.Mem(ub), R20)
fold acc(e.Mem(ub), R20)
return res, start, end
}
Expand All @@ -206,7 +202,6 @@ ensures s.NonInitMem()
decreases
func (s *EndToEndExtnSkipper) DowngradePerm(ghost ub []byte) {
unfold s.Mem(ub)
unfold s.extnBase.Mem(ub)
unfold s.BaseLayer.Mem(ub, s.ActualLen)
fold s.NonInitMem()
}
Expand Down
Loading
Loading