strlcpy
strlcpy はC言語で文字列を安全にコピーするための関数である。ISO/IEC で規定された標準Cライブラリの関数ではないが、BSD libc などに含まれている。危険な使い方をしてしまいがちな関数strcpyやstrncpyの代替として、Todd C. MillerおよびTheo de Raadt (テオ・デ・ラート) が開発した[1]。
概要
[編集]関数プロトタイプ(宣言)は以下である。
size_t strlcpy(char *dst, const char *src, size_t size);
ポインタsrc
の指すアドレスから最大でsize - 1
バイトの文字列をdst
にコピーし、dst
の指す文字列が必ずNUL文字[注釈 1]で終わるようにする。つまり、dst
のバッファの実際の大きさをsize
に指定すれば[注釈 2]、バッファオーバーランしないことが保証される。
strncpy
は似たプロトタイプchar *strncpy(char *dest, const char *src, size_t count)
[2]を持つが、最大でcount
バイトをコピーするためNUL文字で終わるとは限らない点や、文字列が短い場合にdst
の残った部分をすべてゼロで埋める点がstrlcpy
と異なる。
実装状況
[編集]ToddとTheoはOpenBSDの開発者であり、strlcpy
を最初に実装したオペレーティングシステム (OS) はOpenBSD 2.4である。以後、FreeBSD 3.3を含め、SolarisやmacOS等の各OS、OpenSSL等のライブラリにも採用されている。Linuxではlibbsdライブラリ経由で利用できる。
一方で、GNU Cライブラリ (glibc) の開発者たちは、GNU Coding Standardsで禁じられている「長い行を黙って切り詰める」関数である、このような仕様の関数はバグである、いい加減なプログラムを助長してしまう、新たなセキュリティ問題を生む、など否定的な見解を示しており[3]、標準規格に含まれない限りはglibcには実装しない意向であった。しかし、POSIX仕様での標準化を受けて2.38で実装された。
Microsoft Visual C++には実装されていないが、バージョン8.0 (2005) 以降はセキュリティ強化バージョンのCRT関数として、出力バッファサイズを受け取りパラメータ検証を実行するstrcpy_s
が実装されている[4][注釈 3]。strcpy_s
はC11規格で実装任意のセキュリティ強化関数として標準化されている[5]。
危険な利用例
[編集]安易なstrlcpy
の利用が、かえって危険な結果をもたらす例を以下に示す。
char cmd[] = "rm *.bak";
char buf[5];
strlcpy(buf, cmd, sizeof(buf));
system(buf);
sizeof(buf)
が5
であるため、最初の5 - 1
すなわち4
文字しかコピーされず、システムコール"rm *"
(カレントディレクトリ内の全ファイルの削除)が実行されることになる。
本来はstrlcpy
の戻り値をチェックするなどして、文字列がすべて意図した通りにコピーされたかどうかを確認すべきである。
関連項目
[編集]脚注
[編集]注釈
[編集]出典
[編集]- ^ strlcpy and strlcat - consistent, safe, string copy and concatenation. - 1999 USENIX Annual Technical Conference, June 6-11, 1999, Monterey, California, USA
- ^ strncpy, strncpy_s - cppreference.com
- ^ libc-alphaメーリングリストでの議論[1][2]より
- ^ strcpy_s, wcscpy_s, _mbscpy_s, _mbscpy_s_l | Microsoft Learn
- ^ strcpy, strcpy_s - cppreference.com
外部リンク
[編集]strlcpy(3)
– FreeBSD Library Functions Manual Pages (en)