--- name: code-fix description: Coverity の警告を直す修正案を、最小の変更で作る(外から見える仕様を変えない、新しい MISRA・CERT の違反を作らない、まわりの書き方に合わせる)。チャットでは差分を示し、同意を得てから作業中のファイルを直す。作業用のコピーのフォルダを渡されたときは、そのフォルダだけを直す。「この警告を直して」「CID 12345 の修正案を作って」「誤検知だけど警告が消えるように直したい」のように、C / C++ のコードの Coverity の警告を直す・修正の差分を作るよう頼まれたら、ファイルを変える前に必ず使う。最新のコードでもう直っているとき、決まりの中で直せないときの扱いも決めている。 --- # 修正案の作り方 Coverity の警告を、最小の変更で直します。直すのは、警告の経路(★ の場所に至る道筋)を断つのに要る場所だけです。Coverity には何も書き込みません。 ## 頼まれ方で変わること 手順は同じで、直す場所と返し方だけが違います。 | | チャットで直接頼まれたとき | 作業用のコピーのフォルダを渡されたとき | |---|---|---| | 直すファイル | 利用者の作業中のファイル。**差分を示し、同意を得てから**直す | 渡されたフォルダのファイルだけ。聞かずに直す | | 読むだけのもの | 同意を得るまでの、すべてのファイル | 「調べるコード」のフォルダ、利用者の作業中のファイル、渡されたフォルダの外のすべて | | 返し方 | 差分・1行の要約・影響をチャットで | 示されたファイルに示された形で。返事も示された形で | | しないこと | 頼まれない結果のファイルを作る | 差分のファイルやブランチを作る(頼んだ側が作る)、質問する | ## 決まり 1. **最小**:警告をなくすのに要る場所だけを変える。リファクタリング、整形、名前の変更、関係のない改善をしない。 2. **外から見える仕様を変えない**:関数の引数・戻り値の型、公開のヘッダ、大域の変数の形を変えない。 3. **新しい MISRA・CERT の違反を作らない**: - 暗黙の型の変換を増やさない。定数は相手の型に合わせる(符号なしと比べるなら `0U`)。ただし、int より狭い符号なしの型(`uint8_t`・`uint16_t`)の計算の式(`a - b` など)は int で計算されるので、それと比べる定数に `U` を付けると動きが変わることがある。そのときは式の形を直す(`(a - b) > 0` なら `a > b`)。 - 条件は Boolean で書く(`p != NULL`、`(flags & BIT) != 0U`)。 - `if`・`for`・`while` の中身は `{ }` で囲む。`else if` を足したら `else` で終える。 - 関数の出口を増やすときは、既存の書き方に従う(出口が終わりの1つの関数なら、戻り値の変数と `goto` や分岐で、そこへ集める)。 - 使わない戻り値は、まわりの書き方(`(void)` を付けるなど)に合わせる。 - 途中で返す枝を足すときは、それまでに確保した資源(メモリ、開いたファイル)を解放してから返す。新しい漏れを作らない。 4. **まわりの書き方に合わせる**:字下げ(タブか空白か、幅)、名前の付け方、括弧の位置、エラーの扱い(`goto cleanup` の後始末、エラーコードのマクロ、ログの書き方)、注釈の書き方と言葉。 5. **文字コードと改行を変えない**:ファイルの文字コード(UTF-8、Shift_JIS など)、BOM、改行(CRLF / LF)はそのまま。日本語の注釈は、そのファイルの文字コードで表せるときだけ書く。注釈が英語だけのファイルでは英語で書く。 6. **直してよい場所の外を変えない**:チャットなら同意した差分だけ、作業用のコピーならそのフォルダだけ。比べるための写し(バックアップ)や試しのファイルも、その外に作らない。変える前の形は、調べたコードのフォルダや、読んだ内容で比べる。 ## 手順 次のチェックリストを写して、進めながら印を付けます。 ``` 修正の進み具合: - [ ] 1. 警告と、真偽の調べの結果を確かめた - [ ] 2. 直すコード(最新)を読み、もう直っていないかを確かめた - [ ] 3. ★ の経路を断つ、最小の直し方を決めた - [ ] 4. 決まりの中で直せるかを確かめた(直せなければ、超えた決まりと影響を書く) - [ ] 5. 直した(チャットなら、差分を示して同意を得てから) - [ ] 6. 直した後を読み直して確かめた - [ ] 7. 返す項目を書いた ``` 1. **警告を確かめる**:CID、チェッカー、ファイルと行、警告経路(★ の場所)、分かっていれば真偽の判定。 - 足りない情報は、チャットなら聞く。Coverity から警告経路を取れる道具があれば、それで取る(ファイルに書かせず、会話に返させる)。頼まれた作業なら、渡されたものだけで進める。 - リポジトリに `.coverity-triage/knowledge.md` があれば読む(エラーの扱いの決まりなど)。 - チェッカーごとの見方の資料(スキルなど)が使えれば、そのチェッカーの「直し方の定石」を読む。 2. **直すコードを読む**:直すのは最新のコードです。調べたコードと行番号がずれていることがあるので、関数名とコードの形で同じ場所を探す。 - ★ の行の問題がもうなければ、**何も変えず**、最新で直っていること(`already_fixed_on_latest` が真)と、直っている場所(ファイルと行)を返す。直し方が違う形(`goto` で後始末へ飛ぶ、変数の名前が変わった など)でも、★ の経路が断たれていれば直っている。同じ後始末を足すと、2回閉じる・2回解放するバグになる。 - 返す場所の行番号は、最新のコード(直したファイル)の行で書く。調べたコードの行は、警告の行として区別して書く。 3. **直し方を決める**:★ の経路を断つ、最も小さい変更を選ぶ(NULL の確かめ、後始末、範囲の確かめ、初期化、型の接尾辞など)。 - 根の原因が1か所(大きさのマクロの定義など)なら、そこを直す。そのマクロを使うすべての場所を検索し、動きと規則が崩れないかを確かめる。 - **誤検知の警告でも**、修正案を求められたら作る。外から見える動きを変えずに警告が消える形にする:防御の確かめ(今の呼び出し元では通らない枝で、まわりと同じエラーを返す)、初期化の明示、`(void)` での無視の明示など。動きが変わらないことを影響に書く。 4. **決まりの中で直せないとき**(例:エラーを伝えるのに戻り値の型を変える必要がある): - 決まりを超えた修正を作る。 - 超えた決まりと理由を、`exceeded_constraints` に1つずつ書く(例「関数の外部仕様:エラーを戻り値で返す必要がある」)。 - 影響(`impact`)に、影響を受ける呼び出し元を**すべて**、関数名で検索して、ファイルと行で挙げる。 5. **直す**: - チャット:作業中のファイルは、まだ直さない。下の「チャットで直すとき」の順で進める。 - 作業用のコピー:そのフォルダのファイルを、ふつうの編集の機能で直す。 6. **確かめる**(返す前に必ず): - 直したファイルを読み直し、★ の経路が断たれているか、変わったのは要る行だけか、字下げと改行がまわりと同じか。 - 直してよい場所のほか(調べるコードのフォルダ、利用者の作業中のファイル、ほかのファイル)を変えていないか。 - 作業用のコピーで、変更がないまま終えていないか(最新で直っていて `already_fixed_on_latest` を真にしたときを除く)。 - 注釈を入れるよう頼まれていれば、入れたか(下の「注釈」)。 7. **返す**:下の「返す項目」。 ## チャットで直すとき 1. 差分を示す。ファイルのパスはリポジトリの一番上からの相対パスで、unified diff の形(`--- a/src/x.c`、`+++ b/src/x.c`、`@@` の行番号)にする。 2. 直した内容の1行と、影響(どの条件で何が変わるか)を、ふつうの言葉で添える。決まりを超えるときは、超えた決まりと理由、影響を受ける呼び出し元も示す。`summary` や `exceeded_constraints` のような項目の名前は、チャットでは使わない(読むのは人なので)。Classification・Action・Severity は、聞かれたときか、ファイルに書くときだけ。 3. 「この差分で直してよいですか?」と聞き、その返事はそこで終える。利用者が差分を読んで止められるのは、返事が終わってからなので、「見せたらそのまま直してよい」と前もって言われていても、差分を見せた返事では直さない。 4. 見せた差分に同意の返事をもらったら、**示した差分のとおりに**直す。ほかは変えない。直した後、差分のとおりになったかを読み直す。 5. 同意を得られなければ、何も変えない。直す点を言われたら、差分を作り直して、もう一度示す。 頼んだ側の手順が、利用者に聞く道具(`ask_user` など。利用者が答えるまで待つもの)で同意を取ると決めていれば、3 は、その道具で差分を見せて聞きます。返事は終えずに、同意の答えをもらってから、同じ手番で 4 のとおりに直します(同意がなければ 5)。 最新でもう直っているときは、何も変えず、そのことと場所を伝えます。 ## 返す項目 | 項目 | 中身 | |---|---| | `summary` | 直した内容を1行で(例「接続に失敗したときも sock を閉じる」) | | `impact` | どの条件で何が変わるか、影響の範囲(例「connect() が失敗したとき、sock を閉じてから NET_ERR_CONNECT を返す。ほかの経路は変わらない」) | | `exceeded_constraints` | 超えた決まりと理由の並び。超えなければ空の並び | | `already_fixed_on_latest` | 最新でもう直っていれば真(そのときは何も変えない) | | Classification / Action / Severity | `Bug` / `Fix Required` / 警告の Impact に合わせる(High は `Major`、Medium は `Moderate`、Low は `Minor`、分からなければ `Unspecified`) | `result.json` の形で書くよう頼まれたら、これらは `fix` の `summary`・`impact`・`exceeded_constraints`・`already_fixed_on_latest`・`classification`・`action`・`severity` に入ります。ほかの項目は、それぞれの仕事の決まりで作ります。 ## 注釈 逸脱の案として Coverity の注釈を入れるよう頼まれ、注釈を入れるフォルダを渡されたときだけ行います。修正とは別のフォルダです。 - 警告の行の**すぐ上の行**に、ブロックの注釈で入れる。字下げは警告の行に合わせる。注釈のほかは何も変えない。 - `[ ]` の中は ★ のイベントのタグ。Coverity は `:FALSE` のない注釈を「意図的」として扱うので、判定で書き分ける。 - 理由の文は、逸脱コメントと同じ文にする(判定区分で始まる)。 | 判定 | 書き方 | |---|---| | 誤検知(`false_positive`) | `/* coverity[<タグ>:FALSE] 誤検知。… */` | | 意図的(`intentional`)など、それ以外 | `/* coverity[<タグ>] 意図的。… */` |