From 28c6659b060c43e7aa2b91fe0677fb97c60b751f Mon Sep 17 00:00:00 2001 From: ndossche <7771979+ndossche@users.noreply.github.com> Date: Wed, 11 Mar 2026 23:30:02 +0100 Subject: [PATCH 1/5] dom: Simplify return value management of xpath callback --- ext/dom/xpath_callbacks.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/ext/dom/xpath_callbacks.c b/ext/dom/xpath_callbacks.c index 0974db475b3a..2115bc3df41f 100644 --- a/ext/dom/xpath_callbacks.c +++ b/ext/dom/xpath_callbacks.c @@ -435,7 +435,6 @@ static zend_result php_dom_xpath_callback_dispatch(php_dom_xpath_callbacks *xpat if (xpath_callbacks->node_list == NULL) { xpath_callbacks->node_list = zend_new_array(0); } - Z_ADDREF_P(&callback_retval); zend_hash_next_index_insert_new(xpath_callbacks->node_list, &callback_retval); obj = Z_DOMOBJ_P(&callback_retval); nodep = dom_object_get_node(obj); @@ -447,12 +446,10 @@ static zend_result php_dom_xpath_callback_dispatch(php_dom_xpath_callbacks *xpat zval_ptr_dtor(&callback_retval); return FAILURE; } else { - zend_string *tmp_str; - zend_string *str = zval_get_tmp_string(&callback_retval, &tmp_str); - valuePush(ctxt, xmlXPathNewString(BAD_CAST ZSTR_VAL(str))); - zend_tmp_string_release(tmp_str); + convert_to_string(&callback_retval); + valuePush(ctxt, xmlXPathNewString(BAD_CAST Z_STRVAL(callback_retval))); + zval_ptr_dtor_str(&callback_retval); } - zval_ptr_dtor(&callback_retval); } return SUCCESS; From 46357cbaafeba07fdb2ec689bf5b87203b53b915 Mon Sep 17 00:00:00 2001 From: ndossche <7771979+ndossche@users.noreply.github.com> Date: Wed, 11 Mar 2026 23:30:39 +0100 Subject: [PATCH 2/5] dom: Merge declaration and assignment --- ext/dom/xpath_callbacks.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ext/dom/xpath_callbacks.c b/ext/dom/xpath_callbacks.c index 2115bc3df41f..816c925435ae 100644 --- a/ext/dom/xpath_callbacks.c +++ b/ext/dom/xpath_callbacks.c @@ -430,14 +430,12 @@ static zend_result php_dom_xpath_callback_dispatch(php_dom_xpath_callbacks *xpat if (Z_TYPE(callback_retval) != IS_UNDEF) { if (Z_TYPE(callback_retval) == IS_OBJECT && (instanceof_function(Z_OBJCE(callback_retval), dom_get_node_ce(php_dom_follow_spec_node((const xmlNode *) ctxt->context->doc))))) { - xmlNode *nodep; - dom_object *obj; if (xpath_callbacks->node_list == NULL) { xpath_callbacks->node_list = zend_new_array(0); } zend_hash_next_index_insert_new(xpath_callbacks->node_list, &callback_retval); - obj = Z_DOMOBJ_P(&callback_retval); - nodep = dom_object_get_node(obj); + dom_object *obj = Z_DOMOBJ_P(&callback_retval); + xmlNodePtr nodep = dom_object_get_node(obj); valuePush(ctxt, xmlXPathNewNodeSet(nodep)); } else if (Z_TYPE(callback_retval) == IS_FALSE || Z_TYPE(callback_retval) == IS_TRUE) { valuePush(ctxt, xmlXPathNewBoolean(Z_TYPE(callback_retval) == IS_TRUE)); From b0aa6b9626a71dd865a573ef14eeb76fe6a6a372 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Thu, 12 Mar 2026 17:56:43 +0000 Subject: [PATCH 3/5] ext/soap: various optimisations * replace strcat/strncpy with memcpy for pre-allocated buffers. * remove redundant memset before struct copy. --- ext/soap/php_http.c | 10 ++-------- ext/soap/php_sdl.c | 3 --- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/ext/soap/php_http.c b/ext/soap/php_http.c index 4bf599234f78..bac21d26b358 100644 --- a/ext/soap/php_http.c +++ b/ext/soap/php_http.c @@ -1168,18 +1168,12 @@ int make_http_soap_request( char *t = ZSTR_VAL(new_uri->path); char *p = strrchr(t, '/'); if (p) { - zend_string *s = zend_string_alloc((p - t) + ZSTR_LEN(new_uri->path) + 2, 0); - strncpy(ZSTR_VAL(s), t, (p - t) + 1); - ZSTR_VAL(s)[(p - t) + 1] = 0; - strcat(ZSTR_VAL(s), ZSTR_VAL(new_uri->path)); + zend_string *s = zend_string_concat2(t, (p - t) + 1, ZSTR_VAL(new_uri->path), ZSTR_LEN(new_uri->path)); zend_string_release_ex(new_uri->path, 0); new_uri->path = s; } } else { - zend_string *s = zend_string_alloc(ZSTR_LEN(new_uri->path) + 2, 0); - ZSTR_VAL(s)[0] = '/'; - ZSTR_VAL(s)[1] = 0; - strcat(ZSTR_VAL(s), ZSTR_VAL(new_uri->path)); + zend_string *s = zend_string_concat2("/", 1, ZSTR_VAL(new_uri->path), ZSTR_LEN(new_uri->path)); zend_string_release_ex(new_uri->path, 0); new_uri->path = s; } diff --git a/ext/soap/php_sdl.c b/ext/soap/php_sdl.c index e6871cd6e9b3..ad37867dd460 100644 --- a/ext/soap/php_sdl.c +++ b/ext/soap/php_sdl.c @@ -2433,7 +2433,6 @@ static HashTable* make_persistent_sdl_function_headers(HashTable *headers, HashT ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(headers, key, tmp) { pheader = malloc(sizeof(sdlSoapBindingFunctionHeader)); - memset(pheader, 0, sizeof(sdlSoapBindingFunctionHeader)); *pheader = *tmp; if (pheader->name) { @@ -2497,7 +2496,6 @@ static HashTable* make_persistent_sdl_parameters(HashTable *params, HashTable *p ZEND_HASH_FOREACH_STR_KEY_PTR(params, key, tmp) { pparam = malloc(sizeof(sdlParam)); - memset(pparam, 0, sizeof(sdlParam)); *pparam = *tmp; if (pparam->paramName) { @@ -2539,7 +2537,6 @@ static HashTable* make_persistent_sdl_function_faults(sdlFunctionPtr func, HashT ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(faults, key, tmp) { pfault = malloc(sizeof(sdlFault)); - memset(pfault, 0, sizeof(sdlFault)); *pfault = *tmp; if (pfault->name) { From 7950482562f3f53fb06d9933474b981358689faf Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sun, 8 Mar 2026 17:56:29 -0400 Subject: [PATCH 4/5] Fix GH-21083: Skip private_key_bits validation for EC/curve-based keys openssl_pkey_new() checks private_key_bits >= 384 before generating any key. For EC, X25519, ED25519, X448, and ED448 the size is inherent to the curve or algorithm, so this check doesn't apply and causes failures when default_bits is missing from openssl.cnf (which is the case in OpenSSL 3.6's default config). Skip the minimum-bits check for key types that don't use private_key_bits. Closes GH-21387. --- NEWS | 4 +++ ext/openssl/openssl.c | 5 ++- ext/openssl/tests/gh21083.phpt | 61 ++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 ext/openssl/tests/gh21083.phpt diff --git a/NEWS b/NEWS index 088a2768da3c..76cca47611f6 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,10 @@ PHP NEWS - Bz2: . Fix truncation of total output size causing erroneous errors. (ndossche) +- OpenSSL: + . Fixed bug GH-21083 (Skip private_key_bits validation for EC/curve-based + keys). (iliaal) + - PCRE: . Fixed re-entrancy issue on php_pcre_match_impl, php_pcre_replace_impl, php_pcre_split_impl, and php_pcre_grep_impl. (David Carlier) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 2f2aae1e7335..7e2b95683256 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -3828,7 +3828,10 @@ static int php_openssl_get_evp_pkey_type(int key_type) { /* {{{ php_openssl_generate_private_key */ static EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req) { - if (req->priv_key_bits < MIN_KEY_LENGTH) { + if ((req->priv_key_type == OPENSSL_KEYTYPE_RSA || + req->priv_key_type == OPENSSL_KEYTYPE_DH || + req->priv_key_type == OPENSSL_KEYTYPE_DSA) && + req->priv_key_bits < MIN_KEY_LENGTH) { php_error_docref(NULL, E_WARNING, "Private key length must be at least %d bits, configured to %d", MIN_KEY_LENGTH, req->priv_key_bits); return NULL; diff --git a/ext/openssl/tests/gh21083.phpt b/ext/openssl/tests/gh21083.phpt new file mode 100644 index 000000000000..31afb7ca084d --- /dev/null +++ b/ext/openssl/tests/gh21083.phpt @@ -0,0 +1,61 @@ +--TEST-- +GH-21083 (openssl_pkey_new() fails for EC keys when private_key_bits is not set) +--EXTENSIONS-- +openssl +--SKIPIF-- + +--ENV-- +OPENSSL_CONF= +--FILE-- + $conf, + 'private_key_type' => OPENSSL_KEYTYPE_EC, + 'curve_name' => 'prime256v1', +]); +var_dump($key !== false); +$details = openssl_pkey_get_details($key); +var_dump($details['bits']); +var_dump($details['type'] === OPENSSL_KEYTYPE_EC); +echo "EC OK\n"; + +// X25519 - fixed size key, private_key_bits should not be required +if (defined('OPENSSL_KEYTYPE_X25519')) { + $key = openssl_pkey_new([ + 'config' => $conf, + 'private_key_type' => OPENSSL_KEYTYPE_X25519, + ]); + var_dump($key !== false); + echo "X25519 OK\n"; +} else { + echo "bool(true)\nX25519 OK\n"; +} + +// Ed25519 - fixed size key, private_key_bits should not be required +if (defined('OPENSSL_KEYTYPE_ED25519')) { + $key = openssl_pkey_new([ + 'config' => $conf, + 'private_key_type' => OPENSSL_KEYTYPE_ED25519, + ]); + var_dump($key !== false); + echo "Ed25519 OK\n"; +} else { + echo "bool(true)\nEd25519 OK\n"; +} + +unlink($conf); +?> +--EXPECT-- +bool(true) +int(256) +bool(true) +EC OK +bool(true) +X25519 OK +bool(true) +Ed25519 OK From 9150226166ffc3bda3ca341a8b4f37dae09061fa Mon Sep 17 00:00:00 2001 From: ndossche <7771979+ndossche@users.noreply.github.com> Date: Thu, 12 Mar 2026 22:04:08 +0100 Subject: [PATCH 5/5] [ci skip] NEWS for GH-20838 --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index 76cca47611f6..ed0730676567 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,10 @@ PHP NEWS - Bz2: . Fix truncation of total output size causing erroneous errors. (ndossche) +- Opcache: + . Fixed bug GH-20838 (JIT compiler produces wrong arithmetic results). + (Dmitry, iliaal) + - OpenSSL: . Fixed bug GH-21083 (Skip private_key_bits validation for EC/curve-based keys). (iliaal)