メインコンテンツ

意図されない値をもつ memset ファミリへの呼び出しです

memset または wmemset が、不正確とみられる引数とともに使用されている

説明

この欠陥は、Polyspace® Bug Finder™ が、間違っている可能性がある引数が指定された関数 memset または wmemset の使用を検出した場合に発生します。

void *memset (void *ptr, int value, size_t num) は、ptr が指すメモリ ブロックの最初の num バイトを指定の value で埋めます。引数 value が不正確である場合、メモリ ブロックは意図されていない値で初期化されます。

意図されていない初期化は、次のような場合に発生することがあります。

問題リスク考えられる解決方法
2 番目の引数が '0' であり、0'\0' ではない。文字 '0' の ASCII 値は 48 (10 進数)、0x30 (16 進数)、069 (8 進数) であり、0 (あるいは '\0') ではない。'0' で初期化する場合は、ASCII 値のいずれかを使用する。それ以外の場合は 0 または '\0' を使用する。
2 番目の引数と 3 番目の引数がおそらく逆になっている。たとえば、3 番目の引数はリテラルであり、2 番目の引数はリテラルではない。順序が逆になっていると、意図されていないサイズのメモリ ブロックが不適切な引数で初期化される。引数の順序を入れ替える。
2 番目の引数が 1 バイトで表現できない。2 番目の引数が 1 バイトで表現できず、またのメモリ ブロックの各バイトがその引数で埋められると想定されている場合、初期化は想定どおりにはなされない。

引数にビット マスクを適用してラップまたは切り捨てを行い、1 バイトで表現できるような結果を生成する。ビット マスクを適用する際は、想定どおりの結果が生成されることを確認する。

たとえば、memset(a, -13, sizeof(a))memset(a, (-13) & 0xFF, sizeof(a)) で置き換える。

修正方法

修正方法は欠陥の根本原因によって異なります。上の表に記載されている修正と以下の修正付きのコード例を参照してください。

問題を修正しない場合は、改めてレビューされないように結果またはコードにコメントを追加します。詳細は、以下を参照してください。

すべて展開する

#include <string.h>

#define SIZE 32
void func(void) {
    char buf[SIZE];
    int c = -2;
    memset(buf, (char)c, sizeof(buf));
}

この例では、(char)c は 1 バイトで表現できません。

修正 — キャストを適用

1 つの修正方法として、キャストを適用して結果が 1 バイトで表現できるようにします。キャストの結果が許容可能な初期化値となることを確認してください。この修正では、Polyspace はこの欠陥を報告しません。符号付き int から unsigned char へのキャストはベスト プラクティスに反しているため、Polyspace は欠陥 [符号変化する整数の変換のオーバーフロー] を報告します。

#include <string.h>

#define SIZE 32
void func(void) {
    char buf[SIZE   ];
    int c = -2;
    memset(buf, (unsigned char)c, sizeof(buf));// Might Overflow 
}
修正 — memset の使用を避ける

1 つの修正方法として、バッファー内のすべてのビットをセットまたはクリアするためにのみ memset の使用を予約します。たとえば、このコードでは、文字配列 buf のビットをクリアするために memset が呼び出されます。

#include <string.h>

#define SIZE 32
void func(void) {
    char buf[SIZE   ];
    int c = -2;
    memset(buf, 0, sizeof(buf));//Compliant 
	/* After clearing buf, use it in operations*/
}

結果情報

グループ: プログラミング
言語: C | C++
既定値: オフ
コマンド ライン構文: MEMSET_INVALID_VALUE
影響度: Low

バージョン履歴

R2015b で導入