1
scanf_s("%s", a, 10);

このコードは、プログラムをバッファ オーバーフローの悪用から保護します。

しかし、 scanf_s がなければ、次のように書くことができます。

scanf("%9s", a);

このコードは、バッファ オーバーフローもブロックすると思います。これは本当ですか?

では、基本的に2つの方法の違いは何ですか?

また、scanf の幅指定がバッファ オーバーフローをブロックしている場合、元の scanf を「安全ではない」と呼ぶのはなぜですか?

4

1 に答える 1

3

scanf_s()C99 標準 (または以前のもの) では記述されていません。

C99 (またはそれ以前) を対象とするコンパイラを使用する場合は、scanf() を使用します。forC11 Standardは、scanf_s()に対するセキュリティを向上させるため、scanf() よりも使用がはるかに困難buffer overflowsです。

では、基本的に2つの方法の違いは何ですか?

scanf_s()scanf() のより安全なバージョンです。宛先を指定する引数の後に、宛先のサイズを指定する必要があります。プログラムは、バッファをコピーする前に指定されたサイズであることを確認して、上書きや悪意のあるコードが実行されていないことを確認します。の場合、引数を渡す必要がありscanf_s()ます。

また、scanf の幅指定がバッファ オーバーフローをブロックしている場合、元の scanf を「安全ではない」と呼ぶのはなぜですか?

関数で使用できる書式指定子は、scanf明示的なフィールド幅設定をサポートしています。これにより、入力の最大サイズが制限され、バッファ オーバーフローが防止されます。しかしscanf()、フィールド幅を指定する必要があるため、機能を使用するのは困難ですembedded into format string( で実行できるように、可変引数を介して渡す方法はありませんprintf)。scanf は、その点で設計がかなり不十分です。それにもかかわらず、文字列バッファ オーバーフローの安全性に関して scanf がなんらかの方法で壊れているという主張は完全に偽物であり、通常は怠惰なプログラマによって作成されます。

の本当の問題scanf()は、オーバーフローに関するものではありますが、まったく異なる性質を持っています。数値の 10 進数表現を算術型の値に変換するために scanf 関数を使用する場合、算術オーバーフローに対する保護は提供されません。オーバーフローが発生した場合、scanf は未定義の動作を生成します。このため、C 標準ライブラリで変換を実行する唯一の適切な方法は、strtoファミリの関数です。

以上をまとめると、問題scanfは文字列バッファを適切かつ安全に使用するのが難しいことです。また、算術入力に安全に使用することはできません。後者は本当の問題です。前者はただの不便です。

scanf_s文字配列の場合のバッファ オーバーフローの問題は、フィールド幅を可変引数に渡すことで解決されますprintf(scanf()フィールド幅は である必要がありますembedded into format string)。また、フィールド幅は では必須ですscanf_sが、 ではオプションですscanf

于 2016-11-04T11:26:24.393 に答える