CWE Rule 474
説明
ルールの説明
The code uses a function that has inconsistent implementations across operating systems and versions.
Polyspace 実装
ルール チェッカーは以下の問題をチェックします。
信号ハンドラー内からの信号呼び出し
旧式の標準関数が使用されています
例
この問題は、Windows® プラットフォームで信号ハンドラーから関数 signal() を呼び出す場合に発生します。
この欠陥は、Visual Studio コンパイラを指定した場合にのみ検出されます。コンパイラ (-compiler) を参照してください。
関数 signal() は、信号と信号ハンドラー関数を関連付けます。信号の受信後にこの関連付けが削除される Windows などのプラットフォーム上では、"信号ハンドラー内で" 再度関数 signal() を呼び出して、関連付けを再設定することができます。
ただし、信号ハンドラーを永続的にするこの試みによって、競合状態が引き起こされやすくなります。Windows プラットフォームでは、信号ハンドラーが実行を開始してから、関数 signal が再度呼び出されるまでの間に、アクティブになっているのは既定の信号処理 SIG_DFL です。この間に 2 つ目の信号が受信されると、ユーザーの期待に反して、カスタム信号ハンドラーではなく既定の信号ハンドラーが示されます。
Windows プラットフォームでは信号ハンドラーから signal() を呼び出さないようにします。
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
volatile sig_atomic_t e_flag = 0;
void sig_handler(int signum)
{
int s0 = signum;
e_flag = 1;
/* Call signal() to reestablish sig_handler
upon receiving SIG_ERR. */
if (signal(s0, sig_handler) == SIG_ERR) //Noncompliant
{
/* Handle error */
}
}
void func(void)
{
if (signal(SIGINT, sig_handler) == SIG_ERR)
{
/* Handle error */
}
/* more code */
}
この例では、sig_handler() の定義にハンドラーが SIG_ERR をキャッチした際の signal() の呼び出しが含まれています。Windows プラットフォームでは、信号ハンドラーは永続的ではありません。このコードは、競合状態を発生させる可能性があります。
この問題は、visual15.x などのコンパイラを解析用として指定した場合にのみ検出されます。
signal() を呼び出さないWindows 上で信号ハンドラーを永続的にする試みを避けます。コードで Windows プラットフォームで永続的な信号ハンドラーを使用する必要がある場合、徹底的なリスク解析をしてから永続的な信号ハンドラーを使用します。
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
volatile sig_atomic_t e_flag = 0;
void sig_handler(int signum)
{
int s0 = signum;
e_flag = 1;
/* No call to signal() */
}
int main(void)
{
if (signal(SIGINT, sig_handler) == SIG_ERR)
{
/* Handle error */
}
}
この問題は、C/C++ コーディング規約でレガシ、削除済み、非推奨、または旧式とされている標準関数ルーチンが使用された場合に発生します。
| 旧式の関数 | 規格 | リスク | 置換関数 |
|---|---|---|---|
asctime | POSIX.1-2008 で使用終了 | スレッドセーフでない。 | strftime または asctime_s |
asctime_r | POSIX.1-2008 で使用終了 | 安全でない関数 sprintf に基づく実装。 | strftime または asctime_s |
bcmp | 4.3BSD で使用終了 POSIX.1–2001 でレガシとマークされている。 | 最初の異なるバイトを見つけたら関数から戻るため、タイミング攻撃に対して脆弱になる。 | memcmp |
bcopy | 4.3BSD で使用終了 POSIX.1–2001 でレガシとマークされている。 | 最初の異なるバイトを見つけたら関数から戻るため、タイミング攻撃に対して脆弱になる。 | memcpy または memmove |
brk および sbrk | SUSv2 および POSIX.1-2001 でレガシとマークされている。 | malloc | |
bsd_signal | POSIX.1–2008 で削除済み | sigaction | |
bzero | POSIX.1–2001 でレガシとマークされている。POSIX.1–2008 で削除済み。 | memset | |
ctime | POSIX.1-2008 で使用終了 | スレッドセーフでない。 | strftime または asctime_s |
ctime_r | POSIX.1-2008 で使用終了 | 安全でない関数 sprintf に基づく実装。 | strftime または asctime_s |
cuserid | POSIX.1–2001 で削除済み。 | 再呼び出し可能でない。正確な機能が標準化されておらず、移植性の問題の原因となる。 | getpwuid |
ecvt および fcvt | POSIX.1–2001 でレガシとマークされている。POSIX.1–2008 で削除済み | 再呼び出し可能でない | snprintf |
ecvt_r および fcvt_r | POSIX.1–2001 でレガシとマークされている。POSIX.1–2008 で削除済み | snprintf | |
ftime | POSIX.1–2008 で削除済み | time, gettimeofday, clock_gettime | |
gamma, gammaf, gammal | 履歴が錯綜しているため、関数はどの規格でも指定されていない | 移植性の問題。 | tgamma, lgamma |
gcvt | POSIX.1–2001 でレガシとマークされている。POSIX.1–2008 で削除済み。 | snprintf | |
getcontext | POSIX.1–2008 で削除済み。 | 移植性の問題。 | POSIX スレッドを代わりに使用。 |
getdtablesize | BSD API 関数が POSIX.1-2001 に含まれていない | 移植性の問題。 | sysconf( _SC_OPEN_MAX ) |
gethostbyaddr | POSIX.1–2008 で削除済み | 再呼び出し可能でない | getaddrinfo |
gethostbyname | POSIX.1–2008 で削除済み | 再呼び出し可能でない | getnameinfo |
getpagesize | BSD API 関数が POSIX.1-2001 に含まれていない | 移植性の問題。 | sysconf( _SC_PAGESIZE ) |
getpass | POSIX.1–2001 で削除済み。 | 再呼び出し可能でない。 | getpwuid |
getw | POSIX.1-2001 に存在しない。 | fread | |
getwd | POSIX.1-2001 でレガシとマークされている。POSIX.1–2008 で削除済み。 | getcwd | |
index | POSIX.1–2001 でレガシとマークされている。POSIX.1–2008 で削除済み。 | strchr | |
makecontext | POSIX.1–2008 で削除済み。 | 移植性の問題。 | POSIX スレッドを代わりに使用。 |
memalign | SunOS 4.1.3 で登場。4.4 BSD または POSIX.1-2001 にはなし | posix_memalign | |
mktemp | POSIX.1–2008 で削除済み。 | 生成された名前が予測可能であり、競合状態の原因となることがある。 | mkstemp は競合リスクを除去 |
pthread_attr_getstackaddr および pthread_attr_setstackaddr | stackaddr 属性の仕様にあいまいさがあり、移植性の問題の原因となる | pthread_attr_getstack および pthread_attr_setstack | |
putw | POSIX.1-2001 に存在しない。 | 移植性の問題。 | fwrite |
qecvt および qfcvt | POSIX.1-2001 でレガシとマークされ、POSIX.1-2008 で削除済み | snprintf | |
qecvt_r および qfcvt_r | POSIX.1-2001 でレガシとマークされ、POSIX.1-2008 で削除済み | snprintf | |
rand_r | POSIX.1-2008 で旧式とマークされている | ||
re_comp | BSD API 関数 | 移植性の問題 | regcomp |
re_exes | BSD API 関数 | 移植性の問題 | regexec |
rindex | POSIX.1–2001 でレガシとマークされている。POSIX.1–2008 で削除済み。 | strrchr | |
scalb | POSIX.1–2008 で削除済み | scalbln、scalblnf または scalblnl | |
sigblock | 出典が不明な 4.3BSD シグナル API | sigprocmask | |
sigmask | 出典が不明な 4.3BSD シグナル API | sigprocmask | |
sigsetmask | 出典が不明な 4.3BSD シグナル API | sigprocmask | |
sigstack | インターフェイスが旧式であり、ほとんどのプラットフォームで実装されていない。 | 移植性の問題。 | sigaltstack |
sigvec | 出典が不明な 4.3BSD シグナル API | sigaction | |
swapcontext | POSIX.1–2008 で削除済み | 移植性の問題。 | POSIX スレッドを使用。 |
tmpnam および tmpnam_r | POSIX.1–2008 で旧式とマークされている。 | この関数は、呼び出されるたびに TMP_MAX 回目まで異なる文字列を生成。呼び出される回数が TMP_MAX 回を超えると、動作が処理系定義になる。 | mkstemp, tmpfile |
ttyslot | POSIX.1–2001 で削除済み。 | ||
ualarm | POSIX.1–2001 でレガシとマークされている。POSIX.1–2008 で削除済み。 | エラーの指定が不十分。 | setitimer または POSIX timer_create |
usleep | POSIX.1–2008 で削除済み。 | nanosleep | |
utime | SVr4、POSIX.1-2001。POSIX.1-2008 で旧式とマークされている。 | ||
valloc | 4.3BSD で旧式とマークされている。 SUSv2 でレガシとマークされている。 POSIX.1-2001 から削除済み | posix_memalign | |
vfork | POSIX.1-2008 から削除済み | 以前の規格で指定が不十分。 | fork |
wcswcs | この関数は最終的な ISO/IEC 9899:1990/Amendment 1:1995 (E) に含まれていなかった。 | wcsstr | |
WinExec | WinAPI ではこの関数を 16 ビット Windows 互換でのみ提供。 | CreateProcess | |
LoadModule | WinAPI ではこの関数を 16 ビット Windows 互換でのみ提供。 | CreateProcess |
修正方法は欠陥の根本原因によって異なります。上の表に記載されている修正と以下の修正付きのコード例を参照してください。
問題を修正しない場合は、改めてレビューされないように結果またはコードにコメントを追加します。詳細は、以下を参照してください。
Polyspace ユーザー インターフェイスでのバグ修正または正当化による結果への対処 (Polyspace ユーザー インターフェイスで結果をレビューする場合)。
Polyspace Access でのバグ修正または正当化による結果への対処 (Polyspace Access) (Web ブラウザーで結果をレビューする場合)。
コードへの注釈付けと既知の結果または許容可能な結果の非表示 (IDE で結果をレビューする場合)
#include <stdio.h>
#include <time.h>
void timecheck_bad(int argc, char *argv[])
{
time_t ticks;
ticks = time(NULL);
printf("%.24s\r\n", ctime(&ticks)); //Noncompliant
}この例では、関数 ctime が現在の時刻を書式設定して出力します。しかし、ctime はマルチスレッド プログラムで機能しないため、C99 以降で削除されています。
1 つの修正方法として、strftime を代わりに使用します。この関数は一定のバッファー サイズを使用するためです。
#include <stdio.h>
#include <string.h>
#include <time.h>
void timecheck_good(int argc, char *argv[])
{
char outBuff[1025];
time_t ticks;
struct tm * timeinfo;
memset(outBuff, 0, sizeof(outBuff));
ticks = time(NULL);
timeinfo = localtime(&ticks);
strftime(outBuff,sizeof(outBuff),"%I:%M%p.",timeinfo);
fprintf(stdout, outBuff);
}チェック情報
| カテゴリ: API / Function 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)