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