From 7cfde6edba5163db1f8e83cb3bbf3f982d2c64fd Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Fri, 3 Apr 2026 16:38:13 +0200 Subject: [PATCH 1/8] Ignore ZPP in gcovr (GH-21623) The ZPP macros materialize into optimized code with many error branches that aren't useful to test for every function. Ignore these lines completely by using the gcovr --exclude-lines-by-pattern flag. For codecov to pick up on this change, we generate the xml file manually and point to it in the codecov action. Also move the ignore paths from codecov.yml to Makefile.gcov. --- .github/workflows/test-suite.yml | 5 +++++ build/Makefile.gcov | 10 +++++++--- codecov.yml | 15 --------------- 3 files changed, 12 insertions(+), 18 deletions(-) delete mode 100644 codecov.yml diff --git a/.github/workflows/test-suite.yml b/.github/workflows/test-suite.yml index 9eeff1455f8f..ef213a539937 100644 --- a/.github/workflows/test-suite.yml +++ b/.github/workflows/test-suite.yml @@ -413,10 +413,15 @@ jobs: with: enableOpcache: true jitType: tracing + - name: Generate coverage report + if: ${{ !cancelled() }} + run: make gcovr-xml - uses: codecov/codecov-action@v5 if: ${{ !cancelled() }} with: + disable_search: true fail_ci_if_error: true + files: gcovr.xml token: ${{ secrets.CODECOV_TOKEN }} verbose: true COMMUNITY: diff --git a/build/Makefile.gcov b/build/Makefile.gcov index de85893398cd..d389cecdd192 100644 --- a/build/Makefile.gcov +++ b/build/Makefile.gcov @@ -22,8 +22,12 @@ GCOVR_EXCLUDES = \ 'ext/fileinfo/libmagic/.*' \ 'ext/gd/libgd/.*' \ 'ext/hash/sha3/.*' \ + 'ext/lexbor/lexbor/.*' \ 'ext/mbstring/libmbfl/.*' \ - 'ext/pcre/pcre2lib/.*' + 'ext/pcre/pcre2lib/.*' \ + 'ext/uri/uriparser/.*' + +GCOVR_EXCLUDE_LINES_BY_PATTERN = '.*\b(ZEND_PARSE_PARAMETERS_(START|END|NONE)|Z_PARAM_).*' lcov: lcov-html @@ -49,14 +53,14 @@ gcovr-html: @rm -rf gcovr_html/ @mkdir gcovr_html gcovr -sr . -o gcovr_html/index.html --html --html-details \ - --exclude-directories 'ext/date/lib$$' \ + --exclude-lines-by-pattern $(GCOVR_EXCLUDE_LINES_BY_PATTERN) \ $(foreach lib, $(GCOVR_EXCLUDES), -e $(lib)) gcovr-xml: @echo "Generating gcovr XML" @rm -f gcovr.xml gcovr -sr . -o gcovr.xml --xml \ - --exclude-directories 'ext/date/lib$$' \ + --exclude-lines-by-pattern $(GCOVR_EXCLUDE_LINES_BY_PATTERN) \ $(foreach lib, $(GCOVR_EXCLUDES), -e $(lib)) .PHONY: gcovr-html lcov-html php_lcov.info diff --git a/codecov.yml b/codecov.yml deleted file mode 100644 index 4c7648e738cd..000000000000 --- a/codecov.yml +++ /dev/null @@ -1,15 +0,0 @@ -ignore: - # bundled libraries - - "ext/lexbor/lexbor/core" - - "ext/lexbor/lexbor/css" - - "ext/lexbor/lexbor/dom" - - "ext/lexbor/lexbor/encoding" - - "ext/lexbor/lexbor/html" - - "ext/lexbor/lexbor/ns" - - "ext/lexbor/lexbor/ports" - - "ext/lexbor/lexbor/punycode" - - "ext/lexbor/lexbor/tag" - - "ext/lexbor/lexbor/unicode" - - "ext/lexbor/lexbor/url" - - "ext/pcre/pcre2lib" - - "ext/uri/uriparser" From 7782b8876bc0f61b0e8bcce262e22896e423b22e Mon Sep 17 00:00:00 2001 From: Nora Dossche <7771979+ndossche@users.noreply.github.com> Date: Sat, 24 Jan 2026 23:52:14 +0100 Subject: [PATCH 2/8] Fix NULL deref when enabling TLS fails and the peer name needs to be reset The code tries to read the context on NULL when `php_stream_xport_crypto_setup` fails because by then `stream` is reset to NULL. This is also UB, so can cause miscompiles. ``` ==1217==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000090 (pc 0x55d829ed3acf bp 0x7fff045f5770 sp 0x7fff045f4df0 T0) ==1217==The signal is caused by a READ memory access. ==1217==Hint: address points to the zero page. #0 0x55d829ed3acf in php_stream_url_wrap_http_ex /work/php-src/ext/standard/http_fopen_wrapper.c:580 #1 0x55d829ed857e in php_stream_url_wrap_http /work/php-src/ext/standard/http_fopen_wrapper.c:1204 #2 0x55d82a15073d in _php_stream_open_wrapper_ex /work/php-src/main/streams/streams.c:2270 #3 0x55d829e78fa6 in zif_file_get_contents /work/php-src/ext/standard/file.c:409 #4 0x55d829bbfe39 in zif_phar_file_get_contents /work/php-src/ext/phar/func_interceptors.c:226 #5 0x55d82a0b7ed2 in zend_test_execute_internal /work/php-src/ext/zend_test/observer.c:306 #6 0x55d82a3e024a in ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER /work/php-src/Zend/zend_vm_execute.h:2154 #7 0x55d82a540995 in execute_ex /work/php-src/Zend/zend_vm_execute.h:116519 #8 0x55d82a5558b0 in zend_execute /work/php-src/Zend/zend_vm_execute.h:121962 #9 0x55d82a6ba0ab in zend_execute_script /work/php-src/Zend/zend.c:1980 #10 0x55d82a0ec8bb in php_execute_script_ex /work/php-src/main/main.c:2645 #11 0x55d82a0ecccb in php_execute_script /work/php-src/main/main.c:2685 #12 0x55d82a6bfc16 in do_cli /work/php-src/sapi/cli/php_cli.c:951 #13 0x55d82a6c21e3 in main /work/php-src/sapi/cli/php_cli.c:1362 #14 0x7f9e770491c9 (/lib/x86_64-linux-gnu/libc.so.6+0x2a1c9) (BuildId: 274eec488d230825a136fa9c4d85370fed7a0a5e) #15 0x7f9e7704928a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2a28a) (BuildId: 274eec488d230825a136fa9c4d85370fed7a0a5e) #16 0x55d829209b34 in _start (/work/php-src/build-dbg-asan/sapi/cli/php+0x609b34) (BuildId: aa149f943514fff0c491e1f199e30fed0e977f7c) ``` Closes GH-21468. Closes GH-21031. --- NEWS | 4 + ext/openssl/tests/gh21031.phpt | 82 +++++++++++++++++++++ ext/openssl/tests/sni_server_cs_expired.pem | 57 ++++++++++++++ ext/standard/http_fopen_wrapper.c | 12 ++- 4 files changed, 152 insertions(+), 3 deletions(-) create mode 100644 ext/openssl/tests/gh21031.phpt create mode 100644 ext/openssl/tests/sni_server_cs_expired.pem diff --git a/NEWS b/NEWS index c9933ff6b265..1e72166bf934 100644 --- a/NEWS +++ b/NEWS @@ -24,6 +24,10 @@ PHP NEWS . Fixed bug GH-21499 (RecursiveArrayIterator getChildren UAF after parent free). (Girgias) +- Streams: + . Fixed bug GH-21468 (Segfault in file_get_contents w/ a https URL + and a proxy set). (ndossche) + 09 Apr 2026, PHP 8.4.20 - Bz2: diff --git a/ext/openssl/tests/gh21031.phpt b/ext/openssl/tests/gh21031.phpt new file mode 100644 index 000000000000..a35fab927270 --- /dev/null +++ b/ext/openssl/tests/gh21031.phpt @@ -0,0 +1,82 @@ +--TEST-- +GH-21031 (Fix NULL deref when enabling TLS fails and the peer name needs to be reset) +--EXTENSIONS-- +openssl +--SKIPIF-- + +--FILE-- + [ + 'SNI_server_certs' => [ + "cs.php.net" => __DIR__ . "/sni_server_cs_expired.pem", + ] + ]]); + + $server = stream_socket_server('tls://127.0.0.1:0', $errno, $errstr, $serverFlags, $ctx); + phpt_notify_server_start($server); + + $conn = stream_socket_accept($server, 3); + fclose($conn); + + phpt_wait(); +CODE; + +$proxyCode = <<<'CODE' + $flags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN; + $server = stream_socket_server("tcp://127.0.0.1:0", $errornum, $errorstr, $flags); + phpt_notify_server_start($server); + + $upstream = stream_socket_client("tcp://{{ ADDR }}", $errornum, $errorstr, 30, STREAM_CLIENT_CONNECT); + stream_set_blocking($upstream, false); + + $conn = stream_socket_accept($server); + stream_set_blocking($conn, true); + + // reading CONNECT request headers + while (($line = fgets($conn)) !== false) { + if (rtrim($line) === '') break; // empty line means end of headers + } + + // successful CONNECT response + fwrite($conn, "HTTP/1.0 200 Connection established\r\n\r\n"); + + fclose($conn); + fclose($upstream); + phpt_wait(); +CODE; + +$clientCode = <<<'CODE' + $clientCtx = stream_context_create([ + 'ssl' => [ + 'cafile' => __DIR__ . '/sni_server_ca.pem', + 'verify_peer' => true, + 'verify_peer_name' => true, + ], + "http" => [ + "proxy" => "tcp://{{ ADDR }}" + ], + ]); + + var_dump(file_get_contents("https://cs.php.net/", false, $clientCtx)); + + phpt_notify('proxy'); + phpt_notify('server'); +CODE; + +include 'ServerClientTestCase.inc'; +ServerClientTestCase::getInstance()->run($clientCode, [ + 'server' => $serverCode, + 'proxy' => $proxyCode, +]); +?> +--EXPECTF-- +Warning: file_get_contents(https://cs.php.net/): Failed to open stream: Cannot connect to HTTPS server through proxy in %s +bool(false) diff --git a/ext/openssl/tests/sni_server_cs_expired.pem b/ext/openssl/tests/sni_server_cs_expired.pem new file mode 100644 index 000000000000..9f5a201b26d1 --- /dev/null +++ b/ext/openssl/tests/sni_server_cs_expired.pem @@ -0,0 +1,57 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAvy5NhzktzEdsHTbGB6vqYANms5rn1zXFmTJrGlWCwoIsNmTf +ahvZkrC1cCXTZ7fbPB8XQbpAtz2ZSU7OcwBW9B8okYUPo9zi/ptwcrgsQsN0hrcD +8MBRUccevwime5fLvg8E9RJ/68y9y3BnRcVWYO2sAK9juTfidNjETU3Bb05oXv8D +SD/6onXQu4uXDgsQ3cRXeld9UB0xazmQXyyiIqXc/cpTAnaEVYzn28aj7NlUbzNq +511UXMXY44x9EcXWpPVZ7heNcJNzY5DCNzmtXKrt9yiMpWQcPXEzsESVxAMqib9u +TFOlvVX17LIPxBG656PjTD9J1h6kBbMCUxzs7wIDAQABAoIBAQC85lBeY0X4ST3v +I7bJz7kWQ2YP4uhfAdeLhoDDFWjNLffniwYhfwEc6xNri0R2f/jUT9gX7qORKwEx +qPdeNCC2t67LElGg1FlJv2Z9Q7MgCKYzkdQH5s6y4e9kTHTLO/JpiceZKz1QTQ3f +XOH9032E6nIAf0wmr6xHTgOwajrN8VI5BuPEMVmEwIw3AtYeqVuPCNKyGR4HUVkC +2bAydnGngbRJRnNzmKcWJancxpHDGBSFqPyuXMFC7Jgo3ZmyCbGp99vuXVk/sW9x +5aj94M9nRE0guk05ivH2/JZao2uLYkIgjFWlhNxKdWgWRk8DEuN4djC8mKS9YH1q +crYRToMhAoGBAOspUTtKP54mpZmyhxuDqj02JaJRzNTskPHsiF1UhtXuw7uT+ryV +ekUFLNXoFmn9mbx1WVaUvGH4qjilvQOxz7u++lz0ApqJEfyM3jc/cC40Y5zcuGSu +Etbg+SyDoytlgMCIydJyrS7NNALSo5p5oG6XY2f8yd/DCAmo8LzypaHRAoGBANAf +R1SlBMc/bOsi6GrJxcBVSCFMiKYiO5woL5aUKa9yM+UQuQ/6xbQ7Q+sOlt0FH3xo +AJ2L60qTdjyXVtjOdtXs5ZC4l+C6AfnCx6yLr+fNc4SOYXEfqS4LZylgwKd9KyVB +asspIW9Idbgebmi6vPyt9LDkIp0h1VuFGjkvQJK/AoGBAI4pbS0dprXyARyYW6sb +fpgAmuG099IkrT9DUfCx/81myTclr2fAKal+BmvOIXaz0/OlMXvw8K19iVIzh7+r +B70lJ+93p/dKM/BsLI5TsHqOO0YB/QsIXOVAHgJ2FfdPJnW+e9vYba+kZ/Po6PSi +4ITaykJ8BIJcQgis89QWEGFxAoGBAJhQO+jzuDKF9ZWEf6ofrw0anOZZ16wWY5/e +PS2rk3JmVxpuibHrKqPDt+ogTELHDAsFJmYmz3VNxHuFmrajK49Wh4/JuMVr/CQo +6+8YcA1qa/94IFIlBLDBAafjujsZvOjQHnM+z8xcsGKmStF00Pjv6qNG4xoyd646 +FD4DmfOLAoGAWXehpopZKXE9gRAni881ucK6WqxPPBoofbozi09D0MmfarIVaSkv +jNVVHBfLWd7IEXTjiipPBeUqq6Jc3pscN1Vp4rrl8jTmVTdazEv0LuzpdUFqmNo2 +M+xw17uz9D9Q32/aW1Lar0PdIaL/wGEDEyzEBFwrGppcENLilPz8gzU= +-----END RSA PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIFIjCCAwqgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwVTELMAkGA1UEBhMCR0Ix +EDAOBgNVBAgMB0VuZ2xhbmQxEDAOBgNVBAoMB1BIUC5uZXQxEDAOBgNVBAsMB29w +ZW5zc2wxEDAOBgNVBAMMB3BocC5uZXQwHhcNMTgwMTE0MTgzNjEyWhcNMjYwNDAy +MTgzNjEyWjBGMQswCQYDVQQGEwJHQjEQMA4GA1UECAwHRW5nbGFuZDEQMA4GA1UE +CgwHUEhQLm5ldDETMBEGA1UEAwwKY3MucGhwLm5ldDCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAL8uTYc5LcxHbB02xger6mADZrOa59c1xZkyaxpVgsKC +LDZk32ob2ZKwtXAl02e32zwfF0G6QLc9mUlOznMAVvQfKJGFD6Pc4v6bcHK4LELD +dIa3A/DAUVHHHr8IpnuXy74PBPUSf+vMvctwZ0XFVmDtrACvY7k34nTYxE1NwW9O +aF7/A0g/+qJ10LuLlw4LEN3EV3pXfVAdMWs5kF8soiKl3P3KUwJ2hFWM59vGo+zZ +VG8zauddVFzF2OOMfRHF1qT1We4XjXCTc2OQwjc5rVyq7fcojKVkHD1xM7BElcQD +Kom/bkxTpb1V9eyyD8QRuuej40w/SdYepAWzAlMc7O8CAwEAAaOCAQkwggEFMAkG +A1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgZAMDMGCWCGSAGG+EIBDQQmFiRPcGVu +U1NMIEdlbmVyYXRlZCBTZXJ2ZXIgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFHPfd8dK +Lz1R0Ck4WV1B9AWXd5DSMGwGA1UdIwRlMGOAFOPK44Eacedv7HbR2Igcbew+4kUa +oUekRTBDMQswCQYDVQQGEwJHQjEQMA4GA1UECAwHRW5nbGFuZDEQMA4GA1UECgwH +UEhQLm5ldDEQMA4GA1UEAwwHcGhwLm5ldIICEAAwDgYDVR0PAQH/BAQDAgWgMBMG +A1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4ICAQB6WSIHEyDXLZxH +hZjqSNQOA7Wc9Z2FCAiD29xYkGTL8WuPVGGP1mu4B92ytj+PMWwqSReDa7eTGLE7 +O7ozw9l+c+gNmHFNikSsGjlV2E8CToQOFMny+jAQYMSXf8UbTp9xDfgG02t/71hv +SLWqdeHMLcR0xi0nBQH0vDOkwUbuWYqFa3jejHieGhykHM6CkIk6lqnyOEO+ooIF +ZsLprrg1ss/mXCPI6niP0hze55ERKdxI7Rk8sZ4pVkf2SUWqZrUS0aJ+Ymmwi6Xd +2V7izq5N30PkJS8MtqII4FAjRBIkwPh0sy8PmW/DzkYU+lYQnDfYLKDFKcj8xJK/ +o8oZUBsQltrSj0KlM9QuqxCTCBCy1nXZ9WHOhq+jdLiTc1Oi60uEHcUMrLK8aYc4 +HqIvZS6C2iwMI0d1OP3VxmAbMQ9yqRi+FbLYavJ3H40jrU9SYqdxa0BrTaz8MJNE +6AEwgQDPChczSghvHME+Fs4mtGCY3TesbNZKVahQRjaFIhMZIZ4RP4CRc0bJOBG+ +8Me4+KHNsD2ki5b03wAN6C1P2QrMzI+gH9fXLZYp761ciDAsX6YIzrhHHYLxYpJH +BkQKKs8dCQWE5IzgVrdlvC3Z1/l9om66wHqqx7nKnPfYs/Sfnwe9MpCD6xJrXiTm +WS7NM6fbQpO9APNr7o0ZOjbbWFzlNw== +-----END CERTIFICATE----- diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c index 9fefe153622f..89125ed0765e 100644 --- a/ext/standard/http_fopen_wrapper.c +++ b/ext/standard/http_fopen_wrapper.c @@ -540,6 +540,10 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, smart_str_appendl(&header, "\r\n", sizeof("\r\n")-1); if (php_stream_write(stream, ZSTR_VAL(header.s), ZSTR_LEN(header.s)) != ZSTR_LEN(header.s)) { + if (reset_ssl_peer_name) { + php_stream_context_unset_option(PHP_STREAM_CONTEXT(stream), "ssl", "peer_name"); + } + php_stream_wrapper_log_error(wrapper, options, "Cannot connect to HTTPS server through proxy"); php_stream_close(stream); stream = NULL; @@ -561,16 +565,18 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, /* enable SSL transport layer */ if (stream) { + php_stream_context *old_context = PHP_STREAM_CONTEXT(stream); + if (php_stream_xport_crypto_setup(stream, STREAM_CRYPTO_METHOD_SSLv23_CLIENT, NULL) < 0 || php_stream_xport_crypto_enable(stream, 1) < 0) { php_stream_wrapper_log_error(wrapper, options, "Cannot connect to HTTPS server through proxy"); php_stream_close(stream); stream = NULL; } - } - if (reset_ssl_peer_name) { - php_stream_context_unset_option(PHP_STREAM_CONTEXT(stream), "ssl", "peer_name"); + if (reset_ssl_peer_name) { + php_stream_context_unset_option(old_context, "ssl", "peer_name"); + } } } From 678382427fad8457ed4d5dc77654e8aa06bf5f82 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 3 Apr 2026 18:52:09 +0100 Subject: [PATCH 3/8] Zend: mark callable zval* as const (#21582) --- Zend/zend_API.c | 10 +++++----- Zend/zend_API.h | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Zend/zend_API.c b/Zend/zend_API.c index bd3f89a24502..7363a4a12039 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -4031,7 +4031,7 @@ static zend_always_inline bool zend_is_callable_check_func(const zval *callable, } /* }}} */ -ZEND_API zend_string *zend_get_callable_name_ex(zval *callable, const zend_object *object) /* {{{ */ +ZEND_API zend_string *zend_get_callable_name_ex(const zval *callable, const zend_object *object) /* {{{ */ { try_again: switch (Z_TYPE_P(callable)) { @@ -4089,7 +4089,7 @@ ZEND_API zend_string *zend_get_callable_name_ex(zval *callable, const zend_objec } /* }}} */ -ZEND_API zend_string *zend_get_callable_name(zval *callable) /* {{{ */ +ZEND_API zend_string *zend_get_callable_name(const zval *callable) /* {{{ */ { return zend_get_callable_name_ex(callable, NULL); } @@ -4206,7 +4206,7 @@ ZEND_API bool zend_is_callable_at_frame( } /* }}} */ -ZEND_API bool zend_is_callable_ex(zval *callable, zend_object *object, uint32_t check_flags, zend_string **callable_name, zend_fcall_info_cache *fcc, char **error) /* {{{ */ +ZEND_API bool zend_is_callable_ex(const zval *callable, zend_object *object, uint32_t check_flags, zend_string **callable_name, zend_fcall_info_cache *fcc, char **error) /* {{{ */ { /* Determine callability at the first parent user frame. */ const zend_execute_data *frame = EG(current_execute_data); @@ -4221,13 +4221,13 @@ ZEND_API bool zend_is_callable_ex(zval *callable, zend_object *object, uint32_t return ret; } -ZEND_API bool zend_is_callable(zval *callable, uint32_t check_flags, zend_string **callable_name) /* {{{ */ +ZEND_API bool zend_is_callable(const zval *callable, uint32_t check_flags, zend_string **callable_name) /* {{{ */ { return zend_is_callable_ex(callable, NULL, check_flags, callable_name, NULL, NULL); } /* }}} */ -ZEND_API zend_result zend_fcall_info_init(zval *callable, uint32_t check_flags, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string **callable_name, char **error) /* {{{ */ +ZEND_API zend_result zend_fcall_info_init(const zval *callable, uint32_t check_flags, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string **callable_name, char **error) /* {{{ */ { if (!zend_is_callable_ex(callable, NULL, check_flags, callable_name, fcc, error)) { return FAILURE; diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 60acbd63044d..e56ded4e8f1b 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -410,13 +410,13 @@ ZEND_API ZEND_COLD void zend_wrong_property_read(const zval *object, zval *prope #define IS_CALLABLE_SUPPRESS_DEPRECATIONS (1<<1) ZEND_API void zend_release_fcall_info_cache(zend_fcall_info_cache *fcc); -ZEND_API zend_string *zend_get_callable_name_ex(zval *callable, const zend_object *object); -ZEND_API zend_string *zend_get_callable_name(zval *callable); +ZEND_API zend_string *zend_get_callable_name_ex(const zval *callable, const zend_object *object); +ZEND_API zend_string *zend_get_callable_name(const zval *callable); ZEND_API bool zend_is_callable_at_frame( const zval *callable, zend_object *object, const zend_execute_data *frame, uint32_t check_flags, zend_fcall_info_cache *fcc, char **error); -ZEND_API bool zend_is_callable_ex(zval *callable, zend_object *object, uint32_t check_flags, zend_string **callable_name, zend_fcall_info_cache *fcc, char **error); -ZEND_API bool zend_is_callable(zval *callable, uint32_t check_flags, zend_string **callable_name); +ZEND_API bool zend_is_callable_ex(const zval *callable, zend_object *object, uint32_t check_flags, zend_string **callable_name, zend_fcall_info_cache *fcc, char **error); +ZEND_API bool zend_is_callable(const zval *callable, uint32_t check_flags, zend_string **callable_name); ZEND_API const char *zend_get_module_version(const char *module_name); ZEND_API zend_result zend_get_module_started(const char *module_name); @@ -701,7 +701,7 @@ ZEND_API zend_result _call_user_function_impl(zval *object, zval *function_name, * fci->params = NULL; * The callable_name argument may be NULL. */ -ZEND_API zend_result zend_fcall_info_init(zval *callable, uint32_t check_flags, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string **callable_name, char **error); +ZEND_API zend_result zend_fcall_info_init(const zval *callable, uint32_t check_flags, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string **callable_name, char **error); /** Clear arguments connected with zend_fcall_info *fci * If free_mem is not zero then the params array gets free'd as well @@ -2482,7 +2482,7 @@ static zend_always_inline bool zend_parse_arg_resource(zval *arg, zval **dest, b return 1; } -static zend_always_inline bool zend_parse_arg_func(zval *arg, zend_fcall_info *dest_fci, zend_fcall_info_cache *dest_fcc, bool check_null, char **error, bool free_trampoline) +static zend_always_inline bool zend_parse_arg_func(const zval *arg, zend_fcall_info *dest_fci, zend_fcall_info_cache *dest_fcc, bool check_null, char **error, bool free_trampoline) { if (check_null && UNEXPECTED(Z_TYPE_P(arg) == IS_NULL)) { dest_fci->size = 0; From b621f80dce5c63e9e0ff5dfbf5d3da927e77871a Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 3 Apr 2026 18:59:49 +0100 Subject: [PATCH 4/8] ext/mbstring: use new INI API and remove unnecessary casts (#21393) --- ext/mbstring/mbstring.c | 56 ++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 31 deletions(-) diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index 95b624ef1d2d..c5987f3c9e7a 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -1216,17 +1216,17 @@ PHP_FUNCTION(mb_language) ZEND_PARSE_PARAMETERS_END(); if (name == NULL) { - RETVAL_STRING((char *)mbfl_no_language2name(MBSTRG(language))); + RETVAL_STRING(mbfl_no_language2name(MBSTRG(language))); } else { - zend_string *ini_name = ZSTR_INIT_LITERAL("mbstring.language", 0); + zend_string *ini_name = ZSTR_INIT_LITERAL("mbstring.language", false); if (FAILURE == zend_alter_ini_entry(ini_name, name, PHP_INI_USER, PHP_INI_STAGE_RUNTIME)) { zend_argument_value_error(1, "must be a valid language, \"%s\" given", ZSTR_VAL(name)); - zend_string_release_ex(ini_name, 0); + zend_string_release_ex(ini_name, false); RETURN_THROWS(); } // TODO Make return void RETVAL_TRUE; - zend_string_release_ex(ini_name, 0); + zend_string_release_ex(ini_name, false); } } /* }}} */ @@ -1509,7 +1509,7 @@ PHP_FUNCTION(mb_preferred_mime_name) php_error_docref(NULL, E_WARNING, "No MIME preferred name corresponding to \"%s\"", name); RETVAL_FALSE; } else { - RETVAL_STRING((char *)preferred_name); + RETVAL_STRING(preferred_name); } } /* }}} */ @@ -3517,7 +3517,7 @@ PHP_FUNCTION(mb_detect_encoding) RETURN_FALSE; } - RETVAL_STRING((char *)ret->name); + RETVAL_STRING(ret->name); } /* }}} */ @@ -3563,7 +3563,7 @@ PHP_FUNCTION(mb_encoding_aliases) array_init(return_value); if (encoding->aliases != NULL) { for (const char **alias = encoding->aliases; *alias; ++alias) { - add_next_index_string(return_value, (char *)*alias); + add_next_index_string(return_value, *alias); } } } @@ -4768,7 +4768,7 @@ PHP_FUNCTION(mb_send_mail) str_headers = smart_str_extract(&str); - zend_string *force_extra_parameters = zend_ini_str_ex("mail.force_extra_parameters", strlen("mail.force_extra_parameters"), false, NULL); + zend_string *force_extra_parameters = zend_ini_str_literal("mail.force_extra_parameters"); if (force_extra_parameters) { extra_cmd = php_escape_shell_cmd(force_extra_parameters); } else if (extra_cmd) { @@ -4804,7 +4804,7 @@ PHP_FUNCTION(mb_get_info) { zend_string *type = NULL; size_t n; - char *name; + const char *name; zval row; const mbfl_encoding **entry; const mbfl_language *lang = mbfl_no2language(MBSTRG(language)); @@ -4819,26 +4819,26 @@ PHP_FUNCTION(mb_get_info) if (!type || zend_string_equals_literal_ci(type, "all")) { array_init(return_value); if (MBSTRG(current_internal_encoding)) { - add_assoc_string(return_value, "internal_encoding", (char *)MBSTRG(current_internal_encoding)->name); + add_assoc_string(return_value, "internal_encoding", MBSTRG(current_internal_encoding)->name); } if (MBSTRG(http_input_identify)) { - add_assoc_string(return_value, "http_input", (char *)MBSTRG(http_input_identify)->name); + add_assoc_string(return_value, "http_input", MBSTRG(http_input_identify)->name); } if (MBSTRG(current_http_output_encoding)) { - add_assoc_string(return_value, "http_output", (char *)MBSTRG(current_http_output_encoding)->name); + add_assoc_string(return_value, "http_output", MBSTRG(current_http_output_encoding)->name); } add_assoc_str(return_value, "http_output_conv_mimetypes", - zend_ini_str("mbstring.http_output_conv_mimetypes", sizeof("mbstring.http_output_conv_mimetypes") - 1, 0) + zend_string_copy(zend_ini_str_literal("mbstring.http_output_conv_mimetypes")) ); - name = (char *)mbfl_no_encoding2name(lang->mail_charset); + name = mbfl_no_encoding2name(lang->mail_charset); add_assoc_string(return_value, "mail_charset", name); - name = (char *)mbfl_no_encoding2name(lang->mail_header_encoding); + name = mbfl_no_encoding2name(lang->mail_header_encoding); add_assoc_string(return_value, "mail_header_encoding", name); - name = (char *)mbfl_no_encoding2name(lang->mail_body_encoding); + name = mbfl_no_encoding2name(lang->mail_body_encoding); add_assoc_string(return_value, "mail_body_encoding", name); add_assoc_long(return_value, "illegal_chars", MBSTRG(illegalchars)); @@ -4849,7 +4849,7 @@ PHP_FUNCTION(mb_get_info) add_assoc_string(return_value, "encoding_translation", "Off"); } - name = (char *)mbfl_no_language2name(MBSTRG(language)); + name = mbfl_no_language2name(MBSTRG(language)); add_assoc_string(return_value, "language", name); // TODO Seems to always have one entry at least? @@ -4880,31 +4880,25 @@ PHP_FUNCTION(mb_get_info) } } else if (zend_string_equals_literal_ci(type, "internal_encoding")) { ZEND_ASSERT(MBSTRG(current_internal_encoding)); - RETURN_STRING((char *)MBSTRG(current_internal_encoding)->name); + RETURN_STRING(MBSTRG(current_internal_encoding)->name); } else if (zend_string_equals_literal_ci(type, "http_input")) { if (MBSTRG(http_input_identify)) { - RETURN_STRING((char *)MBSTRG(http_input_identify)->name); + RETURN_STRING(MBSTRG(http_input_identify)->name); } RETURN_NULL(); } else if (zend_string_equals_literal_ci(type, "http_output")) { ZEND_ASSERT(MBSTRG(current_http_output_encoding)); - RETURN_STRING((char *)MBSTRG(current_http_output_encoding)->name); + RETURN_STRING(MBSTRG(current_http_output_encoding)->name); } else if (zend_string_equals_literal_ci(type, "http_output_conv_mimetypes")) { - RETURN_STR( - zend_ini_str( - "mbstring.http_output_conv_mimetypes", - sizeof("mbstring.http_output_conv_mimetypes") - 1, - false - ) - ); + RETURN_STR_COPY(zend_ini_str_literal("mbstring.http_output_conv_mimetypes")); } else if (zend_string_equals_literal_ci(type, "mail_charset")) { - name = (char *)mbfl_no_encoding2name(lang->mail_charset); + name = mbfl_no_encoding2name(lang->mail_charset); RETURN_STRING(name); } else if (zend_string_equals_literal_ci(type, "mail_header_encoding")) { - name = (char *)mbfl_no_encoding2name(lang->mail_header_encoding); + name = mbfl_no_encoding2name(lang->mail_header_encoding); RETURN_STRING(name); } else if (zend_string_equals_literal_ci(type, "mail_body_encoding")) { - name = (char *)mbfl_no_encoding2name(lang->mail_body_encoding); + name = mbfl_no_encoding2name(lang->mail_body_encoding); RETURN_STRING(name); } else if (zend_string_equals_literal_ci(type, "illegal_chars")) { RETURN_LONG(MBSTRG(illegalchars)); @@ -4915,7 +4909,7 @@ PHP_FUNCTION(mb_get_info) RETURN_STRING("Off"); } } else if (zend_string_equals_literal_ci(type, "language")) { - name = (char *)mbfl_no_language2name(MBSTRG(language)); + name = mbfl_no_language2name(MBSTRG(language)); RETURN_STRING(name); } else if (zend_string_equals_literal_ci(type, "detect_order")) { // TODO Seems to always have one entry at least? From 5216ca8822ac69cb29abf6c73e085c31802e3421 Mon Sep 17 00:00:00 2001 From: Nora Dossche <7771979+ndossche@users.noreply.github.com> Date: Fri, 3 Apr 2026 20:24:56 +0200 Subject: [PATCH 5/8] Fix build warning on LibreSSL (#21050) When trying to build on LibreSSL, I encounter the following build warning (this was observed on master, but applies to 8.4 too): ``` /work/php-src/ext/openssl/openssl.c: In function 'zif_openssl_x509_parse': /work/php-src/ext/openssl/openssl.c:1101:22: warning: assignment discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers] 1101 | purp = X509_PURPOSE_get0(i); | ^ /work/php-src/ext/openssl/openssl.c:1110:23: warning: assignment discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers] 1110 | pname = useshortnames ? X509_PURPOSE_get0_sname(purp) : X509_PURPOSE_get0_name(purp); ``` --- ext/openssl/openssl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 1c1073345a16..fa104a1a43cb 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -2206,7 +2206,7 @@ PHP_FUNCTION(openssl_x509_parse) for (i = 0; i < X509_PURPOSE_get_count(); i++) { int id, purpset; char * pname; - X509_PURPOSE * purp; + const X509_PURPOSE * purp; zval subsub; array_init(&subsub); From 1aff27101775f6fcb1d8454149f5463837034ac8 Mon Sep 17 00:00:00 2001 From: Nora Dossche <7771979+ndossche@users.noreply.github.com> Date: Fri, 3 Apr 2026 20:26:13 +0200 Subject: [PATCH 6/8] Fix memory leak on failure in openssl_x509_parse() (#21005) Only one of the two arrays (subitem) is destroyed, and critext is not. This leads to a memory leak if the loop bails out: ``` Direct leak of 56 byte(s) in 1 object(s) allocated from: #0 0x7f309fe699c7 in malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69 #1 0x563b9709ca05 in tracked_malloc /work/php-src/Zend/zend_alloc.c:3018 #2 0x563b9709b969 in _emalloc /work/php-src/Zend/zend_alloc.c:2780 #3 0x563b9737dc7b in _zend_new_array /work/php-src/Zend/zend_hash.c:290 #4 0x563b960f40fc in zif_openssl_x509_parse /work/php-src/ext/openssl/openssl.c:1120 #5 0x563b96eb7ed2 in zend_test_execute_internal /work/php-src/ext/zend_test/observer.c:306 #6 0x563b971e024a in ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER /work/php-src/Zend/zend_vm_execute.h:2154 #7 0x563b97340995 in execute_ex /work/php-src/Zend/zend_vm_execute.h:116519 #8 0x563b973558b0 in zend_execute /work/php-src/Zend/zend_vm_execute.h:121962 #9 0x563b974ba0ab in zend_execute_script /work/php-src/Zend/zend.c:1980 #10 0x563b96eec8bb in php_execute_script_ex /work/php-src/main/main.c:2645 #11 0x563b96eecccb in php_execute_script /work/php-src/main/main.c:2685 #12 0x563b974bfc16 in do_cli /work/php-src/sapi/cli/php_cli.c:951 #13 0x563b974c21e3 in main /work/php-src/sapi/cli/php_cli.c:1362 #14 0x7f309f1641c9 (/lib/x86_64-linux-gnu/libc.so.6+0x2a1c9) (BuildId: 274eec488d230825a136fa9c4d85370fed7a0a5e) #15 0x7f309f16428a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2a28a) (BuildId: 274eec488d230825a136fa9c4d85370fed7a0a5e) #16 0x563b96009b34 in _start (/work/php-src/build-dbg-asan/sapi/cli/php+0x609b34) (BuildId: aa149f943514fff0c491e1f199e30fed0e977f7c) ``` --- ext/openssl/openssl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index d447d0ced687..755c2019977b 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -1177,6 +1177,7 @@ PHP_FUNCTION(openssl_x509_parse) err_subitem: zval_ptr_dtor(&subitem); + zval_ptr_dtor(&critext); err: zend_array_destroy(Z_ARR_P(return_value)); if (cert_str) { From 880a6fcf8e7ea37b5fd852110ed63c1c128e4bc8 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+ndossche@users.noreply.github.com> Date: Sun, 25 Jan 2026 23:24:47 +0100 Subject: [PATCH 7/8] Fix memory leak regression in openssl_pbkdf2() We're fetching the digest using the new method, but if an alias is used, the method is fetched via EVP_MD_fetch() which requires lifetime management. This is observable when using "sha-256" instead of "sha256" as an algorithm name. This is a regression in comparison to PHP 8.4. Closes GH-21039. --- NEWS | 3 +++ ext/openssl/openssl.c | 6 ++++-- ext/openssl/tests/openssl_pbkdf2_basic.phpt | 3 +++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index eb098f11c042..09e58c4d9dc9 100644 --- a/NEWS +++ b/NEWS @@ -19,6 +19,9 @@ PHP NEWS zend_jit_use_reg). (Arnaud) . Fixed bug GH-21593 (Borked function JIT JMPNZ smart branch). (ilutov) +- OpenSSL: + . Fix memory leak regression in openssl_pbkdf2(). (ndossche) + - DOM: . Fixed bug GH-21566 (Dom\XMLDocument::C14N() emits duplicate xmlns declarations after setAttributeNS()). (David Carlier) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index a39682963172..9986fd602046 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -2450,12 +2450,14 @@ PHP_FUNCTION(openssl_pbkdf2) if (PKCS5_PBKDF2_HMAC(password, (int)password_len, (unsigned char *)salt, (int)salt_len, (int)iterations, digest, (int)key_length, (unsigned char*)ZSTR_VAL(out_buffer)) == 1) { ZSTR_VAL(out_buffer)[key_length] = 0; - RETURN_NEW_STR(out_buffer); + RETVAL_NEW_STR(out_buffer); } else { php_openssl_store_errors(); zend_string_release_ex(out_buffer, 0); - RETURN_FALSE; + RETVAL_FALSE; } + + php_openssl_release_evp_md(digest); } /* }}} */ diff --git a/ext/openssl/tests/openssl_pbkdf2_basic.phpt b/ext/openssl/tests/openssl_pbkdf2_basic.phpt index fd253ac78bb2..ba79f9415ba8 100644 --- a/ext/openssl/tests/openssl_pbkdf2_basic.phpt +++ b/ext/openssl/tests/openssl_pbkdf2_basic.phpt @@ -19,6 +19,8 @@ var_dump(bin2hex(openssl_pbkdf2('password', 'salt', 20, 16777216))); var_dump(bin2hex(openssl_pbkdf2('passwordPASSWORDpassword', 'saltSALTsaltSALTsaltSALTsaltSALTsalt', 25, 4096))); var_dump(bin2hex(openssl_pbkdf2("pass\0word", "sa\0lt", 16, 4096))); +var_dump(bin2hex(openssl_pbkdf2("password", "salt", 16, 4096, "sha-256"))); + ?> --EXPECT-- string(40) "0c60c80f961f0e71f3a9b524af6012062fe037a6" @@ -26,3 +28,4 @@ string(40) "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957" string(40) "4b007901b765489abead49d926f721d065a429c1" string(50) "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038" string(32) "56fa6aa75548099dcc37d7f03425e0c3" +string(32) "c5e478d59288c841aa530db6845c4c8d" From c349c32301df253f60214e4136783033f7c1493c Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Fri, 3 Apr 2026 20:14:14 +0100 Subject: [PATCH 8/8] Openssl little optims (#21424) - reuse BIO object in certificate chain loops. Avoid repeated BIO_new/BIO_free per iteration in PKCS12, PKCS7, and CMS read functions. Allocate once before the loop, BIO_reset between iterations, free after. - Avoid double zval_get_long() call in threads option parsing. - Reuse already computed string length instead of calling strlen() again. --- ext/openssl/openssl.c | 54 ++++++++++++++++++++++++++---------- ext/openssl/openssl_pwhash.c | 4 +-- ext/openssl/xp_ssl.c | 2 +- 3 files changed, 43 insertions(+), 17 deletions(-) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 2c9b5e1e8adb..fa3fd39ed857 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -1531,6 +1531,10 @@ PHP_FUNCTION(openssl_pkcs12_read) if (pkey) { bio_out = BIO_new(BIO_s_mem()); + if (!bio_out) { + goto cleanup; + } + if (PEM_write_bio_PrivateKey(bio_out, pkey, NULL, NULL, 0, 0, NULL)) { BUF_MEM *bio_buf; BIO_get_mem_ptr(bio_out, &bio_buf); @@ -1545,13 +1549,16 @@ PHP_FUNCTION(openssl_pkcs12_read) cert_num = sk_X509_num(ca); if (ca && cert_num) { array_init(&zextracerts); + bio_out = BIO_new(BIO_s_mem()); + if (!bio_out) { + goto cleanup; + } for (i = 0; i < cert_num; i++) { zval zextracert; X509* aCA = sk_X509_pop(ca); if (!aCA) break; - bio_out = BIO_new(BIO_s_mem()); if (PEM_write_bio_X509(bio_out, aCA)) { BUF_MEM *bio_buf; BIO_get_mem_ptr(bio_out, &bio_buf); @@ -1559,9 +1566,10 @@ PHP_FUNCTION(openssl_pkcs12_read) add_index_zval(&zextracerts, i, &zextracert); } + BIO_reset(bio_out); X509_free(aCA); - BIO_free(bio_out); } + BIO_free(bio_out); sk_X509_free(ca); add_assoc_zval(zout, "extracerts", &zextracerts); @@ -2814,33 +2822,41 @@ PHP_FUNCTION(openssl_pkcs7_read) } if (certs != NULL) { + bio_out = BIO_new(BIO_s_mem()); + if (!bio_out) { + goto clean_exit; + } for (i = 0; i < sk_X509_num(certs); i++) { X509* ca = sk_X509_value(certs, i); - bio_out = BIO_new(BIO_s_mem()); - if (bio_out && PEM_write_bio_X509(bio_out, ca)) { + if (PEM_write_bio_X509(bio_out, ca)) { BUF_MEM *bio_buf; BIO_get_mem_ptr(bio_out, &bio_buf); ZVAL_STRINGL(&zcert, bio_buf->data, bio_buf->length); add_index_zval(zout, i, &zcert); } - BIO_free(bio_out); + BIO_reset(bio_out); } + BIO_free(bio_out); } if (crls != NULL) { + bio_out = BIO_new(BIO_s_mem()); + if (!bio_out) { + goto clean_exit; + } for (i = 0; i < sk_X509_CRL_num(crls); i++) { X509_CRL* crl = sk_X509_CRL_value(crls, i); - bio_out = BIO_new(BIO_s_mem()); - if (bio_out && PEM_write_bio_X509_CRL(bio_out, crl)) { + if (PEM_write_bio_X509_CRL(bio_out, crl)) { BUF_MEM *bio_buf; BIO_get_mem_ptr(bio_out, &bio_buf); ZVAL_STRINGL(&zcert, bio_buf->data, bio_buf->length); add_index_zval(zout, i, &zcert); } - BIO_free(bio_out); + BIO_reset(bio_out); } + BIO_free(bio_out); } RETVAL_TRUE; @@ -3481,33 +3497,43 @@ PHP_FUNCTION(openssl_cms_read) } if (certs != NULL) { + bio_out = BIO_new(BIO_s_mem()); + if (!bio_out) { + goto clean_exit; + } + for (i = 0; i < sk_X509_num(certs); i++) { X509* ca = sk_X509_value(certs, i); - bio_out = BIO_new(BIO_s_mem()); - if (bio_out && PEM_write_bio_X509(bio_out, ca)) { + if (PEM_write_bio_X509(bio_out, ca)) { BUF_MEM *bio_buf; BIO_get_mem_ptr(bio_out, &bio_buf); ZVAL_STRINGL(&zcert, bio_buf->data, bio_buf->length); add_index_zval(zout, i, &zcert); } - BIO_free(bio_out); + BIO_reset(bio_out); } + BIO_free(bio_out); } if (crls != NULL) { + bio_out = BIO_new(BIO_s_mem()); + if (!bio_out) { + goto clean_exit; + } + for (i = 0; i < sk_X509_CRL_num(crls); i++) { X509_CRL* crl = sk_X509_CRL_value(crls, i); - bio_out = BIO_new(BIO_s_mem()); - if (bio_out && PEM_write_bio_X509_CRL(bio_out, crl)) { + if (PEM_write_bio_X509_CRL(bio_out, crl)) { BUF_MEM *bio_buf; BIO_get_mem_ptr(bio_out, &bio_buf); ZVAL_STRINGL(&zcert, bio_buf->data, bio_buf->length); add_index_zval(zout, i, &zcert); } - BIO_free(bio_out); + BIO_reset(bio_out); } + BIO_free(bio_out); } RETVAL_TRUE; diff --git a/ext/openssl/openssl_pwhash.c b/ext/openssl/openssl_pwhash.c index dc125e3b516d..69e9dae3fa99 100644 --- a/ext/openssl/openssl_pwhash.c +++ b/ext/openssl/openssl_pwhash.c @@ -51,6 +51,7 @@ ZEND_EXTERN_MODULE_GLOBALS(openssl) static inline zend_result get_options(zend_array *options, uint32_t *memlimit, uint32_t *iterlimit, uint32_t *threads) { zval *opt; + zend_long sthreads; *iterlimit = PHP_OPENSSL_PWHASH_ITERLIMIT; *memlimit = PHP_OPENSSL_PWHASH_MEMLIMIT; @@ -76,8 +77,7 @@ static inline zend_result get_options(zend_array *options, uint32_t *memlimit, u } *iterlimit = siterlimit; } - if ((opt = zend_hash_str_find(options, "threads", strlen("threads"))) && (zval_get_long(opt) != 1)) { - zend_long sthreads = zval_get_long(opt); + if ((opt = zend_hash_str_find(options, "threads", strlen("threads"))) && ((sthreads = zval_get_long(opt)) != 1)) { if ((sthreads < PHP_OPENSSL_THREADS_MIN) || (sthreads > PHP_OPENSSL_THREADS_MAX)) { zend_value_error("Invalid number of threads"); return FAILURE; diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index 8f9395e46022..5928994d12af 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -1508,7 +1508,7 @@ static unsigned char *php_openssl_alpn_protos_parse(unsigned short *outlen, cons return NULL; } - out = emalloc(strlen(in) + 1); + out = emalloc(len + 1); for (i = 0; i <= len; ++i) { if (i == len || in[i] == ',') {