-
Notifications
You must be signed in to change notification settings - Fork 176
experimental: add specifications to packages pkg/addr and pkg/slayers/path, verify them in the CI with Gobra
#4837
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
jcp19
wants to merge
29
commits into
scionproto:master
Choose a base branch
from
jcp19:jcp19-add-more-gobra-annotations
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from 26 commits
Commits
Show all changes
29 commits
Select commit
Hold shift + click to select a range
e04ac14
add annotations to the package
jcp19 21535a3
more changes
jcp19 558ef09
Start adding annotations to the Path interface
jcp19 e89ce07
add annotations to path.go
jcp19 7cbff69
undo changes to mac.go
jcp19 1eb79da
update the CI config for Gobra to run Gobra on stdlib specs
jcp19 5bf4bcc
Fix module name in the config for the Gobra CI; add job to check the …
jcp19 0a3d770
Add include paths to the config
jcp19 02fb414
fix wrong key in the config
jcp19 7c232e0
fix project location in the config
jcp19 ab7d96c
fix include paths for third-party library specs
jcp19 bd30e9d
fix include paths for third-party library specs
jcp19 d2a8369
enable verification of packages pkg/addr and pkg/slayers/path
jcp19 c663a39
update version of the gobra action
jcp19 cccfeae
small syntactic improvements
jcp19 b63a921
add missing postcondition to Value interface
jcp19 c55f92c
add missing postcondition to TextUnmarshaller interface
jcp19 3973097
continue cleaning-up stdlib-specs
jcp19 72fd62a
Add README.md
jcp19 3bb72eb
tiny simplification in config comment
jcp19 78bdab8
Clean-up specs of stdlib
jcp19 514f0f4
Cleanup
jcp19 58fb065
Merge branch 'master' into jcp19-add-more-gobra-annotations
jcp19 77f8241
fix linting issues in the Gobra readme
jcp19 096aa12
add documentation to Gobra's workflow file
jcp19 c8218a5
make the Gobra checks optional
jcp19 530f628
Merge branch 'master' into jcp19-add-more-gobra-annotations
jcp19 fc8fd06
Update pkg/slayers/path/path.go
jcp19 0ab0635
go fmt
jcp19 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,18 @@ | ||
| # This file sets up a workflow that runs Gobra (github.com/viperproject/gobra) | ||
| # on selected packages of the SCION implementation. Gobra is a program verifier, | ||
| # i.e., it checks that the implementation of each function behaves as expected. | ||
| # The expected behaviour of each function is provided as a formal specification | ||
| # written in comments above the function signature. When Gobra is not able to | ||
| # prove that a function behaves according to its specification, it generates an | ||
| # (hopefully) informative error message, which identifies the parts of the code | ||
| # where the issues might lie. | ||
| # For more information on Gobra and its error messages, check the following: | ||
| # - The Gobra Book (WIP): viperproject.github.io/gobra-book/ | ||
| # - The tutorial: github.com/viperproject/gobra/blob/master/docs/tutorial.md | ||
| # The former covers more features of Gobra and contains more up-to-date | ||
| # information, but it is still under construction. | ||
|
|
||
|
|
||
| name: Verify the specified codebase | ||
|
|
||
| on: | ||
|
|
@@ -8,32 +23,53 @@ jobs: | |
| setup-and-test: | ||
| runs-on: ubuntu-latest | ||
| env: | ||
| statsFile: '/gobra/stats.json' | ||
| imageVersion: 'v25.09' | ||
| module: 'github.com/scionproto/scion/' | ||
| includePaths: '. ./gobra/stdlib-specs' | ||
| continueOnError: true | ||
| steps: | ||
| - name: Checkout the SCION repository | ||
| uses: actions/checkout@v2 | ||
| - name: Set-up caching for the verification results | ||
| uses: actions/cache@v3 | ||
| env: | ||
| cache-name: gobra-cache | ||
| - name: Check that the package gobra/utils is well-formed | ||
| uses: viperproject/[email protected] | ||
| with: | ||
| path: ${{ runner.workspace }}/.gobra/cache.json | ||
| key: ${{ env.cache-name }} | ||
| - name: Verify the specified files | ||
| uses: viperproject/[email protected] | ||
| with: | ||
| # Prefix used to resolve SCION packages | ||
| module: 'github.com/scionproto/scion/' | ||
| packages: 'gobra/utils' | ||
| # Gobra only verifies files annotated with the header "// +gobra" | ||
| headerOnly: '1' | ||
| # Traverse the entire repository, including nested packages, | ||
| # in search for annotated files to verify | ||
| timeout: 2m | ||
| imageVersion: ${{ env.imageVersion }} | ||
| module: ${{ env.module }} | ||
| includePaths: ${{ env.includePaths }} | ||
| continue-on-error: ${{ env.continueOnError }} | ||
| - name: Check that specifications of third-party libraries are well-formed | ||
| uses: viperproject/[email protected] | ||
| with: | ||
| projectLocation: 'scion/gobra/stdlib-specs' | ||
| headerOnly: '1' | ||
| # Check all package specifications in directory stdlib-specs | ||
| recursive: '1' | ||
| timeout: 10m | ||
| caching: '1' | ||
| statsFile: ${{ env.statsFile }} | ||
| - name: Upload the verification report | ||
| uses: actions/upload-artifact@v4 | ||
| imageVersion: ${{ env.imageVersion }} | ||
| module: ${{ env.module }} | ||
| includePaths: '. ../..' # relative to project location | ||
| continue-on-error: ${{ env.continueOnError }} | ||
| - name: Verify package `pkg/addr` | ||
| uses: viperproject/[email protected] | ||
| with: | ||
| packages: 'pkg/addr' | ||
| headerOnly: '1' | ||
| timeout: 2m | ||
| imageVersion: ${{ env.imageVersion }} | ||
| module: ${{ env.module }} | ||
| includePaths: ${{ env.includePaths }} | ||
| continue-on-error: ${{ env.continueOnError }} | ||
| - name: Verify package `pkg/slayers/path` | ||
| uses: viperproject/[email protected] | ||
| with: | ||
| name: verification_stats.json | ||
| path: ${{ env.statsFile }} | ||
| packages: 'pkg/slayers/path' | ||
| headerOnly: '1' | ||
| timeout: 2m | ||
| imageVersion: ${{ env.imageVersion }} | ||
| module: ${{ env.module }} | ||
| includePaths: ${{ env.includePaths }} | ||
| continue-on-error: ${{ env.continueOnError }} | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| # Gobra specs | ||
|
|
||
| This directory contains the formal specification of a small part of the | ||
| Go standard library (in [`./stdlib-specs`](./stdlib-specs)) required to | ||
| verify the annotated files in the SCION codebase. In addition, we provide | ||
| a verified Gobra package in [`./utils`](./utils) that contains useful | ||
| definitions that are used in the verified packages of SCION. | ||
|
|
||
| ## Contributing | ||
|
|
||
| It is expected that we will need a formal specification for more parts | ||
| of the Go standard library as we progress in verifying more code in the | ||
| SCION repository. To do so, one may add the type declarations and | ||
| signatures of unspecified functions and methods (_without the bodies_), | ||
| together with their contracts (i.e., pre- and postconditions), to the | ||
| corresponding package specification in directory | ||
| [`./stdlib-specs`](./stdlib-specs). | ||
|
|
||
| Given that the specification of the standard library is not verified by | ||
| Gobra itself, it is possible to introduce errors when writing the | ||
| specification for these methods. Thus, any extensions to the specification | ||
| require extreme care from the author of the extensions and from code reviewers. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| // Copyright 2025 ETH Zurich | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
|
|
||
| // +gobra | ||
|
|
||
| package encoding | ||
|
|
||
| type TextUnmarshaler interface { | ||
| pred Mem() | ||
|
|
||
| preserves Mem() && acc(text) | ||
| ensures err != nil ==> err.ErrorMem() | ||
| decreases | ||
| UnmarshalText(text []byte) (err error) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
|
|
||
| // +gobra | ||
|
|
||
| package flag | ||
|
|
||
| type Value interface { | ||
| pred Mem() | ||
|
|
||
| preserves Mem() | ||
| decreases | ||
| String() string | ||
|
|
||
| preserves Mem() | ||
| ensures err != nil ==> err.ErrorMem() | ||
| decreases | ||
| Set(string) (err error) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| // Copyright 2025 ETH Zurich | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
|
|
||
| // +gobra | ||
|
|
||
| package fmt | ||
|
|
||
| import "github.com/scionproto/scion/gobra/utils/" | ||
|
|
||
| preserves forall i int :: { &v[i] } 0 <= i && i < len(v) ==> | ||
| acc(&v[i], utils.ReadPerm) | ||
| decreases | ||
| func Sprintf(format string, v ...interface{}) string | ||
|
|
||
| type Stringer interface { | ||
| pred Mem() | ||
|
|
||
| preserves Mem() | ||
| decreases | ||
| String() string | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| // Copyright 2025 ETH Zurich | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
|
|
||
| // +gobra | ||
|
|
||
| package hash | ||
|
|
||
| import "github.com/scionproto/scion/gobra/utils/" | ||
|
|
||
| type Hash interface { | ||
| pred Mem() | ||
|
|
||
| // Implementations of Hash must also implement io.Writer. | ||
| preserves Mem() | ||
| preserves acc(p, utils.ReadPerm) | ||
| ensures 0 <= n && n <= len(p) | ||
| // The documentation of this interface states that the Write | ||
| // method in implementations of Hash may never fail. | ||
| // (https://pkg.go.dev/hash#Hash) | ||
| ensures err == nil && n == len(p) | ||
| ensures Size() == old(Size()) + len(p) | ||
| decreases | ||
| Write(p []byte) (n int, err error) | ||
|
|
||
| preserves acc(Mem(), utils.ReadPerm) | ||
| requires acc(b) | ||
| ensures acc(res) && len(res) == len(b) + Size() | ||
| decreases | ||
| Sum(b []byte) (res []byte) | ||
|
|
||
| preserves Mem() | ||
| decreases | ||
| Reset() | ||
|
|
||
| requires Mem() | ||
| ensures 0 <= res | ||
| decreases | ||
| pure Size() (res int) | ||
|
|
||
| requires Mem() | ||
| ensures 0 <= res | ||
| decreases | ||
| pure BlockSize() (res int) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| // Copyright 2025 ETH Zurich | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
|
|
||
| // +gobra | ||
|
|
||
| package net | ||
|
|
||
| // IP address lengths (bytes). | ||
| const ( | ||
| IPv4len = 4 | ||
| IPv6len = 16 | ||
| ) | ||
|
|
||
| type IP []byte | ||
|
|
||
| pred (ip IP) Mem() { | ||
| (len(ip) == IPv4len || len(ip) == IPv6len) && | ||
| forall i int :: { &ip[i] } 0 <= i && i < len(ip) ==> acc(&ip[i]) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| // Copyright 2025 ETH Zurich | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
|
|
||
| // +gobra | ||
|
|
||
| package net | ||
|
|
||
| ensures err != nil ==> err.ErrorMem() | ||
| decreases | ||
| func SplitHostPort(hostport string) (host string, port string, err error) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| // Copyright 2025 ETH Zurich | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
|
|
||
| // +gobra | ||
|
|
||
| package netip | ||
|
|
||
| import "github.com/scionproto/scion/gobra/utils/" | ||
|
|
||
| type Addr struct { | ||
| privateField utils.PrivateField | ||
| } | ||
|
|
||
| type AddrPort struct { | ||
| privateField utils.PrivateField | ||
| } | ||
|
|
||
| decreases | ||
| func (ip Addr) String() string | ||
|
|
||
| ensures err != nil ==> err.ErrorMem() | ||
| decreases | ||
| func ParseAddr(s string) (addr Addr, err error) | ||
|
|
||
| decreases | ||
| func AddrFrom4(addr [4]byte) Addr | ||
|
|
||
| decreases | ||
| func AddrFrom16(addr [16]byte) Addr | ||
|
|
||
| decreases | ||
| func (ip Addr) Unmap() Addr | ||
|
|
||
| decreases | ||
| func (ip Addr) IsValid() (res bool) | ||
|
|
||
| decreases | ||
| func (ip Addr) Is4() bool | ||
|
|
||
| decreases | ||
| func (ip Addr) Is6() bool | ||
|
|
||
| ensures acc(b) | ||
| decreases | ||
| func (ip Addr) AsSlice() (b []byte) | ||
|
|
||
| decreases | ||
| func (p AddrPort) IsValid() (res bool) | ||
|
|
||
| decreases | ||
| func (p AddrPort) Addr() Addr |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A feedback about the book itself, not this particular PR: the search there doesn't work with special characters, like
@. Fortunately for me (a complete beginner with Gobra), I noticed that one chapter has@in its name. But for people like me, the search bar might be a first place to go...There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you! I added a feature request in the book repository (viperproject/gobra-book#43).