From: hiroaki dot kawai at gmail dot com Operating system: PHP version: 5.3.1 PHP Bug Type: XMLRPC-EPI related Bug description: system.multiCall cause Segmentation fault
Description: ------------ xmlrpc-epi supports system.multiCall(), which packs multiple xmlrpc method call transactions into one. Using this method in php extension cause php process crash. The point was that we must let xmlrpc-epi to decode the multicall request. We must check the method name in the callback function. This bug exists very long time. http://bugs.php.net/bug.php?id=27446 patch is available: ------------------------- --- xmlrpc-epi-php.c.orig 2009-08-18 09:41:43.000000000 +0900 +++ xmlrpc-epi-php.c 2010-01-14 13:58:48.028867000 +0900 @@ -892,12 +892,23 @@ static XMLRPC_VALUE php_xmlrpc_callback(XMLRPC_SERVER server, XMLRPC_REQUEST xRequest, void* data) /* {{{ */ { xmlrpc_callback_data* pData = (xmlrpc_callback_data*)data; + zval** php_function; zval* xmlrpc_params; zval* callback_params[3]; TSRMLS_FETCH(); /* convert xmlrpc to native php types */ + ZVAL_STRING(pData->xmlrpc_method, XMLRPC_RequestGetMethodName(xRequest), 1); xmlrpc_params = XMLRPC_to_PHP(XMLRPC_RequestGetData(xRequest)); + + /* check if the called method has been previous registered */ + if(zend_hash_find(Z_ARRVAL_P(pData->server->method_map), + Z_STRVAL_P(pData->xmlrpc_method), + Z_STRLEN_P(pData->xmlrpc_method) + 1, + (void**)&php_function) == SUCCESS) { + + pData->php_function = *php_function; + } /* setup data hoojum */ callback_params[0] = pData->xmlrpc_method; @@ -913,7 +924,7 @@ zval_ptr_dtor(&xmlrpc_params); - return NULL; + return PHP_to_XMLRPC(pData->return_data TSRMLS_CC); } /* }}} */ @@ -1082,34 +1093,17 @@ if (xRequest) { const char* methodname = XMLRPC_RequestGetMethodName(xRequest); - zval **php_function; XMLRPC_VALUE xAnswer = NULL; MAKE_STD_ZVAL(data.xmlrpc_method); /* init. very important. spent a frustrating day finding this out. */ MAKE_STD_ZVAL(data.return_data); Z_TYPE_P(data.return_data) = IS_NULL; /* in case value is never init'd, we don't dtor to think it is a string or something */ Z_TYPE_P(data.xmlrpc_method) = IS_NULL; - if (!methodname) { - methodname = ""; - } - /* setup some data to pass to the callback function */ - Z_STRVAL_P(data.xmlrpc_method) = estrdup(methodname); - Z_STRLEN_P(data.xmlrpc_method) = strlen(methodname); - Z_TYPE_P(data.xmlrpc_method) = IS_STRING; data.caller_params = *caller_params; data.php_executed = 0; data.server = server; - /* check if the called method has been previous registered */ - if (zend_hash_find(Z_ARRVAL_P(server- >method_map), - Z_STRVAL_P(data.xmlrpc_method), - Z_STRLEN_P(data.xmlrpc_method) + 1, - (void**)&php_function) == SUCCESS) { - - data.php_function = *php_function; - } - /* We could just call the php method directly ourselves at this point, but we do this * with a C callback in case the xmlrpc library ever implements some cool usage stats, * or somesuch. @@ -1119,7 +1113,7 @@ zval_dtor(data.return_data); FREE_ZVAL(data.return_data); data.return_data = XMLRPC_to_PHP(xAnswer); - } else if (data.php_executed && !out.b_php_out) { + } else if (data.php_executed && !out.b_php_out && !xAnswer) { xAnswer = PHP_to_XMLRPC(data.return_data TSRMLS_CC); } Reproduce code: --------------- <?php $req = '<?xml version="1.0"?> <methodCall> <methodName>system.multiCall</methodName> <params><param><value><array><data> <value><struct> <member><name>methodName</name><value><string>testMethodA</string></value></member> <member><name>params</name><value><array><data><value><string>A</string></value></data></array></value></member> </struct></value> <value><struct> <member><name>methodName</name><value><string>testMethodB</string></value></member> <member><name>params</name><value><array><data><value><string>B</string></value></data></array></value></member> </struct></value> </data></array></value></param></params> </methodCall>'; function testA($methodName, $params, $var){ return "C"; } function testB($methodName, $params, $var){ return "D"; } $server = xmlrpc_server_create(); xmlrpc_server_register_method($server, 'testMethodA', 'testA'); xmlrpc_server_register_method($server, 'testMethodB', 'testB'); $res = xmlrpc_server_call_method($server, $req, null); echo $res; Expected result: ---------------- <?xml version="1.0" encoding="iso-8859-1"?> <methodResponse> <params> <param> <value> <array> <data> <value> <array> <data> <value> <string>C</string> </value> </data> </array> </value> <value> <array> <data> <value> <string>D</string> </value> </data> </array> </value> </data> </array> </value> </param> </params> </methodResponse> Actual result: -------------- Segmentation fault -- Edit bug report at http://bugs.php.net/?id=50761&edit=1 -- Try a snapshot (PHP 5.2): http://bugs.php.net/fix.php?id=50761&r=trysnapshot52 Try a snapshot (PHP 5.3): http://bugs.php.net/fix.php?id=50761&r=trysnapshot53 Try a snapshot (PHP 6.0): http://bugs.php.net/fix.php?id=50761&r=trysnapshot60 Fixed in SVN: http://bugs.php.net/fix.php?id=50761&r=fixed Fixed in SVN and need be documented: http://bugs.php.net/fix.php?id=50761&r=needdocs Fixed in release: http://bugs.php.net/fix.php?id=50761&r=alreadyfixed Need backtrace: http://bugs.php.net/fix.php?id=50761&r=needtrace Need Reproduce Script: http://bugs.php.net/fix.php?id=50761&r=needscript Try newer version: http://bugs.php.net/fix.php?id=50761&r=oldversion Not developer issue: http://bugs.php.net/fix.php?id=50761&r=support Expected behavior: http://bugs.php.net/fix.php?id=50761&r=notwrong Not enough info: http://bugs.php.net/fix.php?id=50761&r=notenoughinfo Submitted twice: http://bugs.php.net/fix.php?id=50761&r=submittedtwice register_globals: http://bugs.php.net/fix.php?id=50761&r=globals PHP 4 support discontinued: http://bugs.php.net/fix.php?id=50761&r=php4 Daylight Savings: http://bugs.php.net/fix.php?id=50761&r=dst IIS Stability: http://bugs.php.net/fix.php?id=50761&r=isapi Install GNU Sed: http://bugs.php.net/fix.php?id=50761&r=gnused Floating point limitations: http://bugs.php.net/fix.php?id=50761&r=float No Zend Extensions: http://bugs.php.net/fix.php?id=50761&r=nozend MySQL Configuration Error: http://bugs.php.net/fix.php?id=50761&r=mysqlcfg