JPCERT コーディネーションセンター

安全・安心なIT社会のための、国内・国際連携を支援する

お問い合わせ 採用情報 サイトマップ English

Home > ラーニング > セキュアコーディング > C セキュアコーディングスタンダード

最終更新: 2014-03-31

CERT C セキュアコーディングスタンダード


CERT C セキュアコーディングスタンダード

00はじめに

このページでは、JPCERTコーディネーションセンター、セキュアコーディングプロジェクトが翻訳した 'CERT C Secure Coding Standard' の日本語版『CERT C セキュアコーディングスタンダード』を公開しています。

C セキュアコーディングを実践する上で欠かせない要素のひとつに、プログラマが理解できるように記述され、現場に実際に適用できるコーディングスタンダード(規約)があげられます。コーディングスタンダードを活用することで、プログラマは、ひとりよがりに陥ることなく、プロジェクトや組織が要求にしたがって定めたルールやガイドラインに沿ってコーディングすることが可能になります。こうしたスタンダードはまた、一度確立することでソースコードを評価する指標として用いることもできます。

CERT C セキュアコーディングスタンダードは、C言語を使ってセキュアコーディングを行うためのルール (Rule) とレコメンデーション (Recommendation) を定めています。目的は、脆弱性につながる恐れのある危険なコーディング作法や未定義の動作を削減することです。セキュアコーディングスタンダードを採用することで、より品質の高い、堅牢で攻撃に耐えられるシステム開発が可能になるはずです。

セキュアコーディングスタンダードに関するより詳しい説明は、00.「はじめに」をご一読ください。

Top へ

01プリプロセッサ (PRE)
レコメンデーション
PRE00-C関数形式マクロよりもインライン関数やスタティック関数を使う
PRE01-Cマクロ内の引数名は括弧で囲む
PRE02-Cマクロ置換リストは括弧で囲む
PRE03-C型をエンコードするには define よりも typedef を選ぶ
PRE04-C標準ヘッダファイル名を再利用しない
PRE05-C字句の結合や文字列化を行う際にはマクロ置換をよくよく理解して行う
PRE06-Cヘッダファイルはインクルードガードで囲む
PRE07-C"??" の繰り返しは避ける
PRE08-Cヘッダファイル名が一意であることを保証する
PRE09-Cセキュアな関数をよりセキュアでない関数に置き換えない
PRE10-C複数にわたる文からなるマクロは do-while ループで包む
PRE11-C単一文からなるマクロ定義をセミコロンで終端しない
PRE12-C安全でないマクロを定義しない
PRE13-あらかじめ定義された標準マクロで準拠規格やバージョンをテストする
ルール
PRE30-C文字列連結によってユニバーサル文字名を作成しない
PRE31-C代入、インクリメント、デクリメント、volatile アクセス、または関数呼び出しを含む引数を使って安全でないマクロを呼び出さない
PRE32-Cマクロの引数内で前処理指令を使用しない

Top へ

02宣言と初期化 (DCL)
レコメンデーション
DCL00-C不変(immutable)オブジェクトは const 修飾する
DCL01-Cサブスコープで変数名を再利用しない
DCL02-C視覚的に区別できる識別子を使う
DCL03-C定数式の値をテストするには静的アサートを使う
DCL04-Cひとつの宣言で2つ以上の変数を宣言しない
DCL05-Ctypedef を使いコードの可読性を改善する
DCL06-Cリテラル値の表現には意味のあるシンボル定数を使う
DCL07-C関数宣言子には適切な型情報を含める
DCL08-C定数定義間の関係は適切にコード化する
DCL09-Cerrno を返す関数は返り値を errno_t 型として定義する
DCL10-C可変引数関数の作成者と利用者の間の取り決めを維持する
DCL11-C可変引数関数に関連する型問題について理解する
DCL12-C抽象データ型は opaque な型を使って実装する
DCL13-C関数の引数が関数自身によって変更されない値を参照するポインタならば、関数の引数をconstとして宣言する
DCL15-C外部結合を必要としないファイル有効範囲のオブジェクトや関数は static 宣言する
DCL16-Clong 値を表すには小文字の "l" ではなく大文字の "L" を使う
DCL17-Cvolatile 修飾された変数が間違ってコンパイルされることに注意
DCL18-C10 進値を指定するとき、整数定数を 0 で始めない
DCL19-C変数と関数の有効範囲を最小限にする
DCL20-C引数を受け付けない関数の場合も必ず void を指定する
DCL21-C複合リテラルの記憶域を理解する
DCL22-Cキャッシュできないデータには volatile を使う
DCL23-C相互に可視である識別子が一意であることを保証する
ルール
DCL30-C適切な記憶域期間を持つオブジェクトを宣言する
DCL31-C識別子は宣言してから使用する
DCL33-C関数引数中で restrict 修飾されたコピー元およびコピー先が、重複したオブジェクトを参照しないようにする
DCL35-C関数定義と一致しない型で関数を呼び出さない
DCL36-C矛盾する結合の種類を使用して識別子を宣言しない
DCL37-C予約済みの識別子を宣言または定義しない
DCL38-Cフレキシブル配列メンバには正しい構文を使用する
DCL40-C同一の関数やオブジェクトに対して適合(compatible)しない宣言をしない

Top へ

03式 (EXP)
レコメンデーション
EXP00-C括弧を使用して演算の優先順位を指定する
EXP01-Cポインタが参照する型のサイズを求めるのにポインタのサイズを使わない
EXP02-C論理 AND 演算子および論理 OR 演算子のショートサーキット動作について注意する
EXP03-C構造体のサイズが構造体のメンバのサイズの和に等しいと決めてかからない
EXP04-C構造体を含むバイト単位の比較を行わない
EXP05-Cconst 修飾をキャストではずさない
EXP07-C式中で、定数の値を仮定して定数を使うメリットを損なわない
EXP08-Cポインタ演算は正しく使用する
EXP09-C型や変数のサイズは sizeof を使って求める
EXP10-C部分式の評価順序や副作用の発生順序に依存しない
EXP11-Cビットフィールド構造体のレイアウトについて勝手な想定をしない
EXP12-C関数の返り値を無視しない
EXP13-C関係演算子および等価演算子は、結合則が成り立たないものとして扱う
EXP14-Cchar 型や short 型の値に対してビット単位の演算を行う際には整数拡張(integer promotion)が行われることに注意
EXP15-Cif、for、while 文と同じ行にセミコロンを使用しない
EXP16-C関数ポインタを定数値と比較しない
EXP17-C条件式に対してビット単位の演算を行わない
EXP19-Cif、for、while 文の本体は波括弧で囲む
EXP20-C成功、真偽、等価を判定するには明示的な検査を行う
EXP21-C等価比較の左側に定数を配置する
ルール
EXP30-C副作用完了点間の評価の順序に依存しない
EXP31-Cassert() のなかでは副作用を避ける
EXP32-C非 volatile 参照により volatile オブジェクトにアクセスしない
EXP33-C未初期化のメモリを参照しない
EXP34-CNULL ポインタを参照しない
EXP35-C一時的な生存期間を持つオブジェクトを変更しない
EXP36-Cポインタをより厳密にアラインされるポインタ型に変換しない
EXP37-C正しい引数の数と型で関数を呼び出す
EXP38-Cビットフィールドメンバや無効な型で offsetof() を呼び出さない
EXP39-C適合しない型のポインタを使って変数にアクセスしない
EXP40-C定数オブジェクトを変更しない
EXP44-Csizeof 演算子のオペランドは副作用を持たせない
EXP45-C選択文に対して代入を行わない

Top へ

04整数 (INT)
レコメンデーション
INT00-C処理系のデータモデルについて理解する
INT01-Cオブジェクトのサイズを表現するすべての整数値に rsize_t もしくは size_t を使用する
INT02-C整数変換のルールを理解する
INT03-Cセキュアな整数ライブラリを使用する
INT04-C信頼できない入力源から取得した整数値は制限する
INT05-C可能性のあるすべての入力を処理できない入力関数を使って文字データを変換しない
INT06-C文字列トークンを整数に変換するには strtol() 系の関数を使う
INT07-C数値には符号の有無を明示した文字型のみを使用する
INT08-C全ての整数値が範囲内にあることを確認する
INT09-C列挙定数が一意の値に対応することを保証する
INT10-C% 演算子を使用する際、結果の剰余が正であると想定しない
INT11-Cポインタ型から整数型への変換やその逆の変換は注意して行う
INT12-C式中で使用される単なるintのビットフィールドの型について想定しない
INT13-Cビット単位の演算子は符号無しオペランドに対してのみ使用する
INT14-C同じデータに対してビット単位の演算と算術演算を行わない
INT15-Cプログラマ定義の整数型に対する書式付き入出力には、intmax_t もしくは uintmax_t を使用する
INT16-C符号付き整数の表現形式を想定しない
INT17-C処理系に依存しない方法で整数定数を定義する
ルール
INT30-C符号無し整数の演算結果がラップアラウンドしないようにする
INT31-C整数変換によってデータの消失や解釈間違いが発生しないことを保証する
INT32-C符号付き整数演算がオーバーフローを引き起こさないことを保証する
INT33-C除算および剰余演算がゼロ除算エラーを引き起こさないことを保証する
INT34-C負のビット数、あるいはオペランドのビット数以上シフトしない
INT35-C整数式をより大きなサイズの整数に対して比較や代入をする際には、事前に演算後のサイズで評価する

Top へ

05浮動小数点 (FLP)
レコメンデーション
FLP00-C浮動小数点数の限界を理解する
FLP01-C浮動小数点式の演算の順序に注意する
FLP02-C精度の高い計算が必要な場合は浮動小数点数の使用を避ける
FLP03-C浮動小数点エラーを検知して処理する
FLP04-C浮動小数点入力が例外値でないか検査する
FLP05-C非正規化数を使用しない
ルール
FLP30-C浮動小数点変数をループカウンタに使用しない
FLP31-C実数値を引数にとる関数を複素数値で呼び出さない
FLP32-C数学関数における定義域エラーおよび値域エラーを防止または検出する
FLP33-C浮動小数点数の演算時には整数を浮動小数点数に変換する
FLP34-C浮動小数点の型変換が新しい型の範囲に収まるようにする
FLP35-C浮動小数点数値を比較する際には精度を考慮する
FLP36-C整数型から浮動小数点型への変換時の精度の消失に注意
FLP37-C浮動小数点型を返す関数の返り値をキャストする

Top へ

06配列 (ARR)
レコメンデーション
ARR00-C配列の仕組みを理解する
ARR01-C配列のサイズを求めるときに sizeof 演算子をポインタに適用しない
ARR02-C初期化子が暗黙的にサイズを定義する場合であっても、配列のサイズは明示的に指定する
ルール
ARR30-C境界外を指すポインタや配列添字を生成したり使用したりしない
ARR31-Cすべてのソースファイルで一貫した配列表記を用いる
ARR32-C可変長配列のサイズ引数は適切な範囲内にあることを保証する
ARR33-Cコピーは必ず十分なサイズの記憶領域に対して行われることを保証する
ARR34-C式中の配列の型は適合していることを保証する
ARR36-C異なる配列を指す2つのポインタに対して減算や比較を行わない
ARR37-C配列以外のオブジェクトを指すポインタに対して整数の加算や減算を行わない
ARR38-Cライブラリ関数が無効なポインタを生成しないことを保証する

Top へ

07文字と文字列 (STR)
レコメンデーション
STR00-C文字の表現には適切な型を使用する
STR01-C文字列の管理は一貫した方法で行う
STR02-C複雑なサブシステムに渡すデータは無害化する
STR03-Cnull 終端バイト文字列を不注意に切り捨てない
STR04-C基本文字集合にある文字を表すには単なる char を使用する
STR05-C文字列リテラルの参照には const へのポインタを使用する
STR06-Cstrtok() が分割対象文字列を変更しないと想定しない
STR07-C境界チェックインタフェースを使用し、文字列操作を行う既存のコードの脅威を緩和する
STR08-C新たに開発する文字列処理するコードには managed string を使用する
STR09-C単なる文字型の式に対して数値を想定しない
STR10-C型が異なる文字列リテラルを結合しない
STR11-C文字列リテラルで初期化される文字配列のサイズを指定しない
ルール
STR30-C文字列リテラルを変更しない
STR31-C文字データと null 終端文字を格納するために十分な領域を確保する
STR32-C文字列は null 終端させる
STR33-Cワイド文字の文字列サイズは正しく求める
STR34-C文字データをより大きなサイズの整数型に変換するときは事前に unsigned char 型に変換する
STR35-C長さに制限のないコピー元から固定長配列へデータをコピーしない
STR37-C文字処理関数への引数は unsigned char として表現できなければならない
STR38-Cナロー文字列に対するワイド文字関数の使用、およびその逆を避ける

Top へ

08メモリ管理 (MEM)
レコメンデーション
MEM00-Cメモリの割り当てと解放は、同じ翻訳単位内の同一抽象レベルで行う
MEM01-Cfree() した直後のポインタには新しい値を代入する
MEM02-Cメモリ割り当て関数の結果は、割り当てた型へのポインタに即座にキャストする
MEM03-C再利用可能なリソースに格納された機密情報は消去する
MEM04-Cサイズ 0 のメモリ割り当てを行わない
MEM05-Cスタック上で大きなサイズの割り当てを行わない
MEM06-C機密情報はディスクに書き出さない
MEM07-Ccalloc() の引数は乗算した結果がラップアラウンドしないようにする
MEM08-Crealloc() は動的に割り当てられた配列のサイズ変更にのみ使用する
MEM09-Cメモリ割り当て関数がメモリを初期化すると想定しない
MEM10-Cポインタ検証関数を定義して使用する
MEM11-Cヒープ領域が無限にあると想定しない
MEM12-Cリソースの使用および解放の最中に発生するエラーが原因で関数を終了する場合に、Goto 連鎖の使用を検討する
ルール
MEM30-C解放済みメモリにアクセスしない
MEM31-C動的に割り当てられたメモリは一度だけ解放する
MEM32-Cメモリ割り当てエラーを検出し、対処する
MEM33-Cフレキシブル配列メンバを含む構造を動的に割り当ててコピーする
MEM34-C動的に割り当てられたメモリのみを解放する
MEM35-Cオブジェクトに対して十分なメモリを割り当てる

Top へ

09入出力 (FIO)
レコメンデーション
FIO00-C書式文字列は注意して作成する
FIO01-Cファイル名を使用してファイルを識別する関数の使用に注意する
FIO02-C信頼できない情報源から取得したファイル名は正規化する
FIO03-Cfopen() を使用したファイル作成時に何らかの仮定をしない
FIO04-C入出力エラーを検出し、処理する
FIO05-C複数のファイル属性を使用してファイルを特定する
FIO06-C適切なパーミッションを持つファイルを作成する
FIO07-Crewind() ではなく fseek() を使用する
FIO08-Cオープンしたままのファイルに対する remove() の呼び出しに注意する
FIO09-Cシステム間でのバイナリデータ転送に注意する
FIO10-Crename() 関数の使用に注意する
FIO11-Cfopen() のモード引数の指定は慎重に行う
FIO12-Csetbuf() ではなく setvbuf() を使用する
FIO13-C読み取った一文字以外は押し戻さない
FIO14-Cファイルストリームにおけるテキストモードとバイナリモードの違いを理解する
FIO15-Cファイル操作はセキュアなディレクトリで行われることを保証する
FIO16-Cジェイル(監獄)を作成してファイルへのアクセスを制限する
FIO17-Cfread() を使用するときは、null 終端文字に依存しない
FIO18-Cfwrite() が書き込み操作を null 文字で終了すると想定しない
FIO19-Cファイルサイズの計算に fseek() および ftell() を使用しない
ルール
FIO30-Cユーザからの入力を使って書式指定文字列を組み立てない
FIO31-C同一のファイルを同時に複数回開かない
FIO32-C通常ファイルに固有の操作をデバイスファイルに対して行わない
FIO33-C未定義の動作となる入出力のエラーを検出して処理する
FIO34-C文字入出力関数の返り値の取得には int 型を使用する
FIO35-Csizeof(int) == sizeof(char) の場合、EOF およびファイルエラーの検出には feof() と ferror() を使用する
FIO36-Cfgets() が改行文字を読み取ると仮定しない
FIO37-C読み取られたデータが文字データであると思い込まない
FIO38-C入出力操作に FIlE オブジェクトのコピーを使用しない
FIO39-Cfflush 関数やファイル位置付け関数を呼び出さずにストリームへの入出力を交互に行わない
FIO40-Cfgets() が失敗したときは引数に渡した配列の内容をリセットする
FIO41-C副作用を持つストリーム引数を getc() または putc() に渡さない
FIO42-C不要になったファイルは正しくクローズする
FIO43-C共有ディレクトリに一時ファイルを作成しない
FIO44-Cfsetpos() には fgetpos() が返す値を使用する

Top へ

10環境 (ENV)
レコメンデーション
ENV01-C環境変数のサイズについて勝手な想定をしない
ENV02-C同じ名前の複数の環境変数に注意する
ENV03-C外部プログラムを呼び出す際は環境を無害化する
ルール
ENV30-C関数の返り値によって参照されるオブジェクトを変更しない
ENV31-C環境変数へのポインタを無効にするかもしれない操作の後で、そのポインタを参照しない
ENV32-Catexit で登録したハンドラ関数は必ず return する
ENV33-Cコマンドプロセッサが必要ない場合は system() を呼び出さない
ENV34-Cgetenv() が返す文字列へのポインタを保存しない

Top へ

11シグナル (SIG)
レコメンデーション
SIG00-C割り込み不可能なシグナルハンドラによって処理されるシグナルをマスクする
SIG01-Cシグナルハンドラの継続性に関して処理系定義の詳細を理解する
SIG02-C標準的な機能を実装する際はシグナルの使用を避ける
ルール
SIG30-Cシグナルハンドラ内では非同期安全な関数のみを呼び出す
SIG31-Cシグナルハンドラ内で共有オブジェクトにアクセスしない
SIG32-Cシグナルハンドラ内からlongjmp() を呼び出さない
SIG33-Craise() 関数を再帰的に呼び出さない
SIG34-C割り込み可能なシグナルハンドラ内から signal() を呼び出さない
SIG35-Cシグナルハンドラ SIGSEGV、SIGILL、SIGFPE から復帰しない

Top へ

12エラー処理 (ERR)
レコメンデーション
ERR00-Cエラー処理には一貫性のある方針を採用する
ERR01-Cerrno ではなく ferror() を使って FILE ストリームエラーを検査する
ERR02-C正常終了時の値とエラーの値は別の手段で通知する
ERR03-C境界チェックインタフェースを呼び出す際は、実行時制約ハンドラを使用する
ERR04-Cプログラムの適切な終了方法を選択する
ERR05-Cアプリケーション非依存なコードではエラー検知のみ行ない、エラー処理は行わない
ERR06-Cassert() と abort() の終了動作を理解する
ERR07-Cよりよいエラー検査を行える関数を使用する
ルール
ERR30-C関数を呼び出す前に errno をゼロに初期化し、関数の異常終了時にのみ errno を参照する
ERR31-Cerrno を再定義しない
ERR32-Cerrno の未規定の値を参照しない
ERR33-C標準ライブラリのエラーを検出し、対処する

Top へ

13Application Programming Interface (API)
レコメンデーション
API00-C関数のなかで引数を検証する
API02-C配列の読み書きを行う関数はコピー元やコピー先のサイズを指定する引数を取れ
API03-C関連する関数にはインタフェースと機能に一貫性を持たせる
API04-C一貫性があり使いやすいエラー検査方法を提供する
API07-C型の安全性を徹底する
API08-C関数プロトタイプでは引数に名前をつけない
API09-C互換性のある値には同じ型を使用する
ルール

Top へ

14並行性 (CON)
レコメンデーション
CON00-C複数のスレッドによる競合状態を避ける
CON01-C同期用プリミティブの取得と解放は、同じ翻訳単位内の同一抽象レベルで行う
CON02-Cvolatile を同期用プリミティブとして使用しない
CON04-C終了ステータスが重要でないスレッドでも、join または detach する
CON05-Cロックを保持している状態ではブロックする可能性がある操作を行わない
CON09-Cロックを含まないプログラミングにより ABA 問題を避ける
ルール
CON31-C他のスレッドのミューテックスをアンロックしたり破壊したりしない
CON32-C複数スレッドによる隣接データへのアクセスが必要な場合データ競合を防止する
CON33-Cライブラリ関数の使用時は競合状態を避ける
CON34-Cスレッド間で共有されるオブジェクトは適切な記憶域期間を持つように宣言する
CON35-Cあらかじめ定義した順番でロックしてデッドロックを防ぐ
CON37-Cマルチスレッドプログラムで signal() を呼び出さない
CON38-C1 つのスレッドではなく条件変数を待っているすべてのスレッドに通知する

Top へ

49雑則 (MSC)
レコメンデーション
MSC00-C高い警告レベルで警告を出さずにコンパイルする
MSC01-C論理的な完全性を追求する
MSC04-Cコメントの記法には一貫性を持たせ読みやすくする
MSC05-Ctime_t 型の値を直接操作しない
MSC06-C機密データを扱う場合はコンパイラの最適化に注意する
MSC07-Cデッドコードを検出して削除する
MSC09-C文字の符号化 - 安全対策のために ASCII のサブセットを使用する
MSC10-C文字の符号化 - UTF8 に関連する問題
MSC11-C診断テストはアサートを使って組み込む
MSC12-Cプログラムに対して作用しないコードを検出して削除する
MSC13-C使用されない値を検出して削除する
MSC14-C必要もなくプラットフォーム依存のコードを書かない
MSC15-C未定義の動作に依存しない
MSC16-C関数ポインタの暗号化を検討する
MSC17-Ccase 句に関連付けられた一連の文は break 文で終了する
MSC18-Cプログラムコードの中でパスワードなどの機密情報を扱うときは注意する
MSC19-C配列を返す関数は、NULL 値ではなく空の配列を返すこと
MSC20-C複雑なブロックに制御を渡す際に switch 文を使用しない
MSC21-Cループの終了条件には不等式を用いる
MSC22-Csetjmp()、longjmp() の機能を安全に使用する
ルール
MSC30-C疑似乱数の生成に rand() 関数を使用しない
MSC31-C関数の返り値は必ず適切な型と比較する
MSC32-C乱数生成器は適切なシード値を与えて使う
MSC33-C無効なデータを asctime() 関数に渡さない
MSC34-C廃止予定の関数や古い関数を使用しない
MSC35-C最初の case ラベルよりも前にある switch 文の内側に実行文を含めない
MSC36-Crealloc() 関数の呼び出し前にメモリ領域のアラインメントを確認する
MSC37-C非 void 型関数の制御が関数定義の最終行に到達しないことを保証する
MSC38-Cマクロとして実装されている可能性のある定義済みの識別子をオブジェクトとして扱わない
MSC39-C値が不定の va_list に対して va_arg() を呼び出さない

Top へ

50POSIX (POS)
レコメンデーション
POS01-Cファイルを操作するときにはリンクが存在するかどうかを検査する
POS02-C最小権限の原則に従う
POS03-Cvolatile を同期用プリミティブとして使用しない
POS04-CPTHREAD_MUTEX_NORMAL ミューテックスロックの使用を避ける
ルール
POS30-Creadlink() 関数を正しく使用する
POS33-Cvfork() は使用しない
POS34-C自動変数へのポインタを引数としてputenv()を呼び出さない
POS35-Cシンボリックリンクの有無のチェック時の競合状態を避ける
POS36-C権限は正しい順序で破棄する
POS37-C権限の破棄は確実に行う
POS38-Cfork およびファイル記述子を使用するときには競合状態に注意する
POS39-Cシステム間でデータを送受信するときには正しいバイトオーダーを使用する
POS41-Cスレッドの終了状態が必要ない場合は pthread_detach() または同等の関数を使用する
POS44-Cシグナルを使用してスレッドを終了しない
POS45-C明示的なデストラクタを定義することによりメモリリークを避け、キーに対するスレッド固有データを消去する
POS47-C非同期キャンセルが可能なスレッドを使用しない

Top へ

AA参考情報

Top へ

BBDefinitions

Definitions (CERT C Secure Coding Standard のページにとびます)

Top へ

CC未定義の動作

Undefined Behavior (CERT C Secure Coding Standard のページにとびます)

Top へ

DD未規定の動作

Unspecified Behavior (CERT C Secure Coding Standard のページにとびます)

Top へ

XXお問い合わせ

本ページに関するご質問・お問い合わせは、secure-coding@jpcert.or.jp までメールにてお願いいたします。

Top へ