snprintf
こんな関数あるんだ。 と思ったのでメモ。
snprintf(3)という関数が用意されたシステムでは、下記の様なコーディングでバッファオーバーフローを防げるそうだ。
#include <stdio.h> int main(int argc, char **argv) { int n = 123456; char str[4] = "000"; printf("%s\n", str); snprintf(str, sizeof(str), "%d", n); printf("%s\n", str); return(0); }
000 123
でもこれ、ANSI C はもちろん C99 でも規格化されていないので、仕事で使用するプログラムには皮をかぶせるかなんかしないと使えないみたい。処理系によって戻り値や処理内容まで違うとは恐るべし。…もっとも Visual C の、互換性:Win95,WinNT? てやつも便利な関数が多いけど使い回しできないわけで。
出典:Secure Programming for Linux and Unix HOWTO
http://www.linux.or.jp/JF/JFdocs/Secure-Programs-HOWTO/index.html
snprintf()系は残念ながらもっと問題を抱えています。 sprintf() と違って snprintf()は、公式には ISO 1990(ANSI 1989)規格の標準 C 関数ではありません。したがって、システムすべてに snprintf() があるわけではありません。さらに困ったことに、あるシステムの snprintf()は、バッファオーバーフローを実質防ぎません。ただ sprintf を呼び出すだけです。 Linux の libc4 という古いバージョンは、「libbsd」ライブラリに依存していました。これが実に嫌らしいライブラリでした。古い HP のシステムにも同様なものがありました。 Linux の最近の snprintf は正しく動作することがわかっていて、要求された境界値をたしかに守っています。 snprintf() の返り値もさまざまです。 Single Unix Specification (SUS) version 2 と C99 規格では、何が返るか違っています。結果的にわかったのは、snprintf のバージョンには文字列が NIL で終端するのを保証しないものがある、という事実です。文字列が長すぎれば、NIL がまったくないでしょう。 glib ライブラリ(GTK のベースになっているもので、GNU C ライブラリの glib とは違います)には g_snprintf() があります。返り値が一貫しており、常に NIL で終端します。もっと重要なのは、バッファの長さを常に守っている点です。