mirror of
https://github.com/php/php-src.git
synced 2024-09-21 09:57:23 +00:00
Mitigate #51561: SoapServer with a extented class and using sessions, lost the setPersistence()
The problem is that in the testcase, the session is started before the parent class is loaded. This causes an incomplete class in the session storage. Then in the soap code the check `Z_OBJCE_P(tmp_soap_p) == service->soap_class.ce` fails because it is the incomplete class. It is a silent failure. We cannot fix this easily. But we should let the user know something is wrong, because it leaves them confused otherwise. So emit an error to let them know and suggest a fix. Closes GH-12540.
This commit is contained in:
parent
e71522419f
commit
53218b1a32
2
NEWS
2
NEWS
@ -33,6 +33,8 @@ SimpleXML:
|
||||
|
||||
SOAP:
|
||||
. Add support for clark notation for namespaces in class map. (lxShaDoWxl)
|
||||
. Mitigate #51561 (SoapServer with a extented class and using sessions,
|
||||
lost the setPersistence()). (nielsdos)
|
||||
|
||||
Standard:
|
||||
. Implement GH-12188 (Indication for the int size in phpinfo()). (timwolla)
|
||||
|
@ -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
|
||||
|
2
ext/soap/tests/bugs/bug51561.inc
Normal file
2
ext/soap/tests/bugs/bug51561.inc
Normal file
@ -0,0 +1,2 @@
|
||||
<?php
|
||||
class Server2 {}
|
49
ext/soap/tests/bugs/bug51561.phpt
Normal file
49
ext/soap/tests/bugs/bug51561.phpt
Normal file
@ -0,0 +1,49 @@
|
||||
--TEST--
|
||||
Bug #51561 (SoapServer with a extended class and using sessions, lost the setPersistence())
|
||||
--EXTENSIONS--
|
||||
soap
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!file_exists(__DIR__ . "/../../../../sapi/cli/tests/php_cli_server.inc")) {
|
||||
echo "skip sapi/cli/tests/php_cli_server.inc required but not found";
|
||||
}
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
include __DIR__ . "/../../../../sapi/cli/tests/php_cli_server.inc";
|
||||
|
||||
$args = ["-d", "extension_dir=" . ini_get("extension_dir"), "-d", "extension=" . (substr(PHP_OS, 0, 3) == "WIN" ? "php_" : "") . "soap." . PHP_SHLIB_SUFFIX];
|
||||
if (php_ini_loaded_file()) {
|
||||
// Necessary such that it works from a development directory in which case extension_dir might not be the real extension dir
|
||||
$args[] = "-c";
|
||||
$args[] = php_ini_loaded_file();
|
||||
}
|
||||
$code = "session_start();" .
|
||||
"require_once '" . __DIR__ . "/bug51561.inc';" .
|
||||
<<<'PHP'
|
||||
class Server extends Server2 {
|
||||
private $value;
|
||||
public function setValue($param) { $this->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
|
Loading…
Reference in New Issue
Block a user