From 794226889926bff482856f30dd2bb1511401f19b Mon Sep 17 00:00:00 2001 From: Pierrick Charron Date: Tue, 26 Mar 2024 08:49:44 -0400 Subject: [PATCH 01/64] PHP-8.2 is now for PHP 8.2.19-dev --- NEWS | 5 ++++- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 6 +++--- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index d73bb484d204f..bdc2cd8efa244 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.2.18 +?? ??? ????, PHP 8.2.19 + + +11 Apr 2024, PHP 8.2.18 - Core: . Fixed bug GH-13612 (Corrupted memory in destructor with weak references). diff --git a/Zend/zend.h b/Zend/zend.h index 12a467ee8a44e..ad8fde7a8ad1c 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.2.18-dev" +#define ZEND_VERSION "4.2.19-dev" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index de0eac8498ec8..683029f476a94 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice. dnl ---------------------------------------------------------------------------- AC_PREREQ([2.68]) -AC_INIT([PHP],[8.2.18-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) +AC_INIT([PHP],[8.2.19-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) AC_CONFIG_SRCDIR([main/php_version.h]) AC_CONFIG_AUX_DIR([build]) AC_PRESERVE_HELP_ORDER diff --git a/main/php_version.h b/main/php_version.h index c5491beea546d..a17d49197da51 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -2,7 +2,7 @@ /* edit configure.ac to change version number */ #define PHP_MAJOR_VERSION 8 #define PHP_MINOR_VERSION 2 -#define PHP_RELEASE_VERSION 18 +#define PHP_RELEASE_VERSION 19 #define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.2.18-dev" -#define PHP_VERSION_ID 80218 +#define PHP_VERSION "8.2.19-dev" +#define PHP_VERSION_ID 80219 From d0a8d41eee1912613d33a92e2a0839d3cdb90b5d Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Fri, 22 Mar 2024 13:08:00 +0000 Subject: [PATCH 02/64] Fix GH-13563: Setting bool values via env in FPM config fails Closes GH-13786 --- NEWS | 4 +- sapi/fpm/fpm/fpm_conf.c | 18 +++++- sapi/fpm/tests/gh13563-conf-bool-env.phpt | 75 +++++++++++++++++++++++ sapi/fpm/tests/tester.inc | 3 +- 4 files changed, 96 insertions(+), 4 deletions(-) create mode 100644 sapi/fpm/tests/gh13563-conf-bool-env.phpt diff --git a/NEWS b/NEWS index bdc2cd8efa244..86dccc9a06d03 100644 --- a/NEWS +++ b/NEWS @@ -18,7 +18,9 @@ PHP NEWS . Fix phpdoc for DOMDocument load methods. (VincentLanglet) - FPM - . Fix incorrect check in fpm_shm_free(). (nielsdos) + . Fixed incorrect check in fpm_shm_free(). (nielsdos) + . Fixed bug GH-13563 (Setting bool values via env in FPM config fails). + (Jakub Zelenka) - GD: . Fixed bug GH-12019 (add GDLIB_CFLAGS in feature tests). (Michael Orlitzky) diff --git a/sapi/fpm/fpm/fpm_conf.c b/sapi/fpm/fpm/fpm_conf.c index ef9b35a9994aa..e1aec90ff3e83 100644 --- a/sapi/fpm/fpm/fpm_conf.c +++ b/sapi/fpm/fpm/fpm_conf.c @@ -213,8 +213,22 @@ static int fpm_conf_expand_pool_name(char **value) { static char *fpm_conf_set_boolean(zval *value, void **config, intptr_t offset) /* {{{ */ { zend_string *val = Z_STR_P(value); - bool value_y = zend_string_equals_literal(val, "1"); - bool value_n = ZSTR_LEN(val) == 0; /* Empty string is the only valid false value */ + /* we need to check all allowed values to correctly set value from the environment variable */ + bool value_y = ( + zend_string_equals_literal(val, "1") || + zend_string_equals_literal(val, "yes") || + zend_string_equals_literal(val, "true") || + zend_string_equals_literal(val, "on") + ); + bool value_n = ( + value_y || ZSTR_LEN(val) == 0 || + zend_string_equals_literal(val, "0") || + zend_string_equals_literal(val, "no") || + zend_string_equals_literal(val, "none") || + zend_string_equals_literal(val, "false") || + zend_string_equals_literal(val, "off") + ); + if (!value_y && !value_n) { return "invalid boolean value"; diff --git a/sapi/fpm/tests/gh13563-conf-bool-env.phpt b/sapi/fpm/tests/gh13563-conf-bool-env.phpt new file mode 100644 index 0000000000000..15dce0ecf9b5a --- /dev/null +++ b/sapi/fpm/tests/gh13563-conf-bool-env.phpt @@ -0,0 +1,75 @@ +--TEST-- +FPM: GH-13563 - conf boolean environment variables values +--SKIPIF-- + +--FILE-- + \$val) { + if (str_starts_with(\$name, 'FPM_TEST')) { + printf("%s: %s\n", \$name, \$val); + } +} +file_put_contents('php://stderr', str_repeat('a', 20) . "\n"); +EOT; + +$tester = new FPM\Tester($cfg, $code); +$tester->start(envVars: [ + 'FPM_TEST_LOG_BUF' => 'on', + 'FPM_TEST_DAEMONIZE' => 'false', + 'FPM_TEST_PROC_DUMP' => 'no', + 'FPM_TEST_CATCH_WRK_OUT' => 'yes', + 'FPM_TEST_DECOR_WRK_OUT' => 'true', + 'FPM_TEST_CLEAR_ENV' => 'none', + 'FPM_TEST_REQ_TERM_TRACK_FIN' => '0', +]); +$tester->expectLogStartNotices(); +$tester->request()->expectBody([ + 'FPM_TEST_LOG_BUF: on', + 'FPM_TEST_DAEMONIZE: false', + 'FPM_TEST_PROC_DUMP: no', + 'FPM_TEST_CATCH_WRK_OUT: yes', + 'FPM_TEST_DECOR_WRK_OUT: true', + 'FPM_TEST_CLEAR_ENV: none', + 'FPM_TEST_REQ_TERM_TRACK_FIN: 0', +]); +$tester->terminate(); +$tester->expectLogMessage('a', 1024, 20, true); +$tester->close(); + +?> +Done +--EXPECT-- +Done +--CLEAN-- + diff --git a/sapi/fpm/tests/tester.inc b/sapi/fpm/tests/tester.inc index 66cbad175298d..ff834c329fa50 100644 --- a/sapi/fpm/tests/tester.inc +++ b/sapi/fpm/tests/tester.inc @@ -432,6 +432,7 @@ class Tester bool $daemonize = false, array $extensions = [], array $iniEntries = [], + array $envVars = [], ) { $configFile = $this->createConfig(); $desc = $this->outDesc ? [] : [1 => array('pipe', 'w'), 2 => array('redirect', 1)]; @@ -465,7 +466,7 @@ class Tester $cmd = array_merge($cmd, $extraArgs); $this->trace('Starting FPM using command:', $cmd, true); - $this->masterProcess = proc_open($cmd, $desc, $pipes); + $this->masterProcess = proc_open($cmd, $desc, $pipes, null, $envVars); register_shutdown_function( function ($masterProcess) use ($configFile) { @unlink($configFile); From cd6a58114e9649495d3a4a8c3f628a7473f6c880 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Fri, 29 Mar 2024 16:05:13 +0000 Subject: [PATCH 03/64] Fix NEWS for the last FPM change --- NEWS | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 86dccc9a06d03..3517d0eeb08ad 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.2.19 +- FPM: + . Fixed bug GH-13563 (Setting bool values via env in FPM config fails). + (Jakub Zelenka) 11 Apr 2024, PHP 8.2.18 @@ -19,8 +22,6 @@ PHP NEWS - FPM . Fixed incorrect check in fpm_shm_free(). (nielsdos) - . Fixed bug GH-13563 (Setting bool values via env in FPM config fails). - (Jakub Zelenka) - GD: . Fixed bug GH-12019 (add GDLIB_CFLAGS in feature tests). (Michael Orlitzky) From c087398cc2efb437213cba603e98c82fc9cd88ac Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Sat, 23 Mar 2024 13:09:46 +0000 Subject: [PATCH 04/64] Fix GH-13264: Part 1 - Memory leak on filter failure Closes GH-13790 --- NEWS | 4 ++ ext/standard/tests/filters/gh13264.phpt | 49 +++++++++++++++++++++++++ ext/standard/user_filters.c | 15 -------- main/streams/streams.c | 11 ++++++ 4 files changed, 64 insertions(+), 15 deletions(-) create mode 100644 ext/standard/tests/filters/gh13264.phpt diff --git a/NEWS b/NEWS index 3517d0eeb08ad..b3a9c4963ffc8 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,10 @@ PHP NEWS . Fixed bug GH-13563 (Setting bool values via env in FPM config fails). (Jakub Zelenka) +- Streams: + . Fixed bug GH-13264 (Part 1 - Memory leak on stream filter failure). + (Jakub Zelenka) + 11 Apr 2024, PHP 8.2.18 - Core: diff --git a/ext/standard/tests/filters/gh13264.phpt b/ext/standard/tests/filters/gh13264.phpt new file mode 100644 index 0000000000000..6456a082a1e40 --- /dev/null +++ b/ext/standard/tests/filters/gh13264.phpt @@ -0,0 +1,49 @@ +--TEST-- +GH-81475: Memory leak during stream filter failure +--SKIPIF-- + +--FILE-- + 15]); + +// Read the filtered stream line by line. +while (($line = fgets($stream)) !== false) { + $error = error_get_last(); + if ($error !== null) { + // An error is thrown but fgets didn't return false + var_dump(error_get_last()); + var_dump($line); + } +} + +fclose($stream); +?> +--EXPECTF-- + +Notice: fgets(): zlib: data error in %s on line %d +array(4) { + ["type"]=> + int(8) + ["message"]=> + string(25) "fgets(): zlib: data error" + ["file"]=> + string(%d) "%s" + ["line"]=> + int(%d) +} +string(7) "Hello 6" + diff --git a/ext/standard/user_filters.c b/ext/standard/user_filters.c index dcbfc381d295f..8995471af4597 100644 --- a/ext/standard/user_filters.c +++ b/ext/standard/user_filters.c @@ -196,22 +196,7 @@ php_stream_filter_status_t userfilter_filter( } if (buckets_in->head) { - php_stream_bucket *bucket; - php_error_docref(NULL, E_WARNING, "Unprocessed filter buckets remaining on input brigade"); - while ((bucket = buckets_in->head)) { - /* Remove unconsumed buckets from the brigade */ - php_stream_bucket_unlink(bucket); - php_stream_bucket_delref(bucket); - } - } - if (ret != PSFS_PASS_ON) { - php_stream_bucket *bucket = buckets_out->head; - while (bucket != NULL) { - php_stream_bucket_unlink(bucket); - php_stream_bucket_delref(bucket); - bucket = buckets_out->head; - } } /* filter resources are cleaned up by the stream destructor, diff --git a/main/streams/streams.c b/main/streams/streams.c index d45a9bfab85f8..33f8b7e7a80cd 100644 --- a/main/streams/streams.c +++ b/main/streams/streams.c @@ -632,6 +632,17 @@ PHPAPI zend_result _php_stream_fill_read_buffer(php_stream *stream, size_t size) /* some fatal error. Theoretically, the stream is borked, so all * further reads should fail. */ stream->eof = 1; + /* free all data left in brigades */ + while ((bucket = brig_inp->head)) { + /* Remove unconsumed buckets from the input brigade */ + php_stream_bucket_unlink(bucket); + php_stream_bucket_delref(bucket); + } + while ((bucket = brig_outp->head)) { + /* Remove unconsumed buckets from the output brigade */ + php_stream_bucket_unlink(bucket); + php_stream_bucket_delref(bucket); + } efree(chunk_buf); return FAILURE; } From c1bd9a932a55d2efba64126118477de7055b1c2e Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Thu, 21 Dec 2023 20:12:02 +0000 Subject: [PATCH 05/64] Fix GH-10495: feof on OpenSSL stream hangs indefinitely This fixes the issue with unbounded waiting on SSL_peek which can happen when only part of the record is fetched. It makes socket non blocking so it is possible to verify if OpenSSL is expecting some more data or if there is an error. This also fixes bug #79501 Closes GH-13487 --- NEWS | 4 ++ ext/openssl/tests/gh10495.phpt | 116 +++++++++++++++++++++++++++++++++ ext/openssl/xp_ssl.c | 101 ++++++++++++++++++++++++---- 3 files changed, 208 insertions(+), 13 deletions(-) create mode 100644 ext/openssl/tests/gh10495.phpt diff --git a/NEWS b/NEWS index b3a9c4963ffc8..d7b492e6c37df 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,10 @@ PHP NEWS . Fixed bug GH-13563 (Setting bool values via env in FPM config fails). (Jakub Zelenka) +- OpenSSL: + . Fixed bug GH-10495 (feof on OpenSSL stream hangs indefinitely). + (Jakub Zelenka) + - Streams: . Fixed bug GH-13264 (Part 1 - Memory leak on stream filter failure). (Jakub Zelenka) diff --git a/ext/openssl/tests/gh10495.phpt b/ext/openssl/tests/gh10495.phpt new file mode 100644 index 0000000000000..3ed5a3d384b64 --- /dev/null +++ b/ext/openssl/tests/gh10495.phpt @@ -0,0 +1,116 @@ +--TEST-- +GH-10495: feof hangs indefinitely +--EXTENSIONS-- +openssl +--SKIPIF-- + +--FILE-- + ['verify_peer' => false, 'peer_name' => '%s']]); + + phpt_wait('server'); + phpt_notify('proxy'); + + phpt_wait('proxy'); + $fp = stream_socket_client("tlsv1.2://127.0.0.1:10012", $errornum, $errorstr, 1, STREAM_CLIENT_CONNECT, $context); + + phpt_wait('proxy'); + + $time = microtime(true); + var_dump(feof($fp)); + var_dump(microtime(true) - $time < 0.5); + + var_dump(stream_get_contents($fp, 6)); + + phpt_notify('server'); + phpt_notify('proxy'); +CODE; +$clientCode = sprintf($clientCode, $peerName); + +$serverCode = <<<'CODE' + $context = stream_context_create(['ssl' => ['local_cert' => '%s']]); + + $flags = STREAM_SERVER_BIND|STREAM_SERVER_LISTEN; + $fp = stream_socket_server("tlsv1.2://127.0.0.1:10011", $errornum, $errorstr, $flags, $context); + phpt_notify(); + + $conn = stream_socket_accept($fp); + fwrite($conn, 'warmup'); + + phpt_wait(); + fclose($conn); +CODE; +$serverCode = sprintf($serverCode, $certFile); + +$proxyCode = <<<'CODE' + phpt_wait(); + + $upstream = stream_socket_client("tcp://127.0.0.1:10011", $errornum, $errorstr, 3000, STREAM_CLIENT_CONNECT); + stream_set_blocking($upstream, false); + + $flags = STREAM_SERVER_BIND|STREAM_SERVER_LISTEN; + $server = stream_socket_server("tcp://127.0.0.1:10012", $errornum, $errorstr, $flags); + phpt_notify(); + $conn = stream_socket_accept($server); + stream_set_blocking($conn, false); + + $read = [$upstream, $conn]; + $applicationData = false; + $i = 1; + while (stream_select($read, $write, $except, 1)) { + foreach ($read as $fp) { + $data = stream_get_contents($fp); + if ($fp === $conn) { + fwrite($upstream, $data); + } else { + if ($data !== '' && $data[0] === chr(23)) { + if (!$applicationData) { + $applicationData = true; + fwrite($conn, $data[0]); + phpt_notify(); + sleep(1); + fwrite($conn, substr($data, 1)); + } else { + fwrite($conn, $data); + } + } else { + fwrite($conn, $data); + } + } + } + if (feof($upstream)) { + break; + } + $read = [$upstream, $conn]; + } + + phpt_wait(); +CODE; + +include 'CertificateGenerator.inc'; +$certificateGenerator = new CertificateGenerator(); +$certificateGenerator->saveCaCert($cacertFile); +$certificateGenerator->saveNewCertAsFileWithKey($peerName, $certFile); + +include 'ServerClientTestCase.inc'; +ServerClientTestCase::getInstance()->run($clientCode, [ + 'server' => $serverCode, + 'proxy' => $proxyCode, +]); +?> +--CLEAN-- + +--EXPECT-- +bool(false) +bool(true) +string(6) "warmup" diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index 2e21c138d6b50..e01d53656fe62 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -2484,21 +2484,96 @@ static int php_openssl_sockop_set_option(php_stream *stream, int option, int val /* the poll() call was skipped if the socket is non-blocking (or MSG_DONTWAIT is available) and if the timeout is zero */ /* additionally, we don't use this optimization if SSL is active because in that case, we're not using MSG_DONTWAIT */ if (sslsock->ssl_active) { - int n = SSL_peek(sslsock->ssl_handle, &buf, sizeof(buf)); - if (n <= 0) { - int err = SSL_get_error(sslsock->ssl_handle, n); - switch (err) { - case SSL_ERROR_SYSCALL: - alive = php_socket_errno() == EAGAIN; - break; - case SSL_ERROR_WANT_READ: - case SSL_ERROR_WANT_WRITE: - alive = 1; + int retry = 1; + struct timeval start_time; + struct timeval *timeout = NULL; + int began_blocked = sslsock->s.is_blocked; + int has_timeout = 0; + + /* never use a timeout with non-blocking sockets */ + if (began_blocked) { + timeout = &tv; + } + + if (timeout && php_set_sock_blocking(sslsock->s.socket, 0) == SUCCESS) { + sslsock->s.is_blocked = 0; + } + + if (!sslsock->s.is_blocked && timeout && (timeout->tv_sec > 0 || (timeout->tv_sec == 0 && timeout->tv_usec))) { + has_timeout = 1; + /* gettimeofday is not monotonic; using it here is not strictly correct */ + gettimeofday(&start_time, NULL); + } + + /* Main IO loop. */ + do { + struct timeval cur_time, elapsed_time, left_time; + + /* If we have a timeout to check, figure out how much time has elapsed since we started. */ + if (has_timeout) { + gettimeofday(&cur_time, NULL); + + /* Determine how much time we've taken so far. */ + elapsed_time = php_openssl_subtract_timeval(cur_time, start_time); + + /* and return an error if we've taken too long. */ + if (php_openssl_compare_timeval(elapsed_time, *timeout) > 0 ) { + /* If the socket was originally blocking, set it back. */ + if (began_blocked) { + php_set_sock_blocking(sslsock->s.socket, 1); + sslsock->s.is_blocked = 1; + } + sslsock->s.timeout_event = 1; + return PHP_STREAM_OPTION_RETURN_ERR; + } + } + + int n = SSL_peek(sslsock->ssl_handle, &buf, sizeof(buf)); + /* If we didn't do anything on the last loop (or an error) check to see if we should retry or exit. */ + if (n <= 0) { + /* Now, do the IO operation. Don't block if we can't complete... */ + int err = SSL_get_error(sslsock->ssl_handle, n); + switch (err) { + case SSL_ERROR_SYSCALL: + retry = php_socket_errno() == EAGAIN; + break; + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + retry = 1; + break; + default: + /* any other problem is a fatal error */ + retry = 0; + } + + /* Don't loop indefinitely in non-blocking mode if no data is available */ + if (began_blocked == 0 || !has_timeout) { + alive = retry; break; - default: - /* any other problem is a fatal error */ - alive = 0; + } + + /* Now, if we have to wait some time, and we're supposed to be blocking, wait for the socket to become + * available. Now, php_pollfd_for uses select to wait up to our time_left value only... + */ + if (retry) { + /* Now, how much time until we time out? */ + left_time = php_openssl_subtract_timeval(*timeout, elapsed_time); + if (php_pollfd_for(sslsock->s.socket, PHP_POLLREADABLE|POLLPRI|POLLOUT, has_timeout ? &left_time : NULL) <= 0) { + retry = 0; + alive = 0; + }; + } + } else { + retry = 0; + alive = 1; } + /* Finally, we keep going until there are any data or there is no time to wait. */ + } while (retry); + + if (began_blocked && !sslsock->s.is_blocked) { + // Set it back to blocking + php_set_sock_blocking(sslsock->s.socket, 1); + sslsock->s.is_blocked = 1; } } else if (0 == recv(sslsock->s.socket, &buf, sizeof(buf), MSG_PEEK|MSG_DONTWAIT) && php_socket_errno() != EAGAIN) { alive = 0; From 100258ffd6f9a9094878a5cdaff0aa8986d70eac Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Thu, 21 Dec 2023 20:12:02 +0000 Subject: [PATCH 06/64] Fix test for GH-10495: feof on OpenSSL stream hangs --- ext/openssl/tests/ServerClientTestCase.inc | 29 ++++++++++++++++++++++ ext/openssl/tests/gh10495.phpt | 23 +++++++++-------- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/ext/openssl/tests/ServerClientTestCase.inc b/ext/openssl/tests/ServerClientTestCase.inc index 753366df6f4be..a05a4815a0196 100644 --- a/ext/openssl/tests/ServerClientTestCase.inc +++ b/ext/openssl/tests/ServerClientTestCase.inc @@ -26,6 +26,35 @@ function phpt_has_sslv3() { return $result; } +function phpt_extract_tls_records($rawData) { + $records = []; + $offset = 0; + $dataLength = strlen($rawData); + + while ($offset < $dataLength) { + // Ensure there's enough data left for the header. + if ($offset + 5 > $dataLength) { + break; + } + + // Extract the length of the current record. + $length = unpack("n", substr($rawData, $offset + 3, 2))[1]; + + // Check if the total length is within the bounds of the rawData. + if ($offset + 5 + $length > $dataLength) { + break; + } + + // Extract the record and add it to the records array. + $records[] = substr($rawData, $offset, 5 + $length); + + // Move the offset past the current record. + $offset += 5 + $length; + } + + return $records; +} + /** * This is a singleton to let the wait/notify functions work * I know it's horrible, but it's a means to an end diff --git a/ext/openssl/tests/gh10495.phpt b/ext/openssl/tests/gh10495.phpt index 3ed5a3d384b64..7c743d8de50a5 100644 --- a/ext/openssl/tests/gh10495.phpt +++ b/ext/openssl/tests/gh10495.phpt @@ -63,25 +63,26 @@ $proxyCode = <<<'CODE' $read = [$upstream, $conn]; $applicationData = false; - $i = 1; while (stream_select($read, $write, $except, 1)) { foreach ($read as $fp) { $data = stream_get_contents($fp); if ($fp === $conn) { fwrite($upstream, $data); } else { - if ($data !== '' && $data[0] === chr(23)) { - if (!$applicationData) { - $applicationData = true; - fwrite($conn, $data[0]); - phpt_notify(); - sleep(1); - fwrite($conn, substr($data, 1)); + foreach (phpt_extract_tls_records($data) as $record) { + if ($record !== '' && $record[0] === chr(23)) { + if (!$applicationData) { + $applicationData = true; + fwrite($conn, $record[0]); + phpt_notify(); + sleep(1); + fwrite($conn, substr($record, 1)); + } else { + fwrite($conn, $record); + } } else { - fwrite($conn, $data); + fwrite($conn, $record); } - } else { - fwrite($conn, $data); } } } From d3f1f3ab4070e3d832f801cc353cd522219cfa26 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 29 Mar 2024 00:38:15 +0100 Subject: [PATCH 07/64] Fix GH-13827: Null pointer access of type 'zval' in phpdbg_frame We don't always have the line and filename in a backtrace frame, but phpdbg assumes we do. Closes GH-13831. --- NEWS | 4 ++++ sapi/phpdbg/phpdbg_frame.c | 13 +++++++++++-- sapi/phpdbg/tests/gh13827.phpt | 30 ++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 sapi/phpdbg/tests/gh13827.phpt diff --git a/NEWS b/NEWS index d7b492e6c37df..ff9fa5a959168 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,10 @@ PHP NEWS . Fixed bug GH-10495 (feof on OpenSSL stream hangs indefinitely). (Jakub Zelenka) +- PHPDBG: + . Fixed bug GH-13827 (Null pointer access of type 'zval' in phpdbg_frame). + (nielsdos) + - Streams: . Fixed bug GH-13264 (Part 1 - Memory leak on stream filter failure). (Jakub Zelenka) diff --git a/sapi/phpdbg/phpdbg_frame.c b/sapi/phpdbg/phpdbg_frame.c index 644668d8d14e5..3652d2b2bbaf2 100644 --- a/sapi/phpdbg/phpdbg_frame.c +++ b/sapi/phpdbg/phpdbg_frame.c @@ -274,7 +274,8 @@ void phpdbg_dump_backtrace(size_t num) /* {{{ */ Z_STR(startfile) = zend_string_init(startfilename, strlen(startfilename), 0); zend_hash_internal_pointer_reset_ex(Z_ARRVAL(zbacktrace), &position); - tmp = zend_hash_get_current_data_ex(Z_ARRVAL(zbacktrace), &position); + + zval *function_name = NULL; while ((tmp = zend_hash_get_current_data_ex(Z_ARRVAL(zbacktrace), &position))) { if (file) { /* userland */ phpdbg_out("frame #%d: ", i); @@ -289,10 +290,18 @@ void phpdbg_dump_backtrace(size_t num) /* {{{ */ file = zend_hash_str_find(Z_ARRVAL_P(tmp), ZEND_STRL("file")); line = zend_hash_str_find(Z_ARRVAL_P(tmp), ZEND_STRL("line")); + function_name = zend_hash_find(Z_ARRVAL_P(tmp), ZSTR_KNOWN(ZEND_STR_FUNCTION)); + zend_hash_move_forward_ex(Z_ARRVAL(zbacktrace), &position); } - phpdbg_writeln("frame #%d: {main} at %s:"ZEND_LONG_FMT, i, Z_STRVAL_P(file), Z_LVAL_P(line)); + /* This is possible for fibers' start closure for example, which have a frame that doesn't contain the info + * of which location stated the fiber if that stack frame is already torn down. same behaviour with debug_backtrace(). */ + if (file == NULL) { + phpdbg_writeln(" => %s (internal function)", Z_STRVAL_P(function_name)); + } else { + phpdbg_writeln("frame #%d: {main} at %s:"ZEND_LONG_FMT, i, Z_STRVAL_P(file), Z_LVAL_P(line)); + } zval_ptr_dtor_nogc(&zbacktrace); zend_string_release(Z_STR(startfile)); diff --git a/sapi/phpdbg/tests/gh13827.phpt b/sapi/phpdbg/tests/gh13827.phpt new file mode 100644 index 0000000000000..3d7017bf309f5 --- /dev/null +++ b/sapi/phpdbg/tests/gh13827.phpt @@ -0,0 +1,30 @@ +--TEST-- +GH-13827 (Null pointer access of type 'zval' in phpdbg_frame) +--FILE-- +start(); + +$fiber = null; +gc_collect_cycles(); + +?> +--PHPDBG-- +r +t +q +--EXPECTF-- +[Successful compilation of %s] +prompt> [Uncaught GracefulExit in on line 0: ] +>00006: Fiber::suspend(); + 00007: }); + 00008: +prompt> frame #0: {closure}() at %s:6 + => {closure} (internal function) +prompt> From 11caf094f1af6b47ea2138c5fa907838911ebe01 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Sun, 10 Mar 2024 20:51:22 +0000 Subject: [PATCH 08/64] Fix GH-13620: Failing openssl_private_decrypt tests Use OPENSSL_PKCS1_OAEP_PADDING padding in tests Closes GH-13667 --- ext/openssl/tests/openssl_error_string_basic.phpt | 9 ++++----- .../tests/openssl_error_string_basic_openssl3.phpt | 9 ++++----- .../tests/openssl_private_decrypt_basic.phpt | 13 ++++++------- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/ext/openssl/tests/openssl_error_string_basic.phpt b/ext/openssl/tests/openssl_error_string_basic.phpt index 18e06b30bb447..4b5ca9fd9c042 100644 --- a/ext/openssl/tests/openssl_error_string_basic.phpt +++ b/ext/openssl/tests/openssl_error_string_basic.phpt @@ -6,7 +6,6 @@ openssl = 0x30000000) die('skip For OpenSSL < 3.0'); ?> ---XFAIL-- --FILE-- = 3.0'); ?> ---XFAIL-- --FILE-- getMessage() . \PHP_EOL; } -var_dump(openssl_private_decrypt($encrypted, $output5, array($privkey, ""))); +var_dump(openssl_private_decrypt($encrypted, $output5, array($privkey, ""), OPENSSL_PKCS1_OAEP_PADDING)); var_dump($output5); ?> --EXPECTF-- From 9b1d2e93b81d404815361398cea7a62bf84041e9 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Sat, 30 Mar 2024 14:10:31 +0000 Subject: [PATCH 09/64] Fix FPM tester default env vars change This broke cloexec test --- sapi/fpm/tests/tester.inc | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/sapi/fpm/tests/tester.inc b/sapi/fpm/tests/tester.inc index ff834c329fa50..ed0988f883ac1 100644 --- a/sapi/fpm/tests/tester.inc +++ b/sapi/fpm/tests/tester.inc @@ -417,11 +417,12 @@ class Tester /** * Start PHP-FPM master process * - * @param array $extraArgs Command extra arguments. - * @param bool $forceStderr Whether to output to stderr so error log is used. - * @param bool $daemonize Whether to start FPM daemonized - * @param array $extensions List of extension to add if shared build used. - * @param array $iniEntries List of ini entries to use. + * @param array $extraArgs Command extra arguments. + * @param bool $forceStderr Whether to output to stderr so error log is used. + * @param bool $daemonize Whether to start FPM daemonized + * @param array $extensions List of extension to add if shared build used. + * @param array $iniEntries List of ini entries to use. + * @param array|null $envVars List of env variable to execute FPM with or null to use the current ones. * * @return bool * @throws \Exception @@ -432,7 +433,7 @@ class Tester bool $daemonize = false, array $extensions = [], array $iniEntries = [], - array $envVars = [], + ?array $envVars = null, ) { $configFile = $this->createConfig(); $desc = $this->outDesc ? [] : [1 => array('pipe', 'w'), 2 => array('redirect', 1)]; From ed8ed714a86406eb8634043ac4afab577d0fd546 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 30 Mar 2024 11:53:01 +0100 Subject: [PATCH 10/64] Fix GH-13836: Renaming a file in a Phar to an already existing filename causes a NULL pointer dereference If the destination already exists, then the `add` function on the manifest will return NULL, resulting in a NULL entry and therefore a NULL deref. As `copy()` (not `Phar::copy`) chooses to succeed and overwrite the destination if it already exists, we should do the same. Therefore the fix is as simple as changing `add` to `update`. Closes GH-13840. --- NEWS | 4 ++++ ext/phar/stream.c | 5 +++-- ext/phar/tests/gh13833.phpt | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 ext/phar/tests/gh13833.phpt diff --git a/NEWS b/NEWS index ff9fa5a959168..946ea2911eb34 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,10 @@ PHP NEWS . Fixed bug GH-10495 (feof on OpenSSL stream hangs indefinitely). (Jakub Zelenka) +- Phar: + . Fixed bug GH-13836 (Renaming a file in a Phar to an already existing + filename causes a NULL pointer dereference). (nielsdos) + - PHPDBG: . Fixed bug GH-13827 (Null pointer access of type 'zval' in phpdbg_frame). (nielsdos) diff --git a/ext/phar/stream.c b/ext/phar/stream.c index adebe5ab9bd11..ceedbdae35389 100644 --- a/ext/phar/stream.c +++ b/ext/phar/stream.c @@ -858,8 +858,9 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from entry->link = entry->tmp = NULL; source = entry; - /* add to the manifest, and then store the pointer to the new guy in entry */ - entry = zend_hash_str_add_mem(&(phar->manifest), ZSTR_VAL(resource_to->path)+1, ZSTR_LEN(resource_to->path)-1, (void **)&new, sizeof(phar_entry_info)); + /* add to the manifest, and then store the pointer to the new guy in entry + * if it already exists, we overwrite the destination like what copy('phar://...', 'phar://...') does. */ + entry = zend_hash_str_update_mem(&(phar->manifest), ZSTR_VAL(resource_to->path)+1, ZSTR_LEN(resource_to->path)-1, (void **)&new, sizeof(phar_entry_info)); entry->filename = estrndup(ZSTR_VAL(resource_to->path)+1, ZSTR_LEN(resource_to->path)-1); if (FAILURE == phar_copy_entry_fp(source, entry, &error)) { diff --git a/ext/phar/tests/gh13833.phpt b/ext/phar/tests/gh13833.phpt new file mode 100644 index 0000000000000..d1b79d033e0e8 --- /dev/null +++ b/ext/phar/tests/gh13833.phpt @@ -0,0 +1,33 @@ +--TEST-- +GH-13836 (Renaming a file in a Phar to an already existing filename causes a NULL pointer dereference) +--EXTENSIONS-- +phar +--INI-- +phar.require_hash=0 +phar.readonly=0 +--FILE-- + +--CLEAN-- + +--EXPECTF-- +bool(true) +bool(false) +object(PharFileInfo)#2 (2) { + ["pathName":"SplFileInfo":private]=> + string(%d) "phar://%sgh13836.phar/y" + ["fileName":"SplFileInfo":private]=> + string(1) "y" +} From 47bb6c1b795c494a010e4de9e2de8475675b1ca6 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 31 Mar 2024 01:17:49 +0100 Subject: [PATCH 11/64] Fix GH-13833: Applying zero offset to null pointer in zend_hash.c MAPPHAR_FAIL will call the destructor of the manifest, mounted_dirs, and virtual_dirs tables. When a new phar object is allocated using (p)ecalloc, the bytes are zeroed, but the flag for an uninitialized table is non-zero. So we have to manually set the flag in case that we have a code path that can destroy the tables without first initializing them at least once. Closes GH-13847. --- NEWS | 2 ++ ext/phar/phar.c | 3 +++ ext/phar/tests/gh13833.phpt | 52 +++++++++++++++++++++++-------------- ext/phar/tests/gh13836.phpt | 33 +++++++++++++++++++++++ 4 files changed, 70 insertions(+), 20 deletions(-) create mode 100644 ext/phar/tests/gh13836.phpt diff --git a/NEWS b/NEWS index 946ea2911eb34..adbec6cc43091 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,8 @@ PHP NEWS - Phar: . Fixed bug GH-13836 (Renaming a file in a Phar to an already existing filename causes a NULL pointer dereference). (nielsdos) + . Fixed bug GH-13833 (Applying zero offset to null pointer in zend_hash.c). + (nielsdos) - PHPDBG: . Fixed bug GH-13827 (Null pointer access of type 'zval' in phpdbg_frame). diff --git a/ext/phar/phar.c b/ext/phar/phar.c index f60b0d6a7c04b..b774f22e2d565 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -1090,6 +1090,9 @@ static int phar_parse_pharfile(php_stream *fp, char *fname, size_t fname_len, ch mydata = pecalloc(1, sizeof(phar_archive_data), PHAR_G(persist)); mydata->is_persistent = PHAR_G(persist); + HT_INVALIDATE(&mydata->manifest); + HT_INVALIDATE(&mydata->mounted_dirs); + HT_INVALIDATE(&mydata->virtual_dirs); /* check whether we have meta data, zero check works regardless of byte order */ SAFE_PHAR_GET_32(buffer, endbuffer, len); diff --git a/ext/phar/tests/gh13833.phpt b/ext/phar/tests/gh13833.phpt index d1b79d033e0e8..026735deac14e 100644 --- a/ext/phar/tests/gh13833.phpt +++ b/ext/phar/tests/gh13833.phpt @@ -1,33 +1,45 @@ --TEST-- -GH-13836 (Renaming a file in a Phar to an already existing filename causes a NULL pointer dereference) ---EXTENSIONS-- -phar +GH-13833 (Applying zero offset to null pointer in zend_hash.c) --INI-- phar.require_hash=0 phar.readonly=0 --FILE-- "; +$files = array(); +$files['a'] = 'a'; +include 'files/phar_test.inc'; +include $fname; -$phar = new Phar($fname, 0, 'a.phar'); -$phar['x'] = 'hi1'; -$phar['y'] = 'hi2'; +$file = ""; +$files['a'] = array('cont' => 'a'); +include 'files/phar_test.inc'; -var_dump(rename("phar://a.phar/x", "phar://a.phar/y")); - -var_dump(isset($phar['x'])); -var_dump($phar['y']); +$phar = new Phar($fname); +$phar->setMetadata((object) ['my' => 'friend']); +// NOTE: Phar will use the cached value of metadata if setMetaData was called on that Phar path before. +// Save the writes to the phar and use a different file path. +$fname_new = "$fname.copy.phar"; +copy($fname, $fname_new); +try { + new Phar($fname_new); +} catch (UnexpectedValueException $e) { + echo $e->getMessage(), "\n"; +} ?> +--EXTENSIONS-- +phar --CLEAN-- +--CREDITS-- +Yuancheng Jiang +Felix De Vliegher --EXPECTF-- -bool(true) -bool(false) -object(PharFileInfo)#2 (2) { - ["pathName":"SplFileInfo":private]=> - string(%d) "phar://%sgh13836.phar/y" - ["fileName":"SplFileInfo":private]=> - string(1) "y" -} +internal corruption of phar "%sgh13833.phar.copy.phar" (trying to read past buffer end) diff --git a/ext/phar/tests/gh13836.phpt b/ext/phar/tests/gh13836.phpt new file mode 100644 index 0000000000000..d1b79d033e0e8 --- /dev/null +++ b/ext/phar/tests/gh13836.phpt @@ -0,0 +1,33 @@ +--TEST-- +GH-13836 (Renaming a file in a Phar to an already existing filename causes a NULL pointer dereference) +--EXTENSIONS-- +phar +--INI-- +phar.require_hash=0 +phar.readonly=0 +--FILE-- + +--CLEAN-- + +--EXPECTF-- +bool(true) +bool(false) +object(PharFileInfo)#2 (2) { + ["pathName":"SplFileInfo":private]=> + string(%d) "phar://%sgh13836.phar/y" + ["fileName":"SplFileInfo":private]=> + string(1) "y" +} From 5ed5d37f255d97921a882c69eec7dcb9705cb185 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 31 Mar 2024 16:56:14 +0200 Subject: [PATCH 12/64] Skip test on Windows because of different error output --- ext/phar/tests/gh13833.phpt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/phar/tests/gh13833.phpt b/ext/phar/tests/gh13833.phpt index 026735deac14e..8430bd5e605b2 100644 --- a/ext/phar/tests/gh13833.phpt +++ b/ext/phar/tests/gh13833.phpt @@ -3,6 +3,8 @@ GH-13833 (Applying zero offset to null pointer in zend_hash.c) --INI-- phar.require_hash=0 phar.readonly=0 +--SKIPIF-- + --FILE-- Date: Sun, 31 Mar 2024 16:23:37 +0100 Subject: [PATCH 13/64] ext/sockets: socket_create_listen clearing socket data before binding. Close GH-13855 --- ext/sockets/sockets.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/sockets/sockets.c b/ext/sockets/sockets.c index 73ba905f9c324..8183398a8d322 100644 --- a/ext/sockets/sockets.c +++ b/ext/sockets/sockets.c @@ -219,7 +219,7 @@ int inet_ntoa_lock = 0; static int php_open_listen_sock(php_socket *sock, int port, int backlog) /* {{{ */ { - struct sockaddr_in la; + struct sockaddr_in la = {0}; struct hostent *hp; #ifndef PHP_WIN32 From 46f45a51b48a1d066a8aa7808edce27f3daf6113 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 1 Apr 2024 13:39:38 +0200 Subject: [PATCH 14/64] Fix GH-13856: Member access within null pointer of type 'ps_files' in ext/session/mod_files.c We should not mark the session as opened when there was a failure in open. Closes GH-13858. --- NEWS | 4 ++++ ext/session/mod_user_class.c | 6 ++++-- ext/session/tests/gh13856.phpt | 19 +++++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 ext/session/tests/gh13856.phpt diff --git a/NEWS b/NEWS index adbec6cc43091..7528021f82b6c 100644 --- a/NEWS +++ b/NEWS @@ -20,6 +20,10 @@ PHP NEWS . Fixed bug GH-13827 (Null pointer access of type 'zval' in phpdbg_frame). (nielsdos) +- Session: + . Fixed bug GH-13856 (Member access within null pointer of type 'ps_files' in + ext/session/mod_files.c). (nielsdos) + - Streams: . Fixed bug GH-13264 (Part 1 - Memory leak on stream filter failure). (Jakub Zelenka) diff --git a/ext/session/mod_user_class.c b/ext/session/mod_user_class.c index d5b71da52c282..853db659887be 100644 --- a/ext/session/mod_user_class.c +++ b/ext/session/mod_user_class.c @@ -47,8 +47,6 @@ PHP_METHOD(SessionHandler, open) PS_SANITY_CHECK; - PS(mod_user_is_open) = 1; - zend_try { ret = PS(default_mod)->s_open(&PS(mod_data), save_path, session_name); } zend_catch { @@ -56,6 +54,10 @@ PHP_METHOD(SessionHandler, open) zend_bailout(); } zend_end_try(); + if (SUCCESS == ret) { + PS(mod_user_is_open) = 1; + } + RETURN_BOOL(SUCCESS == ret); } /* }}} */ diff --git a/ext/session/tests/gh13856.phpt b/ext/session/tests/gh13856.phpt new file mode 100644 index 0000000000000..a6d9fa0eaedb7 --- /dev/null +++ b/ext/session/tests/gh13856.phpt @@ -0,0 +1,19 @@ +--TEST-- +GH-13856 (Member access within null pointer of type 'ps_files' in ext/session/mod_files.c) +--EXTENSIONS-- +session +--INI-- +session.save_handler=files +open_basedir=. +error_reporting=E_ALL +--FILE-- + +--EXPECTF-- +Warning: SessionHandler::open(): open_basedir restriction in effect. File(%s) is not within the allowed path(s): (.) in %s on line %d + +Warning: SessionHandler::close(): Parent session handler is not open in %s on line %d + +Warning: session_start(): Failed to initialize storage module: user (path: ) in %s on line %d From 18d70db091d3b378be1e19b5709c72dedd9a5ae4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cristian=20Rodr=C3=ADguez?= Date: Wed, 27 Mar 2024 11:49:18 -0300 Subject: [PATCH 15/64] Fix gcc-14 Wcalloc-transposed-args warnings gcc-14 and later warns of inverted arguments in calloc or calloc-like __alloc_size__ annotated functions. Closes GH-13818. --- NEWS | 3 +++ ext/ffi/ffi.c | 4 ++-- ext/opcache/zend_accelerator_blacklist.c | 2 +- ext/standard/proc_open.c | 2 +- main/streams/glob_wrapper.c | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index 7528021f82b6c..1aebd2b2a7874 100644 --- a/NEWS +++ b/NEWS @@ -28,6 +28,9 @@ PHP NEWS . Fixed bug GH-13264 (Part 1 - Memory leak on stream filter failure). (Jakub Zelenka) +- Treewide: + . Fix gcc-14 Wcalloc-transposed-args warnings. (Cristian Rodríguez) + 11 Apr 2024, PHP 8.2.18 - Core: diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index 4f2bc890a0e7b..5c6ca05f96108 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -2147,7 +2147,7 @@ static zend_result zend_ffi_cdata_get_closure(zend_object *obj, zend_class_entry if (EXPECTED(EG(trampoline).common.function_name == NULL)) { func = &EG(trampoline); } else { - func = ecalloc(sizeof(zend_internal_function), 1); + func = ecalloc(1, sizeof(zend_internal_function)); } func->type = ZEND_INTERNAL_FUNCTION; func->common.arg_flags[0] = 0; @@ -2898,7 +2898,7 @@ static zend_function *zend_ffi_get_func(zend_object **obj, zend_string *name, co if (EXPECTED(EG(trampoline).common.function_name == NULL)) { func = &EG(trampoline); } else { - func = ecalloc(sizeof(zend_internal_function), 1); + func = ecalloc(1, sizeof(zend_internal_function)); } func->common.type = ZEND_INTERNAL_FUNCTION; func->common.arg_flags[0] = 0; diff --git a/ext/opcache/zend_accelerator_blacklist.c b/ext/opcache/zend_accelerator_blacklist.c index 8ddc9298bf4d3..c4a543e6207bb 100644 --- a/ext/opcache/zend_accelerator_blacklist.c +++ b/ext/opcache/zend_accelerator_blacklist.c @@ -58,7 +58,7 @@ void zend_accel_blacklist_init(zend_blacklist *blacklist) zend_accel_blacklist_shutdown(blacklist); } - blacklist->entries = (zend_blacklist_entry *) calloc(sizeof(zend_blacklist_entry), blacklist->size); + blacklist->entries = (zend_blacklist_entry *) calloc(blacklist->size, sizeof(zend_blacklist_entry)); if (!blacklist->entries) { zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Blacklist initialization: no memory\n"); return; diff --git a/ext/standard/proc_open.c b/ext/standard/proc_open.c index 866c7a3c896e2..69095dcd06d81 100644 --- a/ext/standard/proc_open.c +++ b/ext/standard/proc_open.c @@ -646,7 +646,7 @@ static zend_string* get_command_from_array(HashTable *array, char ***argv, int n static descriptorspec_item* alloc_descriptor_array(HashTable *descriptorspec) { uint32_t ndescriptors = zend_hash_num_elements(descriptorspec); - return ecalloc(sizeof(descriptorspec_item), ndescriptors); + return ecalloc(ndescriptors, sizeof(descriptorspec_item)); } static zend_string* get_string_parameter(zval *array, int index, char *param_name) diff --git a/main/streams/glob_wrapper.c b/main/streams/glob_wrapper.c index 813e0bacdfd3f..45147f3fe614a 100644 --- a/main/streams/glob_wrapper.c +++ b/main/streams/glob_wrapper.c @@ -225,7 +225,7 @@ static php_stream *php_glob_stream_opener(php_stream_wrapper *wrapper, const cha } } - pglob = ecalloc(sizeof(*pglob), 1); + pglob = ecalloc(1, sizeof(*pglob)); if (0 != (ret = glob(path, pglob->flags & GLOB_FLAGMASK, NULL, &pglob->glob))) { #ifdef GLOB_NOMATCH From e7462bff19228162a21ccc6dd248b0dbffc15517 Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Tue, 2 Apr 2024 18:11:02 +0200 Subject: [PATCH 16/64] Run one testsuite with observers enabled in CI (#13869) Signed-off-by: Bob Weinand --- .circleci/config.yml | 2 ++ .github/nightly_matrix.php | 1 + Zend/tests/gh10346.phpt | 1 + ext/ffi/tests/gh12905.phpt | 1 + ext/opcache/tests/gh13712.phpt | 1 + ext/opcache/tests/jit/ignored_opcodes.phpt | 1 + ext/zend_test/tests/gh9871.phpt | 1 + ext/zend_test/tests/observer_backtrace_01.phpt | 1 + ext/zend_test/tests/observer_basic_01.phpt | 1 + ext/zend_test/tests/observer_basic_02.phpt | 1 + ext/zend_test/tests/observer_basic_03.phpt | 1 + ext/zend_test/tests/observer_basic_04.phpt | 1 + ext/zend_test/tests/observer_basic_05.phpt | 1 + ext/zend_test/tests/observer_basic_06.phpt | 1 + ext/zend_test/tests/observer_bug81430_1.phpt | 1 + ext/zend_test/tests/observer_bug81430_2.phpt | 1 + ext/zend_test/tests/observer_bug81435.phpt | 1 + ext/zend_test/tests/observer_call_user_func_01.phpt | 1 + ext/zend_test/tests/observer_call_user_func_02.phpt | 1 + ext/zend_test/tests/observer_call_user_func_03.phpt | 1 + ext/zend_test/tests/observer_call_user_func_04.phpt | 1 + ext/zend_test/tests/observer_closure_01.phpt | 1 + ext/zend_test/tests/observer_closure_02.phpt | 1 + ext/zend_test/tests/observer_closure_03.phpt | 1 + ext/zend_test/tests/observer_declarations_01.phpt | 1 + ext/zend_test/tests/observer_declarations_file_cache.phpt | 1 + ext/zend_test/tests/observer_error_01.phpt | 1 + ext/zend_test/tests/observer_error_02.phpt | 1 + ext/zend_test/tests/observer_error_03.phpt | 1 + ext/zend_test/tests/observer_error_04.phpt | 1 + ext/zend_test/tests/observer_error_05.phpt | 1 + ext/zend_test/tests/observer_eval_01.phpt | 1 + ext/zend_test/tests/observer_exception_01.phpt | 1 + ext/zend_test/tests/observer_fiber_01.phpt | 1 + ext/zend_test/tests/observer_fiber_02.phpt | 1 + ext/zend_test/tests/observer_fiber_03.phpt | 1 + ext/zend_test/tests/observer_fiber_04.phpt | 1 + ext/zend_test/tests/observer_fiber_05.phpt | 1 + ext/zend_test/tests/observer_fiber_06.phpt | 1 + ext/zend_test/tests/observer_fiber_functions_01.phpt | 1 + ext/zend_test/tests/observer_fiber_functions_02.phpt | 1 + ext/zend_test/tests/observer_fiber_functions_03.phpt | 1 + ext/zend_test/tests/observer_generator_01.phpt | 1 + ext/zend_test/tests/observer_generator_02.phpt | 1 + ext/zend_test/tests/observer_generator_03.phpt | 1 + ext/zend_test/tests/observer_generator_04.phpt | 1 + ext/zend_test/tests/observer_generator_05.phpt | 1 + ext/zend_test/tests/observer_magic_01.phpt | 1 + ext/zend_test/tests/observer_opline_01.phpt | 1 + ext/zend_test/tests/observer_preload.phpt | 1 + ext/zend_test/tests/observer_retval_01.phpt | 1 + ext/zend_test/tests/observer_retval_02.phpt | 1 + ext/zend_test/tests/observer_retval_03.phpt | 1 + ext/zend_test/tests/observer_retval_04.phpt | 1 + ext/zend_test/tests/observer_retval_05.phpt | 1 + ext/zend_test/tests/observer_retval_06.phpt | 1 + ext/zend_test/tests/observer_retval_07.phpt | 1 + ext/zend_test/tests/observer_retval_by_ref_01.phpt | 1 + ext/zend_test/tests/observer_retval_by_ref_02.phpt | 1 + ext/zend_test/tests/observer_retval_by_ref_03.phpt | 1 + ext/zend_test/tests/observer_shutdown_01.phpt | 1 + ext/zend_test/tests/observer_shutdown_02.phpt | 1 + ext/zend_test/tests/observer_sqlite_create_function.phpt | 1 + ext/zend_test/tests/observer_types_01.phpt | 1 + ext/zend_test/tests/observer_zend_call_function_01.phpt | 1 + 65 files changed, 66 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 332751fb53bd0..26834a9392e0c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -184,6 +184,8 @@ jobs: -d opcache.enable_cli=1 \ -d opcache.jit_buffer_size=16M \ -d opcache.jit=tracing \ + -d zend_test.observer.enabled=1 \ + -d zend_test.observer.show_output=0 \ -P -q -x -j2 \ -g FAIL,BORK,LEAK,XLEAK \ --no-progress \ diff --git a/.github/nightly_matrix.php b/.github/nightly_matrix.php index e74508785e219..23d391ffcff85 100644 --- a/.github/nightly_matrix.php +++ b/.github/nightly_matrix.php @@ -70,6 +70,7 @@ function get_matrix_include(array $branches) { 'debug' => true, 'zts' => true, 'configuration_parameters' => "CFLAGS='-DZEND_RC_DEBUG=1 -DPROFITABILITY_CHECKS=0 -DZEND_VERIFY_FUNC_INFO=1'", + 'run_tests_parameters' => '-d zend_test.observer.enabled=1 -d zend_test.observer.show_output=0', 'timeout_minutes' => 360, 'test_function_jit' => true, ]; diff --git a/Zend/tests/gh10346.phpt b/Zend/tests/gh10346.phpt index 74fce28e2307c..37d46b91317ff 100644 --- a/Zend/tests/gh10346.phpt +++ b/Zend/tests/gh10346.phpt @@ -6,6 +6,7 @@ Florian Sowade zend_test --INI-- zend_test.observer.enabled=1 +zend_test.observer.show_output=1 zend_test.observer.observe_all=1 --FILE-- Date: Thu, 4 Apr 2024 13:26:27 +0200 Subject: [PATCH 17/64] makedist: Reset tar timestamps to the commit date (#13879) This change should make the underlying `.tar` archive fully reproducible (given identical tool versions). --- scripts/dev/makedist | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/dev/makedist b/scripts/dev/makedist index 8e53f1d73a803..ffdf536907651 100755 --- a/scripts/dev/makedist +++ b/scripts/dev/makedist @@ -167,8 +167,9 @@ else fi # Reset the modification and access times of all files to be packaged. -echo "makedist: Resetting the modification and access times of package files." -touch -c NEWS +commitDate="$(git log -1 --format=%cI $treeish)" +echo "makedist: Resetting the modification and access times of package files to $commitDate" +touch -c -d"$commitDate" NEWS find . -exec touch -r NEWS -c {} \; cd .. From 8bfde5d01e9019964047b2d759878b99337555ab Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 4 Apr 2024 19:28:10 +0200 Subject: [PATCH 18/64] Fix shift out of bounds on 32-bit non-fast-path platforms (#10941) The x86-32 build uses a fast path, but when I disabled the fast path I got the following compile error with -Werror: mysqlnd_portability.h:221:95: error: right shift count >= width of type [-Werror=shift-count-overflow] For 32-bit platforms that don't have the fast path, this can cause undefined behaviour at runtime. Some CPUs just mask the shift amount so in those cases you even get wrong results. This is not always found during the build because -Werror is off by default. --- ext/mysqlnd/mysqlnd_portability.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/mysqlnd/mysqlnd_portability.h b/ext/mysqlnd/mysqlnd_portability.h index 295ce393a115a..11ebf4d1bf8ae 100644 --- a/ext/mysqlnd/mysqlnd_portability.h +++ b/ext/mysqlnd/mysqlnd_portability.h @@ -215,8 +215,8 @@ typedef union { *(((char *)(T))+1) = (char)(((A) >> 8));\ *(((char *)(T))+2) = (char)(((A) >> 16));\ *(((char *)(T))+3) = (char)(((A) >> 24)); \ - *(((char *)(T))+4) = (char)(((A) >> 32)); } while (0) -#define int8store(T,A) { uint32_t def_temp= (uint32_t) (A), def_temp2= (uint32_t) ((A) >> 32); \ + *(((char *)(T))+4) = sizeof(A) == 4 ? 0 : (char)(((A) >> 32)); } while (0) +#define int8store(T,A) { uint32_t def_temp= (uint32_t) (A), def_temp2= sizeof(A) == 4 ? 0 : (uint32_t) ((A) >> 32); \ int4store((T),def_temp); \ int4store((T+4),def_temp2); \ } From dfbad9f227cd07dd870b8c778517a212e122f151 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 4 Apr 2024 19:29:04 +0200 Subject: [PATCH 19/64] [ci skip] NEWS --- NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS b/NEWS index 1aebd2b2a7874..96f0aca380803 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,9 @@ PHP NEWS . Fixed bug GH-13563 (Setting bool values via env in FPM config fails). (Jakub Zelenka) +- MySQLnd: + . Fix shift out of bounds on 32-bit non-fast-path platforms. (nielsdos) + - OpenSSL: . Fixed bug GH-10495 (feof on OpenSSL stream hangs indefinitely). (Jakub Zelenka) From 97162e92be18388078f831a7cc9106a3e42f1c47 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Fri, 5 Apr 2024 14:11:41 +0200 Subject: [PATCH 20/64] Fix opcache dump varying tmps --- sapi/phpdbg/tests/print_001.phpt | 8 ++++---- sapi/phpdbg/tests/print_002.phpt | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sapi/phpdbg/tests/print_001.phpt b/sapi/phpdbg/tests/print_001.phpt index c25c5178fef4c..f192cb2ae9fcc 100644 --- a/sapi/phpdbg/tests/print_001.phpt +++ b/sapi/phpdbg/tests/print_001.phpt @@ -13,7 +13,7 @@ q prompt> [User Function foo (8 ops)] foo: - ; (lines=8, args=1, vars=1, tmps=2) + ; (lines=8, args=1, vars=1, tmps=%d) ; %s:14-16 L0014 0000 CV0($baz) = RECV 1 L0015 0001 INIT_FCALL %d %d string("var_dump") @@ -26,7 +26,7 @@ L0016 0007 RETURN null prompt> [User Class: Foo\Bar (2 methods)] Foo\Bar::Foo: - ; (lines=5, args=1, vars=1, tmps=1) + ; (lines=5, args=1, vars=1, tmps=%d) ; %s:5-7 L0005 0000 CV0($bar) = RECV 1 L0006 0001 INIT_NS_FCALL_BY_NAME 1 string("Foo\var_dump") @@ -35,14 +35,14 @@ L0006 0003 DO_FCALL L0007 0004 RETURN null Foo\Bar::baz: - ; (lines=1, args=0, vars=0, tmps=0) + ; (lines=1, args=0, vars=0, tmps=%d) ; %s:9-9 L0009 0000 RETURN null prompt> [Not Executing!] prompt> [Context %s (9 ops)] $_main: - ; (lines=9, args=0, vars=0, tmps=4) + ; (lines=9, args=0, vars=0, tmps=%d) ; %s:1-21 L0018 0000 V0 = NEW 0 string("Foo\Bar") L0018 0001 DO_FCALL diff --git a/sapi/phpdbg/tests/print_002.phpt b/sapi/phpdbg/tests/print_002.phpt index 2358b025d1741..3b46fe0c13c72 100644 --- a/sapi/phpdbg/tests/print_002.phpt +++ b/sapi/phpdbg/tests/print_002.phpt @@ -19,7 +19,7 @@ prompt> string(4) "test" prompt> [Stack in foo() (8 ops)] foo: - ; (lines=8, args=1, vars=1, tmps=2) + ; (lines=8, args=1, vars=1, tmps=%d) ; %s:14-16 L0014 0000 CV0($baz) = RECV 1 L0015 0001 INIT_FCALL %d %d string("var_dump") From 5ce9687cb2bc49e5d95b1c9bda5dc7f711c3da62 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 6 Apr 2024 13:43:26 +0200 Subject: [PATCH 21/64] Fix GH-13891: memleak and segfault when using ini_set with session.trans_sid_hosts (#13892) The hash tables used are allocated via the persistent allocator. When using ini_set, the allocation happens via the non-persistent allocator. When the table is then freed in GSHUTDOWN, we get a crash because the allocators are mismatched. As a side note, it is strange that this is designed this way, because it means that ini_sets persist between requests... Co-authored-by: Kamil Tekiela --- ext/session/tests/gh13891.phpt | 17 +++++++++++++++++ ext/standard/url_scanner_ex.re | 5 +++-- 2 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 ext/session/tests/gh13891.phpt diff --git a/ext/session/tests/gh13891.phpt b/ext/session/tests/gh13891.phpt new file mode 100644 index 0000000000000..7df9bffa770bc --- /dev/null +++ b/ext/session/tests/gh13891.phpt @@ -0,0 +1,17 @@ +--TEST-- +GH-13891 (memleak and segfault when using ini_set with session.trans_sid_hosts) +--INI-- +session.use_cookies=0 +session.use_only_cookies=0 +session.use_trans_sid=1 +session.trans_sid_hosts=php.net +--EXTENSIONS-- +session +--SKIPIF-- + +--FILE-- + +--EXPECT-- diff --git a/ext/standard/url_scanner_ex.re b/ext/standard/url_scanner_ex.re index 8e5b43467fc88..a4a48b6bf60ee 100644 --- a/ext/standard/url_scanner_ex.re +++ b/ext/standard/url_scanner_ex.re @@ -138,9 +138,10 @@ static int php_ini_on_update_hosts(zend_ini_entry *entry, zend_string *new_value } keylen = q - key; if (keylen > 0) { - tmp_key = zend_string_init(key, keylen, 0); + /* Note: the hash table is persistently allocated, so the strings must be too! */ + tmp_key = zend_string_init(key, keylen, true); zend_hash_add_empty_element(hosts, tmp_key); - zend_string_release_ex(tmp_key, 0); + zend_string_release_ex(tmp_key, true); } } efree(tmp); From 8367e9cc3b955f0b3770328277adb4dad1225c9e Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 6 Apr 2024 13:44:34 +0200 Subject: [PATCH 22/64] [ci skip] NEWS --- NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS b/NEWS index 96f0aca380803..8e544dfb91715 100644 --- a/NEWS +++ b/NEWS @@ -26,6 +26,8 @@ PHP NEWS - Session: . Fixed bug GH-13856 (Member access within null pointer of type 'ps_files' in ext/session/mod_files.c). (nielsdos) + . Fixed bug GH-13891 (memleak and segfault when using ini_set with + session.trans_sid_hosts). (nielsdos, kamil-tekiela). - Streams: . Fixed bug GH-13264 (Part 1 - Memory leak on stream filter failure). From 4a14211739982a82893c176f59c86aa090856415 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 7 Apr 2024 15:24:29 +0200 Subject: [PATCH 23/64] Fix persistent local flag in session url updating (#13905) Short-lived regression from 5ce9687cb2bc49e5d95b1c9bda5dc7f711c3da62. I forgot to add the persistent local flag, so that means that RC_DEBUG will complain. These strings are local to the thread so we can just add the flag to silence the debug checker in this case. --- ext/standard/url_scanner_ex.re | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/standard/url_scanner_ex.re b/ext/standard/url_scanner_ex.re index a4a48b6bf60ee..77b4d79793b65 100644 --- a/ext/standard/url_scanner_ex.re +++ b/ext/standard/url_scanner_ex.re @@ -140,6 +140,7 @@ static int php_ini_on_update_hosts(zend_ini_entry *entry, zend_string *new_value if (keylen > 0) { /* Note: the hash table is persistently allocated, so the strings must be too! */ tmp_key = zend_string_init(key, keylen, true); + GC_MAKE_PERSISTENT_LOCAL(tmp_key); zend_hash_add_empty_element(hosts, tmp_key); zend_string_release_ex(tmp_key, true); } From 2aae14c8a97d37239298b7c939c0cca5daeb4c9a Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 5 Apr 2024 23:21:32 +0200 Subject: [PATCH 24/64] Fix GH-13860: Incorrect PHP_STREAM_OPTION_CHECK_LIVENESS case in ext/openssl/xp_ssl.c - causing use of dead socket php_socket_errno() may return a stale value when recv returns a value >= 0. As such, the liveness check is wrong. This is the same bug as #70198 (fixed in GH-1456). So we fix it in the same way. Closes GH-13895. --- NEWS | 2 ++ ext/openssl/tests/gh13860.phpt | 49 ++++++++++++++++++++++++++++++++++ ext/openssl/xp_ssl.c | 16 +++++++++-- 3 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 ext/openssl/tests/gh13860.phpt diff --git a/NEWS b/NEWS index 8e544dfb91715..227ae6f0b2d6b 100644 --- a/NEWS +++ b/NEWS @@ -32,6 +32,8 @@ PHP NEWS - Streams: . Fixed bug GH-13264 (Part 1 - Memory leak on stream filter failure). (Jakub Zelenka) + . Fixed bug GH-13860 (Incorrect PHP_STREAM_OPTION_CHECK_LIVENESS case in + ext/openssl/xp_ssl.c - causing use of dead socket). (nielsdos) - Treewide: . Fix gcc-14 Wcalloc-transposed-args warnings. (Cristian Rodríguez) diff --git a/ext/openssl/tests/gh13860.phpt b/ext/openssl/tests/gh13860.phpt new file mode 100644 index 0000000000000..b915760bee592 --- /dev/null +++ b/ext/openssl/tests/gh13860.phpt @@ -0,0 +1,49 @@ +--TEST-- +GH-13860 (Incorrect PHP_STREAM_OPTION_CHECK_LIVENESS case in ext/openssl/xp_ssl.c - causing use of dead socket) +--EXTENSIONS-- +openssl +--SKIPIF-- + +--FILE-- +run($clientCode, $serverCode); +?> +--EXPECT-- +bool(true) diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index e01d53656fe62..a0db38c20bc02 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -2575,8 +2575,20 @@ static int php_openssl_sockop_set_option(php_stream *stream, int option, int val php_set_sock_blocking(sslsock->s.socket, 1); sslsock->s.is_blocked = 1; } - } else if (0 == recv(sslsock->s.socket, &buf, sizeof(buf), MSG_PEEK|MSG_DONTWAIT) && php_socket_errno() != EAGAIN) { - alive = 0; + } else { +#ifdef PHP_WIN32 + int ret; +#else + ssize_t ret; +#endif + int err; + + ret = recv(sslsock->s.socket, &buf, sizeof(buf), MSG_PEEK|MSG_DONTWAIT); + err = php_socket_errno(); + if (0 == ret || /* the counterpart did properly shutdown */ + (0 > ret && err != EWOULDBLOCK && err != EAGAIN && err != EMSGSIZE)) { /* there was an unrecoverable error */ + alive = 0; + } } } return alive ? PHP_STREAM_OPTION_RETURN_OK : PHP_STREAM_OPTION_RETURN_ERR; From a86256c950e2822b4cb1a15c13d61dceb4de5e3f Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 7 Apr 2024 22:28:23 +0200 Subject: [PATCH 25/64] Improve stability of test gh13860.phpt --- ext/openssl/tests/gh13860.phpt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/openssl/tests/gh13860.phpt b/ext/openssl/tests/gh13860.phpt index b915760bee592..c7c0c40a15760 100644 --- a/ext/openssl/tests/gh13860.phpt +++ b/ext/openssl/tests/gh13860.phpt @@ -21,6 +21,7 @@ $serverCode = <<<'CODE' fwrite($client, "xx"); phpt_wait(); fclose($client); + phpt_notify(); } CODE; @@ -38,6 +39,7 @@ $clientCode = <<<'CODE' while (!($in = fread($fp, 2))) { usleep(1000); } + phpt_wait(); var_dump(feof($fp)); fclose($fp); CODE; From 577b8ae4226368e66fee7a9b5c58f9e2428372fc Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Mon, 8 Apr 2024 14:58:12 +0200 Subject: [PATCH 26/64] Fix cookie_seek_function_t signature under musl (#13890) Fixes GH-11678 --- main/streams/cast.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/main/streams/cast.c b/main/streams/cast.c index 3bad65fbac1f5..8d9f4a9d2d54b 100644 --- a/main/streams/cast.c +++ b/main/streams/cast.c @@ -104,6 +104,9 @@ static ssize_t stream_cookie_writer(void *cookie, const char *buffer, size_t siz # ifdef COOKIE_SEEKER_USES_OFF64_T static int stream_cookie_seeker(void *cookie, off64_t *position, int whence) +# else +static int stream_cookie_seeker(void *cookie, off_t *position, int whence) +# endif { *position = php_stream_seek((php_stream *)cookie, (zend_off_t)*position, whence); @@ -113,13 +116,6 @@ static int stream_cookie_seeker(void *cookie, off64_t *position, int whence) } return 0; } -# else -static int stream_cookie_seeker(void *cookie, zend_off_t position, int whence) -{ - - return php_stream_seek((php_stream *)cookie, position, whence); -} -# endif static int stream_cookie_closer(void *cookie) { From 85d621242a09ad9b36f511b613777352cb90c7f4 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Mon, 8 Apr 2024 15:01:15 +0200 Subject: [PATCH 27/64] [ci skip] NEWS --- NEWS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 227ae6f0b2d6b..5d140d27e5a49 100644 --- a/NEWS +++ b/NEWS @@ -27,13 +27,14 @@ PHP NEWS . Fixed bug GH-13856 (Member access within null pointer of type 'ps_files' in ext/session/mod_files.c). (nielsdos) . Fixed bug GH-13891 (memleak and segfault when using ini_set with - session.trans_sid_hosts). (nielsdos, kamil-tekiela). + session.trans_sid_hosts). (nielsdos, kamil-tekiela) - Streams: . Fixed bug GH-13264 (Part 1 - Memory leak on stream filter failure). (Jakub Zelenka) . Fixed bug GH-13860 (Incorrect PHP_STREAM_OPTION_CHECK_LIVENESS case in ext/openssl/xp_ssl.c - causing use of dead socket). (nielsdos) + . Fixed bug GH-11678 (Build fails on musl 1.2.4 - lfs64). (Arnaud) - Treewide: . Fix gcc-14 Wcalloc-transposed-args warnings. (Cristian Rodríguez) From af098acd6e389a570c6ee3223a46235cf7b407d1 Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Thu, 21 Mar 2024 15:09:20 +0100 Subject: [PATCH 28/64] Always load EX(opline) into the current frame in JIT when observers are enabled Fixes #13772. Closes #13776. --- NEWS | 4 ++++ ext/opcache/jit/zend_jit_arm64.dasc | 7 ++++++- ext/opcache/jit/zend_jit_x86.dasc | 7 ++++++- ext/opcache/tests/jit/gh13772.phpt | 26 ++++++++++++++++++++++++++ ext/zend_test/observer.c | 10 ++++++++++ 5 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 ext/opcache/tests/jit/gh13772.phpt diff --git a/NEWS b/NEWS index 5d140d27e5a49..87b5472d850d9 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.2.19 +- Core: + . Fixed bug GH-13772 (Invalid execute_data->opline pointers in observer fcall + handlers when JIT is enabled). (Bob) + - FPM: . Fixed bug GH-13563 (Setting bool values via env in FPM config fails). (Jakub Zelenka) diff --git a/ext/opcache/jit/zend_jit_arm64.dasc b/ext/opcache/jit/zend_jit_arm64.dasc index 329eb42507e3e..37fca7cfeb60a 100644 --- a/ext/opcache/jit/zend_jit_arm64.dasc +++ b/ext/opcache/jit/zend_jit_arm64.dasc @@ -9449,7 +9449,12 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend } if (ZEND_OBSERVER_ENABLED) { - | SAVE_IP + if (trace && (trace->op != ZEND_JIT_TRACE_END || trace->stop != ZEND_JIT_TRACE_STOP_INTERPRETER)) { + ZEND_ASSERT(trace[1].op == ZEND_JIT_TRACE_VM || trace[1].op == ZEND_JIT_TRACE_END); + | SET_EX_OPLINE trace[1].opline, REG0 + } else { + | SAVE_IP + } | mov FCARG1x, FP | EXT_CALL zend_observer_fcall_begin, REG0 } diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index d1cbbd6391c53..7ae69c9fb657e 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -10187,7 +10187,12 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend } if (ZEND_OBSERVER_ENABLED) { - | SAVE_IP + if (trace && (trace->op != ZEND_JIT_TRACE_END || trace->stop != ZEND_JIT_TRACE_STOP_INTERPRETER)) { + ZEND_ASSERT(trace[1].op == ZEND_JIT_TRACE_VM || trace[1].op == ZEND_JIT_TRACE_END); + | SET_EX_OPLINE trace[1].opline, r0 + } else { + | SAVE_IP + } | mov FCARG1a, FP | EXT_CALL zend_observer_fcall_begin, r0 } diff --git a/ext/opcache/tests/jit/gh13772.phpt b/ext/opcache/tests/jit/gh13772.phpt new file mode 100644 index 0000000000000..97fa6536e0ce7 --- /dev/null +++ b/ext/opcache/tests/jit/gh13772.phpt @@ -0,0 +1,26 @@ +--TEST-- +EX(opline) is correctly set for nested JIT user code calls +--EXTENSIONS-- +opcache +zend_test +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +zend_test.observer.enabled=1 +zend_test.observer.observe_all=1 +zend_test.observer.show_output=0 +--FILE-- + +--EXPECT-- +int(61) + diff --git a/ext/zend_test/observer.c b/ext/zend_test/observer.c index de83d7beb18c5..af45f91a5da5b 100644 --- a/ext/zend_test/observer.c +++ b/ext/zend_test/observer.c @@ -67,8 +67,16 @@ static void observer_show_opcode(zend_execute_data *execute_data) php_printf("%*s\n", 2 * ZT_G(observer_nesting_depth), "", zend_get_opcode_name(EX(opline)->opcode)); } +static inline void assert_observer_opline(zend_execute_data *execute_data) { + ZEND_ASSERT(!ZEND_USER_CODE(EX(func)->type) || + (EX(opline) >= EX(func)->op_array.opcodes && EX(opline) < EX(func)->op_array.opcodes + EX(func)->op_array.last) || + (EX(opline) >= EG(exception_op) && EX(opline) < EG(exception_op) + 3)); +} + static void observer_begin(zend_execute_data *execute_data) { + assert_observer_opline(execute_data); + if (!ZT_G(observer_show_output)) { return; } @@ -112,6 +120,8 @@ static void get_retval_info(zval *retval, smart_str *buf) static void observer_end(zend_execute_data *execute_data, zval *retval) { + assert_observer_opline(execute_data); + if (!ZT_G(observer_show_output)) { return; } From 6f8bda0582087fa04666dd1e9f460fc72a3cc306 Mon Sep 17 00:00:00 2001 From: icy17 <1061499390@qq.com> Date: Mon, 8 Apr 2024 14:49:17 +0800 Subject: [PATCH 29/64] Fix potential NULL pointer dereference before calling EVP_SignInit Closes GH-13870. --- NEWS | 1 + ext/phar/util.c | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/NEWS b/NEWS index 87b5472d850d9..47b3f5efb3a58 100644 --- a/NEWS +++ b/NEWS @@ -22,6 +22,7 @@ PHP NEWS filename causes a NULL pointer dereference). (nielsdos) . Fixed bug GH-13833 (Applying zero offset to null pointer in zend_hash.c). (nielsdos) + . Fix potential NULL pointer dereference before calling EVP_SignInit. (icy17) - PHPDBG: . Fixed bug GH-13827 (Null pointer access of type 'zval' in phpdbg_frame). diff --git a/ext/phar/util.c b/ext/phar/util.c index 003d579bb9a5e..352819bc9348b 100644 --- a/ext/phar/util.c +++ b/ext/phar/util.c @@ -1884,6 +1884,13 @@ int phar_create_signature(phar_archive_data *phar, php_stream *fp, char **signat } md_ctx = EVP_MD_CTX_create(); + if (md_ctx == NULL) { + EVP_PKEY_free(key); + if (error) { + spprintf(error, 0, "unable to initialize openssl signature for phar \"%s\"", phar->fname); + } + return FAILURE; + } siglen = EVP_PKEY_size(key); sigbuf = emalloc(siglen + 1); From e48a5c14b914e69a1ea954071372cd23ebda0253 Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Mon, 8 Apr 2024 20:16:35 +0200 Subject: [PATCH 30/64] Add zend_test.observer.enabled=0 to opcache tests asserting specific TMP count Necessary to succeed when tests are run with zend_test.observer.enabled=1. --- ext/opcache/tests/match/001.phpt | 1 + ext/opcache/tests/match/002.phpt | 1 + ext/opcache/tests/match/003.phpt | 1 + ext/opcache/tests/match/004.phpt | 1 + ext/opcache/tests/opt/coalesce.phpt | 1 + ext/opcache/tests/opt/dce_001.phpt | 1 + ext/opcache/tests/opt/dce_002.phpt | 1 + ext/opcache/tests/opt/dce_003.phpt | 1 + ext/opcache/tests/opt/dce_004.phpt | 1 + ext/opcache/tests/opt/dce_005.phpt | 1 + ext/opcache/tests/opt/dce_006.phpt | 1 + ext/opcache/tests/opt/dce_007.phpt | 1 + ext/opcache/tests/opt/dce_008.phpt | 1 + ext/opcache/tests/opt/dce_009.phpt | 1 + ext/opcache/tests/opt/gh11245_1.phpt | 1 + ext/opcache/tests/opt/gh11245_2.phpt | 1 + ext/opcache/tests/opt/jmp_001.phpt | 1 + ext/opcache/tests/opt/nullsafe_001.phpt | 1 + ext/opcache/tests/opt/sccp_001.phpt | 1 + ext/opcache/tests/opt/sccp_002.phpt | 1 + ext/opcache/tests/opt/sccp_003.phpt | 1 + ext/opcache/tests/opt/sccp_004.phpt | 1 + ext/opcache/tests/opt/sccp_005.phpt | 1 + ext/opcache/tests/opt/sccp_006.phpt | 1 + ext/opcache/tests/opt/sccp_007.phpt | 1 + ext/opcache/tests/opt/sccp_008.phpt | 1 + ext/opcache/tests/opt/sccp_009.phpt | 1 + ext/opcache/tests/opt/sccp_010.phpt | 1 + ext/opcache/tests/opt/sccp_011.phpt | 1 + ext/opcache/tests/opt/sccp_012.phpt | 1 + ext/opcache/tests/opt/sccp_016.phpt | 1 + ext/opcache/tests/opt/sccp_017.phpt | 1 + ext/opcache/tests/opt/sccp_019.phpt | 1 + ext/opcache/tests/opt/sccp_022.phpt | 1 + ext/opcache/tests/opt/sccp_024.phpt | 1 + ext/opcache/tests/opt/sccp_026.phpt | 1 + ext/opcache/tests/opt/sccp_031.phpt | 1 + ext/opcache/tests/opt/sccp_032.phpt | 1 + 38 files changed, 38 insertions(+) diff --git a/ext/opcache/tests/match/001.phpt b/ext/opcache/tests/match/001.phpt index 37f564b5bbc80..502400681cf12 100644 --- a/ext/opcache/tests/match/001.phpt +++ b/ext/opcache/tests/match/001.phpt @@ -4,6 +4,7 @@ Match expression string jump table opcache.enable=1 opcache.enable_cli=1 opcache.opt_debug_level=0x20000 +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/match/002.phpt b/ext/opcache/tests/match/002.phpt index 3743d6bed7930..8e7102d539120 100644 --- a/ext/opcache/tests/match/002.phpt +++ b/ext/opcache/tests/match/002.phpt @@ -4,6 +4,7 @@ Test match jump table optimizer opcache.enable=1 opcache.enable_cli=1 opcache.opt_debug_level=0x20000 +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/match/003.phpt b/ext/opcache/tests/match/003.phpt index 9e55cbba942c5..24f3cd2612105 100644 --- a/ext/opcache/tests/match/003.phpt +++ b/ext/opcache/tests/match/003.phpt @@ -4,6 +4,7 @@ Match expression long jump table opcache.enable=1 opcache.enable_cli=1 opcache.opt_debug_level=0x20000 +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/match/004.phpt b/ext/opcache/tests/match/004.phpt index 551c9a5d0e1dc..d9d4149b94510 100644 --- a/ext/opcache/tests/match/004.phpt +++ b/ext/opcache/tests/match/004.phpt @@ -4,6 +4,7 @@ Match expression mixed jump table opcache.enable=1 opcache.enable_cli=1 opcache.opt_debug_level=0x20000 +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/coalesce.phpt b/ext/opcache/tests/opt/coalesce.phpt index 66a2e7f827419..f60294aadc236 100644 --- a/ext/opcache/tests/opt/coalesce.phpt +++ b/ext/opcache/tests/opt/coalesce.phpt @@ -5,6 +5,7 @@ opcache.enable=1 opcache.enable_cli=1 opcache.optimization_level=-1 opcache.opt_debug_level=0x20000 +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/dce_001.phpt b/ext/opcache/tests/opt/dce_001.phpt index 81e309fa4967d..5f9b001a5def8 100644 --- a/ext/opcache/tests/opt/dce_001.phpt +++ b/ext/opcache/tests/opt/dce_001.phpt @@ -6,6 +6,7 @@ opcache.enable_cli=1 opcache.optimization_level=-1 opcache.opt_debug_level=0x20000 opcache.preload= +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/dce_002.phpt b/ext/opcache/tests/opt/dce_002.phpt index 2f105fe352b76..44f1fb403c26b 100644 --- a/ext/opcache/tests/opt/dce_002.phpt +++ b/ext/opcache/tests/opt/dce_002.phpt @@ -6,6 +6,7 @@ opcache.enable_cli=1 opcache.optimization_level=-1 opcache.opt_debug_level=0x20000 opcache.preload= +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/dce_003.phpt b/ext/opcache/tests/opt/dce_003.phpt index 5824eae5523ad..22355baa68d86 100644 --- a/ext/opcache/tests/opt/dce_003.phpt +++ b/ext/opcache/tests/opt/dce_003.phpt @@ -6,6 +6,7 @@ opcache.enable_cli=1 opcache.optimization_level=-1 opcache.opt_debug_level=0x20000 opcache.preload= +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/dce_004.phpt b/ext/opcache/tests/opt/dce_004.phpt index b49caceb0d70e..2c7e785e4f536 100644 --- a/ext/opcache/tests/opt/dce_004.phpt +++ b/ext/opcache/tests/opt/dce_004.phpt @@ -6,6 +6,7 @@ opcache.enable_cli=1 opcache.optimization_level=-1 opcache.opt_debug_level=0x20000 opcache.preload= +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/dce_005.phpt b/ext/opcache/tests/opt/dce_005.phpt index add703e966a2b..c413913aedb8e 100644 --- a/ext/opcache/tests/opt/dce_005.phpt +++ b/ext/opcache/tests/opt/dce_005.phpt @@ -6,6 +6,7 @@ opcache.enable_cli=1 opcache.optimization_level=-1 opcache.opt_debug_level=0x20000 opcache.preload= +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/dce_006.phpt b/ext/opcache/tests/opt/dce_006.phpt index 97d2988793907..2596651ed3e91 100644 --- a/ext/opcache/tests/opt/dce_006.phpt +++ b/ext/opcache/tests/opt/dce_006.phpt @@ -6,6 +6,7 @@ opcache.enable_cli=1 opcache.optimization_level=-1 opcache.opt_debug_level=0x20000 opcache.preload= +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/dce_007.phpt b/ext/opcache/tests/opt/dce_007.phpt index 0f4da98d05959..9139e0478ece6 100644 --- a/ext/opcache/tests/opt/dce_007.phpt +++ b/ext/opcache/tests/opt/dce_007.phpt @@ -6,6 +6,7 @@ opcache.enable_cli=1 opcache.optimization_level=-1 opcache.opt_debug_level=0x20000 opcache.preload= +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/dce_008.phpt b/ext/opcache/tests/opt/dce_008.phpt index 0a55d83fb83b6..697e29f1ab309 100644 --- a/ext/opcache/tests/opt/dce_008.phpt +++ b/ext/opcache/tests/opt/dce_008.phpt @@ -6,6 +6,7 @@ opcache.enable_cli=1 opcache.optimization_level=-1 opcache.opt_debug_level=0x20000 opcache.preload= +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/dce_009.phpt b/ext/opcache/tests/opt/dce_009.phpt index ea3032460cf6c..4300fdd1c5c5f 100644 --- a/ext/opcache/tests/opt/dce_009.phpt +++ b/ext/opcache/tests/opt/dce_009.phpt @@ -6,6 +6,7 @@ opcache.enable_cli=1 opcache.optimization_level=-1 opcache.opt_debug_level=0x20000 opcache.preload= +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/gh11245_1.phpt b/ext/opcache/tests/opt/gh11245_1.phpt index eac085ac44025..06d6da1413771 100644 --- a/ext/opcache/tests/opt/gh11245_1.phpt +++ b/ext/opcache/tests/opt/gh11245_1.phpt @@ -6,6 +6,7 @@ opcache.enable_cli=1 opcache.optimization_level=0x7FFFBFFF opcache.opt_debug_level=0x20000 opcache.preload= +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/gh11245_2.phpt b/ext/opcache/tests/opt/gh11245_2.phpt index 8e967bf9f41be..f42da12c52743 100644 --- a/ext/opcache/tests/opt/gh11245_2.phpt +++ b/ext/opcache/tests/opt/gh11245_2.phpt @@ -6,6 +6,7 @@ opcache.enable_cli=1 opcache.optimization_level=0x7FFFBFFF opcache.opt_debug_level=0x20000 opcache.preload= +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/jmp_001.phpt b/ext/opcache/tests/opt/jmp_001.phpt index 23cd2f796a45d..71ff73671e81b 100644 --- a/ext/opcache/tests/opt/jmp_001.phpt +++ b/ext/opcache/tests/opt/jmp_001.phpt @@ -5,6 +5,7 @@ opcache.enable=1 opcache.enable_cli=1 opcache.optimization_level=-1 opcache.opt_debug_level=0x20000 +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/nullsafe_001.phpt b/ext/opcache/tests/opt/nullsafe_001.phpt index f0c317564136e..171ac7190af9d 100644 --- a/ext/opcache/tests/opt/nullsafe_001.phpt +++ b/ext/opcache/tests/opt/nullsafe_001.phpt @@ -4,6 +4,7 @@ Nullsafe basic optimization opcache.enable=1 opcache.enable_cli=1 opcache.opt_debug_level=0x20000 +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/sccp_001.phpt b/ext/opcache/tests/opt/sccp_001.phpt index 20869eb624513..727a239e8f2b4 100644 --- a/ext/opcache/tests/opt/sccp_001.phpt +++ b/ext/opcache/tests/opt/sccp_001.phpt @@ -6,6 +6,7 @@ opcache.enable_cli=1 opcache.optimization_level=-1 opcache.opt_debug_level=0x20000 opcache.preload= +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/sccp_002.phpt b/ext/opcache/tests/opt/sccp_002.phpt index 7dda1932e0f61..b290d752e7e2c 100644 --- a/ext/opcache/tests/opt/sccp_002.phpt +++ b/ext/opcache/tests/opt/sccp_002.phpt @@ -6,6 +6,7 @@ opcache.enable_cli=1 opcache.optimization_level=-1 opcache.opt_debug_level=0x20000 opcache.preload= +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/sccp_003.phpt b/ext/opcache/tests/opt/sccp_003.phpt index 3002efcc4a1d2..4db7fe4d13c56 100644 --- a/ext/opcache/tests/opt/sccp_003.phpt +++ b/ext/opcache/tests/opt/sccp_003.phpt @@ -6,6 +6,7 @@ opcache.enable_cli=1 opcache.optimization_level=-1 opcache.opt_debug_level=0x20000 opcache.preload= +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/sccp_004.phpt b/ext/opcache/tests/opt/sccp_004.phpt index 891fa0ed47368..4a0a7598e49c2 100644 --- a/ext/opcache/tests/opt/sccp_004.phpt +++ b/ext/opcache/tests/opt/sccp_004.phpt @@ -6,6 +6,7 @@ opcache.enable_cli=1 opcache.optimization_level=-1 opcache.opt_debug_level=0x20000 opcache.preload= +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/sccp_005.phpt b/ext/opcache/tests/opt/sccp_005.phpt index 1f56feee32018..a673d3092de80 100644 --- a/ext/opcache/tests/opt/sccp_005.phpt +++ b/ext/opcache/tests/opt/sccp_005.phpt @@ -6,6 +6,7 @@ opcache.enable_cli=1 opcache.optimization_level=-1 opcache.opt_debug_level=0x20000 opcache.preload= +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/sccp_006.phpt b/ext/opcache/tests/opt/sccp_006.phpt index c8b6253e5c725..49754566e0785 100644 --- a/ext/opcache/tests/opt/sccp_006.phpt +++ b/ext/opcache/tests/opt/sccp_006.phpt @@ -6,6 +6,7 @@ opcache.enable_cli=1 opcache.optimization_level=-1 opcache.opt_debug_level=0x20000 opcache.preload= +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/sccp_007.phpt b/ext/opcache/tests/opt/sccp_007.phpt index 112b7791910e2..807ce7ed764ac 100644 --- a/ext/opcache/tests/opt/sccp_007.phpt +++ b/ext/opcache/tests/opt/sccp_007.phpt @@ -6,6 +6,7 @@ opcache.enable_cli=1 opcache.optimization_level=-1 opcache.opt_debug_level=0x20000 opcache.preload= +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/sccp_008.phpt b/ext/opcache/tests/opt/sccp_008.phpt index f194249d3513b..f1df4b59980d5 100644 --- a/ext/opcache/tests/opt/sccp_008.phpt +++ b/ext/opcache/tests/opt/sccp_008.phpt @@ -6,6 +6,7 @@ opcache.enable_cli=1 opcache.optimization_level=-1 opcache.opt_debug_level=0x20000 opcache.preload= +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/sccp_009.phpt b/ext/opcache/tests/opt/sccp_009.phpt index ca5ba96bc0c68..34995a0546e60 100644 --- a/ext/opcache/tests/opt/sccp_009.phpt +++ b/ext/opcache/tests/opt/sccp_009.phpt @@ -6,6 +6,7 @@ opcache.enable_cli=1 opcache.optimization_level=-1 opcache.opt_debug_level=0x20000 opcache.preload= +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/sccp_010.phpt b/ext/opcache/tests/opt/sccp_010.phpt index e9dba9978cfa1..e4bf72116604d 100644 --- a/ext/opcache/tests/opt/sccp_010.phpt +++ b/ext/opcache/tests/opt/sccp_010.phpt @@ -6,6 +6,7 @@ opcache.enable_cli=1 opcache.optimization_level=-1 opcache.opt_debug_level=0x20000 opcache.preload= +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/sccp_011.phpt b/ext/opcache/tests/opt/sccp_011.phpt index cba27a0f245ae..78455aa0d80bd 100644 --- a/ext/opcache/tests/opt/sccp_011.phpt +++ b/ext/opcache/tests/opt/sccp_011.phpt @@ -6,6 +6,7 @@ opcache.enable_cli=1 opcache.optimization_level=-1 opcache.opt_debug_level=0x20000 opcache.preload= +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/sccp_012.phpt b/ext/opcache/tests/opt/sccp_012.phpt index 203de5fa56aa1..dbd5ee4fd003b 100644 --- a/ext/opcache/tests/opt/sccp_012.phpt +++ b/ext/opcache/tests/opt/sccp_012.phpt @@ -6,6 +6,7 @@ opcache.enable_cli=1 opcache.optimization_level=-1 opcache.opt_debug_level=0x20000 opcache.preload= +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/sccp_016.phpt b/ext/opcache/tests/opt/sccp_016.phpt index 46154ad9f046c..3e540ea6ce678 100644 --- a/ext/opcache/tests/opt/sccp_016.phpt +++ b/ext/opcache/tests/opt/sccp_016.phpt @@ -6,6 +6,7 @@ opcache.enable_cli=1 opcache.optimization_level=-1 opcache.opt_debug_level=0x20000 opcache.preload= +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/sccp_017.phpt b/ext/opcache/tests/opt/sccp_017.phpt index 43cdc2ed2b648..5afc24bf60ce5 100644 --- a/ext/opcache/tests/opt/sccp_017.phpt +++ b/ext/opcache/tests/opt/sccp_017.phpt @@ -6,6 +6,7 @@ opcache.enable_cli=1 opcache.optimization_level=-1 opcache.opt_debug_level=0x20000 opcache.preload= +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/sccp_019.phpt b/ext/opcache/tests/opt/sccp_019.phpt index e3453cd257ffc..00c8a34c2c060 100644 --- a/ext/opcache/tests/opt/sccp_019.phpt +++ b/ext/opcache/tests/opt/sccp_019.phpt @@ -6,6 +6,7 @@ opcache.enable_cli=1 opcache.optimization_level=-1 opcache.opt_debug_level=0x20000 opcache.preload= +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/sccp_022.phpt b/ext/opcache/tests/opt/sccp_022.phpt index 595e431752748..ffcc48b0dccd9 100644 --- a/ext/opcache/tests/opt/sccp_022.phpt +++ b/ext/opcache/tests/opt/sccp_022.phpt @@ -6,6 +6,7 @@ opcache.enable_cli=1 opcache.optimization_level=-1 opcache.opt_debug_level=0x20000 opcache.preload= +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/sccp_024.phpt b/ext/opcache/tests/opt/sccp_024.phpt index 5fd33e2b7e1a4..56be429cc7994 100644 --- a/ext/opcache/tests/opt/sccp_024.phpt +++ b/ext/opcache/tests/opt/sccp_024.phpt @@ -6,6 +6,7 @@ opcache.enable_cli=1 opcache.optimization_level=-1 opcache.opt_debug_level=0x20000 opcache.preload= +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/sccp_026.phpt b/ext/opcache/tests/opt/sccp_026.phpt index 6d2108409b07f..3e318a7f75dfe 100644 --- a/ext/opcache/tests/opt/sccp_026.phpt +++ b/ext/opcache/tests/opt/sccp_026.phpt @@ -6,6 +6,7 @@ opcache.enable_cli=1 opcache.optimization_level=-1 opcache.opt_debug_level=0x20000 opcache.preload= +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/sccp_031.phpt b/ext/opcache/tests/opt/sccp_031.phpt index 73b5906df64dc..459fb31233d47 100644 --- a/ext/opcache/tests/opt/sccp_031.phpt +++ b/ext/opcache/tests/opt/sccp_031.phpt @@ -6,6 +6,7 @@ opcache.enable_cli=1 opcache.optimization_level=-1 opcache.opt_debug_level=0x20000 opcache.preload= +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- diff --git a/ext/opcache/tests/opt/sccp_032.phpt b/ext/opcache/tests/opt/sccp_032.phpt index 9a03fe4e1d576..dac09a7552745 100644 --- a/ext/opcache/tests/opt/sccp_032.phpt +++ b/ext/opcache/tests/opt/sccp_032.phpt @@ -6,6 +6,7 @@ opcache.enable_cli=1 opcache.optimization_level=-1 opcache.opt_debug_level=0x20000 opcache.preload= +zend_test.observer.enabled=0 --EXTENSIONS-- opcache --FILE-- From ea0268264bd315d6081cbfe065ea4134cc445a93 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 8 Apr 2024 20:09:24 +0200 Subject: [PATCH 31/64] Fix GH-13903: ASAN false positive underflow when executing copy() Closes GH-13917. --- NEWS | 4 ++++ Zend/zend_fibers.c | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/NEWS b/NEWS index 47b3f5efb3a58..14dae5531dcde 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,10 @@ PHP NEWS . Fixed bug GH-13772 (Invalid execute_data->opline pointers in observer fcall handlers when JIT is enabled). (Bob) +- Fibers: + . Fixed bug GH-13903 (ASAN false positive underflow when executing copy()). + (nielsdos) + - FPM: . Fixed bug GH-13563 (Setting bool values via env in FPM config fails). (Jakub Zelenka) diff --git a/Zend/zend_fibers.c b/Zend/zend_fibers.c index ea91219a43a07..81e6e8832a064 100644 --- a/Zend/zend_fibers.c +++ b/Zend/zend_fibers.c @@ -62,6 +62,7 @@ #endif #ifdef __SANITIZE_ADDRESS__ +# include # include #endif @@ -257,6 +258,12 @@ static void zend_fiber_stack_free(zend_fiber_stack *stack) void *pointer = (void *) ((uintptr_t) stack->pointer - ZEND_FIBER_GUARD_PAGES * page_size); +#ifdef __SANITIZE_ADDRESS__ + /* If another mmap happens after unmapping, it may trigger the stale stack red zones + * so we have to unpoison it before unmapping. */ + ASAN_UNPOISON_MEMORY_REGION(pointer, stack->size + ZEND_FIBER_GUARD_PAGES * page_size); +#endif + #ifdef ZEND_WIN32 VirtualFree(pointer, 0, MEM_RELEASE); #else From 20959c38ad2fd2017f2b1494a96b41c7660c679c Mon Sep 17 00:00:00 2001 From: Saki Takamachi Date: Wed, 10 Apr 2024 10:00:14 +0900 Subject: [PATCH 32/64] NEWS: remove ZWSP --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 14dae5531dcde..d4a19d407665d 100644 --- a/NEWS +++ b/NEWS @@ -186,7 +186,7 @@ PHP NEWS (David Carlier). - PDO_Firebird: - . Fix GH-13119 (Changed to convert float and double values ​​into strings using + . Fix GH-13119 (Changed to convert float and double values into strings using `H` format). (SakiTakamachi) - Phar: From e3c784f2bfb6029b49d27783b2efc87ee6923f79 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Thu, 15 Feb 2024 23:53:49 +0000 Subject: [PATCH 33/64] Add proc_open escaping for cmd file execution --- ext/standard/proc_open.c | 86 +++++++++++++++++-- .../ghsa-pc52-254m-w9w7_1.phpt | 29 +++++++ .../ghsa-pc52-254m-w9w7_2.phpt | 29 +++++++ .../ghsa-pc52-254m-w9w7_3.phpt | 29 +++++++ 4 files changed, 168 insertions(+), 5 deletions(-) create mode 100644 ext/standard/tests/general_functions/ghsa-pc52-254m-w9w7_1.phpt create mode 100644 ext/standard/tests/general_functions/ghsa-pc52-254m-w9w7_2.phpt create mode 100644 ext/standard/tests/general_functions/ghsa-pc52-254m-w9w7_3.phpt diff --git a/ext/standard/proc_open.c b/ext/standard/proc_open.c index 3f8eaafd6d281..8aae54072650e 100644 --- a/ext/standard/proc_open.c +++ b/ext/standard/proc_open.c @@ -492,11 +492,32 @@ static void append_backslashes(smart_str *str, size_t num_bs) } } -/* See https://docs.microsoft.com/en-us/cpp/cpp/parsing-cpp-command-line-arguments */ -static void append_win_escaped_arg(smart_str *str, zend_string *arg) +const char *special_chars = "()!^\"<>&|%"; + +static bool is_special_character_present(const zend_string *arg) +{ + for (size_t i = 0; i < ZSTR_LEN(arg); ++i) { + if (strchr(special_chars, ZSTR_VAL(arg)[i]) != NULL) { + return true; + } + } + return false; +} + +/* See https://docs.microsoft.com/en-us/cpp/cpp/parsing-cpp-command-line-arguments and + * https://learn.microsoft.com/en-us/archive/blogs/twistylittlepassagesallalike/everyone-quotes-command-line-arguments-the-wrong-way */ +static void append_win_escaped_arg(smart_str *str, zend_string *arg, bool is_cmd_argument) { size_t num_bs = 0; + bool has_special_character = false; + if (is_cmd_argument) { + has_special_character = is_special_character_present(arg); + if (has_special_character) { + /* Escape double quote with ^ if executed by cmd.exe. */ + smart_str_appendc(str, '^'); + } + } smart_str_appendc(str, '"'); for (size_t i = 0; i < ZSTR_LEN(arg); ++i) { char c = ZSTR_VAL(arg)[i]; @@ -510,18 +531,71 @@ static void append_win_escaped_arg(smart_str *str, zend_string *arg) num_bs = num_bs * 2 + 1; } append_backslashes(str, num_bs); + if (has_special_character && strchr(special_chars, c) != NULL) { + /* Escape special chars with ^ if executed by cmd.exe. */ + smart_str_appendc(str, '^'); + } smart_str_appendc(str, c); num_bs = 0; } append_backslashes(str, num_bs * 2); + if (has_special_character) { + /* Escape double quote with ^ if executed by cmd.exe. */ + smart_str_appendc(str, '^'); + } smart_str_appendc(str, '"'); } +static inline int stricmp_end(const char* suffix, const char* str) { + size_t suffix_len = strlen(suffix); + size_t str_len = strlen(str); + + if (suffix_len > str_len) { + return -1; /* Suffix is longer than string, cannot match. */ + } + + /* Compare the end of the string with the suffix, ignoring case. */ + return _stricmp(str + (str_len - suffix_len), suffix); +} + +static bool is_executed_by_cmd(const char *prog_name) +{ + /* If program name is cmd.exe, then return true. */ + if (_stricmp("cmd.exe", prog_name) == 0 || _stricmp("cmd", prog_name) == 0 + || stricmp_end("\\cmd.exe", prog_name) == 0 || stricmp_end("\\cmd", prog_name) == 0) { + return true; + } + + /* Find the last occurrence of the directory separator (backslash or forward slash). */ + char *last_separator = strrchr(prog_name, '\\'); + char *last_separator_fwd = strrchr(prog_name, '/'); + if (last_separator_fwd && (!last_separator || last_separator < last_separator_fwd)) { + last_separator = last_separator_fwd; + } + + /* Find the last dot in the filename after the last directory separator. */ + char *extension = NULL; + if (last_separator != NULL) { + extension = strrchr(last_separator, '.'); + } else { + extension = strrchr(prog_name, '.'); + } + + if (extension == NULL || extension == prog_name) { + /* No file extension found, it is not batch file. */ + return false; + } + + /* Check if the file extension is ".bat" or ".cmd" which is always executed by cmd.exe. */ + return _stricmp(extension, ".bat") == 0 || _stricmp(extension, ".cmd") == 0; +} + static zend_string *create_win_command_from_args(HashTable *args) { smart_str str = {0}; zval *arg_zv; - bool is_prog_name = 1; + bool is_prog_name = true; + bool is_cmd_execution = false; int elem_num = 0; ZEND_HASH_FOREACH_VAL(args, arg_zv) { @@ -531,11 +605,13 @@ static zend_string *create_win_command_from_args(HashTable *args) return NULL; } - if (!is_prog_name) { + if (is_prog_name) { + is_cmd_execution = is_executed_by_cmd(ZSTR_VAL(arg_str)); + } else { smart_str_appendc(&str, ' '); } - append_win_escaped_arg(&str, arg_str); + append_win_escaped_arg(&str, arg_str, !is_prog_name && is_cmd_execution); is_prog_name = 0; zend_string_release(arg_str); diff --git a/ext/standard/tests/general_functions/ghsa-pc52-254m-w9w7_1.phpt b/ext/standard/tests/general_functions/ghsa-pc52-254m-w9w7_1.phpt new file mode 100644 index 0000000000000..8d0939cdf1bc7 --- /dev/null +++ b/ext/standard/tests/general_functions/ghsa-pc52-254m-w9w7_1.phpt @@ -0,0 +1,29 @@ +--TEST-- +GHSA-54hq-v5wp-fqgv - proc_open does not correctly escape args for bat files +--SKIPIF-- + +--FILE-- + +--EXPECT-- +"¬epad.exe +--CLEAN-- + diff --git a/ext/standard/tests/general_functions/ghsa-pc52-254m-w9w7_2.phpt b/ext/standard/tests/general_functions/ghsa-pc52-254m-w9w7_2.phpt new file mode 100644 index 0000000000000..a1e39d7ef9ba0 --- /dev/null +++ b/ext/standard/tests/general_functions/ghsa-pc52-254m-w9w7_2.phpt @@ -0,0 +1,29 @@ +--TEST-- +GHSA-54hq-v5wp-fqgv - proc_open does not correctly escape args for cmd files +--SKIPIF-- + +--FILE-- +^()!.exe"], $descriptorspec, $pipes); +proc_close($proc); + +?> +--EXPECT-- +"¬epad<>^()!.exe +--CLEAN-- + diff --git a/ext/standard/tests/general_functions/ghsa-pc52-254m-w9w7_3.phpt b/ext/standard/tests/general_functions/ghsa-pc52-254m-w9w7_3.phpt new file mode 100644 index 0000000000000..69f12d7b358d2 --- /dev/null +++ b/ext/standard/tests/general_functions/ghsa-pc52-254m-w9w7_3.phpt @@ -0,0 +1,29 @@ +--TEST-- +GHSA-54hq-v5wp-fqgv - proc_open does not correctly escape args for cmd executing batch files +--SKIPIF-- + +--FILE-- + +--EXPECT-- +"¬epad.exe +--CLEAN-- + From 093c08af25fb323efa0c8e6154aa9fdeae3d3b53 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 17 Mar 2024 21:04:47 +0100 Subject: [PATCH 34/64] Fix GHSA-wpj3-hf5j-x4v4: __Host-/__Secure- cookie bypass due to partial CVE-2022-31629 fix The check happened too early as later code paths may perform more mangling rules. Move the check downwards right before adding the actual variable. --- ext/standard/tests/ghsa-wpj3-hf5j-x4v4.phpt | 63 +++++++++++++++++++++ main/php_variables.c | 41 +++++++++----- 2 files changed, 90 insertions(+), 14 deletions(-) create mode 100644 ext/standard/tests/ghsa-wpj3-hf5j-x4v4.phpt diff --git a/ext/standard/tests/ghsa-wpj3-hf5j-x4v4.phpt b/ext/standard/tests/ghsa-wpj3-hf5j-x4v4.phpt new file mode 100644 index 0000000000000..77fcb68089488 --- /dev/null +++ b/ext/standard/tests/ghsa-wpj3-hf5j-x4v4.phpt @@ -0,0 +1,63 @@ +--TEST-- +ghsa-wpj3-hf5j-x4v4 (__Host-/__Secure- cookie bypass due to partial CVE-2022-31629 fix) +--COOKIE-- +..Host-test=ignore_1; +._Host-test=ignore_2; +.[Host-test=ignore_3; +_.Host-test=ignore_4; +__Host-test=ignore_5; +_[Host-test=ignore_6; +[.Host-test=ignore_7; +[_Host-test=ignore_8; +[[Host-test=ignore_9; +..Host-test[]=ignore_10; +._Host-test[]=ignore_11; +.[Host-test[]=ignore_12; +_.Host-test[]=ignore_13; +__Host-test[]=legitimate_14; +_[Host-test[]=legitimate_15; +[.Host-test[]=ignore_16; +[_Host-test[]=ignore_17; +[[Host-test[]=ignore_18; +..Secure-test=ignore_1; +._Secure-test=ignore_2; +.[Secure-test=ignore_3; +_.Secure-test=ignore_4; +__Secure-test=ignore_5; +_[Secure-test=ignore_6; +[.Secure-test=ignore_7; +[_Secure-test=ignore_8; +[[Secure-test=ignore_9; +..Secure-test[]=ignore_10; +._Secure-test[]=ignore_11; +.[Secure-test[]=ignore_12; +_.Secure-test[]=ignore_13; +__Secure-test[]=legitimate_14; +_[Secure-test[]=legitimate_15; +[.Secure-test[]=ignore_16; +[_Secure-test[]=ignore_17; +[[Secure-test[]=ignore_18; +--FILE-- + +--EXPECT-- +array(3) { + ["__Host-test"]=> + array(1) { + [0]=> + string(13) "legitimate_14" + } + ["_"]=> + array(2) { + ["Host-test["]=> + string(13) "legitimate_15" + ["Secure-test["]=> + string(13) "legitimate_15" + } + ["__Secure-test"]=> + array(1) { + [0]=> + string(13) "legitimate_14" + } +} diff --git a/main/php_variables.c b/main/php_variables.c index 17e4a1e5d2cf1..da7266416a54d 100644 --- a/main/php_variables.c +++ b/main/php_variables.c @@ -54,6 +54,21 @@ static zend_always_inline void php_register_variable_quick(const char *name, siz zend_string_release_ex(key, 0); } +/* Discard variable if mangling made it start with __Host-, where pre-mangling it did not start with __Host- + * Discard variable if mangling made it start with __Secure-, where pre-mangling it did not start with __Secure- */ +static bool php_is_forbidden_variable_name(const char *mangled_name, size_t mangled_name_len, const char *pre_mangled_name) +{ + if (mangled_name_len >= sizeof("__Host-")-1 && strncmp(mangled_name, "__Host-", sizeof("__Host-")-1) == 0 && strncmp(pre_mangled_name, "__Host-", sizeof("__Host-")-1) != 0) { + return true; + } + + if (mangled_name_len >= sizeof("__Secure-")-1 && strncmp(mangled_name, "__Secure-", sizeof("__Secure-")-1) == 0 && strncmp(pre_mangled_name, "__Secure-", sizeof("__Secure-")-1) != 0) { + return true; + } + + return false; +} + PHPAPI void php_register_variable_ex(const char *var_name, zval *val, zval *track_vars_array) { char *p = NULL; @@ -104,20 +119,6 @@ PHPAPI void php_register_variable_ex(const char *var_name, zval *val, zval *trac } var_len = p - var; - /* Discard variable if mangling made it start with __Host-, where pre-mangling it did not start with __Host- */ - if (strncmp(var, "__Host-", sizeof("__Host-")-1) == 0 && strncmp(var_name, "__Host-", sizeof("__Host-")-1) != 0) { - zval_ptr_dtor_nogc(val); - free_alloca(var_orig, use_heap); - return; - } - - /* Discard variable if mangling made it start with __Secure-, where pre-mangling it did not start with __Secure- */ - if (strncmp(var, "__Secure-", sizeof("__Secure-")-1) == 0 && strncmp(var_name, "__Secure-", sizeof("__Secure-")-1) != 0) { - zval_ptr_dtor_nogc(val); - free_alloca(var_orig, use_heap); - return; - } - if (var_len==0) { /* empty variable name, or variable name with a space in it */ zval_ptr_dtor_nogc(val); free_alloca(var_orig, use_heap); @@ -221,6 +222,12 @@ PHPAPI void php_register_variable_ex(const char *var_name, zval *val, zval *trac return; } } else { + if (php_is_forbidden_variable_name(index, index_len, var_name)) { + zval_ptr_dtor_nogc(val); + free_alloca(var_orig, use_heap); + return; + } + gpc_element_p = zend_symtable_str_find(symtable1, index, index_len); if (!gpc_element_p) { zval tmp; @@ -258,6 +265,12 @@ PHPAPI void php_register_variable_ex(const char *var_name, zval *val, zval *trac zval_ptr_dtor_nogc(val); } } else { + if (php_is_forbidden_variable_name(index, index_len, var_name)) { + zval_ptr_dtor_nogc(val); + free_alloca(var_orig, use_heap); + return; + } + zend_ulong idx; /* From 0ba5229a3f7572846e91c8f5382e87785f543826 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Fri, 29 Mar 2024 15:27:59 +0000 Subject: [PATCH 35/64] Fix bug GHSA-q6x7-frmf-grcw: password_verify can erroneously return true Disallow null character in bcrypt password --- ext/standard/password.c | 5 +++++ ext/standard/tests/password/password_bcrypt_errors.phpt | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/ext/standard/password.c b/ext/standard/password.c index 651cffc9fe656..fbe58da603053 100644 --- a/ext/standard/password.c +++ b/ext/standard/password.c @@ -184,6 +184,11 @@ static zend_string* php_password_bcrypt_hash(const zend_string *password, zend_a zval *zcost; zend_long cost = PHP_PASSWORD_BCRYPT_COST; + if (memchr(ZSTR_VAL(password), '\0', ZSTR_LEN(password))) { + zend_value_error("Bcrypt password must not contain null character"); + return NULL; + } + if (options && (zcost = zend_hash_str_find(options, "cost", sizeof("cost")-1)) != NULL) { cost = zval_get_long(zcost); } diff --git a/ext/standard/tests/password/password_bcrypt_errors.phpt b/ext/standard/tests/password/password_bcrypt_errors.phpt index 10c3483f5a80d..5d823cba0217d 100644 --- a/ext/standard/tests/password/password_bcrypt_errors.phpt +++ b/ext/standard/tests/password/password_bcrypt_errors.phpt @@ -14,7 +14,14 @@ try { } catch (ValueError $exception) { echo $exception->getMessage() . "\n"; } + +try { + var_dump(password_hash("null\0password", PASSWORD_BCRYPT)); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} ?> --EXPECT-- Invalid bcrypt cost parameter specified: 3 Invalid bcrypt cost parameter specified: 32 +Bcrypt password must not contain null character From de4f7f932166e66ff0950d97ae3bda5e355003d7 Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Tue, 9 Apr 2024 23:41:29 -0500 Subject: [PATCH 36/64] Update NEWS --- NEWS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/NEWS b/NEWS index 8373c66329af5..0539611812d92 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,13 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.1.28 +- Standard: + . Fixed bug GHSA-pc52-254m-w9w7 (Command injection via array-ish $command + parameter of proc_open). (CVE-2024-1874) (Jakub Zelenka) + . Fixed bug GHSA-wpj3-hf5j-x4v4 (__Host-/__Secure- cookie bypass due to + partial CVE-2022-31629 fix). (CVE-2024-2756) (nielsdos) + . Fixed bug GHSA-h746-cjrr-wfmr (password_verify can erroneously return true, + opening ATO risk). (CVE-2024-3096) (Jakub Zelenka) 21 Dec 2023, PHP 8.1.27 From ca5fe4030cddfdb654b2752fa147997efa3ad714 Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Wed, 10 Apr 2024 00:48:59 -0500 Subject: [PATCH 37/64] PHP-8.1 is now for PHP 8.1.29-dev --- NEWS | 6 +++++- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 6 +++--- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index 0539611812d92..f9b8fb276472d 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.1.28 +?? ??? ????, PHP 8.1.29 + + + +11 Apr 2024, PHP 8.1.28 - Standard: . Fixed bug GHSA-pc52-254m-w9w7 (Command injection via array-ish $command diff --git a/Zend/zend.h b/Zend/zend.h index 2bba956fe4744..9a414960e2a87 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.1.28-dev" +#define ZEND_VERSION "4.1.29-dev" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index 90e1f8e8a6588..83d50445be205 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice. dnl ---------------------------------------------------------------------------- AC_PREREQ([2.68]) -AC_INIT([PHP],[8.1.28-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) +AC_INIT([PHP],[8.1.29-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) AC_CONFIG_SRCDIR([main/php_version.h]) AC_CONFIG_AUX_DIR([build]) AC_PRESERVE_HELP_ORDER diff --git a/main/php_version.h b/main/php_version.h index 59842b5307cb7..a7b35a63a9285 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -2,7 +2,7 @@ /* edit configure.ac to change version number */ #define PHP_MAJOR_VERSION 8 #define PHP_MINOR_VERSION 1 -#define PHP_RELEASE_VERSION 28 +#define PHP_RELEASE_VERSION 29 #define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.1.28-dev" -#define PHP_VERSION_ID 80128 +#define PHP_VERSION "8.1.29-dev" +#define PHP_VERSION_ID 80129 From 5035b8509016c4cf2cda883b4d3f245054a71626 Mon Sep 17 00:00:00 2001 From: Appla Date: Wed, 10 Apr 2024 16:17:03 +0800 Subject: [PATCH 38/64] ext/mysqlnd: support ER_CLIENT_INTERACTION_TIMEOUT Closes GH-13618. --- NEWS | 2 ++ ext/mysqli/tests/bug81335.phpt | 34 ++++++++++++++++++++++++++++++ ext/mysqlnd/mysqlnd_enum_n_def.h | 1 + ext/mysqlnd/mysqlnd_result.c | 2 +- ext/mysqlnd/mysqlnd_wireprotocol.c | 17 ++++++++++++++- 5 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 ext/mysqli/tests/bug81335.phpt diff --git a/NEWS b/NEWS index bfd2617878d5f..e96e9bbc4fe06 100644 --- a/NEWS +++ b/NEWS @@ -16,6 +16,8 @@ PHP NEWS - MySQLnd: . Fix shift out of bounds on 32-bit non-fast-path platforms. (nielsdos) + . Fixed bug #81335 (PHP Warning, Packets out of order after connection + timeout). (Appla) - OpenSSL: . Fixed bug GH-10495 (feof on OpenSSL stream hangs indefinitely). diff --git a/ext/mysqli/tests/bug81335.phpt b/ext/mysqli/tests/bug81335.phpt new file mode 100644 index 0000000000000..26f6bcd7e2d14 --- /dev/null +++ b/ext/mysqli/tests/bug81335.phpt @@ -0,0 +1,34 @@ +--TEST-- +Bug #81335: Packets out of order after connection timeout +--EXTENSIONS-- +mysqli +--SKIPIF-- += 8.0.24"); +} +?> +--FILE-- +query('SET WAIT_TIMEOUT=1'); +usleep(1000000 * 1.1); +try { + $mysqli->query('SELECT 1 + 1'); +} catch(mysqli_sql_exception $e) { + echo $e->getMessage(); + echo "\n"; + echo $e->getCode(); +} +?> +--EXPECTF-- +The client was disconnected by the server because of inactivity. See wait_timeout and interactive_timeout for configuring this behavior. +4031 diff --git a/ext/mysqlnd/mysqlnd_enum_n_def.h b/ext/mysqlnd/mysqlnd_enum_n_def.h index 110e62c71bab0..00b46e8c7d22d 100644 --- a/ext/mysqlnd/mysqlnd_enum_n_def.h +++ b/ext/mysqlnd/mysqlnd_enum_n_def.h @@ -130,6 +130,7 @@ #define CR_INVALID_PARAMETER_NO 2034 #define CR_INVALID_BUFFER_USE 2035 #define CR_LOAD_DATA_LOCAL_INFILE_REJECTED 2068 +#define CR_CLIENT_INTERACTION_TIMEOUT 4031 #define MYSQLND_EE_FILENOTFOUND 7890 diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index 0331518d7d3d6..cf5013ed42d51 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -185,7 +185,7 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s) UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status); if (FAIL == (ret = PACKET_READ(conn, &rset_header))) { - if (conn->error_info->error_no != CR_SERVER_GONE_ERROR) { + if (conn->error_info->error_no != CR_SERVER_GONE_ERROR && conn->error_info->error_no != CR_CLIENT_INTERACTION_TIMEOUT) { php_error_docref(NULL, E_WARNING, "Error reading result set's header"); } break; diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c index fed191c74fa52..16ca9aaf29d42 100644 --- a/ext/mysqlnd/mysqlnd_wireprotocol.c +++ b/ext/mysqlnd/mysqlnd_wireprotocol.c @@ -267,6 +267,19 @@ mysqlnd_read_header(MYSQLND_PFC * pfc, MYSQLND_VIO * vio, MYSQLND_PACKET_HEADER pfc->data->packet_no++; DBG_RETURN(PASS); } + // @see https://dev.mysql.com/worklog/task/?id=12999 + if (header->size > 0) { + zend_uchar *buf = mnd_emalloc(header->size); + if ((PASS == pfc->data->m.receive(pfc, vio, buf, header->size, conn_stats, error_info)) && buf[0] == ERROR_MARKER) { + php_mysqlnd_read_error_from_line(buf + 1, header->size - 1, + error_info->error, sizeof(error_info->error), + &error_info->error_no, error_info->sqlstate + ); + mnd_efree(buf); + DBG_RETURN(FAIL); + } + mnd_efree(buf); + } DBG_ERR_FMT("Logical link: packets out of order. Expected %u received %u. Packet size=%zu", pfc->data->packet_no, header->packet_no, header->size); @@ -294,7 +307,9 @@ mysqlnd_read_packet_header_and_body(MYSQLND_PACKET_HEADER * packet_header, DBG_INF_FMT("buf=%p size=%zu", buf, buf_size); if (FAIL == mysqlnd_read_header(pfc, vio, packet_header, stats, error_info)) { SET_CONNECTION_STATE(connection_state, CONN_QUIT_SENT); - SET_CLIENT_ERROR(error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone); + if (error_info->error_no == 0) { + SET_CLIENT_ERROR(error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone); + } DBG_ERR_FMT("Can't read %s's header", packet_type_as_text); DBG_RETURN(FAIL); } From ea927caffa52c249e4976110be1d147c2d035e2c Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Wed, 10 Apr 2024 20:37:54 +0200 Subject: [PATCH 39/64] Fix exception IP in JIT (#13929) --- ext/opcache/jit/zend_jit_arm64.dasc | 3 ++- ext/opcache/jit/zend_jit_x86.dasc | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ext/opcache/jit/zend_jit_arm64.dasc b/ext/opcache/jit/zend_jit_arm64.dasc index 37fca7cfeb60a..910105aa5bbff 100644 --- a/ext/opcache/jit/zend_jit_arm64.dasc +++ b/ext/opcache/jit/zend_jit_arm64.dasc @@ -688,7 +688,7 @@ static bool logical_immediate_p(uint64_t value, uint32_t reg_size) | .if ZTS || if (GCC_GLOBAL_REGS) { | LOAD_TSRM_CACHE IP -| MEM_ACCESS_64_WITH_UOFFSET ldr, IP, IP, (struct.._offset+offsetof(zend_..struct, field)), tmp_reg +| ADD_SUB_64_WITH_CONST_32 add, IP, IP, (struct.._offset+offsetof(zend_..struct, field)), tmp_reg || } else { | LOAD_TSRM_CACHE RX | ADD_SUB_64_WITH_CONST_32 add, RX, RX, (struct.._offset+offsetof(zend_..struct, field)), tmp_reg @@ -1935,6 +1935,7 @@ static int zend_jit_leave_throw_stub(dasm_State **Dst) |5: | // opline = EG(exception_op); | LOAD_IP_ADDR_ZTS executor_globals, exception_op, TMP2 + | str IP, EX->opline | // HANDLE_EXCEPTION() | b ->exception_handler } else { diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 7ae69c9fb657e..d083bf47c76d9 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -406,7 +406,7 @@ static size_t tsrm_tls_offset; | .if ZTS || if (GCC_GLOBAL_REGS) { | LOAD_TSRM_CACHE IP -| mov IP, aword [IP + (struct.._offset + offsetof(zend_..struct, field))] +| lea IP, aword [IP + (struct.._offset + offsetof(zend_..struct, field))] || } else { | LOAD_TSRM_CACHE RX | lea RX, aword [RX + (struct.._offset + offsetof(zend_..struct, field))] @@ -1884,6 +1884,7 @@ static int zend_jit_leave_throw_stub(dasm_State **Dst) |5: | // opline = EG(exception_op); | LOAD_IP_ADDR_ZTS executor_globals, exception_op + | mov aword EX->opline, IP | // HANDLE_EXCEPTION() | jmp ->exception_handler } else { From 66809c05b7e5184f87e88caf6fa04d87a7c79ede Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Thu, 11 Apr 2024 13:27:39 +0200 Subject: [PATCH 40/64] Fix usage of reentrant functions in ext/posix (#13921) - It's not necessarily an error of sysconf(_SC_GETPW_R_SIZE_MAX) returns -1, as specified by posix (and the musl implementation always returns -1). Pick an initial buffer size in this case. - Reentrant variants return an error number an may not set errno - Implement retry logic for ttyname_r() - Fix retry logic for getpwnam_r() (pw would be NULL after the first try) - Test retry logic by setting the initial buffer size to 1 in debug builds --- ext/posix/posix.c | 78 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 23 deletions(-) diff --git a/ext/posix/posix.c b/ext/posix/posix.c index 788fca0b2879d..e5ab4b5940a55 100644 --- a/ext/posix/posix.c +++ b/ext/posix/posix.c @@ -447,6 +447,7 @@ PHP_FUNCTION(posix_ttyname) int fd; #if defined(ZTS) && defined(HAVE_TTYNAME_R) && defined(_SC_TTY_NAME_MAX) zend_long buflen; + int err; #endif ZEND_PARSE_PARAMETERS_START(1, 1) @@ -465,12 +466,23 @@ PHP_FUNCTION(posix_ttyname) #if defined(ZTS) && defined(HAVE_TTYNAME_R) && defined(_SC_TTY_NAME_MAX) buflen = sysconf(_SC_TTY_NAME_MAX); if (buflen < 1) { - RETURN_FALSE; + buflen = 32; } +#if ZEND_DEBUG + /* Test retry logic */ + buflen = 1; +#endif p = emalloc(buflen); - if (ttyname_r(fd, p, buflen)) { - POSIX_G(last_error) = errno; +try_again: + err = ttyname_r(fd, p, buflen); + if (err) { + if (err == ERANGE) { + buflen *= 2; + p = erealloc(p, buflen); + goto try_again; + } + POSIX_G(last_error) = err; efree(p); RETURN_FALSE; } @@ -719,6 +731,7 @@ PHP_FUNCTION(posix_getgrnam) struct group gbuf; long buflen; char *buf; + int err; #endif ZEND_PARSE_PARAMETERS_START(1, 1) @@ -728,19 +741,24 @@ PHP_FUNCTION(posix_getgrnam) #if defined(ZTS) && defined(HAVE_GETGRNAM_R) && defined(_SC_GETGR_R_SIZE_MAX) buflen = sysconf(_SC_GETGR_R_SIZE_MAX); if (buflen < 1) { - RETURN_FALSE; + buflen = 1024; } +#if ZEND_DEBUG + /* Test retry logic */ + buflen = 1; +#endif buf = emalloc(buflen); try_again: g = &gbuf; - if (getgrnam_r(name, g, buf, buflen, &g) || g == NULL) { - if (errno == ERANGE) { + err = getgrnam_r(name, g, buf, buflen, &g); + if (err || g == NULL) { + if (err == ERANGE) { buflen *= 2; buf = erealloc(buf, buflen); goto try_again; } - POSIX_G(last_error) = errno; + POSIX_G(last_error) = err; efree(buf); RETURN_FALSE; } @@ -768,7 +786,7 @@ PHP_FUNCTION(posix_getgrgid) { zend_long gid; #if defined(ZTS) && defined(HAVE_GETGRGID_R) && defined(_SC_GETGR_R_SIZE_MAX) - int ret; + int err; struct group _g; struct group *retgrptr = NULL; long grbuflen; @@ -784,20 +802,24 @@ PHP_FUNCTION(posix_getgrgid) grbuflen = sysconf(_SC_GETGR_R_SIZE_MAX); if (grbuflen < 1) { - RETURN_FALSE; + grbuflen = 1024; } +#if ZEND_DEBUG + /* Test retry logic */ + grbuflen = 1; +#endif grbuf = emalloc(grbuflen); try_again: - ret = getgrgid_r(gid, &_g, grbuf, grbuflen, &retgrptr); - if (ret || retgrptr == NULL) { - if (errno == ERANGE) { + err = getgrgid_r(gid, &_g, grbuf, grbuflen, &retgrptr); + if (err || retgrptr == NULL) { + if (err == ERANGE) { grbuflen *= 2; grbuf = erealloc(grbuf, grbuflen); goto try_again; } - POSIX_G(last_error) = ret; + POSIX_G(last_error) = err; efree(grbuf); RETURN_FALSE; } @@ -849,6 +871,7 @@ PHP_FUNCTION(posix_getpwnam) struct passwd pwbuf; long buflen; char *buf; + int err; #endif ZEND_PARSE_PARAMETERS_START(1, 1) @@ -858,20 +881,25 @@ PHP_FUNCTION(posix_getpwnam) #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWNAM_R) buflen = sysconf(_SC_GETPW_R_SIZE_MAX); if (buflen < 1) { - RETURN_FALSE; + buflen = 1024; } +#if ZEND_DEBUG + /* Test retry logic */ + buflen = 1; +#endif buf = emalloc(buflen); - pw = &pwbuf; try_again: - if (getpwnam_r(name, pw, buf, buflen, &pw) || pw == NULL) { - if (errno == ERANGE) { + pw = &pwbuf; + err = getpwnam_r(name, pw, buf, buflen, &pw); + if (err || pw == NULL) { + if (err == ERANGE) { buflen *= 2; buf = erealloc(buf, buflen); goto try_again; } efree(buf); - POSIX_G(last_error) = errno; + POSIX_G(last_error) = err; RETURN_FALSE; } #else @@ -902,7 +930,7 @@ PHP_FUNCTION(posix_getpwuid) struct passwd *retpwptr = NULL; long pwbuflen; char *pwbuf; - int ret; + int err; #endif struct passwd *pw; @@ -913,19 +941,23 @@ PHP_FUNCTION(posix_getpwuid) #if defined(ZTS) && defined(_SC_GETPW_R_SIZE_MAX) && defined(HAVE_GETPWUID_R) pwbuflen = sysconf(_SC_GETPW_R_SIZE_MAX); if (pwbuflen < 1) { - RETURN_FALSE; + pwbuflen = 1024; } +#if ZEND_DEBUG + /* Test retry logic */ + pwbuflen = 1; +#endif pwbuf = emalloc(pwbuflen); try_again: - ret = getpwuid_r(uid, &_pw, pwbuf, pwbuflen, &retpwptr); - if (ret || retpwptr == NULL) { + err = getpwuid_r(uid, &_pw, pwbuf, pwbuflen, &retpwptr); + if (err || retpwptr == NULL) { if (errno == ERANGE) { pwbuflen *= 2; pwbuf = erealloc(pwbuf, pwbuflen); goto try_again; } - POSIX_G(last_error) = ret; + POSIX_G(last_error) = err; efree(pwbuf); RETURN_FALSE; } From ed84bcd8b1b0e0e386c6b41d27967957646a128f Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Thu, 11 Apr 2024 13:29:29 +0200 Subject: [PATCH 41/64] [ci skip] NEWS --- NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS b/NEWS index e96e9bbc4fe06..ef8802a56efc0 100644 --- a/NEWS +++ b/NEWS @@ -34,6 +34,9 @@ PHP NEWS . Fixed bug GH-13827 (Null pointer access of type 'zval' in phpdbg_frame). (nielsdos) +- Posix: + . Fix usage of reentrant functions in ext/posix. (Arnaud) + - Session: . Fixed bug GH-13856 (Member access within null pointer of type 'ps_files' in ext/session/mod_files.c). (nielsdos) From 3b93f1319907a361fca5b039ad0832c67ba85425 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Fri, 12 Apr 2024 10:54:49 +0100 Subject: [PATCH 42/64] Revert "ext/mysqlnd: support ER_CLIENT_INTERACTION_TIMEOUT" This reverts commit 5035b8509016c4cf2cda883b4d3f245054a71626. This broke Doctrine DBAL tests - more discussion in GH-13618. --- NEWS | 2 -- ext/mysqli/tests/bug81335.phpt | 34 ------------------------------ ext/mysqlnd/mysqlnd_enum_n_def.h | 1 - ext/mysqlnd/mysqlnd_result.c | 2 +- ext/mysqlnd/mysqlnd_wireprotocol.c | 17 +-------------- 5 files changed, 2 insertions(+), 54 deletions(-) delete mode 100644 ext/mysqli/tests/bug81335.phpt diff --git a/NEWS b/NEWS index ef8802a56efc0..0b50a7af1ea27 100644 --- a/NEWS +++ b/NEWS @@ -16,8 +16,6 @@ PHP NEWS - MySQLnd: . Fix shift out of bounds on 32-bit non-fast-path platforms. (nielsdos) - . Fixed bug #81335 (PHP Warning, Packets out of order after connection - timeout). (Appla) - OpenSSL: . Fixed bug GH-10495 (feof on OpenSSL stream hangs indefinitely). diff --git a/ext/mysqli/tests/bug81335.phpt b/ext/mysqli/tests/bug81335.phpt deleted file mode 100644 index 26f6bcd7e2d14..0000000000000 --- a/ext/mysqli/tests/bug81335.phpt +++ /dev/null @@ -1,34 +0,0 @@ ---TEST-- -Bug #81335: Packets out of order after connection timeout ---EXTENSIONS-- -mysqli ---SKIPIF-- -= 8.0.24"); -} -?> ---FILE-- -query('SET WAIT_TIMEOUT=1'); -usleep(1000000 * 1.1); -try { - $mysqli->query('SELECT 1 + 1'); -} catch(mysqli_sql_exception $e) { - echo $e->getMessage(); - echo "\n"; - echo $e->getCode(); -} -?> ---EXPECTF-- -The client was disconnected by the server because of inactivity. See wait_timeout and interactive_timeout for configuring this behavior. -4031 diff --git a/ext/mysqlnd/mysqlnd_enum_n_def.h b/ext/mysqlnd/mysqlnd_enum_n_def.h index 00b46e8c7d22d..110e62c71bab0 100644 --- a/ext/mysqlnd/mysqlnd_enum_n_def.h +++ b/ext/mysqlnd/mysqlnd_enum_n_def.h @@ -130,7 +130,6 @@ #define CR_INVALID_PARAMETER_NO 2034 #define CR_INVALID_BUFFER_USE 2035 #define CR_LOAD_DATA_LOCAL_INFILE_REJECTED 2068 -#define CR_CLIENT_INTERACTION_TIMEOUT 4031 #define MYSQLND_EE_FILENOTFOUND 7890 diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index cf5013ed42d51..0331518d7d3d6 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -185,7 +185,7 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s) UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status); if (FAIL == (ret = PACKET_READ(conn, &rset_header))) { - if (conn->error_info->error_no != CR_SERVER_GONE_ERROR && conn->error_info->error_no != CR_CLIENT_INTERACTION_TIMEOUT) { + if (conn->error_info->error_no != CR_SERVER_GONE_ERROR) { php_error_docref(NULL, E_WARNING, "Error reading result set's header"); } break; diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c index 16ca9aaf29d42..fed191c74fa52 100644 --- a/ext/mysqlnd/mysqlnd_wireprotocol.c +++ b/ext/mysqlnd/mysqlnd_wireprotocol.c @@ -267,19 +267,6 @@ mysqlnd_read_header(MYSQLND_PFC * pfc, MYSQLND_VIO * vio, MYSQLND_PACKET_HEADER pfc->data->packet_no++; DBG_RETURN(PASS); } - // @see https://dev.mysql.com/worklog/task/?id=12999 - if (header->size > 0) { - zend_uchar *buf = mnd_emalloc(header->size); - if ((PASS == pfc->data->m.receive(pfc, vio, buf, header->size, conn_stats, error_info)) && buf[0] == ERROR_MARKER) { - php_mysqlnd_read_error_from_line(buf + 1, header->size - 1, - error_info->error, sizeof(error_info->error), - &error_info->error_no, error_info->sqlstate - ); - mnd_efree(buf); - DBG_RETURN(FAIL); - } - mnd_efree(buf); - } DBG_ERR_FMT("Logical link: packets out of order. Expected %u received %u. Packet size=%zu", pfc->data->packet_no, header->packet_no, header->size); @@ -307,9 +294,7 @@ mysqlnd_read_packet_header_and_body(MYSQLND_PACKET_HEADER * packet_header, DBG_INF_FMT("buf=%p size=%zu", buf, buf_size); if (FAIL == mysqlnd_read_header(pfc, vio, packet_header, stats, error_info)) { SET_CONNECTION_STATE(connection_state, CONN_QUIT_SENT); - if (error_info->error_no == 0) { - SET_CLIENT_ERROR(error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone); - } + SET_CLIENT_ERROR(error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone); DBG_ERR_FMT("Can't read %s's header", packet_type_as_text); DBG_RETURN(FAIL); } From 8421cfda61cffc45efad2d6156f5042930aaa93e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damian=20W=C3=B3jcik?= Date: Fri, 12 Apr 2024 15:17:45 +0200 Subject: [PATCH 43/64] Fix file_get_contents() on Windows fails with "errno=22 Invalid argument" Closes GH-13948 --- NEWS | 4 +++ ...e_get_contents_file_put_contents_5gb.phpt} | 29 ++++++++++++++----- main/streams/plain_wrapper.c | 4 +-- 3 files changed, 27 insertions(+), 10 deletions(-) rename ext/standard/tests/file/{file_put_contents_5gb.phpt => file_get_contents_file_put_contents_5gb.phpt} (60%) diff --git a/NEWS b/NEWS index 0b50a7af1ea27..b462b9b8344e0 100644 --- a/NEWS +++ b/NEWS @@ -41,6 +41,10 @@ PHP NEWS . Fixed bug GH-13891 (memleak and segfault when using ini_set with session.trans_sid_hosts). (nielsdos, kamil-tekiela) +- Standard: + . Fixed file_get_contents() on Windows fails with "errno=22 Invalid + argument". (Damian Wójcik) + - Streams: . Fixed bug GH-13264 (Part 1 - Memory leak on stream filter failure). (Jakub Zelenka) diff --git a/ext/standard/tests/file/file_put_contents_5gb.phpt b/ext/standard/tests/file/file_get_contents_file_put_contents_5gb.phpt similarity index 60% rename from ext/standard/tests/file/file_put_contents_5gb.phpt rename to ext/standard/tests/file/file_get_contents_file_put_contents_5gb.phpt index d552d86279d03..854996a6481e7 100644 --- a/ext/standard/tests/file/file_put_contents_5gb.phpt +++ b/ext/standard/tests/file/file_get_contents_file_put_contents_5gb.phpt @@ -1,5 +1,5 @@ --TEST-- -Test file_put_contents() function with 5GB string +Test file_put_contents() and file_get_contents() functions with 5GB string --SKIPIF-- --CLEAN-- --EXPECT-- File written successfully. +File read successfully. diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c index c77bd1e2415a8..c92b76d196da0 100644 --- a/main/streams/plain_wrapper.c +++ b/main/streams/plain_wrapper.c @@ -54,7 +54,7 @@ extern int php_get_gid_by_name(const char *name, gid_t *gid); #endif #if defined(PHP_WIN32) -# define PLAIN_WRAP_BUF_SIZE(st) (((st) > UINT_MAX) ? UINT_MAX : (unsigned int)(st)) +# define PLAIN_WRAP_BUF_SIZE(st) ((unsigned int)(st > INT_MAX ? INT_MAX : st)) #define fsync _commit #define fdatasync fsync #else @@ -354,7 +354,7 @@ static ssize_t php_stdiop_write(php_stream *stream, const char *buf, size_t coun if (data->fd >= 0) { #ifdef PHP_WIN32 - ssize_t bytes_written = _write(data->fd, buf, (unsigned int)(count > INT_MAX ? INT_MAX : count)); + ssize_t bytes_written = _write(data->fd, buf, PLAIN_WRAP_BUF_SIZE(count)); #else ssize_t bytes_written = write(data->fd, buf, count); #endif From c618d3e84b43f20c9a1ebe328763c65ee8ab431e Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Sun, 14 Apr 2024 14:32:10 +0100 Subject: [PATCH 44/64] Set streams NEWS category for file_get_contents fix --- NEWS | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/NEWS b/NEWS index b462b9b8344e0..cd339a91b16e4 100644 --- a/NEWS +++ b/NEWS @@ -41,11 +41,9 @@ PHP NEWS . Fixed bug GH-13891 (memleak and segfault when using ini_set with session.trans_sid_hosts). (nielsdos, kamil-tekiela) -- Standard: +- Streams: . Fixed file_get_contents() on Windows fails with "errno=22 Invalid argument". (Damian Wójcik) - -- Streams: . Fixed bug GH-13264 (Part 1 - Memory leak on stream filter failure). (Jakub Zelenka) . Fixed bug GH-13860 (Incorrect PHP_STREAM_OPTION_CHECK_LIVENESS case in From f2cd0d5752c94423a1c212ecd767ee01b391183e Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Mon, 15 Apr 2024 13:42:40 +0200 Subject: [PATCH 45/64] Fix rename test file name collision --- .../tests/file/rename_variation2-win32.phpt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/ext/standard/tests/file/rename_variation2-win32.phpt b/ext/standard/tests/file/rename_variation2-win32.phpt index b486fcc543d63..e1ce5c22afbd8 100644 --- a/ext/standard/tests/file/rename_variation2-win32.phpt +++ b/ext/standard/tests/file/rename_variation2-win32.phpt @@ -11,28 +11,28 @@ if (substr(PHP_OS, 0, 3) != 'WIN') { require __DIR__.'/file.inc'; $file_path = __DIR__; -mkdir("$file_path/rename_variation2_dir"); +mkdir("$file_path/rename_variation2-win32_dir"); /* Renaming a file and directory to numeric name */ echo "\n*** Testing rename() by renaming a file and directory to numeric name ***\n"; -$fp = fopen($file_path."/rename_variation2.tmp", "w"); +$fp = fopen($file_path."/rename_variation2-win32.tmp", "w"); fclose($fp); // renaming existing file to numeric name -var_dump( rename($file_path."/rename_variation2.tmp", $file_path."/12345") ); +var_dump( rename($file_path."/rename_variation2-win32.tmp", $file_path."/12346") ); // ensure that rename worked fine -var_dump( file_exists($file_path."/rename_variation2.tmp" ) ); // expecting false -var_dump( file_exists($file_path."/12345" ) ); // expecting true +var_dump( file_exists($file_path."/rename_variation2-win32.tmp" ) ); // expecting false +var_dump( file_exists($file_path."/12346" ) ); // expecting true -unlink($file_path."/12345"); +unlink($file_path."/12346"); // renaming a directory to numeric name -var_dump( rename($file_path."/rename_variation2_dir/", $file_path."/12345") ); +var_dump( rename($file_path."/rename_variation2-win32_dir/", $file_path."/12346") ); // ensure that rename worked fine -var_dump( file_exists($file_path."/rename_variation2_dir" ) ); // expecting false -var_dump( file_exists($file_path."/12345" ) ); // expecting true +var_dump( file_exists($file_path."/rename_variation2-win32_dir" ) ); // expecting false +var_dump( file_exists($file_path."/12346" ) ); // expecting true echo "Done\n"; ?> From a7a7e6d57cca6a672759f940addde47d6626b01d Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Mon, 15 Apr 2024 14:14:47 +0200 Subject: [PATCH 46/64] Fix clean section in test --- ext/standard/tests/file/rename_variation2-win32.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/standard/tests/file/rename_variation2-win32.phpt b/ext/standard/tests/file/rename_variation2-win32.phpt index e1ce5c22afbd8..b23e1a1bbb048 100644 --- a/ext/standard/tests/file/rename_variation2-win32.phpt +++ b/ext/standard/tests/file/rename_variation2-win32.phpt @@ -39,7 +39,7 @@ echo "Done\n"; --CLEAN-- --EXPECT-- *** Testing rename() by renaming a file and directory to numeric name *** From 5f9b9c4e236a16c9994462a668ade14f64c61778 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 15 Apr 2024 18:27:12 +0300 Subject: [PATCH 47/64] Fixed missed exception --- Zend/Optimizer/zend_inference.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index 681173f094d40..600719cc6ce7a 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -5051,6 +5051,9 @@ ZEND_API bool zend_may_throw_ex(const zend_op *opline, const zend_ssa_op *ssa_op return 1; } } + if (t1 & (MAY_BE_ARRAY_OF_OBJECT|MAY_BE_ARRAY_OF_RESOURCE|MAY_BE_ARRAY_OF_ARRAY|MAY_BE_ARRAY_OF_REF)) { + return 1; + } return (t1 & (MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_TRUE|MAY_BE_FALSE|MAY_BE_STRING|MAY_BE_LONG|MAY_BE_DOUBLE)) || opline->op2_type == IS_UNUSED || (t2 & (MAY_BE_UNDEF|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)); case ZEND_ASSIGN_OBJ: From c3acfb1b57f4375ca1d8e78161c89785d5ad855c Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 10 Apr 2024 20:26:16 +0200 Subject: [PATCH 48/64] Fix GH-13931: Applying zero offset to null pointer in Zend/zend_opcode.c In the test cases, the compiler bails out due to a fatal error. The data structures used by the compiler will contain stale values. In particular, for the test case CG(loop_var_stack) will contain data. The next compilation will incorrectly use elements from the previous stack. To solve this, we reset part of the compiler data structures. We don't do a full re-initialization via init_compiler() because that will also reset streams and resources. Closes GH-13938. --- NEWS | 2 ++ Zend/tests/gh13931.phpt | 23 +++++++++++++++++++++++ main/main.c | 8 ++++++++ sapi/phpdbg/tests/gh13931.phpt | 21 +++++++++++++++++++++ 4 files changed, 54 insertions(+) create mode 100644 Zend/tests/gh13931.phpt create mode 100644 sapi/phpdbg/tests/gh13931.phpt diff --git a/NEWS b/NEWS index cd339a91b16e4..f9664526c9a24 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,8 @@ PHP NEWS - Core: . Fixed bug GH-13772 (Invalid execute_data->opline pointers in observer fcall handlers when JIT is enabled). (Bob) + . Fixed bug GH-13931 (Applying zero offset to null pointer in + Zend/zend_opcode.c). (nielsdos) - Fibers: . Fixed bug GH-13903 (ASAN false positive underflow when executing copy()). diff --git a/Zend/tests/gh13931.phpt b/Zend/tests/gh13931.phpt new file mode 100644 index 0000000000000..5f2873b449f94 --- /dev/null +++ b/Zend/tests/gh13931.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-13931 (Applying zero offset to null pointer in Zend/zend_opcode.c) +--FILE-- + +--EXPECTF-- +Fatal error: 'break' not in the 'loop' or 'switch' context in %s on line %d +int(4) diff --git a/main/main.c b/main/main.c index 83f8829890e40..634b00936bc3e 100644 --- a/main/main.c +++ b/main/main.c @@ -1405,6 +1405,14 @@ static ZEND_COLD void php_error_cb(int orig_type, zend_string *error_filename, c /* restore memory limit */ zend_set_memory_limit(PG(memory_limit)); zend_objects_store_mark_destructed(&EG(objects_store)); + if (CG(in_compilation) && (type == E_COMPILE_ERROR || type == E_PARSE)) { + /* We bailout during compilation which may for example leave stale entries in CG(loop_var_stack). + * If code is compiled during shutdown, we need to make sure the compiler is reset to a clean state, + * otherwise this will lead to incorrect compilation during shutdown. + * We don't do a full re-initialization via init_compiler() because that will also reset streams and resources. */ + shutdown_compiler(); + zend_init_compiler_data_structures(); + } zend_bailout(); return; } diff --git a/sapi/phpdbg/tests/gh13931.phpt b/sapi/phpdbg/tests/gh13931.phpt new file mode 100644 index 0000000000000..25520435feb9b --- /dev/null +++ b/sapi/phpdbg/tests/gh13931.phpt @@ -0,0 +1,21 @@ +--TEST-- +Applying zero offset to null pointer in Zend/zend_opcode.c +--FILE-- + +--PHPDBG-- +ev 1 + 3 +ev 2 ** 3 +q +--EXPECTF-- +Fatal error: 'break' not in the 'loop' or 'switch' context in %s on line %d +prompt> 4 +prompt> 8 +prompt> From 32efc76c327fc8e968a34b327f7ce5b2e205070e Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Tue, 16 Apr 2024 14:08:28 +0200 Subject: [PATCH 49/64] Use return value of getpwuid_r(), not errno (#13969) --- ext/posix/posix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/posix/posix.c b/ext/posix/posix.c index e5ab4b5940a55..dbc888a7ea697 100644 --- a/ext/posix/posix.c +++ b/ext/posix/posix.c @@ -952,7 +952,7 @@ PHP_FUNCTION(posix_getpwuid) try_again: err = getpwuid_r(uid, &_pw, pwbuf, pwbuflen, &retpwptr); if (err || retpwptr == NULL) { - if (errno == ERANGE) { + if (err == ERANGE) { pwbuflen *= 2; pwbuf = erealloc(pwbuf, pwbuflen); goto try_again; From f6e8145b475f0b39046dd081372e5335acf5e174 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Tue, 16 Apr 2024 14:13:36 +0200 Subject: [PATCH 50/64] fix: zend-max-execution-timers with negative or high timeout value (#13942) Align the behavior of zend-max-execution-timers with other timeout impls: Negative or very high timeout values are equivalent to no timeout --- Zend/zend_execute_API.c | 5 +++++ Zend/zend_max_execution_timer.c | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index fa5e13dba2ea8..0e2ff263c9a85 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -1518,6 +1518,11 @@ static void zend_set_timeout_ex(zend_long seconds, bool reset_signals) /* {{{ */ struct itimerval t_r; /* timeout requested */ int signo; + // Prevent EINVAL error + if (seconds < 0 || seconds > 999999999) { + seconds = 0; + } + if(seconds) { t_r.it_value.tv_sec = seconds; t_r.it_value.tv_usec = t_r.it_interval.tv_sec = t_r.it_interval.tv_usec = 0; diff --git a/Zend/zend_max_execution_timer.c b/Zend/zend_max_execution_timer.c index 48a4d1bd66415..f9f9740fd8a00 100644 --- a/Zend/zend_max_execution_timer.c +++ b/Zend/zend_max_execution_timer.c @@ -71,6 +71,11 @@ void zend_max_execution_timer_settime(zend_long seconds) /* {{{ }*/ timer_t timer = EG(max_execution_timer_timer); + // Prevent EINVAL error + if (seconds < 0 || seconds > 999999999) { + seconds = 0; + } + struct itimerspec its; its.it_value.tv_sec = seconds; its.it_value.tv_nsec = its.it_interval.tv_sec = its.it_interval.tv_nsec = 0; From d47aaacf3caf7f4adcf9f651a081187644b0ad2d Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Tue, 16 Apr 2024 14:18:48 +0200 Subject: [PATCH 51/64] [ci skip] NEWS --- NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS b/NEWS index f9664526c9a24..cfb310512a87c 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,8 @@ PHP NEWS handlers when JIT is enabled). (Bob) . Fixed bug GH-13931 (Applying zero offset to null pointer in Zend/zend_opcode.c). (nielsdos) + . Fixed bug GH-13942 (Align the behavior of zend-max-execution-timers with + other timeout implementations). (Kévin Dunglas) - Fibers: . Fixed bug GH-13903 (ASAN false positive underflow when executing copy()). From 093d33468428859078e470488f4d3cc0ab61dd66 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Tue, 16 Apr 2024 22:16:51 +0200 Subject: [PATCH 52/64] Fix GH-13978: Fuzzer readme still mentions obsolete --enable-json flag (#13983) [ci skip] --- sapi/fuzzer/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sapi/fuzzer/README.md b/sapi/fuzzer/README.md index ee2d0ee4e0262..b4bb2bbe4573f 100644 --- a/sapi/fuzzer/README.md +++ b/sapi/fuzzer/README.md @@ -26,7 +26,7 @@ When running `make` it creates these binaries in `sapi/fuzzer/`: * `php-fuzz-parser`: Fuzzing language parser and compiler * `php-fuzz-unserialize`: Fuzzing unserialize() function * `php-fuzz-unserializehash`: Fuzzing unserialize() for HashContext objects -* `php-fuzz-json`: Fuzzing JSON parser (requires --enable-json) +* `php-fuzz-json`: Fuzzing JSON parser * `php-fuzz-exif`: Fuzzing `exif_read_data()` function (requires --enable-exif) * `php-fuzz-mbstring`: Fuzzing `mb_convert_encoding()` (requires `--enable-mbstring`) * `php-fuzz-mbregex`: Fuzzing `mb_ereg[i]()` (requires --enable-mbstring) From 1acd7a09190daad70624684b9024287479cbc073 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Wed, 17 Apr 2024 14:09:08 +0200 Subject: [PATCH 53/64] Add missing COMPILE_IGNORE_OTHER_FILES check for static calls Closes GH-13986 --- NEWS | 4 ++++ Zend/zend_compile.c | 47 +++++++++++++++++++++++++++++++-------------- 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/NEWS b/NEWS index cfb310512a87c..703795dfa1c50 100644 --- a/NEWS +++ b/NEWS @@ -21,6 +21,10 @@ PHP NEWS - MySQLnd: . Fix shift out of bounds on 32-bit non-fast-path platforms. (nielsdos) +- Opcache: + . Fixed incorrect assumptions across compilation units for static calls. + (ilutov) + - OpenSSL: . Fixed bug GH-10495 (feof on OpenSSL stream hangs indefinitely). (Jakub Zelenka) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index cba90112cfc18..e7f9ed8f000a2 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -3996,6 +3996,27 @@ static bool fbc_is_finalized(zend_function *fbc) { return !ZEND_USER_CODE(fbc->type) || (fbc->common.fn_flags & ZEND_ACC_DONE_PASS_TWO); } +static bool zend_compile_ignore_class(zend_class_entry *ce, zend_string *filename) +{ + if (ce->type == ZEND_INTERNAL_CLASS) { + return CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES; + } else { + return (CG(compiler_options) & ZEND_COMPILE_IGNORE_OTHER_FILES) + && ce->info.user.filename != filename; + } +} + +static bool zend_compile_ignore_function(zend_function *fbc, zend_string *filename) +{ + if (fbc->type == ZEND_INTERNAL_FUNCTION) { + return CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS; + } else { + return (CG(compiler_options) & ZEND_COMPILE_IGNORE_USER_FUNCTIONS) + || ((CG(compiler_options) & ZEND_COMPILE_IGNORE_OTHER_FILES) + && fbc->op_array.filename != filename); + } +} + static zend_result zend_try_compile_ct_bound_init_user_func(zend_ast *name_ast, uint32_t num_args) /* {{{ */ { zend_string *name, *lcname; @@ -4010,11 +4031,9 @@ static zend_result zend_try_compile_ct_bound_init_user_func(zend_ast *name_ast, lcname = zend_string_tolower(name); fbc = zend_hash_find_ptr(CG(function_table), lcname); - if (!fbc || !fbc_is_finalized(fbc) - || (fbc->type == ZEND_INTERNAL_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS)) - || (fbc->type == ZEND_USER_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_USER_FUNCTIONS)) - || (fbc->type == ZEND_USER_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_OTHER_FILES) && fbc->op_array.filename != CG(active_op_array)->filename) - ) { + if (!fbc + || !fbc_is_finalized(fbc) + || zend_compile_ignore_function(fbc, CG(active_op_array)->filename)) { zend_string_release_ex(lcname, 0); return FAILURE; } @@ -4538,11 +4557,9 @@ static void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{ return; } - if (!fbc || !fbc_is_finalized(fbc) - || (fbc->type == ZEND_INTERNAL_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS)) - || (fbc->type == ZEND_USER_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_USER_FUNCTIONS)) - || (fbc->type == ZEND_USER_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_OTHER_FILES) && fbc->op_array.filename != CG(active_op_array)->filename) - ) { + if (!fbc + || !fbc_is_finalized(fbc) + || zend_compile_ignore_function(fbc, CG(active_op_array)->filename)) { zend_string_release_ex(lcname, 0); zend_compile_dynamic_call(result, &name_node, args_ast, ast->lineno); return; @@ -4709,7 +4726,11 @@ static void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type if (opline->op1_type == IS_CONST) { zend_string *lcname = Z_STR_P(CT_CONSTANT(opline->op1) + 1); ce = zend_hash_find_ptr(CG(class_table), lcname); - if (!ce && CG(active_class_entry) + if (ce) { + if (zend_compile_ignore_class(ce, CG(active_op_array)->filename)) { + ce = NULL; + } + } else if (CG(active_class_entry) && zend_string_equals_ci(CG(active_class_entry)->name, lcname)) { ce = CG(active_class_entry); } @@ -7990,9 +8011,7 @@ static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel) ce->parent_name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD); if (parent_ce - && ((parent_ce->type != ZEND_INTERNAL_CLASS) || !(CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES)) - && ((parent_ce->type != ZEND_USER_CLASS) || !(CG(compiler_options) & ZEND_COMPILE_IGNORE_OTHER_FILES) || (parent_ce->info.user.filename == ce->info.user.filename))) { - + && !zend_compile_ignore_class(parent_ce, ce->info.user.filename)) { if (zend_try_early_bind(ce, parent_ce, lcname, NULL)) { zend_string_release(lcname); return; From fda91a054301605ac89049c13e2b3aba07e60319 Mon Sep 17 00:00:00 2001 From: Saki Takamachi Date: Thu, 18 Apr 2024 08:35:50 +0900 Subject: [PATCH 54/64] Fix GH-13984: Buffer size is now checked before memcmp (#13991) Fixed an issue where a buffer overflow occurred when a string shorter than `:memory:` was passed as the db name of pdo_sqlite. fixed #13984 closes #13991 --- NEWS | 3 +++ ext/pdo_sqlite/sqlite_driver.c | 2 +- ext/pdo_sqlite/tests/gh13991.phpt | 18 ++++++++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 ext/pdo_sqlite/tests/gh13991.phpt diff --git a/NEWS b/NEWS index 703795dfa1c50..bcff2820ded76 100644 --- a/NEWS +++ b/NEWS @@ -29,6 +29,9 @@ PHP NEWS . Fixed bug GH-10495 (feof on OpenSSL stream hangs indefinitely). (Jakub Zelenka) +- PDO SQLite: + . Fix GH-13984 (Buffer size is now checked before memcmp). (Saki Takamachi) + - Phar: . Fixed bug GH-13836 (Renaming a file in a Phar to an already existing filename causes a NULL pointer dereference). (nielsdos) diff --git a/ext/pdo_sqlite/sqlite_driver.c b/ext/pdo_sqlite/sqlite_driver.c index de5170a35a96b..2f494c2ddb8b3 100644 --- a/ext/pdo_sqlite/sqlite_driver.c +++ b/ext/pdo_sqlite/sqlite_driver.c @@ -751,7 +751,7 @@ static char *make_filename_safe(const char *filename) } return estrdup(filename); } - if (*filename && memcmp(filename, ":memory:", sizeof(":memory:"))) { + if (*filename && strcmp(filename, ":memory:")) { char *fullpath = expand_filepath(filename, NULL); if (!fullpath) { diff --git a/ext/pdo_sqlite/tests/gh13991.phpt b/ext/pdo_sqlite/tests/gh13991.phpt new file mode 100644 index 0000000000000..fa847f8ba5b42 --- /dev/null +++ b/ext/pdo_sqlite/tests/gh13991.phpt @@ -0,0 +1,18 @@ +--TEST-- +Fix GH-13984: Buffer size is now checked before memcmp +--EXTENSIONS-- +pdo_sqlite +--SKIPIF-- + +--FILE-- + true]); +echo 'done!'; +?> +--CLEAN-- + +--EXPECT-- +done! From cc46a4e6b5a413bab3e264c1dcaaf7052f54fbc4 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 17 Feb 2024 21:38:21 +0000 Subject: [PATCH 55/64] ext/intl: level up c++ runtime std for icu 74 and onwards. to align with what is required to build icu 74 itself. Close GH-14002 --- NEWS | 3 +++ ext/intl/config.m4 | 11 ++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index bcff2820ded76..e5f8e3eba5ff3 100644 --- a/NEWS +++ b/NEWS @@ -18,6 +18,9 @@ PHP NEWS . Fixed bug GH-13563 (Setting bool values via env in FPM config fails). (Jakub Zelenka) +- Intl: + . Fixed build for icu 74 and onwards. (dunglas) + - MySQLnd: . Fix shift out of bounds on 32-bit non-fast-path platforms. (nielsdos) diff --git a/ext/intl/config.m4 b/ext/intl/config.m4 index dd687bcd97de3..48f5147ca7bbf 100644 --- a/ext/intl/config.m4 +++ b/ext/intl/config.m4 @@ -80,7 +80,16 @@ if test "$PHP_INTL" != "no"; then breakiterator/codepointiterator_methods.cpp" PHP_REQUIRE_CXX() - PHP_CXX_COMPILE_STDCXX(11, mandatory, PHP_INTL_STDCXX) + + AC_MSG_CHECKING([if intl requires -std=gnu++17]) + AS_IF([test "$PKG_CONFIG icu-uc --atleast-version=74"],[ + AC_MSG_RESULT([yes]) + PHP_CXX_COMPILE_STDCXX(17, mandatory, PHP_INTL_STDCXX) + ],[ + AC_MSG_RESULT([no]) + PHP_CXX_COMPILE_STDCXX(11, mandatory, PHP_INTL_STDCXX) + ]) + PHP_INTL_CXX_FLAGS="$INTL_COMMON_FLAGS $PHP_INTL_STDCXX $ICU_CXXFLAGS" case $host_alias in *cygwin*) PHP_INTL_CXX_FLAGS="$PHP_INTL_CXX_FLAGS -D_POSIX_C_SOURCE=200809L" From 04b864e56655d030894a38c9044172cf8ea361d4 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Fri, 19 Apr 2024 14:09:22 +0100 Subject: [PATCH 56/64] Fix GH-13806: openssl_x509_parse_basic test fails with OpenSSL 3.2+ (#13961) Closes GH-13961 --- .../tests/openssl_x509_parse_basic.phpt | 4 + .../openssl_x509_parse_basic_openssl32.phpt | 331 ++++++++++++++++++ 2 files changed, 335 insertions(+) create mode 100644 ext/openssl/tests/openssl_x509_parse_basic_openssl32.phpt diff --git a/ext/openssl/tests/openssl_x509_parse_basic.phpt b/ext/openssl/tests/openssl_x509_parse_basic.phpt index f9181dd65d5a3..ef63f0f85f497 100644 --- a/ext/openssl/tests/openssl_x509_parse_basic.phpt +++ b/ext/openssl/tests/openssl_x509_parse_basic.phpt @@ -2,6 +2,10 @@ openssl_x509_parse() tests --EXTENSIONS-- openssl +--SKIPIF-- += 0x30200000) die('skip For OpenSSL < 3.2'); +?> --FILE-- = 3.2'); +?> +--FILE-- + +--EXPECTF-- +bool(true) +array(16) { + ["name"]=> + string(96) "/C=BR/ST=Rio Grande do Sul/L=Porto Alegre/CN=Henrique do N. Angelo/emailAddress=hnangelo@php.net" + ["subject"]=> + array(5) { + ["C"]=> + string(2) "BR" + ["ST"]=> + string(17) "Rio Grande do Sul" + ["L"]=> + string(12) "Porto Alegre" + ["CN"]=> + string(21) "Henrique do N. Angelo" + ["emailAddress"]=> + string(16) "hnangelo@php.net" + } + ["hash"]=> + string(8) "%s" + ["issuer"]=> + array(5) { + ["C"]=> + string(2) "BR" + ["ST"]=> + string(17) "Rio Grande do Sul" + ["L"]=> + string(12) "Porto Alegre" + ["CN"]=> + string(21) "Henrique do N. Angelo" + ["emailAddress"]=> + string(16) "hnangelo@php.net" + } + ["version"]=> + int(2) + ["serialNumber"]=> + string(20) "12593567369101004962" + ["serialNumberHex"]=> + string(16) "AEC556CC723750A2" + ["validFrom"]=> + string(13) "080630102843Z" + ["validTo"]=> + string(13) "080730102843Z" + ["validFrom_time_t"]=> + int(1214821723) + ["validTo_time_t"]=> + int(1217413723) + ["signatureTypeSN"]=> + string(8) "RSA-SHA1" + ["signatureTypeLN"]=> + string(21) "sha1WithRSAEncryption" + ["signatureTypeNID"]=> + int(65) + ["purposes"]=> + array(10) { + [1]=> + array(3) { + [0]=> + bool(true) + [1]=> + bool(true) + [2]=> + string(9) "sslclient" + } + [2]=> + array(3) { + [0]=> + bool(true) + [1]=> + bool(true) + [2]=> + string(9) "sslserver" + } + [3]=> + array(3) { + [0]=> + bool(true) + [1]=> + bool(true) + [2]=> + string(11) "nssslserver" + } + [4]=> + array(3) { + [0]=> + bool(true) + [1]=> + bool(true) + [2]=> + string(9) "smimesign" + } + [5]=> + array(3) { + [0]=> + bool(true) + [1]=> + bool(true) + [2]=> + string(12) "smimeencrypt" + } + [6]=> + array(3) { + [0]=> + bool(true) + [1]=> + bool(true) + [2]=> + string(7) "crlsign" + } + [7]=> + array(3) { + [0]=> + bool(true) + [1]=> + bool(true) + [2]=> + string(3) "any" + } + [8]=> + array(3) { + [0]=> + bool(true) + [1]=> + bool(true) + [2]=> + string(10) "ocsphelper" + } + [9]=> + array(3) { + [0]=> + bool(false) + [1]=> + bool(true) + [2]=> + string(13) "timestampsign" + } + [10]=> + array(3) { + [0]=> + bool(false) + [1]=> + bool(true) + [2]=> + string(8) "codesign" + } + } + ["extensions"]=> + array(3) { + ["subjectKeyIdentifier"]=> + string(59) "DB:7E:40:72:BD:5C:35:85:EC:29:29:81:12:E8:62:68:6A:B7:3F:7D" + ["authorityKeyIdentifier"]=> + string(%d) "keyid:DB:7E:40:72:BD:5C:35:85:EC:29:29:81:12:E8:62:68:6A:B7:3F:7D +DirName:/C=BR/ST=Rio Grande do Sul/L=Porto Alegre/CN=Henrique do N. Angelo/emailAddress=hnangelo@php.net +serial:AE:C5:56:CC:72:37:50:A2%A" + ["basicConstraints"]=> + string(7) "CA:TRUE" + } +} +array(16) { + ["name"]=> + string(96) "/C=BR/ST=Rio Grande do Sul/L=Porto Alegre/CN=Henrique do N. Angelo/emailAddress=hnangelo@php.net" + ["subject"]=> + array(5) { + ["countryName"]=> + string(2) "BR" + ["stateOrProvinceName"]=> + string(17) "Rio Grande do Sul" + ["localityName"]=> + string(12) "Porto Alegre" + ["commonName"]=> + string(21) "Henrique do N. Angelo" + ["emailAddress"]=> + string(16) "hnangelo@php.net" + } + ["hash"]=> + string(8) "%s" + ["issuer"]=> + array(5) { + ["countryName"]=> + string(2) "BR" + ["stateOrProvinceName"]=> + string(17) "Rio Grande do Sul" + ["localityName"]=> + string(12) "Porto Alegre" + ["commonName"]=> + string(21) "Henrique do N. Angelo" + ["emailAddress"]=> + string(16) "hnangelo@php.net" + } + ["version"]=> + int(2) + ["serialNumber"]=> + string(20) "12593567369101004962" + ["serialNumberHex"]=> + string(16) "AEC556CC723750A2" + ["validFrom"]=> + string(13) "080630102843Z" + ["validTo"]=> + string(13) "080730102843Z" + ["validFrom_time_t"]=> + int(1214821723) + ["validTo_time_t"]=> + int(1217413723) + ["signatureTypeSN"]=> + string(8) "RSA-SHA1" + ["signatureTypeLN"]=> + string(21) "sha1WithRSAEncryption" + ["signatureTypeNID"]=> + int(65) + ["purposes"]=> + array(10) { + [1]=> + array(3) { + [0]=> + bool(true) + [1]=> + bool(true) + [2]=> + string(10) "SSL client" + } + [2]=> + array(3) { + [0]=> + bool(true) + [1]=> + bool(true) + [2]=> + string(10) "SSL server" + } + [3]=> + array(3) { + [0]=> + bool(true) + [1]=> + bool(true) + [2]=> + string(19) "Netscape SSL server" + } + [4]=> + array(3) { + [0]=> + bool(true) + [1]=> + bool(true) + [2]=> + string(14) "S/MIME signing" + } + [5]=> + array(3) { + [0]=> + bool(true) + [1]=> + bool(true) + [2]=> + string(17) "S/MIME encryption" + } + [6]=> + array(3) { + [0]=> + bool(true) + [1]=> + bool(true) + [2]=> + string(11) "CRL signing" + } + [7]=> + array(3) { + [0]=> + bool(true) + [1]=> + bool(true) + [2]=> + string(11) "Any Purpose" + } + [8]=> + array(3) { + [0]=> + bool(true) + [1]=> + bool(true) + [2]=> + string(11) "OCSP helper" + } + [9]=> + array(3) { + [0]=> + bool(false) + [1]=> + bool(true) + [2]=> + string(18) "Time Stamp signing" + } + [10]=> + array(3) { + [0]=> + bool(false) + [1]=> + bool(true) + [2]=> + string(12) "Code signing" + } + } + ["extensions"]=> + array(3) { + ["subjectKeyIdentifier"]=> + string(59) "DB:7E:40:72:BD:5C:35:85:EC:29:29:81:12:E8:62:68:6A:B7:3F:7D" + ["authorityKeyIdentifier"]=> + string(%d) "keyid:DB:7E:40:72:BD:5C:35:85:EC:29:29:81:12:E8:62:68:6A:B7:3F:7D +DirName:/C=BR/ST=Rio Grande do Sul/L=Porto Alegre/CN=Henrique do N. Angelo/emailAddress=hnangelo@php.net +serial:AE:C5:56:CC:72:37:50:A2%A" + ["basicConstraints"]=> + string(7) "CA:TRUE" + } +} From b3e26c3036a54e9821ea7119c26cdabe484fe36d Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Fri, 19 Apr 2024 15:19:02 +0200 Subject: [PATCH 57/64] Fix missing handling of CALLABLE_CONVERT in cleanup_unfinished_calls() Fixes GH-14003 --- NEWS | 2 ++ Zend/tests/gh14003.phpt | 24 ++++++++++++++++++++++++ Zend/zend_execute.c | 4 ++++ 3 files changed, 30 insertions(+) create mode 100644 Zend/tests/gh14003.phpt diff --git a/NEWS b/NEWS index e5f8e3eba5ff3..0cc2d50baf281 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,8 @@ PHP NEWS Zend/zend_opcode.c). (nielsdos) . Fixed bug GH-13942 (Align the behavior of zend-max-execution-timers with other timeout implementations). (Kévin Dunglas) + . Fixed bug GH-14003 (Broken cleanup of unfinished calls with callable convert + parameters). (ilutov) - Fibers: . Fixed bug GH-13903 (ASAN false positive underflow when executing copy()). diff --git a/Zend/tests/gh14003.phpt b/Zend/tests/gh14003.phpt new file mode 100644 index 0000000000000..92a6c5919ab5b --- /dev/null +++ b/Zend/tests/gh14003.phpt @@ -0,0 +1,24 @@ +--TEST-- +GH-14003: Missing handling of CALLABLE_CONVERT in cleanup_unfinished_calls() +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught Exception: Test in %s:%d +Stack trace: +#0 [internal function]: foo('a') +#1 %s(%d): array_map(Object(Closure), Array) +#2 {main} + thrown in %s on line %d diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 0df529203c1b9..5a060540db015 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -4104,6 +4104,7 @@ ZEND_API void zend_unfinished_calls_gc(zend_execute_data *execute_data, zend_exe case ZEND_DO_ICALL: case ZEND_DO_UCALL: case ZEND_DO_FCALL_BY_NAME: + case ZEND_CALLABLE_CONVERT: level++; break; case ZEND_INIT_FCALL: @@ -4159,6 +4160,7 @@ ZEND_API void zend_unfinished_calls_gc(zend_execute_data *execute_data, zend_exe case ZEND_DO_ICALL: case ZEND_DO_UCALL: case ZEND_DO_FCALL_BY_NAME: + case ZEND_CALLABLE_CONVERT: level++; break; case ZEND_INIT_FCALL: @@ -4237,6 +4239,7 @@ static void cleanup_unfinished_calls(zend_execute_data *execute_data, uint32_t o case ZEND_DO_ICALL: case ZEND_DO_UCALL: case ZEND_DO_FCALL_BY_NAME: + case ZEND_CALLABLE_CONVERT: level++; break; case ZEND_INIT_FCALL: @@ -4292,6 +4295,7 @@ static void cleanup_unfinished_calls(zend_execute_data *execute_data, uint32_t o case ZEND_DO_ICALL: case ZEND_DO_UCALL: case ZEND_DO_FCALL_BY_NAME: + case ZEND_CALLABLE_CONVERT: level++; break; case ZEND_INIT_FCALL: From 2a1aa8cac53006a987ff1bb7f5c43279c6f62564 Mon Sep 17 00:00:00 2001 From: Saki Takamachi Date: Sat, 20 Apr 2024 22:33:25 +0900 Subject: [PATCH 58/64] Fix GH-13998: Manage refcount of agg_context->val correctly (#14004) When step_callback fails, agg_context->val is passed dtor, but agg_context->val is also used in final_callback regardless of the success/failure of step_callback, so should not call dtor. closes #14004 fixes #13998 --- NEWS | 2 ++ ext/pdo_sqlite/sqlite_driver.c | 1 - ext/pdo_sqlite/tests/gh13998.phpt | 25 +++++++++++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 ext/pdo_sqlite/tests/gh13998.phpt diff --git a/NEWS b/NEWS index 0cc2d50baf281..4b1a4aa8fe8bc 100644 --- a/NEWS +++ b/NEWS @@ -36,6 +36,8 @@ PHP NEWS - PDO SQLite: . Fix GH-13984 (Buffer size is now checked before memcmp). (Saki Takamachi) + . Fix GH-13998 (Manage refcount of agg_context->val correctly). + (Saki Takamachi) - Phar: . Fixed bug GH-13836 (Renaming a file in a Phar to an already existing diff --git a/ext/pdo_sqlite/sqlite_driver.c b/ext/pdo_sqlite/sqlite_driver.c index 2f494c2ddb8b3..03b212bf75c1b 100644 --- a/ext/pdo_sqlite/sqlite_driver.c +++ b/ext/pdo_sqlite/sqlite_driver.c @@ -441,7 +441,6 @@ static int do_callback(struct pdo_sqlite_fci *fc, zval *cb, * the context */ if (agg_context) { if (Z_ISUNDEF(retval)) { - zval_ptr_dtor(&agg_context->val); return FAILURE; } zval_ptr_dtor(Z_REFVAL(agg_context->val)); diff --git a/ext/pdo_sqlite/tests/gh13998.phpt b/ext/pdo_sqlite/tests/gh13998.phpt new file mode 100644 index 0000000000000..c87b4acdd214b --- /dev/null +++ b/ext/pdo_sqlite/tests/gh13998.phpt @@ -0,0 +1,25 @@ +--TEST-- +Fix GH-13998: Manage refcount of agg_context->val correctly +--EXTENSIONS-- +pdo_sqlite +--FILE-- +query('CREATE TABLE test (a int, b int)'); +$stmt = $db->query('INSERT INTO test VALUES (1, 1), (2, 2), (3, 3)'); +$db->sqliteCreateAggregate('S', $step, $finalize, 1); + +try { + $db->query('SELECT S(a) FROM test'); +} catch (Exception $e) { + echo 'done!'; +} +?> +--EXPECT-- +done! From 42443b4c2e23c2bed2b53208ea7ccb5683a8f254 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 20 Apr 2024 15:40:01 +0100 Subject: [PATCH 59/64] ext/session: fix _read/_write buffer limit. MSDN pages mention the buffer size upper limit is INT_MAX not UINT_MAX. inspired by GH-13205. Close GH-14017 --- NEWS | 1 + ext/session/mod_files.c | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index 4b1a4aa8fe8bc..9a6bf178e8da8 100644 --- a/NEWS +++ b/NEWS @@ -58,6 +58,7 @@ PHP NEWS ext/session/mod_files.c). (nielsdos) . Fixed bug GH-13891 (memleak and segfault when using ini_set with session.trans_sid_hosts). (nielsdos, kamil-tekiela) + . Fixed buffer _read/_write size limit on windows for the file mode. (David Carlier) - Streams: . Fixed file_get_contents() on Windows fails with "errno=22 Invalid diff --git a/ext/session/mod_files.c b/ext/session/mod_files.c index e640f96f93221..9396f16b93581 100644 --- a/ext/session/mod_files.c +++ b/ext/session/mod_files.c @@ -86,6 +86,7 @@ # ifndef O_NOFOLLOW # define O_NOFOLLOW 0 # endif +#define SESS_FILE_BUF_SIZE(sz) ((unsigned int)(sz > INT_MAX ? INT_MAX : (unsigned int)sz)) #endif typedef struct { @@ -246,7 +247,7 @@ static zend_result ps_files_write(ps_files *data, zend_string *key, zend_string lseek(data->fd, 0, SEEK_SET); #ifdef PHP_WIN32 { - unsigned int to_write = ZSTR_LEN(val) > UINT_MAX ? UINT_MAX : (unsigned int)ZSTR_LEN(val); + unsigned int to_write = SESS_FILE_BUF_SIZE(ZSTR_LEN(val)); char *buf = ZSTR_VAL(val); int wrote; @@ -255,7 +256,7 @@ static zend_result ps_files_write(ps_files *data, zend_string *key, zend_string n += wrote; buf = wrote > -1 ? buf + wrote : 0; - to_write = wrote > -1 ? (ZSTR_LEN(val) - n > UINT_MAX ? UINT_MAX : (unsigned int)(ZSTR_LEN(val) - n)): 0; + to_write = wrote > -1 ? SESS_FILE_BUF_SIZE(ZSTR_LEN(val) - n) : 0; } while(wrote > 0); } @@ -493,7 +494,7 @@ PS_READ_FUNC(files) lseek(data->fd, 0, SEEK_SET); #ifdef PHP_WIN32 { - unsigned int to_read = ZSTR_LEN(*val) > UINT_MAX ? UINT_MAX : (unsigned int)ZSTR_LEN(*val); + unsigned int to_read = SESS_FILE_BUF_SIZE(ZSTR_LEN(*val)); char *buf = ZSTR_VAL(*val); int read_in; @@ -502,7 +503,7 @@ PS_READ_FUNC(files) n += read_in; buf = read_in > -1 ? buf + read_in : 0; - to_read = read_in > -1 ? (ZSTR_LEN(*val) - n > UINT_MAX ? UINT_MAX : (unsigned int)(ZSTR_LEN(*val) - n)): 0; + to_read = read_in > -1 ? SESS_FILE_BUF_SIZE(ZSTR_LEN(*val) - n) : 0; } while(read_in > 0); From 469ad32581292693dd3338a486f40ab7cbec33f9 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Sun, 21 Apr 2024 16:05:26 +0200 Subject: [PATCH 60/64] [skip ci] Backport 0e7ef95 and 4f0d4c0 --- .github/workflows/push.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 52f70f809e9ce..ddb4ee0aaf172 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -41,6 +41,7 @@ env: CXX: ccache g++ jobs: LINUX_X64: + if: github.repository == 'php/php-src' || github.event_name == 'pull_request' strategy: fail-fast: false matrix: @@ -94,6 +95,7 @@ jobs: - name: Verify generated files are up to date uses: ./.github/actions/verify-generated-files MACOS_DEBUG_NTS: + if: github.repository == 'php/php-src' || github.event_name == 'pull_request' runs-on: macos-12 steps: - name: git checkout @@ -126,6 +128,7 @@ jobs: - name: Verify generated files are up to date uses: ./.github/actions/verify-generated-files WINDOWS: + if: github.repository == 'php/php-src' || github.event_name == 'pull_request' name: WINDOWS_X64_ZTS runs-on: windows-2019 env: From 7d3d8de1f3f9d3da5c8a80db2c18493dd1be048e Mon Sep 17 00:00:00 2001 From: Peter Kokot Date: Sun, 21 Apr 2024 17:23:22 +0200 Subject: [PATCH 61/64] Fix erroneous dnl appended in configure (#14013) This is a backport of commit 03f15534a17c7031b89dac7aaa21d59474517321 to PHP-8.2 due to GH-14002 and fixes the PHP_CXX_COMPILE_STDCXX check in ext/intl whether the specified C++ standard is mandatory or optional. The `dnl` (Discard to Next Line) M4 macro in this combination of `m4_if` macros and arguments isn't properly replaced and a literal `dnl` string is appended in the configure script. The `[]dnl` works ok. --- NEWS | 1 + build/php_cxx_compile_stdcxx.m4 | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 9a6bf178e8da8..33ce2e0bd3756 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,7 @@ PHP NEWS other timeout implementations). (Kévin Dunglas) . Fixed bug GH-14003 (Broken cleanup of unfinished calls with callable convert parameters). (ilutov) + . Fixed bug GH-14013 (Erroneous dnl appended in configure). (Peter Kokot) - Fibers: . Fixed bug GH-13903 (ASAN false positive underflow when executing copy()). diff --git a/build/php_cxx_compile_stdcxx.m4 b/build/php_cxx_compile_stdcxx.m4 index f8e97fce708f0..8f723266b2c4f 100644 --- a/build/php_cxx_compile_stdcxx.m4 +++ b/build/php_cxx_compile_stdcxx.m4 @@ -27,11 +27,11 @@ AC_DEFUN([PHP_CXX_COMPILE_STDCXX], [dnl [$1], [14], [ax_cxx_compile_alternatives="14 1y"], [$1], [17], [ax_cxx_compile_alternatives="17 1z"], [$1], [20], [ax_cxx_compile_alternatives="20"], - [m4_fatal([invalid first argument `$1' to PHP_CXX_COMPILE_STDCXX])])dnl + [m4_fatal([invalid first argument `$1' to PHP_CXX_COMPILE_STDCXX])])[]dnl m4_if([$2], [], [ax_cxx_compile_cxx$1_required=true], [$2], [mandatory], [ax_cxx_compile_cxx$1_required=true], [$2], [optional], [ax_cxx_compile_cxx$1_required=false], - [m4_fatal([invalid third argument `$2' to PHP_CXX_COMPILE_STDCXX])])dnl + [m4_fatal([invalid third argument `$2' to PHP_CXX_COMPILE_STDCXX])])[]dnl AC_LANG_PUSH([C++])dnl ac_success=no From f8b9030b4ee506e20919b35acb4f17609054d4aa Mon Sep 17 00:00:00 2001 From: SATO Kentaro Date: Sat, 17 Feb 2024 00:23:12 +0900 Subject: [PATCH 62/64] Temporary reset filename and lineno override before autoload Closes GH-10232 Closes GH-13313 --- NEWS | 2 ++ Zend/tests/gh10232.phpt | 33 +++++++++++++++++++++++++++++ Zend/tests/gh10232/constant_def.inc | 12 +++++++++++ Zend/tests/gh10232/required.inc | 5 +++++ Zend/tests/gh7771_3.phpt | 2 +- Zend/zend_execute_API.c | 6 ++++++ 6 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 Zend/tests/gh10232.phpt create mode 100644 Zend/tests/gh10232/constant_def.inc create mode 100644 Zend/tests/gh10232/required.inc diff --git a/NEWS b/NEWS index 33ce2e0bd3756..39b6e539737bb 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,8 @@ PHP NEWS . Fixed bug GH-14003 (Broken cleanup of unfinished calls with callable convert parameters). (ilutov) . Fixed bug GH-14013 (Erroneous dnl appended in configure). (Peter Kokot) + . Fixed bug GH-10232 (If autoloading occurs during constant resolution + filename and lineno are identified incorrectly). (ranvis) - Fibers: . Fixed bug GH-13903 (ASAN false positive underflow when executing copy()). diff --git a/Zend/tests/gh10232.phpt b/Zend/tests/gh10232.phpt new file mode 100644 index 0000000000000..8e8d7ff86b5c6 --- /dev/null +++ b/Zend/tests/gh10232.phpt @@ -0,0 +1,33 @@ +--TEST-- +GH-10232 (Weird behaviour when a file is autoloaded in assignment of a constant) +--FILE-- +getLine(), "\n"; + require_once __DIR__ . '/gh10232/constant_def.inc'; +}, true); + + +class ConstantRef +{ + public const VALUE = ConstantDef::VALUE; +} + +ConstantRef::VALUE; + +?> +--EXPECTF-- +Notice: 7 in %sgh10232.php on line 7 +Exception on line 8 + +Notice: constant_def.inc in %sconstant_def.inc on line 3 +Exception in constant_def.inc on line 4 + +Notice: required.inc in %srequired.inc on line 3 +Exception in required.inc on line 4 diff --git a/Zend/tests/gh10232/constant_def.inc b/Zend/tests/gh10232/constant_def.inc new file mode 100644 index 0000000000000..22e469af63828 --- /dev/null +++ b/Zend/tests/gh10232/constant_def.inc @@ -0,0 +1,12 @@ +getFile()), ' on line ', $ex->getLine(), "\n"; + +require_once 'required.inc'; // The script of the same directory. + +class ConstantDef +{ + const VALUE = true; +} diff --git a/Zend/tests/gh10232/required.inc b/Zend/tests/gh10232/required.inc new file mode 100644 index 0000000000000..d5ff90da0211c --- /dev/null +++ b/Zend/tests/gh10232/required.inc @@ -0,0 +1,5 @@ +getFile()), ' on line ', $ex->getLine(), "\n"; diff --git a/Zend/tests/gh7771_3.phpt b/Zend/tests/gh7771_3.phpt index f6780814b89b4..e44a01a8aec74 100644 --- a/Zend/tests/gh7771_3.phpt +++ b/Zend/tests/gh7771_3.phpt @@ -12,5 +12,5 @@ spl_autoload_register(function($class) use ($classlist) { var_dump(D::HW); ?> --EXPECTF-- -Fatal error: Constant expression contains invalid operations in %sgh7771_3.php(7) : eval()'d code(1) : eval()'d code on line 1 +Fatal error: Constant expression contains invalid operations in %sgh7771_3.php(7) : eval()'d code on line 1 diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 0e2ff263c9a85..c7f814138d00d 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -1205,9 +1205,15 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, zend_string * autoload_name = zend_string_copy(name); } + zend_string *previous_filename = EG(filename_override); + zend_long previous_lineno = EG(lineno_override); + EG(filename_override) = NULL; + EG(lineno_override) = -1; zend_exception_save(); ce = zend_autoload(autoload_name, lc_name); zend_exception_restore(); + EG(filename_override) = previous_filename; + EG(lineno_override) = previous_lineno; zend_string_release_ex(autoload_name, 0); zend_hash_del(EG(in_autoload), lc_name); From 44775b7617f8e078df1c5ee6cadccd454e63cae0 Mon Sep 17 00:00:00 2001 From: Peter Kokot Date: Mon, 22 Apr 2024 21:21:40 +0200 Subject: [PATCH 63/64] Fix GH-13727: Building with -Werror=strict-prototypes (#14029) This is addon to the GH-13727 bug fix. When configuring the build with: ./configure CFLAGS=-Werror=strict-prototypes libtool check for parsing nm command would fail: checking command to parse /usr/bin/nm -B output from cc object... failed Upstream libtool has this specific check already fixed. Note that this works only with Autoconf version 2.72 and later and is preparation for future compilers that might have this error enabled by default. --- NEWS | 1 + build/libtool.m4 | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 39b6e539737bb..087409db243ee 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,7 @@ PHP NEWS . Fixed bug GH-14013 (Erroneous dnl appended in configure). (Peter Kokot) . Fixed bug GH-10232 (If autoloading occurs during constant resolution filename and lineno are identified incorrectly). (ranvis) + . Fixed bug GH-13727 (Missing void keyword). (Peter Kokot) - Fibers: . Fixed bug GH-13903 (ASAN false positive underflow when executing copy()). diff --git a/build/libtool.m4 b/build/libtool.m4 index 5b518d50e4ef5..0b9528d7dc7bf 100644 --- a/build/libtool.m4 +++ b/build/libtool.m4 @@ -4636,7 +4636,7 @@ for ac_symprfx in "" "_"; do extern "C" { #endif char nm_test_var; -void nm_test_func(){} +void nm_test_func(void){} #ifdef __cplusplus } #endif From 2d641982fd720762e09d8386bca3bb5348a03de4 Mon Sep 17 00:00:00 2001 From: Sergey Panteleev Date: Tue, 7 May 2024 17:19:14 +0300 Subject: [PATCH 64/64] Update versions for PHP 8.2.19 --- NEWS | 2 +- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index 087409db243ee..3b7f2e43e9970 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,6 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.2.19 +09 May 2024, PHP 8.2.19 - Core: . Fixed bug GH-13772 (Invalid execute_data->opline pointers in observer fcall diff --git a/Zend/zend.h b/Zend/zend.h index ad8fde7a8ad1c..95bc49df8db49 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.2.19-dev" +#define ZEND_VERSION "4.2.19" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index 683029f476a94..f3892dbaaad07 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice. dnl ---------------------------------------------------------------------------- AC_PREREQ([2.68]) -AC_INIT([PHP],[8.2.19-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) +AC_INIT([PHP],[8.2.19],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) AC_CONFIG_SRCDIR([main/php_version.h]) AC_CONFIG_AUX_DIR([build]) AC_PRESERVE_HELP_ORDER diff --git a/main/php_version.h b/main/php_version.h index a17d49197da51..6a9708f9d0bd6 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -3,6 +3,6 @@ #define PHP_MAJOR_VERSION 8 #define PHP_MINOR_VERSION 2 #define PHP_RELEASE_VERSION 19 -#define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.2.19-dev" +#define PHP_EXTRA_VERSION "" +#define PHP_VERSION "8.2.19" #define PHP_VERSION_ID 80219