[php-src] PHP-8.4: Fix GH-23447: segfault when the SoapServer class fails to initialize

Lazizbek Ergashev via David Carlier <[email protected]>
Newsgroups gmane.comp.php.cvs.general
Message-ID <[email protected]>
Author: Lazizbek Ergashev (lazerg)
Committer: David Carlier (devnexen)
Date: 2026-08-30T12:49:03+01:00

Commit: https://github.com/php/php-src/commit/8dafaf5da2f5fc1c332c1fd3c1ccb0f322d21c51
Raw diff: https://github.com/php/php-src/commit/8dafaf5da2f5fc1c332c1fd3c1ccb0f322d21c51.diff

Fix GH-23447: segfault when the SoapServer class fails to initialize

SoapServer::handle() ignored the return value of object_init_ex(), so when
the class given to setClass() could not be instantiated the code carried on
with a NULL zval and crashed on Z_OBJCE_P(soap_obj). That happens for
instance when a property default references an undefined constant, since
evaluating it throws an Error and object creation fails.

Now the failure is reported as a SOAP fault, the same way a throwing
constructor already is.

Close GH-23448

Changed paths:
  A  ext/soap/tests/gh23447.phpt
  M  NEWS
  M  ext/soap/soap.c


Diff:

diff --git a/NEWS b/NEWS
index 519b0ccaf053..04adab59625e 100644
--- a/NEWS
+++ b/NEWS
@@ -62,6 +62,10 @@ PHP                                                                        NEWS
   . Fixed bug GH-23477 (Memory leak on duplicate native Phar manifest entries).
     (Weilin Du)
 
+- SOAP:
+  . Fixed bug GH-23447 (Segfault when a class passed to SoapServer::setClass()
+    fails to initialize). (Lazizbek Ergashev)
+
 - Standard:
   . Fixed a segfault when a stream filter callback unsets StreamBucket::$data
     before re-attaching the bucket. (iliaal)
diff --git a/ext/soap/soap.c b/ext/soap/soap.c
index 3d5536ef8628..4703c7779305 100644
--- a/ext/soap/soap.c
+++ b/ext/soap/soap.c
@@ -1478,7 +1478,11 @@ PHP_METHOD(SoapServer, handle)
 
 		/* If new session or something weird happned */
 		if (soap_obj == NULL) {
-			object_init_ex(&tmp_soap, service->soap_class.ce);
+			if (UNEXPECTED(object_init_ex(&tmp_soap, service->soap_class.ce) != SUCCESS)) {
+				php_output_discard();
+				_soap_server_exception(service, function, ZEND_THIS);
+				goto fail;
+			}
 
 			/* Call constructor */
 			if (service->soap_class.ce->constructor) {
diff --git a/ext/soap/tests/gh23447.phpt b/ext/soap/tests/gh23447.phpt
new file mode 100644
index 000000000000..16ecc4568ebd
--- /dev/null
+++ b/ext/soap/tests/gh23447.phpt
@@ -0,0 +1,28 @@
+--TEST--
+GH-23447 (Segfault when a class passed to SoapServer::setClass() fails to initialize)
+--EXTENSIONS--
+soap
+--CREDITS--
+Lu Maltsis (@lmaltsis)
+--FILE--
+<?php
+class foo {
+    private $broken = undefinedConstant;
+}
+
+$server = new SoapServer(null, ['uri' => 'http://testuri.org']);
+$server->setClass('foo');
+
+$server->handle(<<<'XML'
+<?xml version="1.0"?>
+<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
+  <SOAP-ENV:Body><anything/></SOAP-ENV:Body>
+</SOAP-ENV:Envelope>
+XML);
+
+echo "ok\n";
+?>
+--EXPECT--
+<?xml version="1.0" encoding="UTF-8"?>
+<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body><SOAP-ENV:Fault><faultcode>SOAP-ENV:Server</faultcode><faultstring>Undefined constant "undefinedConstant"</faultstring></SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope>
+ok
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.