SV.FMT_STR.PRINT_FORMAT_MISMATCH.BAD

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

表示関数のパラメーターにより、機械語の整数から成るスタックメモリのブロックがいっぱいになる可能性があります。関数パラメーターを表示することにより、対応する書式文字列指定から期待していたものとは異なるスタックメモリの容量がいっぱいになると、脆弱性の問題が発生する場合があります。SV.FMT_STR.PRINT_FORMAT_MISMATCH.BAD チェッカーは、表示するパラメーターと対応する書式文字列指定のメモリブロックのサイズが一致しない場合、コードにフラグを立てます。

脆弱性とリスク

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

脆弱コード例

コピー
   # include <string>
   # include <stdio.h>
   void print_string(double weight, std::string str) {
     printf("String of weight %d:", weight);   // defect
     printf(" %s\n", str);                     // defect
   }

Klocwork は 4 行目で、パーセント指定が型 double のパラメーターと一致しないため、フラグを立てます。必要なメモリ容量は、型 int (パーセント指定では当然) と型 double (実際には提供されます) とで異なります。多くの 32 ビットシステムでは、型 int は 1 ワードの機械語が必要ですが、型 double は 2 ワードの機械語が必要です。パラメーターが実際に占有する 2 ワードではなく 1 ワードの機械語がスタックから読み取られると、メモリアクセスの違反が発生する可能性があります。

5 行目には、std::string::c_str() メソッドへの呼び出しがないため、フラグを立てます。null 終了した文字列はパーセント指定が期待されますが、代わりにオブジェクトは実際に提供されます。null 文字が見つかるまでオブジェクトおよび任意の連続したバイトが占有するメモリバイトの読み取りが試みられた場合は、メモリアクセス違反が発生しかねません。

修正コード例

コピー
   # include <string>
   # include <stdio.h>
   void print_string(double weight, std::string str) {
     printf("String of weight %f:", weight);   
     printf(" %s\n", str.c_str());            
   }

修正されたコードの 4 行目では、浮動小数点値を表示するために正しい書式指定子 %f が使用されています。5 行目には、std::string::c_str() メソッドへの呼び出しが追加されています (誤って抜けている場合がしばしばあります)。