strlcpyC言語文字列を安全にコピーするための関数である。ISO/IEC で規定された標準Cライブラリの関数ではないが、BSD libc などに含まれている。危険な使い方をしてしまいがちな関数strcpystrncpyの代替として、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を含め、SolarismacOS等の各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_sC11規格で実装任意のセキュリティ強化関数として標準化されている[5]

危険な利用例

編集

安易なstrlcpyの利用が、かえって危険な結果をもたらす例を以下に示す。

char cmd[] = "rm *.bak";
char buf[5];
strlcpy(buf, cmd, sizeof(buf));
system(buf);

sizeof(buf)5であるため、最初の5 - 1すなわち4文字しかコピーされず、システムコール"rm *"(カレントディレクトリ内の全ファイルの削除)が実行されることになる。

本来はstrlcpyの戻り値をチェックするなどして、文字列がすべて意図した通りにコピーされたかどうかを確認すべきである。

関連項目

編集

脚注

編集

注釈

編集
  1. ^ NULLポインタと区別するため、意図的にASCIIの略称NULを使っている。
  2. ^ 例えば引数dstに固定長配列変数char buf[N]を渡す場合、Nまたはsizeof(buf)を引数sizeに指定すればよい。
  3. ^ C++の場合はテンプレート非型引数として固定長配列の要素数を受け取る関数オーバーロードが利用でき、また通常はコンパイラの推論によって自動的に決定されるため、固定長配列の場合は要素数を明示的に渡す必要がなく、また要素数の指定ミスを防ぐことができる。これは特にwcscpy_sのようなwchar_t配列を受け取る関数を使用する場合に有用である。

出典

編集

外部リンク

編集