[PHP-dev 1435] Re: mb_check_encoding() の第1引数の最初に \0 が入力された場合の問題について

Yasuo Ohgaki yohgaki @ ohgaki.net
2008年 10月 16日 (木) 12:58:25 JST


大垣です。

ちょっとCVSを覗いてみました。
HEAD, PHP_5_3はパッチが当たっていますが、PHP_5_2は当たっていないようです。

コミット漏れですか?それともリリース直前にコミット予定でしょうか?

--
Yasuo Ohgaki

Moriyoshi Koizumi さんは書きました:
> 小泉です。
> 
> すみません、実はすでにパッチを作っていてコミットしようとしています。
> 
> Yasuo Ohgaki wrote:
>> 大垣です。
>>
>> このパッチ、HEAD, PHP_5_3, PHP_5_2にコミットしようと思いますが、
>> 何かご意見あるかたいらっしゃいます?
>>
>> --
>> Yasuo Ohgaki
>>
>> komura さんは書きました:
>>> komura です。
>>>
>>> 1つ前のメールにも関連することなのですが、mb_check_encoding() の第1引数
>>> の最初の文字列に \0 を入力すると、条件によっては、必ず TRUE になる問題
>>> があります。
>>>
>>> 例としては、以下の通りです。
>>>
>>> 1. mbstring.substitute_character に "none" が指定された場合
>>>    <?php
>>>        mb_substitute_character( 'none' );
>>>        $result = mb_check_encoding( "\0\xFF\xFF\xFF", 'SJIS' );
>>>        var_dump( $result );
>>>    ?>
>>>    -- 結果 --
>>>    bool(true)
>>>
>>> 2. 第2引数のエンコーディングに UTF-8 が指定された場合
>>>    <?php
>>>        mb_substitute_character( 63 );
>>>        $result = mb_check_encoding( "\0\xFF\xFF\xFF", 'UTF-8' );
>>>        var_dump( $result );
>>>    ?>
>>>    -- 結果 --
>>>    bool(true)
>>>
>>>
>>> 以上の問題が発生するのは、mb_check_encoding() の処理が以下のように
>>> なっているためです。
>>>
>>> 1) 第2引数で指定されたエンコーディングで第1引数の文字列を変換
>>> 2) 不正文字カウント(illegal_chars) が 0 で、さらに、変換前と
>>>    変換後の文字列が同一の場合、TRUE を返す(比較関数として
>>>    strncmp() を使用)
>>>
>>> 不正文字カウント(illegal_chars) が正しくカウントされない理由は
>>> 以下の通りです。
>>>
>>> 1. substitute_character を "none" に設定した場合、illegal_chars の
>>>    カウントが行われない(ext/mbstring/libmbfl/filters/mbfilter_*.c)
>>>
>>>    各ファイルの mbfl_filt_conv_wchar_*() を見ると、
>>>    filter->illegal_mode が MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE 
>>>    (ubstitute_character を "none" にすると設定される) の場合は
>>>    illegal_chars のカウントが行われないコードになっています。
>>>
>>> 2. UTF-8 は不正文字の判定が厳しくないため、ほとんどの場合、
>>>    illegal_chars のカウントが行われない
>>>    (ext/mbstring/libmbfl/filters/mbfilter_utf8.c)
>>>
>>>    illegal_chars がカウントされる可能性が非常に低いコードになって
>>>    います。
>>>
>>> 2) に関してですが、strncmp() は '\0' 以降の比較を行わないという
>>> ことが原因です。不正文字カウントが 0 でも、変換後の文字列は破壊
>>> されていますので、バイナリ比較を行えば、正しく判定できるように
>>> 思います。
>>> この部分(strncmp() を使用するようにした)は以前私が Patch を書き
>>> ましたが、本件の問題については考慮不足でした。すみません。
>>>
>>>
>>> substitute_character の挙動を変更するのは非常に大変ですので、
>>> mb_check_encoding() の変換後の文字列比較を行っている部分を
>>> バイナリで行うようにする Patch を作成してみました。
>>>
>>>
>>> diff -ru php-5.2.6.orig/ext/mbstring/mbstring.c php-5.2.6/ext/mbstring/mbstring.c
>>> --- php-5.2.6.orig/ext/mbstring/mbstring.c  2008-02-17 11:06:56.000000000 +0900
>>> +++ php-5.2.6/ext/mbstring/mbstring.c   2008-05-18 18:13:51.007778173 +0900
>>> @@ -4088,7 +4088,7 @@
>>>
>>>     if (ret != NULL) {
>>>         MBSTRG(illegalchars) += illegalchars;
>>> -       if (illegalchars == 0 && strncmp(string.val, ret->val, string.len) == 0) {
>>> +       if (illegalchars == 0 && memcmp(string.val, ret->val, string.len) == 0) {
>>>             efree(ret->val);
>>>             RETURN_TRUE;
>>>         } else {
>>>
>> _______________________________________________
>> PHP-dev mailing list
>> PHP-dev @ php.gr.jp
>> http://ml.php.gr.jp/mailman/listinfo/php-dev
>>
> 
> 



PHP-dev メーリングリストの案内