INT05-C. 可能性のあるすべての入力を処理できない入力関数を使って文字データを変換しない
文字を入力し整数に変換する関数が、想定されるすべての入力を処理できないなら、その関数を使用しないこと。たとえば、scanf(), fscanf(), vscanf(), vfscanf() などの書式付き入力関数を使って stdin や他の入力ストリーム(fscanf() や vfscanf() の場合)から文字列データを読みこむことができる。これらの関数は、有効な整数値に対しては問題なく動作するが、無効な値に対しては堅牢なエラー処理を行わない。
代わりに、strtol() や別の関数を使ってnull終端バイト文字列として文字データを入力し、整数値に変換すること。(「INT06-C. 文字列トークンを整数に変換するには strtol() 系の関数を使う」を参照。)
違反コード
以下のコード例では、scanf() 関数を使って stdin から文字列を読み long に変換している。結果の値が整数として表現できない場合 scanf() と fscanf() は未定義の動作となる。
long sl;
if (scanf("%ld", &sl) != 1) {
  /* エラー処理 */
}
一般に、入力文字列を整数や浮動小数点数として解釈するために fscanf() を使わないこと。入力には scanf の引数の型では表現できない数が含まれているかもしれない。
適合コード (Linux)
以下の適合コードでは、Linux で使われている scanf() 実装のエラー処理を使用して入力を検証している。Linux プラットフォームでは、整数変換の結果が書式指定文字列によって指定されたサイズに収まらない場合、scanf() は errno に ERANGE を設定する[Linux 2008]。この適合コードはプラットフォーム依存なので、可搬性が問題とならない場合にのみ使用するべきである。
long sl;
errno = 0;
if (scanf("%ld", &sl) != 1) {
  /* エラー処理 */
}
else if (ERANGE == errno) {
  if (puts("number out of range\n") == EOF) {
      /* エラー処理 */
  }
}
適合コード
以下の適合コードでは fgets() を使用して文字列を入力し、strtol() を使用して文字列を整数に変換している。エラーチェクを行い、値が long の範囲におさまる有効な整数であることを保証している。
char buff[25];
char *end_ptr;
long sl;
if (fgets(buff, sizeof(buff), stdin) == NULL) {
  if (puts("EOF or read error\n") == EOF) {
    /* エラー処理 */
  }
} else {
  errno = 0;
  sl = strtol(buff, &end_ptr, 10);
  if (ERANGE == errno) {
    if (puts("number out of range\n") == EOF) {
      /* エラー処理 */
    }
  }
  else if (end_ptr == buff) {
    if (puts("not valid numeric input\n") == EOF) {
      /* エラー処理 */
    }
  }
  else if ('\n' != *end_ptr && '\0' != *end_ptr) {
    if (puts("extra characters on input line\n") == EOF) {
      /* エラー処理 */
    }
  }
}
このコードでは、空白文字を含むすべての終端文字をエラー条件として扱っていることに注意。
リスク評価
このレコメンデーションに違反した結果セキュリティ上の脆弱性につながることは比較的まれではあるが、データの欠損や誤解釈には容易につながる。
| 
         レコメンデーション  | 
      
         深刻度  | 
      
         可能性  | 
      
         修正コスト  | 
      
         優先度  | 
      
         レベル  | 
    
|---|---|---|---|---|---|
| 
         INT05-C  | 
      
         中  | 
      
         中  | 
      
         高  | 
      
         P4  | 
      
         L3  | 
    
自動検出(最新の情報はこちら)
| 
         ツール  | 
      
         バージョン  | 
      
         チェッカー  | 
      
         説明  | 
    
|---|---|---|---|
| 
         
  | 
      
         
  | 
      
         このレコメンデーションの違反を検出できる。とくに型指定子が浮動小数点数や整数であるような場合の   | 
    |
| 
         5.0  | 
      
         
  | 
      
         CERT C Rule Packを使ってこのレコメンデーションの違反を検出できる  | 
    |
| PRQA QA-C | 8.1 | Warncall for scanf etc | 実装済み | 
関連するガイドライン
| CERT C++ Secure Coding Standard | INT05-CPP. Do not use input functions to convert character data if they cannot handle all possible inputs | 
| MITRE CWE | CWE-192, Integer coercion error CWE-197, Numeric truncation error  | 
    
参考資料
| [Klein 2002] | |
| [Linux 2008] | scanf(3) | 
    
翻訳元
これは以下のページを翻訳したものです。
INT05-C. Do not use input functions to convert character data if they cannot handle all possible inputs (revision 84)
