dotnet-inspect-correctness について
dotnet-inspectで.NETメソッドの例外動作や安全でない操作を調べるためのスキルです。証拠に基づいて評価し、検出結果がないことを安全の証明とみなさない手順を示します。
主な機能
- 01例外領域とコールグラフの確認
- 02メソッド本体の安全でない操作の特定
- 03パッケージ間の安全性検出結果の比較
- 04jqによる型付き証拠の集約
- 05調査範囲と未検証事項の記録
活用シーン
- 01メソッドの例外処理のレビュー
- 02安全でないメモリ操作の調査
- 03安全でないコードとリソース所有権の評価
- 04.NETの安全でないコード指針に沿った証拠整理
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ richlander/ dotnet-inspect --skill dotnet-inspect-correctnessインストール後、Claude Code で/dotnet-inspect-correctnessを入力して読み込まれたか確認します。
詳細
dotnet-inspect:正確性と安全性
コードを安全に呼び出せるかどうかを判断する際に、このスキルを使用してください。コードがスローする可能性のある例外、エラーの処理方法、安全なマネージド実行の範囲外に出る箇所を確認できます。これは単一バージョンの分析です。これらのシグナルがバージョン間でどのように変化するかを調べるには、互換性スキルを使用してください。
dnx dotnet-inspect -y -- <command>
何をスローする可能性がありますか?(例外の範囲)
「例外」という専用セクションはありません。例外の動作はメソッド本体の分析から確認できます。「例外リージョン」には、catch/filter/finally の正確な配置が表示され、グラフのフィールドと非表示の事実が動作を要約します。
dnx dotnet-inspect -y -- member Type Method:1 -S "Exception Regions"
dnx dotnet-inspect -y -- member Type Method:1 -S "Call Graph" --fields "Throws,ThrowSites,ExceptionTypes,ConstructedExceptions,Catch,Finally"
dnx dotnet-inspect -y -- member Type Method:1 -S "Call Graph" --fields "Throws,Catch,Finally"
dnx dotnet-inspect -y -- member Type Method:1 -S Facts --tsv
Throws/ThrowSites はスローサイトの数を示し、ExceptionTypes/ConstructedExceptions は例外型を示します。Catch/Finally は処理方法を示します。「例外リージョン」には IL の範囲と捕捉された型が保持されます。-S Facts(メンバー、単一メソッド)は本体内の非表示の事実を一覧表示し、--tsv に対応しています。
メモリー安全ですか?(安全でない操作)
dnx dotnet-inspect -y -- member Type Method:1 --library MyLib.dll -S "Unsafe Operations,IL"
-S "Unsafe Operations" は、単一のメソッド本体内にある安全でない操作を IL の証拠とともに表示します。ライブラリ全体の安全性の範囲(安全でないメンバー、P/Invoke メソッド)と来歴/サプライチェーンのシグナルについては、signals スキルを参照してください。
クラッシュまたはプロファイラーの座標を調べる場合は、library coordinate 0x06000001+0x5 --library Foo.dll を使用すると、デフォルトでソース位置、メンバー、命令、例外、呼び出し元、戻りアドレスのコンテキストを確認できます。安全性の証拠はオプトインです。library coordinate 0x06000001+0x5 --library Foo.dll -S "Context: Safety" を使用してください。
隣接するバージョンの境界で、特定の安全でない操作が確実に追加されたかどうかを確認するには、まず呼び出し元が選択したパッケージのセルを照合します。
dnx dotnet-inspect -y -- diff --history --package [email protected] \
-t MyType -m Method \
--finding analysis.unsafety --at first --at last
疎なプローブには --at を繰り返し指定し、明示的に範囲を限定した密な走査には --at all を使用します。複数バージョンにまたがる Added 行は、候補となる境界の位置を示しますが、正確な導入バージョンを示すものではありません。隣接するペアを確認してください。
dnx dotnet-inspect -y -- diff --package [email protected] \
-t MyType -m Method \
--finding analysis.unsafety
PairFinding.Added は導入の証拠です。Present と Removed で、継続しているか消失したかを区別できます。このコマンドは、指定された 2 つのエンドポイントのみを比較します。
.NET のガイダンスに照らして安全でないコードと所有権をレビューする
ポリシーの基準として、.NET の安全でないコードに関するベストプラクティスガイドを使用してください。そのソースドキュメントでは、現在、レビューを 26 の番号付きトピックに分けています。
dotnet-inspect が提供するのはコンパイル済みコードの証拠であり、包括的なコンプライアンス判定ではありません。再利用可能な JSONL 行セットを取得し、エージェントと jq を使って質問ごとに抽出・結合してから、重大なメンバーだけを詳しく調べてください。同じ行セットで、新たな集約コマンドを追加せずに他の安全性に関する質問にも答えられます。
再利用可能な行セットを取得する
各行の種類は個別に保持し、識別情報、形状、完了状況が分かるようにしてください。各コマンドの終了ステータスと診断情報を記録してください。対象を絞ったセクションが空でも、正常に空の一覧を取得したのではなく、ゼロ以外の結果である場合があります。
capture()
{
output="$1"
shift
status=0
"$@" > "$output" 2> "$output.stderr" || status=$?
printf '%s\t%s\n' "$output" "$status" >> inspection-status.tsv
}
: > inspection-status.tsv
capture unsafe-members.jsonl \
dnx dotnet-inspect -y -- library MyLib.dll \
-S "Unsafe Members" --jsonl
capture pinvoke-methods.jsonl \
dnx dotnet-inspect -y -- library MyLib.dll \
-S "P/Invoke Methods" --jsonl
capture custom-attributes.jsonl \
dnx dotnet-inspect -y -- library MyLib.dll \
-S "Custom Attributes" --jsonl
capture references.jsonl \
dnx dotnet-inspect -y -- library MyLib.dll \
-S References --jsonl
capture signals.json \
dnx dotnet-inspect -y -- library MyLib.dll \
-S Signals --json
ライブラリの Custom Attributes は、アセンブリレベルおよびモジュールレベルの属性のうち、フィルターされたものを対象とします。型、フィールド、メソッドの属性は検出せず、SkipLocalsInit の適用範囲も確認できません。この範囲を維持してください。型またはメンバーが別の行やソースの証拠によって選択された後にのみ、対象を正確に指定した属性を使用し、ライブラリ全体の属性検出については「未検証」と報告してください。
所有権と安全でないコードは重なり合う領域です。プールされたバッファーにはポインター命令がなくても、返却後の使用、クリーンアップの欠落、所有権の移譲によって問題が発生することがあります。同じラッパーを使って、安全でないコードの証拠と併せてリソーストリアージを取得してください。
capture resource-triage.jsonl \
dnx dotnet-inspect -y -- library MyLib.dll \
-S "Resource Triage" --jsonl
リソーストリアージには現在、肯定的な完了を示す確認情報がなく、一部のリソースルートが未完了のまま行を出力する場合があります。所有権の適用範囲は常に「未検証」と記述してください。より具体的な診断情報がある場合は保持し、行が 0 件であることを「所有権の問題なし」と読み替えないでください。
行を絞り込んで結合する
操作が完全一致する危険な呼び出しをまとめて取得します。
jq -s '
map(select(.reason == "Unsafe call"))
| sort_by(.detail)
| group_by(.detail)
| map({
operation: .[0].detail,
sites: length,
members: (map(.member) | unique)
})
' unsafe-members.jsonl
ガイダンスで取り上げられている API ファミリーを選択します。
jq -s --arg pattern \
'Unsafe\.(AsPointer|As|BitCast|Add|NullRef|SkipInit|ReadUnaligned|WriteUnaligned|CopyBlock)' '
map(select(.detail | test($pattern)))
' unsafe-members.jsonl
stackalloc(localloc)の箇所を選択します。
jq -s '
map(select(.detail == "localloc"))
| group_by(.member)
| map({member: .[0].member, sites: map(.il)})
' unsafe-members.jsonl
1 つのエージェント用パケットにまとめる際も、証拠ファミリーの型を維持します。
jq -n \
--slurpfile unsafe unsafe-members.jsonl \
--slurpfile ownership resource-triage.jsonl \
--slurpfile interop pinvoke-methods.jsonl \
'{
unsafe: $unsafe,
ownership: $ownership,
interop: $interop
}'
これらはスライスであり、表示テキストによる結合ではありません。各行の Member、IL、 token、Candidate、Finding、Acquire IL、Boundary IL、および境界フィールドを保持してください。詳細を確認する前に、 Type と Member の完全一致セレクターを解決してください。書式化された Member ラベルから対応関係を推測してはいけません。
1 つの候補を詳しく確認する
対象を絞った証拠には個別の機械可読出力を使用し、レビュー用に Markdown 形式の IL を保持します。空または失敗した詳細確認も表示されるように、capture ラッパーを再利用してください。
capture candidate-unsafe.jsonl \
dnx dotnet-inspect -y -- member MyType Method:1 --library MyLib.dll \
-S "Unsafe Operations" --jsonl
capture candidate-exceptions.jsonl \
dnx dotnet-inspect -y -- member MyType Method:1 --library MyLib.dll \
-S "Exception Regions" --jsonl
capture candidate-attributes.jsonl \
dnx dotnet-inspect -y -- member MyType Method:1 --library MyLib.dll \
-S "Custom Attributes" --jsonl
capture candidate-calls.jsonl \
dnx dotnet-inspect -y -- member MyType Method:1 --library MyLib.dll \
-S "Call Graph" --fields "Unsafe,Throw,Catch,Finally,Loop" --jsonl
capture candidate-il.md \
dnx dotnet-inspect -y -- member MyType Method:1 --library MyLib.dll \
-S IL
再構成された C# が IL の説明に役立つ場合に限り、skill decompiler を読み込みます。質問が字句スコープ、記述されたガード、コンパイラーの警告、またはリポジトリのテスト手法に依存する場合は、ソースの証拠を使用します。
26 のガイダンスに関する質問のルート
以下のルートは、最小限かつ有用な証拠の組み合わせを示します。一致する証拠が違反を証明するとも、確認済みで空の行が安全性を証明するとも主張するものではありません。
| # | ガイダンスのトピック | 証拠の確認経路と境界 |
|---|---|---|
| 1 | 追跡されていない管理対象ポインター | AsPointer の安全でない呼び出しを絞り込み、ポインターの出所、ピン留め、使用箇所、エスケープを詳しく調べます。 |
| 2 | fixed からのポインターのエスケープ | 安全でない操作やピン留めの証拠に加え、IL のストア、戻り値、呼び出しを調べます。字句上の fixed スコープの確認にはソースが必要な場合があります。 |
| 3 | ランタイムまたはライブラリの内部 | 安全でない呼び出し、属性、参照、非公開の呼び出しの証拠を調べます。広範な依存については、引き続きレビューによる判断が必要です。 |
| 4 | 無効な管理対象ポインター | Unsafe.Add と関連する byref 算術を絞り込み、範囲と制御フローの証拠を詳しく調べます。 |
| 5 | 再解釈キャスト | Unsafe.As と BitCast を絞り込み、互換性を判断する前に、ソースと宛先の正確な Type メタデータを結合します。 |
| 6 | 書き込みバリアと GC 参照のアトミック性 | cpblk、initblk、間接ストア、コピー API を絞り込み、宛先の出所とフィールド型を詳しく調べます。 |
| 7 | オブジェクトのライフタイム | GC.KeepAlive、SafeHandle、ファイナライザー、コールバック、相互運用境界への呼び出しを調べます。通常、存在しないことは未検証のままです。 |
| 8 | スレッド間で受け渡されるローカル変数 | 呼び出しグラフ、非同期処理/ステートマシン、ポインター/byref、所有権の証拠を調べます。スレッド間の受け渡しには、通常ソースまたはランタイムの証拠が必要です。 |
| 9 | 安全でない境界チェックの削除 | ポインターの逆参照と Unsafe.Add を絞り込み、ガードと範囲を調べたうえで、ランタイムのパフォーマンス証拠を求めます。 |
| 10 | メモリアクセスの結合 | Unsafe/MemoryMarshal の呼び出しとストアを絞り込み、安全な代替手段とランタイムの証拠を比較します。 |
| 11 | アラインメントされていないメモリアクセス | アラインメントされていないアクセスの API と間接操作を絞り込みます。対象プラットフォームのアラインメントとアトミック性は、引き続きプラットフォームやコンテキストに依存する問題です。 |
| 12 | バイナリ構造体のシリアル化 | MemoryMarshal/Unsafe による読み取り、書き込み、コピーと、正確な Type レイアウトを絞り込みます。オープンジェネリックは不完全なままです。 |
| 13 | null の管理対象ポインター | Unsafe.NullRef とポインターから byref への変換を絞り込み、使用箇所と破棄される逆参照を詳しく調べます。 |
| 14 | stackalloc | localloc を絞り込みます。ループへの所属、長さの構築、スパンへの変換、境界を詳しく調べます。 |
| 15 | 固定サイズバッファー | 安全でない宣言から候補を絞り込めますが、ライブラリ属性ではフィールドレベルの FixedBufferAttribute を検出できません。ライブラリ全体の検出は未検証のため、既知の候補にはソースまたは正確な Type の逆コンパイルを使用してください。 |
| 16 | ポインターと長さを受け取る API | ポインターのシグネチャと P/Invoke の行から候補を特定し、明示的な長さと終端に関する前提を調べます。 |
| 17 | 文字列の変更 | ポインターストアと文字列の出所に関する証拠を調べます。対象の特定には、通常ソースまたは逆コンパイルが必要です。 |
| 18 | 生の IL 生成 | 参照と呼び出しから Reflection.Emit または Cecil の使用を特定します。生成された IL の妥当性には、別途証拠が必要です。 |
| 19 | 初期化されていないローカル変数 | Unsafe.SkipInit の呼び出しを絞り込みます。ライブラリ属性では SkipLocalsInit を確認できません。このライブラリ全体の調査は未検証のため、ソースを使用するか、正確な Member の属性と IL のローカル初期化を調べたうえで、読み取り、書き込み、プールされたバッファーの初期化を詳しく調べてください。 |
| 20 | ArrayPool<T> とプーリング | リソーストリアージ、安全でない呼び出し、例外、返却を結合します。現在の所有権に関する網羅状況は、常に未検証です。 |
| 21 | bool/整数変換 | Boolean と整数の Type に関わる Unsafe.As、BitCast、アラインメントされていない読み取りを絞り込みます。 |
| 22 | 相互運用 | P/Invoke の行、シグネチャ、属性、安全でない操作、所有権/ライフタイムの証拠を調べます。 |
| 23 | スレッドセーフ性 | 呼び出しグラフと可変リソースの証拠から候補を絞り込めますが、一般的なスレッドセーフ性の判定は対象外です。 |
| 24 | SIMD/ベクトル化 | 呼び出しと安全でない操作からロード/ストアを特定します。境界、アラインメント、アトミック性、効果の判断には、コンテキストやランタイムの証拠が必要です。 |
| 25 | ファズテスト | アセンブリの証拠から、リポジトリのファズテスト網羅状況は確認できません。テストと CI を別途調べてください。 |
| 26 | コンパイラー警告 | 通常のアセンブリには警告が保持されません。ビルド診断情報または SARIF が必要です。 |
レビューを報告する
該当する各質問について、次の項目を報告してください。
- ガイダンスのトピックと、正確に調査した対象。
- 所有者が発行した行と、正確な座標。
- 候補を絞り込んだ集合を生成した
jqのスライスまたは結合。 - エージェントによる、ラベル付きの解釈。
- 完了範囲または
unverifiedの境界。 - 証拠だけでは判断できない場合、次に行う対象を絞った調査。
該当する行が見つからなかったからといって、26 個すべてのトピックに問題がないと報告してはいけません。真に該当しないトピックは省き、証拠を入手できない、または不完全な該当質問とは区別してください。