CWE Rule 839
説明
ルールの説明
The program checks a value to ensure that it is less than or equal to a maximum, but it does not also verify that the value is greater than or equal to the minimum.
Polyspace 実装
ルール チェッカーは以下の問題をチェックします。
汚染されたオフセットによるポインターのデリファレンス
汚染された符号変化の変換
例
この問題は、ポインターのデリファレンスで、不明なソースまたはセキュリティで保護されていないソースからのオフセット変数が使用された場合に発生します。
このチェックでは、動的に割り当てられたバッファーに注目します。静的バッファーのオフセットについては、汚染されたインデックスによる配列へのアクセス
を参照してください。
インデックスは有効な配列範囲を外れている可能性があります。汚染されたインデックスが配列範囲を外れていると、以下の原因となることがあります。
バッファー アンダーフローまたはアンダーライト、すなわち、バッファーの先頭より前でのメモリへの書き込み。
バッファー オーバーフロー、すなわち、バッファーの末尾より後でのメモリへの書き込み。
バッファー オーバーリード、すなわち、対象バッファーの末尾より後でのメモリへのアクセス。
バッファーのアンダーリード、すなわち、対象バッファーの先頭より前のメモリへのアクセス。
攻撃者は、無効な読み取りや書き込みを使用してプログラムを侵害できます。
変数を使用してポインターにアクセスする前に、インデックスを検証します。変数が有効範囲内にありオーバーフローしないことを確認します。
既定では、Polyspace® は外部ソースからのデータは汚染されていると仮定します。Polyspace 解析での汚染のソースを参照してください。Polyspace 解析の現在のスコープ以外から発生したすべてのデータを汚染されたものと見なすには、コマンド ライン オプション [-consider-analysis-perimeter-as-trust-boundary]
を使用します。
#include <stdio.h>
#include <stdlib.h>
enum {
SIZE10 = 10,
SIZE100 = 100,
SIZE128 = 128
};
extern void read_pint(int*);
int taintedptroffset(void) {
int offset;
scanf("%d",&offset);
int* pint = (int*)calloc(SIZE10, sizeof(int));
int c = 0;
if(pint) {
/* Filling array */
read_pint(pint);
c = pint[offset];//Noncompliant
free(pint);
}
return c;
}
この例では、関数が整数ポインター pint
を初期化しています。ポインターは、入力インデックス offset
を使用してデリファレンスされています。offset
の値はポインター範囲外である可能性があり、値域外エラーの原因となります。
1 つの修正方法として、offset
の値を検証します。offset
が有効範囲内にある場合のみ、ポインターのデリファレンスを続行します。
#include <stdlib.h>
#include <stdio.h>
enum {
SIZE10 = 10,
SIZE100 = 100,
SIZE128 = 128
};
extern void read_pint(int*);
int taintedptroffset(void) {
int offset;
scanf("%d",&offset);
int* pint = (int*)calloc(SIZE10, sizeof(int));
int c = 0;
if (pint) {
/* Filling array */
read_pint(pint);
if (offset>0 && offset<SIZE10) {
c = pint[offset];
}
free(pint);
}
return c;
}
この問題は、セキュリティで保護されていないソースからの値が、符号付きの値から符号なしの値に暗黙的または明示的に変換された場合に発生します。
たとえば、size_t
を引数として使用する関数では、引数が暗黙的に符号なし整数に変換されます。size_t
を暗黙的に変換する関数のいくつかを、以下に挙げます。
bcmp
memcpy
memmove
strncmp
strncpy
calloc
malloc
memalign
小さい負の数値を符号なしに変換すると、その結果は大きい正の数値となります。大きい正の数値により、セキュリティが脆弱になる可能性があります。たとえば、符号なしの値を以下で使用した場合がこれに該当します。
メモリ サイズ ルーチン — メモリ割り当ての問題の原因となります。
文字列操作ルーチン — バッファー オーバーフローの原因となります。
ループ境界 — 無限ループの原因となります。
符号なしの負の値の変換を避けるため、変換対象の値が許容範囲内にあることを確認します。たとえば、値がサイズを表す場合は、その値が負ではなく値の最大サイズより小さいことを検証します。
既定では、Polyspace は外部ソースからのデータは汚染されていると仮定します。Polyspace 解析での汚染のソースを参照してください。Polyspace 解析の現在のスコープ以外から発生したすべてのデータを汚染されたものと見なすには、コマンド ライン オプション [-consider-analysis-perimeter-as-trust-boundary]
を使用します。
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
enum {
SIZE10 = 10,
SIZE100 = 100,
SIZE128 = 128
};
void bug_taintedsignchange(void) {
int size;
scanf("%d",&size);
char str[SIZE128] = "";
if (size<SIZE128) {
memset(str, 'c', size); //Noncompliant
}
}
この例では、バッファー char
が作成され、memset
を使用して埋められます。memset
のサイズ引数は、関数の入力引数です。
memset
を呼び出すことにより、size
が符号なし整数へと暗黙的に変換されます。size
が大きい負の数値である場合、その絶対値は整数で表現するには大きすぎる可能性があり、バッファー オーバーフローの原因となります。
size
の値をチェック1 つの修正方法として、size
が有効範囲内にあるかどうかをチェックします。この修正では、size
がゼロより大きくバッファー サイズより小さいかどうかを、memset
を呼び出す前にチェックします。
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
enum {
SIZE10 = 10,
SIZE100 = 100,
SIZE128 = 128
};
void corrected_taintedsignchange(void) {
int size;
scanf("%d",&size);
char str[SIZE128] = "";
if (size>0 && size<SIZE128) {
memset(str, 'c', size);
}
}
チェック情報
カテゴリ: Numeric Errors |
バージョン履歴
R2023a で導入
MATLAB Command
You clicked a link that corresponds to this MATLAB command:
Run the command by entering it in the MATLAB Command Window. Web browsers do not support MATLAB commands.
Web サイトの選択
Web サイトを選択すると、翻訳されたコンテンツにアクセスし、地域のイベントやサービスを確認できます。現在の位置情報に基づき、次のサイトの選択を推奨します:
また、以下のリストから Web サイトを選択することもできます。
最適なサイトパフォーマンスの取得方法
中国のサイト (中国語または英語) を選択することで、最適なサイトパフォーマンスが得られます。その他の国の MathWorks のサイトは、お客様の地域からのアクセスが最適化されていません。
南北アメリカ
- América Latina (Español)
- Canada (English)
- United States (English)
ヨーロッパ
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)