▼ 2016/11/30 (水) 01:15:39 ばぼ | |
Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko |
[2386] Re4:セキュアなsnprintf関数。 |
> この二つは何がどう違うのか説明可能ですか。
> void my_functuin1(wchar* out, size_t size){
> auto_snprintf_s(out, size, size, L"%d", g_linenum);
> }
> void my_functuin2(wchar* out, size_t size){
> auto_snprintf(out, size, L"%d", g_linenum);
> }
・1はoutにsize - 1文字書き込んで'\0'を付加します(溢れません)。
出力がsizeを越えた場合、出力はsize-1文字に切り詰められます(溢れません)。
出力がsizeを越えた場合、バッファサイズが足りない警告(戻り値!=0)が出ます。
・2はoutにsize文字書き込んで'\0'を付加します(出力=sizeで溢れます)。
出力がsizeを越えた場合、出力はsize-1文字に切り詰められます(溢れません)。
いちおうちゃんと説明しましょう。
何が問題なのかを知るためには
sprintfシリーズの関数について、
発生した経緯から語るのがよさそうです。
まず、sprintf関数について。
40年くらい前、C言語が発生すると同時に生まれました。
sprintf(out, format, ...)
outに...の内容をformatの書式で出力する。
任意のデータを書式出力するprintf系関数の1つです。
出力先がメモリなのでI/O処理が要らず高速です。
確保したメモリの領域外に出力があふれてしまう障害、
バッファオーバーフローの危険が古くから指摘される関数です。
つぎに、snprintf関数。
15年くらい前にC言語の規格が改定されるときにできました。
sprintfが抱えるオーバーフロー問題への対策版です。
snprintf(out, count, format, ...)
countで最大文字数を指定し、出力を制限できる。
count文字出力すると末尾に'\0'を付加して終了します。
出力数がcount+1になるのが微妙ですが、
これはC言語が規格として提供するセキュア版sprintfです。
最後にマイクロソフトのセキュア版関数について。
10年くらい前、vc++2005が出たときにできました。
ほとんどすべてのメモリ書込みを行う関数に_s付きバージョンができました。
sprintf_s(out, size, format, ...)
size - 1文字出力すると末尾に'\0'を付加して終了します。
最大出力数はsizeになります。
sprintf_s関数を使えば、sprintfの抱える問題をカバーできます。
じゃあ、snprintf_s関数は?
snprintf_s(out, size, count, format, ...)
・・・ぶっちゃけるとわたしにもよく分りません。
countには _TRUNCATE という特別な値を指定できるのですが、
_TRUNCATEを指定した場合の動作はsprintf_sと等価です。
size - 1文字を上限に、できるだけたくさん出力する、という動きになります。
なんで存在するのかよく分らない関数です。
いま、snprintf_sが定義されていて、
snprintfがない状態になっています。
当然ですが、sprintf_sはちゃんとあります。
必要性が微妙な関数が間違った定義で定義されていて、
本来の使い方をできない状態になっています。
(sprintf_sを使うべき箇所に誤ったsnprintf_s利用)
LR4氏の言うように「もっと大事なことがある」と思います。
ただ、他の部分の共通関数の品質は高いので、放置したままにしとくのももったいないなーとも思います。
|
|