[PHP-users 12945] Re: wddxについて(一応解決)
Reiji Matsumoto
php-users@php.gr.jp
Mon, 3 Feb 2003 06:19:04 +0900
澤田様
> すいません、えらい回り道をしてしまって。
追試ばかりか、深い所までお付き合い頂きありがとうございます。
> > iscntrl()はロケール依存ですので、この判定を省略してみました。
> と判断したあたりが落とし穴かと。
実際、Linuxのマニュアルで確認してしまいました。Linuxで
man iscntrl
とすると、ロケールに依存する旨が記述されています。
NetBSDで同様に確認すると、特にロケールについて言及していませんでした。
> NetBSD の iscntrl(3) は ctype.h にて、
> #define iscntrl(c) ((int)((_ctype_ + 1)[(int)(c)] & _C))
> となっていて locale を見てません。
> NetBSD では「ワイド文字を喰わせるならば iswcntrl(3) を使え」が
> 美しいということでしょう。
早速 NetBSDのctype.hを参照してみました。
_C は
ctype.h:55:#define _C 0x20
との事ですが、_ctype_ は、
ctype.h:59:extern const unsigned char *_ctype_;
と、あります。現在、NetBSDのソースが無くダウンロード中なのでこれから
調査しようと思っていますが、つまり_ctype_ が恐らく256バイト程度の配
列であり、調査する文字コードと0x20との論理積を取る事で制御文字かどう
か判断しているようです。となるとあらかじめ_ctype_に値を代入しておく
処理がどこかで行われていると思うのですが、その時にロケールを参照して
フラグを立てているのではないでしょうか。ロケール対応を謳っている1.6は、
そうあるべきだと思います。
また、int型にキャストして利用するのですから、_ctype_ は少なくとも
_ctype_[-127] から _ctype_[128] までが有効な領域でなくてはならない
はずです。しかし、実際に「赤黒」のそれぞれのコード"C0 D6 B9 F5"を
代入する事で結果が揺れているのですから、_ctype_の負の領域が確保さ
れていないのではないかと疑っています。
> 該当部分を isascii() && iscntrl() に書き換えると、
> とりあえず「赤黒」が出るようになります。
isascii(3)の実装は
ctype.h:109:#define isascii(c) ((unsigned)(c) <= 0177)
ですので、疑う余地なく正常に動作すると思います。よってこのチェックを
入れた方がよさそうですね。対してiscntrl(3) は _ctype_ の領域がどのよう
に確保されているか確認しないと、かなり不安要素が大きいです。
ところでLinuxの `man iscntrl`によると、入力パラメーター c について
これらの関数は c をチェックして、現在のlocaleに従い分類す
る。この c は unsigned char か EOF でなければならない。
と、あります。ならば wddx.c の394行にある、
wddx.c:349: if (iscntrl((int)*p)){
というキャストは、pが
wddx.c:363:char *buf,
wddx.c:364: *p,
と宣言されている事を考えると、そもそも問題があるような気がします。
(int)*p の取りうる範囲が 0xffffff80 から 0x0000007f になって
しまうからです。Linuxで正常に動作するのは偶然という事になりますでしょうか。
Linux のiscntrl(3)の実装も調査してみたいと思います。
またNetBSD1.6においてもマニュアルに記載が無いだけでLinuxのiscntrl(3)と
同等の処理を行う物として用意されているなら(そうあって欲しいです)
負の値がパラメーターとして与えられた事によって誤動作するのは納得の
行く事です。
色々と検証しなくてはならない事が多いのですが、現時点では
wddx.cの394行のキャストは誤りであると考えております。394行を
wddx.c:394: if (iscntrl((int)*((unsgined char*)p))){
として再コンパイルして試してみたいのですが、現在当該サーバーが稼動中
につきしばらくお待ち下さい。後ほど結果をレポートさせて頂きます。
> #「赤黒」が出たり出なかったりと揺れる問題は、なんでしょうねぇ。
> # あと setlocale の戻値が各種の値なのは、別に追い掛けないといけませんね。
澤田さんの環境でも同じ結果でしょうか?
Matsumoto@Sp