Re: strcpy, strlcpy.
新城@筑波大学情報です。こんにちは。
In article <c6hhvv$1eaf$1@news2.rim.or.jp>
dohzono@hf.rim.or.jp (Kazuo Fox DOHZONO) writes:
> > strlcpy() の方が、プログラマの負担が増えるという主張ですか?
> はい. これについては共通の見解だと思っていました↓.
> 「既にチェックされたものに対する strl?cpy」の話なので, strlcpy の方は
> 加算のはずです.
いいえ。「既にチェックされたかどうかを判断する」というコスト
を無視しては困ります。「既にチェックされたかどうかを判断する」
のは、相当大きなコストがかかります。関数呼出しがあったり、長
年に渡って別の人が維持したりする時。
> すぐに思いつくのは最近やった仕事の変形ですが.
>
> unsigned
> txbuf_set (char *txbuf)
> {
> unsigned wi = 0;
> …;
> {
> foo_t *foop;
> if ((foop = foo_get ()) != NULL)
> {
> strcpy (&txbuf[wi], foop->name);
> wi += foop->nlen;
> }
> }
> …;
> return wi;
> }
>
> txbuf の具体的な大きさは (自動的に算出されているので) 私は知りませんし,
> strlcpy を使うには残りバイト数も数えなければなりませんし, rewind 要件
> も洗い出さなければなりません.
このプログラム、私からすると怖いです。プログラムを書いた人は
安全だと信じているのですが、読んだ人はとても安全とは思えません。
> txbuf の具体的な大きさは (自動的に算出されているので) 私は知りませんし,
この「 txbuf を使う人がバッファの長さを知らなくてもよい」と
いう特性自体は、良いことです。モジュール性が高い。ただそこで
止まるるではなくて、もう一歩進めてたい。C++ のクラスか何かに
してとするのがいいでしょう。
txbuf->append( foop->name );
「知りません」というからには。逆に、そういうカプセル化ができ
ないとすると、
> txbuf_set (char *txbuf)
この関数の引数は不足しています。txbuf の長さも引数で渡すべき
です。そういう修正は、簡単です。mallo() したり、auto の & な
どで、長さが分かっているから、先頭番地といっしょに長さも引き
回せばいいだけです。簡単簡単。このコストは、ほとんど0と言っ
てもいいです。
< txbuf_set (char *txbuf,size_t len)
...
< strlcat(txbuf,foop->name,len);
あ、strlcpy() が strcat() に化けちゃった。
> strcpy → strlcpy の書き替えとは違いますが, やっちゃいそうな間違いと言
> うと
> void
> foo (char *d, const char *s)
> {
> …;
> if (strlcpy (d, s, sizeof d) == sizeof d)
> むにゃむにゃ;
> …;
> }
> なんていうのも思いつきます.
これは、strcpy() でも問題があるプログラムですよね。
foo (char *d, const char *s)
{
…;
strcpy(d, s);
むにゃむにゃ;
…;
}
この strcpy() を strlcpy() に書き換える時に、「あ、d の長さ
がない」と気が付くはずです。これでバグが1つ減ります。
> 面白いことに secure であるとされる qmail は, よくある string 型のよう
> に文字列を扱っているにも関わらず, 型チェックの恩恵の一部を放棄している
> ように見えます (traditional C な関数宣言).
qmail が secure とされている理由は、観測結果です。sendmail
のバグがボロボロ見つかるのに、qmail はそんなには見つかってい
ません。DJB 大先生ならではの方法論です。一般の人には、なかな
か真似できません。
一般の人に「 DJB 大先生みたにいなれ」といって、なれるものな
ら話は終りですが、そうはいかないでしょ。
> # ひょっとしてディストリビュート時に unprotoize 通してる?
> stralloccopy なんていうのも使われていたと思いますが, strcpy そっくりな
> 関数もあったはずです.
stralloccopy() って、名前からすると strdup() に思えます。
\\ 新城 靖 (しんじょう やすし) \\
\\ 筑波大学 電子・情報 \\
Fnews-brouse 1.9(20180406) -- by Mizuno, MWE <mwe@ccsf.jp>
GnuPG Key ID = ECC8A735
GnuPG Key fingerprint = 9BE6 B9E9 55A5 A499 CD51 946E 9BDC 7870 ECC8 A735