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

Starting static analysis with Go

Tsuji Daishiro
November 13, 2021

Starting static analysis with Go

Go Conference 2021 Autumn のセッションで使用した資料です。
- セッションの詳細: https://gocon.jp/2021autumn/sessions/go-static-analysis/
- 発表者: https://twitter.com/d_tutuz

資料に誤りがあればtwitterでご連絡ください。

Tsuji Daishiro

November 13, 2021
Tweet

More Decks by Tsuji Daishiro

Other Decks in Technology

Transcript

  1. analysis パッケージの中心的な構造体 • analysis.Pass ◦ 静的解析に使う情報を扱う構造体 ◦ analysis.Pass を利用することでパッケージの情報や型、抽象構文木のトラ バース結果が簡単に手に入る!

    type Pass struct { // ... Pkg *types.Package // パッケージに関する情報 TypesInfo *types.Info // 抽象構文木の型に関する情報 // ... ResultOf map[*Analyzer]interface{} // 解析器をキーにした解析結果を保持 // ... }
  2. unmarshal モジュールで静的解析する流れ • Goのお手本の実装例を見るのがおすすめ ◦ unmarshal モジュール ◦ https://pkg.go.dev/golang.org/x/[email protected]/go/analysis/passes/unm arshal

    • 例:JSON のデコード ◦ json.Unmarshal や (*"encoding/json".Decoder).Decodeでは引数はポイ ンタ型である必要がある ◦ 引数がポインタ型でない場合は実行時エラー ◦ 静的解析(unmarshal モジュール)で引数の型をチェックできる
  3. unmarshal モジュールの実装 1. PreOrder(深さ優先探索)で抽象構文木の解析結果を取得 2. ノードがレシーバを保持しているかチェック 3. ノードの名前が Unmarshal か

    Decode であるかチェック 4. 関数呼び出しノードの引数の型情報を取得。ポインタ型やイン ターフェース型の場合はOK
  4. unmarshal モジュールの実装 (コア実装は70行程度) 1. PreOrder(深さ優先探索)で抽象構文木の解析結果を取得 → Pass.ResultOf の利用 2. ノードがレシーバを保持しているかチェック

    → Pass.ResultOf と Pass.TypesInfo の利用 3. ノードの名前が Unmarshal か Decode であるかチェック → Pass.ResultOf と Pass.TypesInfo の利用 4. 型情報から関数呼び出しノードの引数の型情報を取得。ポイ ンタ型やインターフェース型の場合はOK → Pass.ResultOf と Pass.TypesInfo の利用 Pass 構造体のフィールドを利用してロジックを実装できる