[PHP-dev 181] Re: 関数オーバーロード

Youichi Iwakiri php-dev@php.gr.jp
Wed, 26 Dec 2001 00:21:35 +0900


いわきりです

Rui Hirokawa wrote in <20011224004401.610ddfed.rui_hirokawa@ybb.ne.jp>:
 >以前、話題になったオリジナルのPHP関数をマルチバイト対応の
 >関数で置き換える件ですが、CVSに入れてみました。
 >テストをお願いできればと思います。

やってみました。mbstring拡張モジュールの使用法によって
問題が発生します。

1. staticにmbstringをリンクする場合は問題発生せず
2. dynamicにmbstringをリンクする場合は設定(php.ini)により変化
 2.1 php.iniに 
     extension = mbstring.so
     を記述しモジュールを常に有効とする場合は問題発生せず
 2.2 php.iniに 
     extension = mbstring.so
     を記述せずdl()でmbstringを使用する際に問題有り。

mbstring.cを見ましたが、RINITフェーズで関数の置換えを
行っていますが、RSHUTDOWNフェーズで関数をオリジナルに戻して
いないため、dl()でmbstringが呼ばれた場合、次回リクエスト時に
mail()へのポインタが失われているようです。

gdbのログは下記の通り

(gdb) b execute
Breakpoint 1 at 0x1821f9e0: file ./zend_execute.c, line 999.
(gdb) b zif_mail
Breakpoint 2 at 0x1827ff78: file mail.c, line 82.
(gdb) c
Continuing.

Breakpoint 1, execute (op_array=0x80fd40c) at ./zend_execute.c:999
999             zend_op *opline;
(gdb) c
Continuing.

Breakpoint 2, zif_mail (ht=3, return_value=0x80fc42c, this_ptr=0x0, 
    return_value_used=0) at mail.c:82
82              char *to=NULL, *message=NULL, *headers=NULL, *subject=NULL, *extra_cmd=NULL;
(gdb) c
Continuing.

Breakpoint 1, execute (op_array=0x80f548c) at ./zend_execute.c:999
999             zend_op *opline;
(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x1832729c in ?? ()
(gdb) bt
#0  0x1832729c in ?? ()
#1  0x182317f6 in zend_execute_scripts (type=8, retval=0x0, file_count=3)
    at zend.c:814
#2  0x1823f4b6 in php_execute_script (primary_file=0xbfbfd8b0) at main.c:1309
#3  0x1823b4ee in apache_php_module_main (r=0x80f9034, display_source_mode=0)
    at sapi_apache.c:90
#4  0x1823bfce in send_php (r=0x80f9034, display_source_mode=0, filename=0x0)
    at mod_php4.c:575
#5  0x1823c02a in send_parsed_php (r=0x80f9034) at mod_php4.c:590
#6  0x8053ff9 in ap_invoke_handler ()
#7  0x806884f in ap_some_auth_required ()
#8  0x80688b6 in ap_process_request ()
#9  0x805f776 in ap_child_terminate ()
#10 0x805f9f8 in ap_child_terminate ()
#11 0x805fd88 in ap_child_terminate ()
#12 0x80602bc in ap_child_terminate ()
#13 0x80608fc in main ()
#14 0x804ea4d in _start ()
(gdb) 

この際、使用したscriptは

<script language="php">
mail("iwakiri", "test mail from php 1", "Hello");
/* MultiByte String Module Use */
if (!extension_loaded('mbstring')) {
	if(!dl('mbstring.so')) {
		echo 'error';
		exit;
	}
}
mail("iwakiri", "test mail from php 2", "Hello こんにちは");
echo "send mail to iwakiri\n";
</script>

1回目は正常に動作しますが、2回目のアクセスでSegmentation faultと
なります。

 >overloadというよりもoverride という話もありますが。。。

たしかに乗っ取ってますね :-)
zendのお作法に従っているかどうか怪しいのですが、APCの
overrideは参考になるかもしれません。INITフェーズでオリジナルの
関数へのポインタを保存しておきSHUTDOWNフェーズで元に戻していました。
compile(), execute()の部分です。

 >将来的には、正規表現関数の上書き等もできればと思います。

mbregexもmbstringにマージですか? 期待してます。