これら 2 つのオプションのどちらを使用する方が安全かを知りたいです。
#define MAXLEN 255
char buff[MAXLEN + 1]
sprintf(buff, "%.*s", MAXLEN, name)
snprintf(buff, MAXLEN, "%s", name)
私の理解では、どちらも同じです。提案してください。
これら 2 つのオプションのどちらを使用する方が安全かを知りたいです。
#define MAXLEN 255
char buff[MAXLEN + 1]
sprintf(buff, "%.*s", MAXLEN, name)
snprintf(buff, MAXLEN, "%s", name)
私の理解では、どちらも同じです。提案してください。
指定した 2 つの式は同等ではありませんsprintf
。書き込む最大バイト数を指定する引数はありません。宛先バッファ、フォーマット文字列、および一連の引数を受け取るだけです。したがって、バッファの空き容量よりも多くのバイトが書き込まれる可能性があり、その場合、任意のコードが書き込まれます。次の%.*s
理由により、これは満足のいく解決策ではありません。
strlen
;と同等のものを参照しています。これは、メモリ内の長さではなく、文字列内の文字数の尺度です (つまり、null ターミネータはカウントされません)。sprintf
バッファ オーバーフローに関するバージョンの動作を変更します。を使用snprintf
すると、書式文字列や入力タイプの変更に関係なく、固定された明確な最大値が設定されます。質問の単純な例では、2 つの呼び出しのセキュリティに大きな違いはない可能性があります。ただし、一般的なケースsnprintf()
では、おそらくより安全です。複数の変換仕様を持つより複雑なフォーマット文字列を作成すると、異なる変換間でバッファ長が正確に考慮されていることを確認することは困難 (またはほぼ不可能) になる可能性があります。特に、以前の変換が必ずしも固定数を生成するとは限らないためです。出力文字の。
だから、私は固執しsnprintf()
ます。
snprintf()
(セキュリティ関連ではありませんが)のもう 1 つの小さな利点は、必要なバッファーの大きさがわかることです。
最後の注意 -snprintf()
呼び出しで実際のバッファ サイズを指定する必要があります - null ターミネータのアカウンティングを処理します。
snprintf(buff, sizeof(buff), "%s", name);
snprintf()
この一節を読むまでは、はるかに優れていると思います。
https://buildsecurityin.us-cert.gov/bsi/articles/knowledge/coding/838-BSI.html
短い要約は次のとおりですsnprintf()
。システムからシステムへの動作の変更は移植できません。の最も深刻な問題は、単に を呼び出すだけで実装されsnprintf()
た場合に発生する可能性があります。バッファ オーバーフローから身を守って警戒を緩めると思うかもしれませんが、そうではないかもしれません。snprintf()
sprintf()
だから今でも私はsnprintf()
より安全だと言っていますが、使用するときは慎重になっています.
あなたの sprintf ステートメントは正しいですが、任意の形式に適用できる snprintf が周りにある間、安全目的でそれを使用するのに十分な自信がありません (たとえば、暗号化された文字が 1 つなく、シールドがありません)。snprintf は ANSI C ではありません。(だけ?)C99です。それは、他のものを好む(弱い)理由かもしれません。
良い。も使えstrncpy
ますよね?
例えば
char buffer[MAX_LENGTH+1];
buffer[MAX_LENGTH]=0; // just be safe in case name is too long
strncpy(buffer,MAX_LENGTH,name); // strncpy will never overwrite last byte
どちらも希望する結果をもたらしますが、snprintf
より一般的であり、指定されたフォーマット文字列に関係なく、文字列をオーバーランから保護します。
さらに、snprintf
(またはsprintf
そのことについては)final\0
を追加するため、文字列バッファを1バイト大きくする必要がありますchar buff[MAXLEN + 1]
。