SV.FMT_STR.SCAN_FORMAT_MISMATCH.BAD

指定とパラメーターの不一致

スキャン関数のパラメーターは、さまざまな型の項目のポインターとして指定される場合があるため、それらの項目が占有するメモリ量には違いがあります。スキャン関数パラメーターが、対応する書式文字列仕様を下回るサイズのメモリ項目を指定している場合、脆弱性の問題が発生する場合があります。SV.FMT_STR.SCAN_FORMAT_MISMATCH.BAD チェッカーは、スキャンパラメーターが指定するメモリ項目の型サイズと対応する書式文字列仕様が一致しないコードにフラグを立てます。

脆弱性とリスク

パラメーターと書式文字列指定が一致しないと、メモリアクセス違反となり、プログラムを実行した際に望ましくない結果になりかねません。未定義の動作やプログラムの異常終了が発生する可能性があります。

脆弱コード例

コピー
   # include <string>
   # include <stdio.h>

   std::string scan_int() {
     int length;
     std::string str;
     scanf("%lf", &length); // defect
     scanf("%s\n", str);    // defect
   }

Klocwork は 7 行目で、%lf 仕様が int 型のパラメーターと一致しないため、フラグを立てます。double 型 (%lf 仕様で期待されている型) に通常必要なメモリ量は、int 型 (パラメーターについて実際に指定されている型) に必要なメモリ量よりも常に大きくなります。実際には int 型に必要なメモリが割り当てられているのに、double 型に必要なメモリにアクセスしようとすると、メモリアクセス違反が発生する可能性があります。

Line 8 行目には、C 文字列が期待されているのに、実際には %s 仕様のオブジェクトが指定されているため、フラグが立てられます。このオブジェクトが占有しているメモリへのバイト作成が試みられた場合、メモリアクセス違反が発生する可能性があります。

修正コード例

コピー
   # include <string>
   # include <stdio.h>

   std::string scan_int() {
     int length;
     char *str;
     scanf("%d", &length); 
     str = (char *)malloc(length + 1);
     scanf("%s\n", str);   
  }

修正されたコードの 7 行目では、整数値を表示するために正しい書式指定子 %f が使用されています。9 行目では、std::string の代わりに、暫定的に割り当てられた C 文字列が使用されています。