diff --git a/ext/soap/soap.c b/ext/soap/soap.c index 17ed373b4398b..d28c77ca9bb68 100644 --- a/ext/soap/soap.c +++ b/ext/soap/soap.c @@ -26,6 +26,7 @@ #include "soap_arginfo.h" #include "zend_exceptions.h" #include "zend_interfaces.h" +#include "ext/standard/php_incomplete_class.h" static int le_sdl = 0; @@ -1330,9 +1331,13 @@ PHP_METHOD(SoapServer, handle) ZVAL_DEREF(session_vars); if (Z_TYPE_P(session_vars) == IS_ARRAY && (tmp_soap_p = zend_hash_str_find(Z_ARRVAL_P(session_vars), "_bogus_session_name", sizeof("_bogus_session_name")-1)) != NULL && - Z_TYPE_P(tmp_soap_p) == IS_OBJECT && - Z_OBJCE_P(tmp_soap_p) == service->soap_class.ce) { - soap_obj = tmp_soap_p; + Z_TYPE_P(tmp_soap_p) == IS_OBJECT) { + if (EXPECTED(Z_OBJCE_P(tmp_soap_p) == service->soap_class.ce)) { + soap_obj = tmp_soap_p; + } else if (Z_OBJCE_P(tmp_soap_p) == php_ce_incomplete_class) { + /* See #51561, communicate limitation to user */ + soap_server_fault("Server", "SoapServer class was deserialized from the session prior to loading the class passed to SoapServer::setClass(). Start the session after loading all classes to resolve this issue.", NULL, NULL, NULL); + } } } #endif diff --git a/ext/soap/tests/bugs/bug51561.inc b/ext/soap/tests/bugs/bug51561.inc new file mode 100644 index 0000000000000..27778d07c5e6c --- /dev/null +++ b/ext/soap/tests/bugs/bug51561.inc @@ -0,0 +1,2 @@ + +--FILE-- +value = $param; } + public function getValue() { return $this->value; } + } + $server = new SoapServer(null, array('uri' => "blablabla.com",'encoding' => "ISO-8859-1",'soap_version' => SOAP_1_2)); + $server->setClass("Server"); + $server->setPersistence(SOAP_PERSISTENCE_SESSION); + $server->handle(); + PHP; + +php_cli_server_start($code, null, $args); + +$cli = new SoapClient(null, array('location' => "http://".PHP_CLI_SERVER_ADDRESS, 'uri' => "blablabla.com",'encoding' => "ISO-8859-1",'soap_version' => SOAP_1_2)); +$cli->setValue(100); +$response = $cli->getValue(); +echo "Get = ".$response; + +?> +--EXPECTF-- +Fatal error: Uncaught SoapFault exception: [env:Receiver] SoapServer class was deserialized from the session prior to loading the class passed to SoapServer::setClass(). Start the session after loading all classes to resolve this issue. in %s:%d +Stack trace: +#0 %s(%d): SoapClient->__call('getValue', Array) +#1 {main} + thrown in %s on line %d