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

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

お問い合わせ サイトマップ English

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

  1. HTTPS

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

最終更新: 2012-01-25

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-C.マクロ定義の中で制御の流れを変更しない
ルール
PRE30-C.文字列連結によってユニバーサル文字名を作成しない
PRE31-C.代入、インクリメント、デクリメント、volatile アクセス、または関数呼び出しを含む引数を使って安全でないマクロを呼び出さない
PRE32-C.マクロの引数内で前処理指令を使用しない

Topへ

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

Topへ

03式 (EXP)
レコメンデーション
EXP00-C.括弧を使用して演算の優先順位を指定する
EXP01-C.ポインタが参照する型のサイズを求めるのにポインタのサイズを使わない
EXP02-C.論理 AND 演算子および論理 OR 演算子のショートサーキット動作について注意する
EXP03-C.構造体のサイズが構造体のメンバのサイズの和に等しいと決めてかからない
EXP04-C.構造体を含むバイト単位の比較を行わない
EXP05-C.const 修飾をキャストではずさない
EXP06-C.sizeof 演算子のオペランドは副作用を持たせない
EXP07-C.式中で、定数の値を仮定して定数を使うメリットを損なわない
EXP08-C.ポインタ演算は正しく使用する
EXP09-C.型や変数のサイズは sizeof を使って求める
EXP10-C.部分式の評価順序や副作用の発生順序に依存しない
EXP11-C.ある型を期待している演算子に互換性のない型のデータを渡さない
EXP12-C.関数の返り値を無視しない
EXP13-C.関係演算子および等価演算子は、結合則が成り立たないものとして扱う
EXP14-C.char 型や short 型の値に対してビット単位の演算を行う際には整数拡張(integer promotion)が行われることに注意
EXP15-C.if、for、while 文と同じ行にセミコロンを使用しない
EXP16-C.関数ポインタを定数値と比較しない
EXP17-C.条件式に対してビット単位の演算を行わない
EXP18-C.選択文に対して代入を行わない
EXP19-C.if、for、while 文の本体は波括弧で囲む
EXP20-C.成功、真偽、等価を判定するには明示的な検査を行う
ルール
EXP30-C.副作用完了点間の評価の順序に依存しない
EXP31-C.assert() のなかでは副作用を避ける
EXP32-C.volatile 修飾子をキャストにより無効にしない
EXP33-C.未初期化のメモリを参照しない
EXP34-C.NULL ポインタを参照しない
EXP35-C.関数呼び出しの結果に含まれる配列に、次の副作用完了点より後でアクセスしたり変更を行わない
EXP36-C.ポインタをより厳密にアラインされるポインタ型に変換しない
EXP37-C.API が意図した引数で関数を呼び出す
EXP38-C.ビットフィールドメンバや無効な型で offsetof() を呼び出さない
EXP39-C.適合しない型のポインタを使って変数にアクセスしない
EXP40-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-C.null 終端バイト文字列を不注意に切り捨てない
STR04-C.基本文字集合にある文字を表すには単なる char を使用する
STR05-C.文字列リテラルの参照には const へのポインタを使用する
STR06-C.strtok() が分割対象文字列を変更しないと想定しない
STR07-C.TR 24731 を使用し、文字列操作を行う既存のコードの脅威を緩和する
STR08-C.新たに開発する文字列処理するコードには managed string を使用する
STR09-C.単なる文字型の式に対して数値を想定しない
STR10-C.型が異なる文字列リテラルを結合しない
ルール
STR30-C.文字列リテラルを変更しない
STR31-C.文字データと null 終端文字を格納するために十分な領域を確保する
STR32-C.文字列は null 終端させる
STR33-C.ワイド文字の文字列サイズは正しく求める
STR34-C.文字データをより大きなサイズの整数型に変換するときは事前に unsigned 型に変換する
STR35-C.長さに制限のないコピー元から固定長配列へデータをコピーしない
STR36-C.文字列リテラルで初期化される文字配列のサイズを指定しない
STR37-C.文字処理関数への引数は unsigned char として表現できなければならない
STR38-C.ナロー文字列に対するワイド文字関数の使用、およびその逆を避ける

Topへ

08メモリ管理 (MEM)
レコメンデーション
MEM00-C.メモリの割り当てと解放は、同じ翻訳単位内の同一抽象レベルで行う
MEM01-C.free() の直後に新しい値をポインタに代入する
MEM02-C.メモリ割り当て関数の結果は、割り当てた型へのポインタに即座にキャストする
MEM03-C.再利用可能なリソースに格納された機密情報は消去する
MEM04-C.サイズ 0 のメモリ割り当てを行わない
MEM05-C.大きなスタックを割り当てない
MEM06-C.機密情報はディスクに書き出さない
MEM07-C.calloc() の二つの引数を乗算した結果は size_t 型で表現できること
MEM08-C.realloc() は動的に割り当てられた配列のサイズ変更にしか使用してはならない
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-C.fopen() を使用したファイル作成時に何らかの仮定をしない
FIO04-C.入出力エラーを検出し、処理する
FIO05-C.複数のファイル属性を使用してファイルを特定する
FIO06-C.適切なパーミッションを持つファイルを作成する
FIO07-C.rewind() ではなく fseek() を使用する
FIO08-C.オープンしたままのファイルに対する remove() の呼び出しに注意する
FIO09-C.システム間でのバイナリデータ転送に注意する
FIO10-C.rename() 関数の使用に注意する
FIO11-C.fopen() のモード引数の指定は慎重に行う
FIO12-C.setbuf() ではなく setvbuf() を使用する
FIO13-C.読み取った一文字以外は押し戻さない
FIO14-C.ファイルストリームにおけるテキストモードとバイナリモードの違いを理解する
FIO15-C.ファイル操作はセキュアなディレクトリで行われることを保証する
FIO16-C.ジェイル(監獄)を作成してファイルへのアクセスを制限する
FIO17-C.fread() を使用するときは、null 終端文字に依存しない
FIO18-C.fwrite() が書き込み操作を null 文字で終了すると想定しない
FIO19-C.ファイルサイズの計算に fseek() および ftell() を使用しない
ルール
FIO30-C.ユーザからの入力を使って書式指定文字列を組み立てない
FIO31-C.同一のファイルを同時に複数回開かない
FIO32-C.通常ファイルに固有の操作をデバイスファイルに対して行わない
FIO33-C.未定義の動作となる入出力のエラーを検出して処理する
FIO34-C.文字入出力関数の返り値の取得には int 型を使用する
FIO35-C.sizeof(int) == sizeof(char) の場合、EOF およびファイルエラーの検出には feof() と ferror() を使用する
FIO36-C.fgets() が改行文字を読み取ると仮定しない
FIO37-C.読み取られたデータが文字データであると思い込まない
FIO38-C.入出力操作に FIlE オブジェクトのコピーを使用しない
FIO39-C.fflush 関数やファイル位置付け関数を呼び出さずにストリームへの入出力を交互に行わない
FIO40-C.fgets() が失敗したときは引数に渡した配列の内容をリセットする
FIO41-C.副作用を持つストリーム引数を getc() または putc() に渡さない
FIO42-C.不要になったファイルは正しくクローズする
FIO43-C.共有ディレクトリに一時ファイルを作成しない
FIO44-C.fsetpos() には fgetpos() が返す値を使用する

Topへ

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

Topへ

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

Topへ

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

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.同期用プリミティブの取得と解放は、同じ翻訳単位内の同一抽象レベルで行う
ルール
CON31-C.他のスレッドのミューテックスをアンロックしたり破壊したりしない
CON32-C.複数スレッドによるビットフィールドへのアクセスは、ミューテックスで保護する
CON33-C.ライブラリ関数の使用時は競合状態を避ける
CON34-C.スレッド間で共有されるオブジェクトは適切な記憶域期間を持つように宣言する
CON35-C.あらかじめ定義した順番でロックしてデッドロックを防ぐ

Topへ

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

Topへ

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

Topへ

AA参考情報

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

ソースコード解析ツールを活用した CERT セキュアコーディングルールの有効性評価』(PDF: 853KB)

BBDefinitions

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

CC未定義の動作

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

DD未規定の動作

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

Topへ

XXお問い合わせ

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

Top へ