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

Yasuo Ohgaki yohgaki @ ohgaki.net
2008年 8月 8日 (金) 11:18:42 JST


大垣です。

このパッチ、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 メーリングリストの案内