[スレッド全体]

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氏の言うように「もっと大事なことがある」と思います。
ただ、他の部分の共通関数の品質は高いので、放置したままにしとくのももったいないなーとも思います。

[▼次のスレッド]
INCM/CMT
Cyclamen v3.81
[ut:0.010][st:0.000]