オルタナティブ・ブログ > プログラマー社長のブログ >

プログラミングでメシが食えるか!?

vsnprintfを使えば安心というものでもないという例

»

今日はバリバリC言語の話題です。C言語はバッファオーバーフローの問題が発生しやすく、初心者は使うな、とか、そもそも今時使うな、とか言われていますが、性能要求が高い場合や組み込みなど環境制限が厳しい場合などにはまだまだ大活躍です。さすがにWEBシステムの大規模なものなどで使うケースはほとんどないでしょうけれど。

そんなC言語も、一応バッファオーバーフローしにくいようなライブラリを使うようにいわれています。たとえば、sprintf(),vsprintf()などの代わりに、snprintf(),vsnprintf()を使うという感じです。'n'がつく方は、格納先のサイズを指定できるのでバッファオーバーフローを防ぎやすいのです。

ところが、あるシステムでこの部分でメモリーアクセス違反で死ぬ現象が発生しました。デバッガで確認すると、vsnprintf()で死んでます。格納先バッファのサイズなどは問題なく指定できています。さっぱり原因がわかりません・・・。

void BadFunc(int priority, char *fmt,...)
{
va_list args;
char    buf[1024];

        va_start(args,fmt);
        vsnprintf(buf,sizeof(buf),fmt,args);
// 諸々の処理
        va_end(args);
}

こんな感じのソースです。特に問題なさそうですが・・・

実は原因は、渡すデータというか、この関数の使い方にありました。

BadFunc(1,buf);

という感じに呼び出していたのですが、bufの中に"%s"という文字列が含まれることがあったのです!すると、BadFunc()内で

vsnprintf(buf,sizeof(buf),"...%s...");

という感じになり、%sなので文字列を得ようとして死んでしまうのです。

BadFunc(1,"%s",buf);

という感じに呼び出せば問題なかったのですが、printf系はフォーマット文字列には十分な注意が必要です!

Comment(0)