8

Cppcheckは、scanfに対して次の警告を表示します。

メッセージ:フィールド幅の制限がないscanfは、膨大な入力データでクラッシュする可能性があります。このエラーメッセージを修正するには、フィールド幅指定子を追加します。
    %s =>%20s
    %i =>%3i

クラッシュする可能性のあるサンプルプログラム:

#含む
int main()
{{
    int a;
    scanf( "%i"、&a);
    0を返します。
}

クラッシュさせるには:
perl -e'print "5" x2100000' | ./a.out

「巨大な入力データ」と入力してこのプログラムをクラッシュさせることはできません。このクラッシュを取得するには、正確に何を入力する必要がありますか?また、この警告の最後の行の意味もわかりません。

perl-e..。

4

3 に答える 3

6

最後の行は、サンプル プログラムでのクラッシュを示すために実行するコマンドの例です。基本的に、perl は 2.100.000 倍の "5" を出力し、これをプログラム "a.out" (コンパイルされたサンプル プログラムを意味します) の stdin に渡します。

まず第一にscanf()、実際のプログラムではなく、テストのみに使用する必要があります。これは、適切に処理できないいくつかの問題があるためです (たとえば、「%i」を要求してもユーザーは「12345abc」を入力します (「abc」は stdin に残り、ユーザーがそれらを変更する機会なしに、次の入力が入力される可能性があります)。

この問題に関して:scanf()整数値を読み取る必要があることはわかりますが、それがどれくらいの長さになるかはわかりません。ポインターは、16 ビット整数、32 ビット整数、または 64 ビット整数、またはさらに大きなもの (認識されていません) を指す可能性があります。可変数の引数 ( で定義) を持つ関数は、...渡された要素の正確なデータ型がわからないため、書式文字列に依存する必要があります (書式タグがオプションではない理由は、C# のように番号を付けるだけです。例"{0} {1} {2}")。また、特定の長さがないと、プラットフォームに依存する可能性のある長さを想定する必要があります(関数を使用するにはさらに保存できなくなります)。

一般に、これは有害である可能性があり、バッファ オーバーフロー攻撃の開始点であると考えてください。プログラムを保護して最適化したい場合は、まず代替品に置き換えることから始めてください。

于 2011-08-11T07:57:26.723 に答える
0

C プログラムに対して perl 式を実行しようとしたところ、Linux でクラッシュしました (セグメンテーション違反)。

于 2011-08-11T07:51:31.647 に答える
0

実際のアプリケーションで 'scanf' (または fscanf と sscanf) 関数を使用することは、通常はまったく推奨されません。なぜなら、それは安全ではなく、通常、誤った入力データが提供された場合にバッファ オーバーランの穴になるからです。C++ で一般的に使用される多くのライブラリ (QT、Microsoft Visual C++ のランタイム ライブラリなど) には、より安全に数値を入力する方法があります。おそらく、「純粋な」C 言語の安全な代替手段も見つけることができます。

于 2011-08-11T07:52:41.157 に答える