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
。