Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Gobra で見る形式検証 (mercari.go #26)

Gobra で見る形式検証 (mercari.go #26)

mercari.go #26 (https://mercari.connpass.com/event/320135/) での発表資料

kobaryo

June 18, 2024
Tweet

More Decks by kobaryo

Other Decks in Programming

Transcript

  1. 3 • Goal ◦ Gobra で何ができるかざっくりと把握する ◦ 形式検証を使うべきタイミングが分かる • Non-Goal

    ◦ Gobra で Go プログラムを検証する具体的なアノテーションの書き方を身に付ける 今回のGoal
  2. 8 目次 1 形式検証のメリット 2 Gobra a. Gobra とは b.

    インターフェースを含むプログラムの検証 c. Goroutine を含むプログラムの検証 3 形式検証のデメリット
  3. 9 • Go プログラムの検証器 ◦ アノテーション付きの Go プログラムを 入力すれば検証結果を出力してくれる •

    主に関数の仕様について検証可能 • Go の主要な機能に対応している ◦ 組み込みのデータ型 ◦ インターフェース ◦ Goroutine • CAV 2021 で発表 • 実装は Scala • VSCodeの拡張機能も提供されている Gobra https://github.com/viperproject/gobra
  4. 12 type SomeInterface interface { require A ensure B func

    f {...} } 実装を増やして仕様が変わってしまう例 require C ensure D func (s SomeStruct) f {...} SomeStruct の f は、SomeInterface の f の仕様を満たしているとは限らない → インターフェースの仕様を 再証明する必 要性 追加 証明済み
  5. 13 type SomeInterface interface { require A ensure B func

    f {...} } Gobra におけるモジュラーな検証 require C ensure D func (s SomeStruct) f {...} 追加 証明済み (SomeStruct) implements SomeInterface { (s SomeStruct) f { // A ⟹ C と D ⟹ B の証明 } } SomeStruct の f が、SomeInterface の f の仕様を満たしていること の証明をプ ログラマが書けば再証明しなくて OK Behavioral Subtyping
  6. 14 ensure *x == old(*x) + 1 func inc(x *int)

    { *x = *x + 1 } ensure x == 3 func concurrentInc() { x := 1 go inc(&x) go inc(&x) } Goroutine を含むプログラムの検証例 Goroutine 1 Goroutine 2 Read / Write Read / Write
  7. 15 ensure *x == old(*x) + 1 func inc(x *int)

    { *x = *x + 1 } ensure x == 3 func concurrentInc() { x := 1 go inc(&x) go inc(&x) } Goroutine を含むプログラムの検証例 1 Goroutine 1 Goroutine 2 Read / Write Read / Write
  8. 16 ensure *x == old(*x) + 1 func inc(x *int)

    { *x = *x + 1 } ensure x == 3 func concurrentInc() { x := 1 go inc(&x) go inc(&x) } Goroutine を含むプログラムの検証例 1 1 Goroutine 1 Goroutine 2 Read / Write Read / Write
  9. 17 ensure *x == old(*x) + 1 func inc(x *int)

    { *x = *x + 1 } ensure x == 3 func concurrentInc() { x := 1 go inc(&x) go inc(&x) } Goroutine を含むプログラムの検証例 1 2 Goroutine 1 1 Goroutine 2 Read / Write Read / Write ポインタの指す 先が更新される 前に読み込み
  10. 18 ensure *x == old(*x) + 1 func inc(x *int)

    { *x = *x + 1 } ensure x == 3 func concurrentInc() { x := 1 go inc(&x) go inc(&x) } Goroutine を含むプログラムの検証例 2 2 Goroutine 1 2 Goroutine 2 Read / Write Read / Write 3にならない可能性がある → Failにしなければならない
  11. 20 Fractional Permission v Pointer 1 Pointer 2 v Pointer

    1 Pointer 2 v Pointer 1 Pointer 2 🙆 󰢃 Read / Write Read Read Read Read / Write Rust の所有権・借 用と大体同じ ここの行き来は人間が 書く必要がある
  12. 21 Gobra によるレースコンディションの防止例 x の Read / Write 権限を持っている 1行上の

    inc(&x) の &x が Write 権限を 持っているので、この inc は requiresで ある acc を達成できない → Fail
  13. 27 • Gobra は Go の多くの機能をサポートするプログラム検証器 ◦ インターフェース ◦ Goroutine

    • 形式検証はテストの問題点を解決するが、まだ大きな欠点が残っている ◦ それでもやはり形式検証はパワフルな技法なので、デメリットを受け入れた上で使う タイミングを見極めたい まとめ
  14. 28 • Felix A. Wolf, Linard Arquint, Martin Clochard, Wytse

    Oortwijn, João C. Pereira, & Peter Müller. (2021). Gobra: Modular Specification and Verification of Go Programs (extended version). • A Tutorial on Gobra https://github.com/viperproject/gobra/blob/master/docs/tutorial. md 参考文献