[PHP-dev 884]mb_ereg_replaceについて
komura
komura @ ma9.seikyou.ne.jp
2003年 9月 20日 (土) 08:51:01 JST
komura です。こちらでは初めてです。
mb_ereg_replace() について、少し気になる点がありました。
今まで問題になったような投稿などは見つけられませんでしたし、正規表現の
書き方によって回避することができますので、大きな問題ではないのかも
しれませんが、報告します。
環境は、RedHat Linux 7.3、PHP 4.3.3 ですが、Windows 版の
PHP-4.3.3-Win32 でも同じ問題を確認しました。
1. 無限ループ
以下の行を実行すると、無限ループになります。
echo mb_ereg_replace( ".*", "", "" );
2. 結果に NULL が追加される
'?' や '*' を使って置き換えを行うと、後ろに NULL が追加されます。
// $s = mb_ereg_replace( "C?$", "Z", "ABC" );
$s = mb_ereg_replace( "C*$", "Z", "ABC" );
var_dump( $s );
echo bin2hex( $s );
--
string(5) "ABZZ"
41425a5a00
一応、ソースを調べてみたのですが、私にとってはマルチバイト正規表現の
部分は複雑で、詳しくは分かりません。
調べたことを書いておきます。
1. の無限ループに関しては、マルチバイト正規表現のオプションを空にして
実行すると、無限ループにはなりませんでした。
mb_regex_set_options( "" );
echo mb_ereg_replace( ".*", "", "" );
PHP 4.3.3 のソースを確認してみましたが、 ext/mbstring/mbregex.c の以下の
部分で無限ループになっているようです。
3301 if (bufp->used > 0) {
3302 switch ((enum regexpcode)bufp->buffer[0]) {
3303 case begbuf:
3304 begbuf_match:
3305 if (range > 0) {
3306 if (startpos > 0) return -1;
3307 else {
3308 val = re_match(bufp, string, size, 0, regs);
3309 if (val >= 0) return 0;
3310 return val;
3311 }
3312 }
3313 break;
...
3328 if (bufp->options & MBRE_OPTIMIZE_ANCHOR) {
3329 if (bufp->options&MBRE_OPTION_SINGLELINE) {
3330 goto begbuf_match;
3331 }
3332 anchor = 1;
3333 }
MBRE_OPTION_SINGLELINE が有効になっていると、無限ループになるようです。
mb_ereg_replace() で指定するオプションに、's' か、'p'(デフォルト) を
指定すると、MBRE_OPTION_SINGLELINE が有効になります。
また、マルチバイト正規表現の処理に oniguruma が組み込まれている、
CVS 版の php5-200309180130 でも試してみましたが、Segmentation fault を
起こします。
$ php -v
PHP 5.0.0b2-dev (cli) (built: Sep 18 2003 17:01:41)
Copyright (c) 1997-2003 The PHP Group
Zend Engine v2.0.0-dev, Copyright (c) 1998-2003 Zend Technologies
$ php -r 'mb_ereg_replace( "C*$", "Z", "ABC" );'
セグメンテーション違反です
--
komura <komura @ ma9.seikyou.ne.jp>
PHP-dev メーリングリストの案内