From 8987c0b66120e8e3143796f58a64211ac8522baa Mon Sep 17 00:00:00 2001
From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
Date: Fri, 12 Sep 2025 22:06:10 +0200
Subject: [PATCH] Fix uninitialized soap lang_en string on ZTS
Replaces GH-19772.
Closes GH-19772.
Fixes GH-19773.
Closes GH-19819.
---
NEWS | 5 ++++-
ext/soap/php_http.c | 24 ++++++++++++------------
ext/soap/php_packet_soap.c | 30 +++++++++++++++---------------
ext/soap/php_soap.h | 3 ++-
ext/soap/soap.c | 16 +++++++++-------
ext/soap/tests/bugs/bug38005.phpt | 2 +-
ext/soap/tests/bugs/bug68996.phpt | 2 +-
ext/soap/tests/soap12/T63.phpt | 2 +-
8 files changed, 45 insertions(+), 39 deletions(-)
diff --git a/NEWS b/NEWS
index 10d90647822..a6749b8ed40 100644
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,10 @@ PHP NEWS
- URI:
. Fixed Uri\WhatWg\Url::withPort() when an invalid value is passed. (timwolla)
+- SOAP:
+ . Fixed bug GH-19773 (SIGSEGV due to uninitialized soap_globals->lang_en).
+ (nielsdos, KaseyJenkins)
+
25 Sep 2025, PHP 8.5.0RC1
- Core:
@@ -771,5 +775,4 @@ PHP NEWS
opening HTTP URLs). (nielsdos)
. Implemented GH-17668 (zlib streams should support locking). (nielsdos)
-
<<< NOTE: Insert NEWS from last stable release here prior to actual release! >>>
diff --git a/ext/soap/php_http.c b/ext/soap/php_http.c
index ac5f0f0f9d1..7d8538b36c2 100644
--- a/ext/soap/php_http.c
+++ b/ext/soap/php_http.c
@@ -460,7 +460,7 @@ try_again:
if (request != buf) {
zend_string_release_ex(request, 0);
}
- add_soap_fault(this_ptr, "HTTP", "Unable to parse URL", NULL, NULL, SOAP_GLOBAL(lang_en));
+ add_soap_fault(this_ptr, "HTTP", "Unable to parse URL", NULL, NULL, soap_lang_en);
smart_str_free(&soap_headers_z);
efree(http_msg);
return FALSE;
@@ -474,7 +474,7 @@ try_again:
if (request != buf) {
zend_string_release_ex(request, 0);
}
- add_soap_fault(this_ptr, "HTTP", "Unknown protocol. Only http and https are allowed.", NULL, NULL, SOAP_GLOBAL(lang_en));
+ add_soap_fault(this_ptr, "HTTP", "Unknown protocol. Only http and https are allowed.", NULL, NULL, soap_lang_en);
smart_str_free(&soap_headers_z);
efree(http_msg);
return FALSE;
@@ -487,7 +487,7 @@ try_again:
if (request != buf) {
zend_string_release_ex(request, 0);
}
- add_soap_fault(this_ptr, "HTTP", "SSL support is not available in this build", NULL, NULL, SOAP_GLOBAL(lang_en));
+ add_soap_fault(this_ptr, "HTTP", "SSL support is not available in this build", NULL, NULL, soap_lang_en);
PG(allow_url_fopen) = old_allow_url_fopen;
smart_str_free(&soap_headers_z);
efree(http_msg);
@@ -540,7 +540,7 @@ try_again:
if (request != buf) {
zend_string_release_ex(request, 0);
}
- add_soap_fault(this_ptr, "HTTP", "Could not connect to host", NULL, NULL, SOAP_GLOBAL(lang_en));
+ add_soap_fault(this_ptr, "HTTP", "Could not connect to host", NULL, NULL, soap_lang_en);
PG(allow_url_fopen) = old_allow_url_fopen;
smart_str_free(&soap_headers_z);
efree(http_msg);
@@ -911,14 +911,14 @@ try_again:
php_stream_close(stream);
convert_to_null(Z_CLIENT_HTTPURL_P(this_ptr));
ZVAL_NULL(Z_CLIENT_USE_PROXY_P(this_ptr));
- add_soap_fault(this_ptr, "HTTP", "Failed Sending HTTP SOAP request", NULL, NULL, SOAP_GLOBAL(lang_en));
+ add_soap_fault(this_ptr, "HTTP", "Failed Sending HTTP SOAP request", NULL, NULL, soap_lang_en);
smart_str_free(&soap_headers_z);
efree(http_msg);
return FALSE;
}
smart_str_free(&soap_headers);
} else {
- add_soap_fault(this_ptr, "HTTP", "Failed to create stream??", NULL, NULL, SOAP_GLOBAL(lang_en));
+ add_soap_fault(this_ptr, "HTTP", "Failed to create stream??", NULL, NULL, soap_lang_en);
smart_str_free(&soap_headers_z);
efree(http_msg);
return FALSE;
@@ -935,7 +935,7 @@ try_again:
ZVAL_NULL(Z_CLIENT_HTTPSOCKET_P(this_ptr));
php_stream_close(stream);
ZVAL_NULL(Z_CLIENT_USE_PROXY_P(this_ptr));
- add_soap_fault(this_ptr, "HTTP", "Error Fetching http headers", NULL, NULL, SOAP_GLOBAL(lang_en));
+ add_soap_fault(this_ptr, "HTTP", "Error Fetching http headers", NULL, NULL, soap_lang_en);
smart_str_free(&soap_headers_z);
efree(http_msg);
return FALSE;
@@ -1124,7 +1124,7 @@ try_again:
php_stream_close(stream);
zend_string_release_ex(http_headers, 0);
ZVAL_NULL(Z_CLIENT_USE_PROXY_P(this_ptr));
- add_soap_fault(this_ptr, "HTTP", "Error Fetching http body, No Content-Length, connection closed or chunked data", NULL, NULL, SOAP_GLOBAL(lang_en));
+ add_soap_fault(this_ptr, "HTTP", "Error Fetching http body, No Content-Length, connection closed or chunked data", NULL, NULL, soap_lang_en);
if (http_msg) {
efree(http_msg);
}
@@ -1190,7 +1190,7 @@ try_again:
uri = new_uri;
if (--redirect_max < 1) {
- add_soap_fault(this_ptr, "HTTP", "Redirection limit reached, aborting", NULL, NULL, SOAP_GLOBAL(lang_en));
+ add_soap_fault(this_ptr, "HTTP", "Redirection limit reached, aborting", NULL, NULL, soap_lang_en);
smart_str_free(&soap_headers_z);
efree(http_msg);
return FALSE;
@@ -1326,7 +1326,7 @@ try_again:
if (http_msg) {
efree(http_msg);
}
- add_soap_fault(this_ptr, "HTTP", "Unknown Content-Encoding", NULL, NULL, SOAP_GLOBAL(lang_en));
+ add_soap_fault(this_ptr, "HTTP", "Unknown Content-Encoding", NULL, NULL, soap_lang_en);
return FALSE;
}
zend_call_known_function(decompression_fn, NULL, NULL, &retval, 1, params, NULL);
@@ -1338,7 +1338,7 @@ try_again:
efree(content_encoding);
zend_string_release_ex(http_headers, 0);
zend_string_release_ex(http_body, 0);
- add_soap_fault(this_ptr, "HTTP", "Can't uncompress compressed response", NULL, NULL, SOAP_GLOBAL(lang_en));
+ add_soap_fault(this_ptr, "HTTP", "Can't uncompress compressed response", NULL, NULL, soap_lang_en);
if (http_msg) {
efree(http_msg);
}
@@ -1372,7 +1372,7 @@ try_again:
if (error) {
zval_ptr_dtor(return_value);
ZVAL_UNDEF(return_value);
- add_soap_fault(this_ptr, "HTTP", http_msg, NULL, NULL, SOAP_GLOBAL(lang_en));
+ add_soap_fault(this_ptr, "HTTP", http_msg, NULL, NULL, soap_lang_en);
efree(http_msg);
return FALSE;
}
diff --git a/ext/soap/php_packet_soap.c b/ext/soap/php_packet_soap.c
index 31ed094ef2f..1019949093f 100644
--- a/ext/soap/php_packet_soap.c
+++ b/ext/soap/php_packet_soap.c
@@ -40,11 +40,11 @@ bool parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctio
response = soap_xmlParseMemory(buffer, buffer_size);
if (!response) {
- add_soap_fault(this_ptr, "Client", "looks like we got no XML document", NULL, NULL, SOAP_GLOBAL(lang_en));
+ add_soap_fault(this_ptr, "Client", "looks like we got no XML document", NULL, NULL, soap_lang_en);
return false;
}
if (xmlGetIntSubset(response) != NULL) {
- add_soap_fault(this_ptr, "Client", "DTD are not supported by SOAP", NULL, NULL, SOAP_GLOBAL(lang_en));
+ add_soap_fault(this_ptr, "Client", "DTD are not supported by SOAP", NULL, NULL, soap_lang_en);
xmlFreeDoc(response);
return false;
}
@@ -63,7 +63,7 @@ bool parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctio
envelope_ns = SOAP_1_2_ENV_NAMESPACE;
soap_version = SOAP_1_2;
} else {
- add_soap_fault(this_ptr, "VersionMismatch", "Wrong Version", NULL, NULL, SOAP_GLOBAL(lang_en));
+ add_soap_fault(this_ptr, "VersionMismatch", "Wrong Version", NULL, NULL, soap_lang_en);
xmlFreeDoc(response);
return false;
}
@@ -71,7 +71,7 @@ bool parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctio
trav = trav->next;
}
if (env == NULL) {
- add_soap_fault(this_ptr, "Client", "looks like we got XML without \"Envelope\" element", NULL, NULL, SOAP_GLOBAL(lang_en));
+ add_soap_fault(this_ptr, "Client", "looks like we got XML without \"Envelope\" element", NULL, NULL, soap_lang_en);
xmlFreeDoc(response);
return false;
}
@@ -79,16 +79,16 @@ bool parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctio
attr = env->properties;
while (attr != NULL) {
if (attr->ns == NULL) {
- add_soap_fault(this_ptr, "Client", "A SOAP Envelope element cannot have non Namespace qualified attributes", NULL, NULL, SOAP_GLOBAL(lang_en));
+ add_soap_fault(this_ptr, "Client", "A SOAP Envelope element cannot have non Namespace qualified attributes", NULL, NULL, soap_lang_en);
xmlFreeDoc(response);
return false;
} else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
if (soap_version == SOAP_1_2) {
- add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Envelope", NULL, NULL, SOAP_GLOBAL(lang_en));
+ add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Envelope", NULL, NULL, soap_lang_en);
xmlFreeDoc(response);
return false;
} else if (strcmp((char*)attr->children->content, SOAP_1_1_ENC_NAMESPACE) != 0) {
- add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL, SOAP_GLOBAL(lang_en));
+ add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL, soap_lang_en);
xmlFreeDoc(response);
return false;
}
@@ -120,7 +120,7 @@ bool parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctio
trav = trav->next;
}
if (body == NULL) {
- add_soap_fault(this_ptr, "Client", "Body must be present in a SOAP envelope", NULL, NULL, SOAP_GLOBAL(lang_en));
+ add_soap_fault(this_ptr, "Client", "Body must be present in a SOAP envelope", NULL, NULL, soap_lang_en);
xmlFreeDoc(response);
return false;
}
@@ -128,17 +128,17 @@ bool parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctio
while (attr != NULL) {
if (attr->ns == NULL) {
if (soap_version == SOAP_1_2) {
- add_soap_fault(this_ptr, "Client", "A SOAP Body element cannot have non Namespace qualified attributes", NULL, NULL, SOAP_GLOBAL(lang_en));
+ add_soap_fault(this_ptr, "Client", "A SOAP Body element cannot have non Namespace qualified attributes", NULL, NULL, soap_lang_en);
xmlFreeDoc(response);
return false;
}
} else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
if (soap_version == SOAP_1_2) {
- add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Body", NULL, NULL, SOAP_GLOBAL(lang_en));
+ add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Body", NULL, NULL, soap_lang_en);
xmlFreeDoc(response);
return false;
} else if (strcmp((char*)attr->children->content, SOAP_1_1_ENC_NAMESPACE) != 0) {
- add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL, SOAP_GLOBAL(lang_en));
+ add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL, soap_lang_en);
xmlFreeDoc(response);
return false;
}
@@ -146,7 +146,7 @@ bool parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctio
attr = attr->next;
}
if (trav != NULL && soap_version == SOAP_1_2) {
- add_soap_fault(this_ptr, "Client", "A SOAP 1.2 envelope can contain only Header and Body", NULL, NULL, SOAP_GLOBAL(lang_en));
+ add_soap_fault(this_ptr, "Client", "A SOAP 1.2 envelope can contain only Header and Body", NULL, NULL, soap_lang_en);
xmlFreeDoc(response);
return false;
}
@@ -155,16 +155,16 @@ bool parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctio
attr = head->properties;
while (attr != NULL) {
if (attr->ns == NULL) {
- add_soap_fault(this_ptr, "Client", "A SOAP Header element cannot have non Namespace qualified attributes", NULL, NULL, SOAP_GLOBAL(lang_en));
+ add_soap_fault(this_ptr, "Client", "A SOAP Header element cannot have non Namespace qualified attributes", NULL, NULL, soap_lang_en);
xmlFreeDoc(response);
return false;
} else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
if (soap_version == SOAP_1_2) {
- add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Header", NULL, NULL, SOAP_GLOBAL(lang_en));
+ add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Header", NULL, NULL, soap_lang_en);
xmlFreeDoc(response);
return false;
} else if (strcmp((char*)attr->children->content, SOAP_1_1_ENC_NAMESPACE) != 0) {
- add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL, SOAP_GLOBAL(lang_en));
+ add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL, soap_lang_en);
xmlFreeDoc(response);
return false;
}
diff --git a/ext/soap/php_soap.h b/ext/soap/php_soap.h
index 48f8fb50591..aa3fb79e570 100644
--- a/ext/soap/php_soap.h
+++ b/ext/soap/php_soap.h
@@ -171,9 +171,10 @@ ZEND_BEGIN_MODULE_GLOBALS(soap)
HashTable wsdl_cache;
int cur_uniq_ref;
HashTable *ref_map;
- zend_string *lang_en;
ZEND_END_MODULE_GLOBALS(soap)
+extern zend_string *soap_lang_en;
+
#ifdef ZTS
#include "TSRM.h"
#endif
diff --git a/ext/soap/soap.c b/ext/soap/soap.c
index 167dd4bb30a..55bcdf3eb88 100644
--- a/ext/soap/soap.c
+++ b/ext/soap/soap.c
@@ -194,6 +194,8 @@ static zend_object_handlers soap_server_object_handlers;
static zend_object_handlers soap_url_object_handlers;
static zend_object_handlers soap_sdl_object_handlers;
+zend_string *soap_lang_en;
+
typedef struct {
soapServicePtr service;
zend_object std;
@@ -472,7 +474,7 @@ PHP_MSHUTDOWN_FUNCTION(soap)
zend_hash_destroy(SOAP_GLOBAL(mem_cache));
free(SOAP_GLOBAL(mem_cache));
}
- zend_string_release_ex(SOAP_GLOBAL(lang_en), true);
+ zend_string_release_ex(soap_lang_en, true);
UNREGISTER_INI_ENTRIES();
return SUCCESS;
}
@@ -552,7 +554,7 @@ PHP_MINIT_FUNCTION(soap)
old_error_handler = zend_error_cb;
zend_error_cb = soap_error_handler;
- SOAP_GLOBAL(lang_en) = zend_string_init_interned(ZEND_STRL("en"), true);
+ soap_lang_en = zend_string_init_interned(ZEND_STRL("en"), true);
return SUCCESS;
}
@@ -712,7 +714,7 @@ PHP_METHOD(SoapFault, __construct)
}
this_ptr = ZEND_THIS;
- set_soap_fault(this_ptr, fault_code_ns, fault_code, fault_string, fault_actor, details, name, lang);
+ set_soap_fault(this_ptr, fault_code_ns, fault_code, fault_string, fault_actor, details, name, soap_lang_en);
if (headerfault != NULL) {
ZVAL_COPY(Z_FAULT_HEADERFAULT_P(this_ptr), headerfault);
}
@@ -1859,7 +1861,7 @@ static ZEND_NORETURN void soap_server_fault(char* code, char* string, char *acto
static ZEND_NORETURN void soap_server_fault_en(char* code, char* string, char *actor, zval* details, zend_string* name)
{
- soap_server_fault(code, string, actor, details, name, SOAP_GLOBAL(lang_en));
+ soap_server_fault(code, string, actor, details, name, soap_lang_en);
}
static zend_never_inline ZEND_COLD void soap_real_error_handler(int error_num, zend_string *error_filename, const uint32_t error_lineno, zend_string *message) /* {{{ */
@@ -1928,7 +1930,7 @@ static zend_never_inline ZEND_COLD void soap_real_error_handler(int error_num, z
}
ZVAL_NULL(&fault_obj);
- set_soap_fault(&fault_obj, NULL, code, ZSTR_VAL(buffer), NULL, &outbuf, NULL, SOAP_GLOBAL(lang_en));
+ set_soap_fault(&fault_obj, NULL, code, ZSTR_VAL(buffer), NULL, &outbuf, NULL, soap_lang_en);
zend_string_release(buffer);
fault = 1;
}
@@ -2941,7 +2943,7 @@ static void add_soap_fault_ex(zval *fault, zval *obj, char *fault_code, char *fa
static void add_soap_fault_ex_en(zval *fault, zval *obj, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail)
{
- add_soap_fault_ex(fault, obj, fault_code, fault_string, fault_actor, fault_detail, SOAP_GLOBAL(lang_en));
+ add_soap_fault_ex(fault, obj, fault_code, fault_string, fault_actor, fault_detail, soap_lang_en);
}
void add_soap_fault(zval *obj, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail, zend_string *lang) /* {{{ */
@@ -2953,7 +2955,7 @@ void add_soap_fault(zval *obj, char *fault_code, char *fault_string, char *fault
static void add_soap_fault_en(zval *obj, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail)
{
- add_soap_fault(obj, fault_code, fault_string, fault_actor, fault_detail, SOAP_GLOBAL(lang_en));
+ add_soap_fault(obj, fault_code, fault_string, fault_actor, fault_detail, soap_lang_en);
}
static void set_soap_fault(zval *obj, const char *fault_code_ns, const char *fault_code, const char *fault_string, const char *fault_actor, zval *fault_detail, zend_string *name, zend_string *lang) /* {{{ */
diff --git a/ext/soap/tests/bugs/bug38005.phpt b/ext/soap/tests/bugs/bug38005.phpt
index 67837861ea5..dc2437baa9e 100644
--- a/ext/soap/tests/bugs/bug38005.phpt
+++ b/ext/soap/tests/bugs/bug38005.phpt
@@ -42,4 +42,4 @@ echo($client->__getLastResponse());
--EXPECT--
This is our fault: Ä
-TestThis is our fault: Ä
+TestThis is our fault: Ä
diff --git a/ext/soap/tests/bugs/bug68996.phpt b/ext/soap/tests/bugs/bug68996.phpt
index bcc0e66cbeb..8aa858e6545 100644
--- a/ext/soap/tests/bugs/bug68996.phpt
+++ b/ext/soap/tests/bugs/bug68996.phpt
@@ -56,4 +56,4 @@ handleFormatted($s, $HTTP_RAW_POST_DATA);
some msg
-some msg
+some msg
diff --git a/ext/soap/tests/soap12/T63.phpt b/ext/soap/tests/soap12/T63.phpt
index a8cf3c431b2..810207e50ee 100644
--- a/ext/soap/tests/soap12/T63.phpt
+++ b/ext/soap/tests/soap12/T63.phpt
@@ -21,5 +21,5 @@ include "soap12-test.inc";
?>
--EXPECT--
-Country code must be 2 letters.env:SenderNot a valid country code
+Country code must be 2 letters.env:SenderNot a valid country code
ok