新城@筑波大学情報です。こんにちは。

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() に思えます。

\\ 新城 靖 (しんじょう やすし) \\
\\ 筑波大学 電子・情報       \\