メインコンテンツ

ポインターのスケーリングが無効です

ポインター演算での暗黙的なスケーリングは無視される場合がある

説明

この欠陥は、Polyspace® Bug Finder™ によって、ポインター演算での暗黙的なスケーリングが無視されているとみなされた場合に発生します。

たとえば、欠陥は次のような状況で発生します。

状態リスク考えられる解決方法
ポインターでの算術演算で sizeof 演算子を使用する。

sizeof 演算子が、データ型のサイズをバイト数で返す。

ポインター演算は既に、指されている変数のデータ型のサイズによって暗黙的にスケーリングされている。そのため、ポインター演算で sizeof を使用すると想定外の結果が生成される。

ポインター演算で sizeof 演算子を使用しない。
ポインターに対し算術演算を実行してから、キャストを適用する。ポインター演算は暗黙的にスケーリングされている。この暗黙的なスケーリングを考慮せずにポインター演算の結果をキャストすると、想定外の結果が生成される。キャストをポインター演算の前に適用する。

修正方法

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

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

すべて展開する

void func(void) {
    int arr[5] = {1,2,3,4,5};
    int *ptr = arr;

    int value_in_position_2 = *(ptr + 2*(sizeof(int)));
}

この例では、演算 2*(sizeof(int)) で変数 int の 2 倍のサイズ (バイト単位) が返されます。ただし、ポインター演算は暗黙的にスケーリングされているため、ptr がオフセットされるバイト数は 2*(sizeof(int))*(sizeof(int)) となります。

この例では、不正確なスケーリングにより、ptr が配列の境界外にシフトされます。したがって、[範囲外にアクセスするポインター] エラーが * 演算に表示されます。

修正 — sizeof 演算子を削除

1 つの修正方法として、sizeof 演算子を削除します。

void func(void) {
    int arr[5] = {1,2,3,4,5};
    int *ptr = arr;

    int value_in_position_2 = *(ptr + 2);
}
int func(void) {
    int x = 0;
    char r = *(char *)(&x + 1);
    return r;
}

この例では、演算 &x + 1 により &xsizeof(int) の分オフセットされます。演算後、その結果であるポインターは、許容されているバッファーの外を指しています。ポインターをデリファレンスすると、[範囲外にアクセスするポインター] エラーが * 演算に表示されます。

修正 — キャストをポインター演算の前に適用

x の 2 番目のバイトにアクセスする場合は、まず &xchar* ポインターにキャストしてからポインター演算を実行します。その結果得られるポインターは、sizeof(char) バイト分オフセットされたうえで、サイズが sizeof(int) バイトの許容されているバッファー内を指しています。

int func(void) {
    int x = 0;
    char r = *((char *)(&x )+ 1);
    return r;
}

結果情報

グループ: プログラミング
言語: C | C++
既定値: 手書きコードはオン、生成コードはオフ
コマンド ライン構文: BAD_PTR_SCALING
影響度: Medium

バージョン履歴

R2015b で導入