CWE Rule 121
説明
ルールの説明
A stack-based buffer overflow condition is a condition where the buffer being overwritten is allocated on the stack (i.e., is a local variable or, rarely, a parameter to a function).
Polyspace 実装
ルール チェッカーは以下の問題をチェックします。
汚染されたインデックスによる配列へのアクセス
文字列操作で格納先バッファーがオーバーフローしています
標準ライブラリ メモリ ルーチンの無効な使用
標準ライブラリ文字列ルーチンの無効な使用
例
この問題は、セキュリティで保護されていないソースから取得され、検証されていないインデックスを使用して配列にアクセスした場合に発生します。
インデックスは有効な配列範囲を外れている可能性があります。汚染されたインデックスが配列範囲を外れていると、以下の原因となることがあります。
バッファー アンダーフローまたはアンダーライト — バッファーの先頭より前のメモリへの書き込み。
バッファー オーバーフロー — バッファーの末尾より後のメモリへの書き込み。
バッファーのオーバーリード — 対象バッファーの末尾より後のメモリへのアクセス。
バッファーのアンダーリード、すなわち、対象バッファーの先頭より前のメモリへのアクセス。
攻撃者は無効な読み取りや書き込みの操作を利用して、プログラムに問題を生じさせることができます。
インデックスを使用して配列にアクセスする前に、インデックス値を検証して、それが配列範囲内にあることを確認します。
既定では、Polyspace® は外部ソースからのデータは汚染されていると仮定します。Polyspace 解析での汚染のソースを参照してください。Polyspace 解析の現在のスコープ以外から発生したすべてのデータを汚染されたものと見なすには、コマンド ライン オプション [-consider-analysis-perimeter-as-trust-boundary] を使用します。
#include <stdlib.h>
#include <stdio.h>
#define SIZE100 100
extern int tab[SIZE100];
static int tainted_int_source(void) {
return strtol(getenv("INDEX"),NULL,10);
}
int taintedarrayindex(void) {
int num = tainted_int_source();
return tab[num];//Noncompliant
}この例では、インデックス num により配列 tab にアクセスします。インデックス num は保護されないソースから取得され、関数 taintedarrayindex は num が tab の範囲内にあるかどうかをチェックしません。
1 つの修正方法として、num が範囲内にあることを使用前にチェックします。
#include <stdlib.h>
#include <stdio.h>
#define SIZE100 100
extern int tab[SIZE100];
static int tainted_int_source(void) {
return strtol(getenv("INDEX"),NULL,10);
}
int taintedarrayindex(void) {
int num = tainted_int_source();
if (num >= 0 && num < SIZE100) {
return tab[num];
} else {
return -1;
}
}
この問題は、特定の文字列操作関数によって、その格納先バッファー引数にバッファー サイズを超えるオフセットで書き込まれた場合に発生します。
たとえば、関数 sprintf(char* buffer, const char* format) を呼び出す際に、buffer より大きいサイズの定数文字列 format を使用する場合などです。
バッファー オーバーフローにより、メモリ破損やシステム停止といった予期しない動作を引き起こす可能性があります。また、バッファー オーバーフローは、コード インジェクションのリスクにもつながります。
1 つの解決策として、代替となる関数を使用して、書き込まれる文字の数を制限します。次に例を示します。
書式設定されたデータを文字列に書き込むのに
sprintfを使用している場合は、代わりにsnprintf、_snprintfまたはsprintf_sを使用して長さを制御します。あるいは、asprintfを使用して、格納先バッファーに必要なメモリを自動で割り当てます。書式設定されたデータを可変引数リストから文字列に書き込むのに
vsprintfを使用している場合は、代わりにvsnprintfまたはvsprintf_sを使用して長さを制御します。ワイド文字列をコピーするのに
wcscpyを使用している場合は、代わりにwcsncpy、wcslcpyまたはwcscpy_sを使用して長さを制御します。
別の解決策として、バッファー サイズを増やします。
#include <stdio.h>
void func(void) {
char buffer[20];
char *fmt_string = "This is a very long string, it does not fit in the buffer";
sprintf(buffer, fmt_string); //Noncompliant
}この例では、buffer は char 要素を 20 個格納できますが、fmt_string はより大きいサイズとなっています。
snprintf を sprintf の代わりに使用1 つの修正方法として、関数 snprintf を使用して長さを制御します。
#include <stdio.h>
void func(void) {
char buffer[20];
char *fmt_string = "This is a very long string, it does not fit in the buffer";
snprintf(buffer, 20, fmt_string);
}この問題は、メモリ ライブラリ関数が無効な引数で呼び出された場合に発生します。たとえば、関数 memcpy でコピー先の配列に格納できないバイト数をコピーする場合が該当します。
無効な引数でメモリ ライブラリ関数を使用すると、バッファー オーバーフローなどの問題が発生する可能性があります。
修正方法は欠陥の根本原因によって異なります。多くの場合、結果の詳細 (または Polyspace as You Code のソース コード ツールヒント) には欠陥につながる一連のイベントが表示されます。そのシーケンス内のどのイベントについても修正を実装できます。結果の詳細にイベント履歴が表示されない場合は、ソース コード内で右クリック オプションを使用して、欠陥に関連する変数のこれまでの参照を検索し、関連するイベントを検出できます。Polyspace デスクトップ ユーザー インターフェイスでの Bug Finder の結果の解釈またはPolyspace Access Web インターフェイスでの Bug Finder の結果の解釈 (Polyspace Access)も参照してください。
以下の修正例を参照してください。
問題を修正しない場合は、改めてレビューされないように結果またはコードにコメントを追加します。詳細は、以下を参照してください。
Polyspace ユーザー インターフェイスでのバグ修正または正当化による結果への対処 (Polyspace ユーザー インターフェイスで結果をレビューする場合)。
Polyspace Access でのバグ修正または正当化による結果への対処 (Polyspace Access) (Web ブラウザーで結果をレビューする場合)。
コードへの注釈付けと既知の結果または許容可能な結果の非表示 (IDE で結果をレビューする場合)
#include <string.h>
#include <stdio.h>
char* Copy_First_Six_Letters(void)
{
char str1[10],str2[5];
printf("Enter string:\n");
scanf("%s",str1);
memcpy(str2,str1,6); //Noncompliant
/* Defect: Arguments of memcpy invalid: str2 has size < 6 */
return str2;
}文字列 str2 のサイズは 5 ですが、関数 memcpy を使用して 6 文字の文字列 str1 が str2 にコピーされています。
1 つの修正方法として、関数 memcpy でコピーされる文字が収まるように、str2 のサイズを調整するとします。
#include <string.h>
#include <stdio.h>
char* Copy_First_Six_Letters(void)
{
/* Fix: Declare str2 with size 6 */
char str1[10],str2[6];
printf("Enter string:\n");
scanf("%s",str1);
memcpy(str2,str1,6);
return str2;
}この問題は、文字列ライブラリ関数が無効な引数で呼び出された場合に発生します。
リスクは無効な引数のタイプによって異なります。たとえば、コピー先引数より大きいコピー元引数を指定して関数 strcpy を使用すると、バッファー オーバーフローが発生する可能性があります。
修正方法は欠陥に関連する標準ライブラリ関数に依存します。場合によっては、関数呼び出しの前に関数の引数を制約することができます。たとえば、次の関数 strcpy を考えます。
char * strcpy(char * destination, const char* source)strcpy を呼び出す前にコピー元引数を制約します。場合によっては、代替となる関数を使用してエラーを回避できます。たとえば、strcpy の代わりに strncpy を使用するとコピーされるバイト数を制御できます。以下の修正例を参照してください。
問題を修正しない場合は、改めてレビューされないように結果またはコードにコメントを追加します。詳細は、以下を参照してください。
Polyspace ユーザー インターフェイスでのバグ修正または正当化による結果への対処 (Polyspace ユーザー インターフェイスで結果をレビューする場合)。
Polyspace Access でのバグ修正または正当化による結果への対処 (Polyspace Access) (Web ブラウザーで結果をレビューする場合)。
コードへの注釈付けと既知の結果または許容可能な結果の非表示 (IDE で結果をレビューする場合)
#include <string.h>
#include <stdio.h>
char* Copy_String(void)
{
char *res;
char gbuffer[5],text[20]="ABCDEFGHIJKL";
res=strcpy(gbuffer,text); //Noncompliant
/* Error: Size of text is less than gbuffer */
return(res);
}
文字列 text はサイズが gbuffer より大きくなっています。したがって、関数 strcpy は text を gbuffer にコピーできません。
1 つの修正方法として、コピー先の文字列 gbuffer をソース文字列 text 以上のサイズで宣言するとします。
#include <string.h>
#include <stdio.h>
char* Copy_String(void)
{
char *res;
/*Fix: gbuffer has equal or larger size than text */
char gbuffer[20],text[20]="ABCDEFGHIJKL";
res=strcpy(gbuffer,text);
return(res);
}
チェック情報
| カテゴリ: その他 |
バージョン履歴
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)