スレッドメモ

MLやNewsのスレッドをメモする試み。

2003|01|02|04|05|06|07|08|10|11|
2004|01|04|05|06|07|08|09|11|12|
2005|01|02|04|08|09|
2006|01|03|04|08|
2007|01|05|
2009|05|

2004-01-09 (金)

[fj][fj.comp.lang.c] [Q] see return value (strncpy)

<YAS.04Jan9214824@kirk.is.tsukuba.ac.jp> Yasushi Shinjo (1/9)

バッファ・オーバーフローを防ぐには、strncpy() は実は今一つで す。n を取りますが、最後に埋めるだけなので。結構、誤用される 関数だと思います。私もだいぶ長い間誤用していた気がします。

本当は、strlcpy() がいいんですよね。

ただ、strlcpy() は、Linux に入ってなくて困るんですよね。しょ うがないので代りに snprintf() を使うように勧めているんですけ ど。いくら snprintf() を使えと言っても、strcpy() とか strcat() 使う人が多くて困ります。どうしたらいいでしょうか。

<bto666$e39$2@caraway.media.kyoto-u.ac.jp> NIDE Naoyuki (1/10)

そういう場合は、strlcpy()互換品を作ってプログラムに添付しておいて、Linuxで使う場合はそれがリンクされるようにしておくのがよくある手ですよね。1度作っておけば以後使い回しもできるし。snprintf()だと(マニュアル見ても難しそうなので?)使ってくれない人も、strlcpy()だと(慣れているstrncpy()に似ているからと)使ってくれませんかね。

<m3ad4wl1yq.fsf@kzin.dip.jp> Mito (1/10)

すみません、もう少し詳しく教えてください。この文は、

strncpy(dest, src, n) は n > strlen(src) の場合に dest+strlen(src) 以降に nul を埋めるだけで、 strlcpy の場合はこれに加え、n <= strlen(src) の場合も dest+n に nul を埋めるので、バッファ・オーバーフローを防ぐ には strlcpy のほうがベターである

ということをおっしゃっているのでしょうか?

私は strcpy や strcat を好んで使いますし、これからも使ってい くと思います。strncpy などは n なしに比べてだいぶ遅いんです もん。

<YAS.04Jan12063406@kirk.is.tsukuba.ac.jp> Yasushi Shinjo (1/12)

strncpy() は、0 を埋めるので遅いけど、strlcpy() は埋めないので速い。

<m34quy63bi.fsf@kzin.dip.jp> Mito (1/14)

とにかく、strlcpy() は strncpy() と違い、n 未満の文字列をコ ピーする場合も、dst[n] まで nul を埋めることはしないというこ とはわかりましたし、strlcpy() があるなら使うべきで、ない環境 でもある程度以上の規模のソフトを作るなら自前のものを用意して 使うべきだという意見にも同意します。

新城さんの考えは、たとえ strcpy の正しい使いかたを知ったとし ても使うべきではない、というふうに思われるのですが、もしそう なら理由を教えてもらえませんか?

私は正しい使いかたを知っていれば別に使ってはいけない関数では ないと思うのです。

<YAS.04Jan16033731@kirk.is.tsukuba.ac.jp> Yasushi Shinjo (1/16)

strcpy() を使った方がよい局面というのが、なかなか出てこない ので、「strcpy()使うな」でいいんじゃないか、ということです。 何か「こういう時には strcpy() がいい」という状況はありますか?

<c17e5u$2eji$1@news2.rim.or.jp> Kazuo Fox DOHZONO (2/21)

# 今更感バリバリですが, 先の記事を読んで何も考えずに strcpy を strlcpy
# にする人がいるといけないと思って色々書いてみました. 意見を求めます.

どうも私の感覚と strlcpy って合いません. 特に strcpy の置き換えとしては考えられない.

マズイことの本質は「不適当な大きさのバッファを適当に取ってしまうこと」だと思うんです. 長さのチェックは入力時や文字列の切り出し時にやればいいわけで, *cpy なんかする前にわかるでしょ? ということ.

そもそもこれで足りなくなる場合はバグ (バッファ長不足) か仕様外の入力かのどちらかで, バグなら strlcpy を使ってもバッファを定められた長さまで増やさなければ正しく動作しないでしょうし, 仕様外の入力がこういうところにまで入り込んでくるのなら, そもそも strcpy を使える場面ではなかったわけです. 後者を問題にするのなら, 別の問題も抱え込んでいる可能性が大きい.

<YAS.04Feb21235337@kirk.is.tsukuba.ac.jp> Yasushi Shinjo (2/21)

はい。それはそうです。strlcpy() は、バッファ・オーバーフロー を起さないという目的で使うものです。strlcpy() を使ったからと いって、間違ったプログラムが「正しく」動作するようになるわけ ではありません。

<c1fl9o$dl5$1@news2.rim.or.jp> Kazuo Fox DOHZONO (2/24)

確認しておきますが, strlcpy によってバッファオーバーフローが「起こらなくなる」ケースでは間違ったプログラムを前提としているわけであり, それは strlcpy を使っても依然として間違ったプログラムであることに変わりありません.

人的ミスならそういうものを持ち込ませない, 或は, 万が一持ち込まれてもテスト等で発覚するような設計にするべきで (Java を使うってのもこの辺に入ってくるわけでしょう), 「持ち込まれても strlcpy で」っていうのは問題に対処するベクトルがずれている気がするんです. 新人君に教える心得としても甚だ不適当なものでしょう.

<YAS.04Feb25010034@kirk.is.tsukuba.ac.jp> Yasushi Shinjo (2/25)

それより重要なことは、間違いには2種類あるということです。

(A)セキュリティ上の弱点に繋がる間違い
(B)セキュリティ上の弱点には繋がらない間違い

strlcpy() を使うと、(A)は出てきません。この性質を有りがた いと思う人は、多いでしょう。

最後の部分、同意できませんね。人間は間違う、だから、間違ったとしても安全側に倒れるように作るようにプログラムは作るべしと。

<c2esvq$2ta5$1@nsvn01.zaq.ne.jp> Takashi SHIRAI (3/7)

 この過ちを侵している代表例が Samba ですね。こいつは一つも strcpy() を使わないように工夫していますが、長さ指定ミスによ る buffer overflow は過去幾つも発見されています。

 開発チームは strcpy() を使っていないことから慢心してしまい、 文字列 copy に関するチェックを疎かにしているため、新たに何か 実装する度にこのミスが生じ、結果 buffer overflow は後を絶ち ません。

私は fgets() の代わりに asprintf() みたい な仕組みを実装することが多いですね。


2003|01|02|04|05|06|07|08|10|11|
2004|01|04|05|06|07|08|09|11|12|
2005|01|02|04|08|09|
2006|01|03|04|08|
2007|01|05|
2009|05|