--- /dev/null
+--TEST--
+Bug #45556 (Return value from callback isn't freed)
+--FILE--
+<?php
+
+$options = array ();
+$request = xmlrpc_encode_request ("system.describeMethods", $options);
+$server = xmlrpc_server_create ();
+
+
+function foo() { return 11111; }
+
+class bar {
+ static public function test() {
+ return 'foo';
+ }
+}
+
+xmlrpc_server_register_introspection_callback($server, 'foobar');
+xmlrpc_server_register_introspection_callback($server, array('bar', 'test'));
+xmlrpc_server_register_introspection_callback($server, array('foo', 'bar'));
+
+$options = array ('output_type' => 'xml', 'version' => 'xmlrpc');
+xmlrpc_server_call_method ($server, $request, NULL, $options);
+
+?>
+--EXPECTF--
+
+Warning: xmlrpc_server_call_method(): Invalid callback 'foobar' passed in %s on line %d
+expat reports error code 5
+ description: Invalid document end
+ line: 1
+ column: 1
+ byte index: 0
+ total bytes: 0
+
+ data beginning 0 before byte index: foo
+
+Warning: xmlrpc_server_call_method(): xml parse error: [line 1, column 1, message: Invalid document end] Unable to add introspection data returned from bar::test() in %s on line %d
+
+Warning: xmlrpc_server_call_method(): Invalid callback 'foo::bar' passed in %s on line %d
static
ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlrpc_encode_request, 0, 0, 2)
ZEND_ARG_INFO(0, method)
- ZEND_ARG_INFO(1, params)
+ ZEND_ARG_INFO(0, params)
ZEND_ARG_INFO(0, output_options)
ZEND_END_ARG_INFO()
*/
static void php_xmlrpc_introspection_callback(XMLRPC_SERVER server, void* data) /* {{{ */
{
- zval *retval_ptr, **php_function;
+ zval retval, **php_function;
zval* callback_params[1];
+ zval php_function_name;
xmlrpc_callback_data* pData = (xmlrpc_callback_data*)data;
TSRMLS_FETCH();
- MAKE_STD_ZVAL(retval_ptr);
- Z_TYPE_P(retval_ptr) = IS_NULL;
-
/* setup data hoojum */
callback_params[0] = pData->caller_params;
/* loop through and call all registered callbacks */
zend_hash_internal_pointer_reset(Z_ARRVAL_P(pData->server->introspection_map));
while(1) {
- if(zend_hash_get_current_data(Z_ARRVAL_P(pData->server->introspection_map),
- (void**)&php_function) == SUCCESS) {
-
- /* php func prototype: function string user_func($user_params) */
- if(call_user_function(CG(function_table), NULL, *php_function,
- retval_ptr, 1, callback_params TSRMLS_CC) == SUCCESS) {
- XMLRPC_VALUE xData;
- STRUCT_XMLRPC_ERROR err = {0};
+ if(zend_hash_get_current_data(Z_ARRVAL_P(pData->server->introspection_map), (void**)&php_function) == SUCCESS) {
+ if (zend_is_callable(*php_function, 0, &php_function_name)) {
+ /* php func prototype: function string user_func($user_params) */
+ if (call_user_function(CG(function_table), NULL, *php_function, &retval, 1, callback_params TSRMLS_CC) == SUCCESS) {
+ XMLRPC_VALUE xData;
+ STRUCT_XMLRPC_ERROR err = {0};
- /* return value should be a string */
- convert_to_string(retval_ptr);
+ /* return value should be a string */
+ convert_to_string(&retval);
- xData = XMLRPC_IntrospectionCreateDescription(Z_STRVAL_P(retval_ptr), &err);
+ xData = XMLRPC_IntrospectionCreateDescription(Z_STRVAL(retval), &err);
- if(xData) {
- if(!XMLRPC_ServerAddIntrospectionData(server, xData)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to add introspection data returned from %s(), improper element structure", Z_STRVAL_PP(php_function));
- }
- XMLRPC_CleanupValue(xData);
- }
- else {
- /* could not create description */
- if(err.xml_elem_error.parser_code) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "xml parse error: [line %ld, column %ld, message: %s] Unable to add introspection data returned from %s()",
- err.xml_elem_error.column, err.xml_elem_error.line, err.xml_elem_error.parser_error, Z_STRVAL_PP(php_function));
- }
- else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to add introspection data returned from %s()",
- Z_STRVAL_PP(php_function));
+ if(xData) {
+ if(!XMLRPC_ServerAddIntrospectionData(server, xData)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to add introspection data returned from %v(), improper element structure", Z_UNIVAL(php_function_name));
+ }
+ XMLRPC_CleanupValue(xData);
+ } else {
+ /* could not create description */
+ if(err.xml_elem_error.parser_code) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "xml parse error: [line %ld, column %ld, message: %s] Unable to add introspection data returned from %v()",
+ err.xml_elem_error.column, err.xml_elem_error.line, err.xml_elem_error.parser_error, Z_UNIVAL(php_function_name));
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to add introspection data returned from %v()", Z_UNIVAL(php_function_name));
+ }
}
+ zval_dtor(&retval);
+ } else {
+ /* user func failed */
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error calling user introspection callback: %v()", Z_UNIVAL(php_function_name));
}
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid callback '%v' passed", Z_UNIVAL(php_function_name));
}
- else {
- /* user func failed */
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error calling user introspection callback: %s()", Z_STRVAL_PP(php_function));
- }
- }
- else {
+ zval_dtor(&php_function_name);
+ } else {
break;
}