CXX.MALLOC.SIZEOF

malloc でメモリを割り当てるときに sizeof() を常に呼び出します

バッファのコピーなどの操作を実行するときに、バッファのサイズを計算することは非常に重要です。配列や構造体のバッファサイズを計算するときに、配列や構造体の要素の数を考慮するだけでバッファサイズを計算すると、基本データ型のサイズが考慮されずに、正しくないサイズ計算になってしまいます。また、データ型のサイズが構造体で考慮されていても、配置やパディングなどの問題により、コンパイラは異なる結果を出す場合があります。たとえば、"struct {char test[3]; short test2[2];}" のような構造体のサイズについては、char は 1 バイト、short は 2 バイトであるため、(1 バイト * 3) + (2 バイト * 2) = 7 バイトの計算結果になる可能性がありますが、32 ビット VS2013 ではパディングを含めて合計 8 バイトが割り当てられます。

軽減と防止

この間違いを避けるには、デベロッパーがサイズ計算を直接行うのではなく、sizeof() 関数 (sizeof (構造体) や sizeof (配列) など) を使用して、サイズを正しく計算します。ここで、データ型のサイズを計算するときに、ポインターで sizeof() を実行しないように注意する必要があります。基本データ型 (char、short、int など) のサイズは、それらのサイズによって決まります。一方、ポインター (char *、short *、int * など) は、すべて 1 ワードのサイズです。ポインターのサイズは、プラットフォームによってのみ異なりますが、同じプラットフォーム (32 ビットマシン: 4 バイト、16 ビットマシン: 2 バイト) では同じです。つまり、ポインターによってポイントされるデータ型のサイズへのポインターのサイズを計算すると、大きなエラーが発生します。このため、ポインター型では、sizeof() 操作を実行しないように注意してください。このように、バッファサイズの計算が不正確であると、バッファオーバーフローなどの脆弱性がいくつか生じる可能性があります。

脆弱コード例

コピー
void mc_int_009(){
    int *pi_bad = malloc(2);
    int *pi_good = malloc(2*sizeof(int));
    int *pi_good2 = malloc(sizeof(int));
}

上記のコード例では、サイズ計算に sizeof() が使用されていないため、pi_bad の割り当てにエラーが報告されます。