ISO/IEC TS 17961 [addrescape]
Escaping of the address of an automatic object
説明
ルール定義
自動オブジェクトのアドレスのエスケープ。1
Polyspace 実装
このチェッカーは以下の問題をチェックします。
スタック変数へのポインターまたは参照が範囲外。
putenv ファミリ関数の引数としての自動変数の使用。
例
スタック変数へのポインターまたは参照が範囲外は、ローカル変数へのポインターまたは参照が変数のスコープを逸脱している場合に発生します。次に例を示します。
関数が、ローカル変数を指すポインターを返す。
関数が代入
globPtr = &locVarを実行する。globPtrはグローバル ポインター変数、locVarはローカル変数です。関数が代入
*paramPtr = &locVarを実行する。paramPtrは関数パラメーター (つまりint**ポインターなど)、locVarはローカルのint変数です。C++ メソッドが代入
memPtr = &locVarを実行する。memPtrはメソッドが属するクラスのポインター データ メンバー、locVarはメソッドから見てローカルな変数です。
欠陥は、関数 alloca を使用して割り当てたメモリにも適用されます。この欠陥は静的なローカル変数には適用されません。Polyspace® は、関数定義に含まれるローカル オブジェクトは同じスコープ内にあると仮定します。
ローカル変数にはスタック上のアドレスが割り当てられます。ローカル変数のスコープがいったん終了すると、このアドレスは再利用可能になります。このアドレスを使用して変数のスコープ外にあるローカル変数値にアクセスすると、予期しない動作を引き起こす可能性があります。
ローカル変数を指すポインターが変数のスコープを逸脱していると、Polyspace Bug Finder™ によってその欠陥が強調表示されます。この欠陥は、ポインターに格納されているアドレスが使用されていない場合でも発生します。コードを保守可能なものにするため、ポインターが変数のスコープを逸脱しないようにすることをお勧めします。ポインター内のアドレスが現在使用されていない場合でも、関数の他の使用者がそのアドレスを使用することで動作が未定義となる可能性があります。
ローカル変数へのポインターまたは参照が変数スコープを逸脱しないようにします。
void func2(int *ptr) {
*ptr = 0;
}
int* func1(void) {
int ret = 0;
return &ret ;
}
void main(void) {
int* ptr = func1() ;
func2(ptr) ;
}この例では、func1 はローカル変数 ret を指すポインターを返します。
main では、ptr はローカル変数のアドレスを指します。ret のスコープは func1 に制限されているため、func2 内で ptr がアクセスされると、そのアクセスは無効になります。
putenv ファミリ関数の引数としての自動変数の使用は、putenv ファミリ関数の引数が自動の存続期間をもつローカル変数である場合に発生します。
関数 putenv(char *string) は、引数のコピーを作成するのではなく、指定された引数を指すポインターを環境配列に挿入します。引数が自動変数の場合、putenv() 呼び出しを含む関数から値が返された後、メモリが上書きされる可能性があります。その後、別の関数が getenv() を呼び出した場合、適切にデリファレンスできないスコープ外の変数のアドレスが返されます。このスコープ外の変数は、環境変数が予期しない値を取る、プログラムが応答を停止する、任意のコード実行を可能にする脆弱性を生むなどの原因になる可能性があります。
環境変数の設定/設定解除に setenv()/unsetenv() を使用します。または、putenv ファミリ関数の引数と動的に割り当てられたメモリを使用するか、アプリケーションに再入要件がない場合は引数と静的存続期間を使用します。たとえば、再帰や割り込みのないシングルスレッド実行には再入は必要ありません。実行中の呼び出し (再入) はできません。
putenv() の引数としての自動変数#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE1024 1024
void func(int var)
{
char env[SIZE1024];
int retval = sprintf(env, "TEST=%s", var ? "1" : "0");
if (retval <= 0) {
/* Handle error */
}
/* Environment variable TEST is set using putenv().
The argument passed to putenv is an automatic variable. */
retval = putenv(env);
if (retval != 0) {
/* Handle error */
}
}
この例では、sprintf() は文字列 TEST=var を env に格納します。その後、環境変数 TEST の値が putenv() を使用して var に設定されます。env は自動変数であるので、TEST の値は func() が値を返すときに変化する可能性があります。
putenv() の引数に static 変数を使用env を静的存続期間の変数として宣言します。env のメモリ位置は、func() が値を返した後でも、プログラムの存続期間中は上書きされません。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE1024 1024
void func(int var)
{
/* static duration variable */
static char env[SIZE1024];
int retval = sprintf(env,"TEST=%s", var ? "1" : "0");
if (retval <= 0) {
/* Handle error */
}
/* Environment variable TEST is set using putenv() */
retval=putenv(env);
if (retval != 0) {
/* Handle error */
}
}setenv() を使用して環境変数値を設定TEST の値を var に設定するために、setenv() を使用します。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE1024 1024
void func(int var)
{
/* Environment variable TEST is set using setenv() */
int retval = setenv("TEST", var ? "1" : "0", 1);
if (retval != 0) {
/* Handle error */
}
}チェック情報
| 決定可能性:決定不可能 |
バージョン履歴
R2019a で導入ルール チェッカーは、関数定義に含まれるローカル オブジェクトはすべて同じスコープ内にあると仮定します。次のコードについて考えます。
void foo(){
int* p;
{
int tmp = 4;
p = &tmp;
}
int q = *p;//Compliant
}tmp、p、q はすべて同じスコープ内にあると仮定します。1 Extracts from the standard "ISO/IEC TS 17961 Technical Specification - 2013-11-15" are reproduced with the agreement of AFNOR. Only the original and complete text of the standard, as published by AFNOR Editions - accessible via the website www.boutique.afnor.org - has normative value.
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)