Coverityを用いたC++のバグ検出とセキュリティ解析の完全ガイド

CoverityでC++のバグとセキュリティ問題を見つけるには、実際の製品ビルドを正しくキャプチャし、解析し、結果をプロジェクトまたはstreamへ登録し、パスイベントを読んで修正し、同じ構成で再解析する流れを作ります。検出件数をゼロにすることより、解析対象が十分に捕捉されていること、新規の重大問題を止めること、誤検出を根拠付きでトリアージすることが重要です。

2026年7月時点の公式情報はBlack DuckのCoverityドキュメントで提供されています。画面名、コマンドオプション、ライセンス、対応コンパイラーはリリースごとに変わり得るため、手元のCoverity AnalysisとCoverity Connectの版を確認してください。Coverity Scanは登録されたオープンソースプロジェクト向けの別サービスであり、企業の非公開コードを無断でアップロードする用途ではありません。

目次

導入前の判断表

状況進め方確認事項
商用・社内の非公開C++契約済みCoverity環境ライセンス、Connect、コード持ち出し規程
登録済みOSSCoverity Scan利用条件、ビルド回数制限、公開範囲
ローカルの早期確認Desktop/IDE連携またはCLI中央解析との差、同じ設定・モデル
CIで品質ゲート新規重大issueを基準baseline、例外承認、障害時の扱い
組み込み・クロスコンパイル実コンパイラー構成を登録マクロ、include、派生ビルド、生成コード

最初に保護すべきものはソースコードと解析中間ディレクトリです。キャプチャ結果にはソース、ヘッダー、ビルド情報、パス、マクロなど機密性の高い情報が含まれ得ます。共有CIワーカーへ置く場合はアクセス権、保存期間、暗号化、バックアップ、ログのマスキングを決めます。解析トークンやパスワードをコマンド行、ビルドログ、リポジトリへ直接書かず、承認された資格情報ストアから渡します。

Coverity解析の基本ワークフロー

1. 対象と成功条件を決める

リポジトリ全体を一つのstreamへ入れる前に、製品、リリースブランチ、コンポーネント、所有チーム、サードパーティコード、生成コードを区分します。成功条件には、キャプチャされた翻訳単位数、ビルド成功、解析警告、重大度別の新規issue数、未担当issueの滞留時間を含めます。単に『コマンドが終了コード0だった』だけでは、主要なC++ファイルが解析されていない状態を見逃します。

2. コンパイラーを構成する

Coverityはコンパイラー、組み込み定義、includeパス、言語拡張を理解して解析モデルを作ります。GCC、Clang、MSVC、クロスコンパイラーなど、実際に製品を作るツールチェーンを対象版の公式対応表で確認し、必要な構成を作成します。別コンパイラーのテンプレートを流用すると、条件コンパイルや型サイズがずれ、未解析や誤った経路の原因になります。

3. クリーンビルドをキャプチャする

C/C++では通常、Coverityのキャプチャコマンドで実際のビルドを包みます。キャッシュによりコンパイルが省略されると必要な翻訳単位が取り込まれないため、解析専用ワークスペースでクリーンビルドを行い、ビルドログとキャプチャ概要を確認します。ただし毎回の完全クリーンが非常に高コストなプロジェクトでは、公式の増分・キャッシュ対応を対象版資料に従って設計します。

DebugとRelease、機能フラグ、OS、CPU、製品派生でコンパイル対象が違う場合、単一構成だけではコード全体を見られません。実運用で出荷する構成を優先し、追加構成のキャプチャを計画します。同じソースを異なるマクロで解析するとissueの重複やパス差が生じるため、stream分割と統合方針を先に決めます。

4. 解析して結果を登録する

キャプチャ後に静的解析を実行し、解析概要のエラー、未認識コンパイラー、解析対象数、メモリ不足を確認します。結果をCoverity Connectへcommitする前に、接続先、stream、snapshot名、ブランチを確認します。誤ったstreamへ大量issueを登録すると、履歴と担当割当の修復が難しくなります。本番Connectへの初回投入は管理者と小規模な試験streamで確認します。

5. パスを読んで修正する

issueには、問題点の1行だけでなく、値の発生源、条件分岐、関数間の伝播、危険な利用地点を示すイベント列が含まれます。最後の行だけをNULLチェックで塞ぐのではなく、最初に不正な状態が生まれた場所と所有権を追います。修正後は単体テスト、回帰テスト、同じ構成のCoverity再解析を行い、issueが消えた理由がコード修正によるものか、解析対象から外れただけかを確認します。

C++で優先して見る問題

分類代表的なリスクレビューの観点
NULL・無効ポインタークラッシュ、未定義動作生成条件、所有者、全分岐の検証
解放後使用・二重解放任意コード実行、破損RAII、寿命、例外経路、別名参照
境界外アクセス情報漏えい、破損長さの単位、符号、終端、算術あふれ
リソースリーク長時間稼働で枯渇早期return、例外、所有権移譲
未初期化値非決定動作、情報漏えいすべての構築経路と部分初期化
汚染データの流入注入、パストラバーサルsource、検証、正規化、sink
並行性競合、デッドロックロック順、共有状態、原子性、寿命

メモリ所有権をコードで表す

C++では生ポインターの手動new/deleteを減らし、std::unique_ptr、適切なコンテナー、値型、スコープベースのロックで所有権を明確にすると、解析と人間のレビューの両方が正確になります。ただし機械的にshared_ptrへ置き換えると循環参照や寿命の延長を招きます。誰が破棄するか、借用参照がいつまで有効かを設計し、API境界で明示します。

整数とサイズを一緒に追う

バッファ長計算では、符号付き・符号なし変換、乗算のあふれ、バイト数と要素数、終端文字を確認します。『上限チェックがある』だけでなく、チェック前の計算ですでにあふれていないか、別の型へ縮小されていないかをパス全体で見ます。外部入力から確保サイズやコピー長へ到達するissueは、再現しにくくてもセキュリティ優先度を上げます。

セキュリティissueは到達可能性を確認する

入力源から危険なAPIまでデータが流れるtaint系issueでは、ネットワーク、ファイル、環境変数、IPC、設定値の信頼境界を確認します。途中で検証していても、正規化の順序、文字コード、別名パス、シェル展開が残っていないかを見ます。単に『社内入力だから安全』と分類せず、攻撃者がその値を制御できる条件と防御層を記録します。

トリアージを品質活動にする

issueの分類は、担当者の感覚だけで決めず、真の不具合、意図した動作、誤検出、修正済み、保留など組織の定義を作ります。各判断には、対象版、コード上の根拠、テスト、リスク受容者、期限を残します。『誤検出』を件数削減のために使うと、モデルや設定の問題が蓄積し、将来の同種issueも見落とします。

最初の全体解析では既存issueが大量に出ることがあります。すべてを一度にCI失敗へすると開発が停止するため、基準snapshotを固定し、新規または変更コードで増えた高影響issueからゲートします。既存issueは、外部入力に到達するもの、メモリ安全性、頻繁に実行される経路、障害履歴のあるコンポーネントを優先して計画的に減らします。

誤検出はモデルで減らす

社内のメモリアロケーター、NULLにならない関数、サニタイザー、ロックラッパーをCoverityが理解できないと、誤検出や見逃しが増えます。個別行を大量に抑制する前に、対象版の公式ドキュメントに従ってカスタムモデルや注釈を検討します。モデル変更は解析全体へ影響するため、レビュー、バージョン管理、代表issueによる回帰試験を行います。

CI/CDへ組み込む

CIでは、ビルドキャプチャ、解析、commit、品質判定を分けてログと失敗理由を残します。Coverityサーバーが一時的に使えないことと、重大issueが検出されたことを同じエラーにしないでください。前者は再試行や保留、後者は変更の修正または承認済み例外という異なる運用です。資格情報は最小権限とし、外部pull requestの未信頼コードへ秘密を渡さないようジョブ境界を分けます。

短いプルリクエスト解析と、夜間またはリリース前の全体解析を組み合わせます。増分解析は開発者の待ち時間を減らせますが、関数間・コンポーネント間の影響を完全に代替するとは限りません。定期的なフル解析で差分を照合し、解析時間、失敗率、新規issue、修正までの日数、再発率を監視します。

修正時の安全な手順

  1. CID、checker、発生snapshot、コンポーネント、全イベントを保存する。
  2. 問題が成立する入力条件と実行経路をコード・テストで確認する。
  3. 症状の直前だけでなく、所有権や検証境界の原因を修正する。
  4. 境界値、失敗経路、並行実行を含む回帰テストを追加する。
  5. 同じコンパイラー構成で再キャプチャ・再解析し、対象数も比較する。
  6. issueを閉じ、修正コミット、テスト、残留リスクをトリアージ記録へ紐付ける。

セキュリティ修正を公開する場合は、脆弱性管理担当と公開時期、影響版、回避策、CVEの要否を調整します。解析結果には未公開脆弱性の詳細が含まれるため、一般チャットや公開issueへそのまま貼らないでください。修正ブランチ、ログ、レポートの閲覧権限を必要な担当者に限定します。

元記事から引き継いだコード例

以下のCoverityカスタムコードブロックは、CLIの処理順を理解するための旧例です。コマンド名、オプション、サーバーURL、stream名はCoverityの版と組織構成で異なります。プレースホルダーを確認せず実行したり、資格情報をコマンドへ直書きしたり、誤ったConnect環境へcommitしたりしないでください。現在のBlack Duck公式ドキュメントを優先します。

CIの標準成果物へCoverityの中間ディレクトリ全体を登録しないでください。中間ディレクトリには、環境変数、コマンドライン引数、ソースコード、ビルド成果物、ホスト名、検出した欠陥、解析ログが含まれ得ます。通常のCIでは、必要な担当者だけが閲覧できるCoverity側の結果と、秘密情報を除いた件数・成否の要約だけを残します。

  • 既定はアップロードしない。ジョブ専用の隔離ワークスペースで処理し、組織の廃棄手順に従う
  • 保存が必要なら、非公開プロジェクト内の暗号化された成果物ストアだけを使う
  • 閲覧者を指名した担当者とサービスアカウントへ限定し、公開リンクと未信頼forkからの参照を禁止する
  • 通信は保護された経路を使い、資格情報、トークン、環境変数、絶対パスをログと成果物から除く
  • 保持期間は調査に必要な最短時間とし、自動削除日時、所有者、削除確認を記録する
  • 社外サービスへ送る前に、契約、データ所在地、輸出管理、顧客コードの扱いを承認者へ確認する

ベンダーサポートから中間ディレクトリの提出を明示的に求められた場合も、対象ジョブだけを再現し、提出範囲を最小化します。組織が承認した非公開窓口、保存時と転送時の暗号化、個別アクセス権、短い有効期限を設定し、調査終了後の削除を確認してください。汎用のCI設定へ残したまま、以後の全ビルドを蓄積しないことが重要です。

   cov-build --dir <output_directory> make
   cov-analyze --dir <output_directory>
   cov-commit-defects --dir <output_directory> --host <coverity_server> --stream <project_name>

症状別の切り分け

症状主な原因確認するもの
issueがほとんど出ないキャプチャ不足、無効checker翻訳単位数、build-log、解析概要
解析結果が急増構成・モデル・版の変更前回snapshotとの差とrelease notes
ビルドは成功し解析が失敗未対応コンパイラー、メモリ、破損中間DIR公式対応表、ログ、ディスク、再現用クリーン環境
同じissueが再発症状だけ修正、別経路、モデル不足全イベント、所有権、回帰テスト
CIが不安定サーバー接続、並列競合、資格情報失敗段階、再試行、ワークスペース分離
誤検出が多い社内APIのモデル不足共通パターンを抽出してモデル化を検討

解析対象が突然減った、streamを取り違えた、機密ソースを誤って外部サービスへ送った、重大なメモリ破損や外部到達可能な脆弱性が見つかった場合は、追加commitや公開を止めてCoverity管理者とセキュリティ担当へ連絡します。コマンド、版、構成、ログ、snapshot、影響ブランチ、資格情報の露出範囲を保全し、必要ならトークンを失効します。

よくある質問

Coverityはコンパイルせずソースだけで使えますか?

C/C++では実ビルドのキャプチャが重要です。製品版には複数の解析方式がありますが、コンパイラー設定、マクロ、includeを実構成に合わせ、解析対象数を確認します。

検出されたissueはすべて本物ですか?

静的解析結果には要調査のものが含まれます。イベントパスと実行条件を確認し、根拠を残して分類します。誤検出と判断しても共通原因ならモデル改善を検討します。

最初からissueゼロをCI条件にすべきですか?

既存コードでは現実的でない場合があります。baselineを固定し、新規の重大issueを止めつつ、既存分をリスク順に減らす方法が運用しやすいです。

Coverity Scanへ会社のコードを送れますか?

Coverity Scanは登録されたオープンソースプロジェクト向けです。非公開コードは契約、社内規程、データ所在地を確認した承認済み環境だけで扱います。

警告を抑制すれば品質は上がりますか?

件数は減っても品質は上がりません。個別抑制より、APIモデル、所有権設計、入力検証、共通修正で原因を減らします。

C++のどのissueから直すべきですか?

外部入力から到達するメモリ安全性、解放後使用、境界外、注入、権限境界を優先し、到達可能性と影響を組み合わせて判断します。

公式情報源

まとめ

CoverityをC++開発で有効にする鍵は、実際のコンパイラーと出荷構成を正しくキャプチャし、解析対象数を検証し、issueのイベントパスから原因を直し、同じ条件で再解析することです。新規重大issueをCIで管理し、既存分はリスク順に減らし、誤検出は根拠とモデルで扱います。現行Black Duck資料と手元の版を合わせ、ソース、中間ディレクトリ、資格情報、未公開脆弱性を厳格に保護してください。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次