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

Moriyoshi Koizumi moriyoshi @ at.wakwak.com
2008年 8月 9日 (土) 18:33:15 JST


小泉です。

すみません、実はすでにパッチを作っていてコミットしようとしています。

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
> 


-- 
Moriyoshi Koizumi <moriyoshi @ at.wakwak.com>


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