From 8db7fd8a2ac0bb406863d1ca9415f7236aa2f210 Mon Sep 17 00:00:00 2001 From: Patrick Allaert Date: Thu, 3 Feb 2022 02:21:29 +0100 Subject: [PATCH 01/55] Bump for 8.1.4-dev --- NEWS | 4 +++- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 6 +++--- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index 5fe565cb881f3..c6d1a7c277307 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,8 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.1.3 +?? ??? ????, PHP 8.1.4 + +03 Feb 2022, PHP 8.1.3 - Core: . Fixed bug #81430 (Attribute instantiation leaves dangling pointer). diff --git a/Zend/zend.h b/Zend/zend.h index 071901d4c5725..67afd49421fd9 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.1.3-dev" +#define ZEND_VERSION "4.1.4-dev" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index 4c111b8a9b3dd..57e01def67e0e 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.3-dev],[https://bugs.php.net],[php],[https://www.php.net]) +AC_INIT([PHP],[8.1.4-dev],[https://bugs.php.net],[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 e0e76bd6aaca1..fd5b1b0854a9b 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 3 +#define PHP_RELEASE_VERSION 4 #define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.1.3-dev" -#define PHP_VERSION_ID 80103 +#define PHP_VERSION "8.1.4-dev" +#define PHP_VERSION_ID 80104 From 9bd468da6341d38f9b006b5ca407f79bb5d91393 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Thu, 20 Jan 2022 16:55:57 +0100 Subject: [PATCH 02/55] Fix GH-7953: ob_clean() only does not set Content-Encoding If an output handler has not yet been started, calling `ob_clean()` causes it to start. If that happens, we must not forget to set the `Content-Encoding` and `Vary` headers. Closes GH-7960. --- NEWS | 5 +++++ ext/iconv/iconv.c | 2 +- ext/iconv/tests/gh7953.phpt | 21 +++++++++++++++++++++ ext/zlib/tests/gh7953.phpt | 21 +++++++++++++++++++++ ext/zlib/zlib.c | 2 +- 5 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 ext/iconv/tests/gh7953.phpt create mode 100644 ext/zlib/tests/gh7953.phpt diff --git a/NEWS b/NEWS index 3d6d992ae1b16..3b25cf62d3f27 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,11 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 2022, PHP 8.0.17 +- Iconv: + . Fixed bug GH-7953 (ob_clean() only does not set Content-Encoding). (cmb) + +- Zlib: + . Fixed bug GH-7953 (ob_clean() only does not set Content-Encoding). (cmb) 17 Feb 2022, PHP 8.0.16 diff --git a/ext/iconv/iconv.c b/ext/iconv/iconv.c index 90c209cbcbf00..d0693c08f2062 100644 --- a/ext/iconv/iconv.c +++ b/ext/iconv/iconv.c @@ -311,7 +311,7 @@ static int php_iconv_output_handler(void **nothing, php_output_context *output_c mimetype = SG(default_mimetype) ? SG(default_mimetype) : SAPI_DEFAULT_MIMETYPE; } - if (mimetype != NULL && !(output_context->op & PHP_OUTPUT_HANDLER_CLEAN)) { + if (mimetype != NULL && (!(output_context->op & PHP_OUTPUT_HANDLER_CLEAN) || (output_context->op & PHP_OUTPUT_HANDLER_START))) { size_t len; char *p = strstr(get_output_encoding(), "//"); diff --git a/ext/iconv/tests/gh7953.phpt b/ext/iconv/tests/gh7953.phpt new file mode 100644 index 0000000000000..bfc249fb9f21e --- /dev/null +++ b/ext/iconv/tests/gh7953.phpt @@ -0,0 +1,21 @@ +--TEST-- +GH-7953 (ob_clean() only may not set Content-* header) +--SKIPIF-- + +--INI-- +input_encoding=UTF-8 +output_encoding=ISO-8859-1 +--CGI-- +--FILE-- + +--EXPECTF-- +%a +--EXPECTHEADERS-- +Content-Type: text/html; charset=ISO-8859-1 diff --git a/ext/zlib/tests/gh7953.phpt b/ext/zlib/tests/gh7953.phpt new file mode 100644 index 0000000000000..d5d9011c03281 --- /dev/null +++ b/ext/zlib/tests/gh7953.phpt @@ -0,0 +1,21 @@ +--TEST-- +GH-7953 (ob_clean() only may not set Content-* header) +--SKIPIF-- + +--CGI-- +--ENV-- +HTTP_ACCEPT_ENCODING=gzip +--FILE-- + +--EXPECTF-- +%a +--EXPECTHEADERS-- +Content-Encoding: gzip +Vary: Accept-Encoding diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c index 75bd273526eb6..f7cf0d5dac76a 100644 --- a/ext/zlib/zlib.c +++ b/ext/zlib/zlib.c @@ -281,7 +281,7 @@ static int php_zlib_output_handler(void **handler_context, php_output_context *o return FAILURE; } - if (!(output_context->op & PHP_OUTPUT_HANDLER_CLEAN)) { + if (!(output_context->op & PHP_OUTPUT_HANDLER_CLEAN) || (output_context->op & PHP_OUTPUT_HANDLER_START)) { int flags; if (SUCCESS == php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_GET_FLAGS, &flags)) { From bea542a9536013390b40b7c32ddf94676e56001b Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 6 Feb 2022 17:18:46 +0000 Subject: [PATCH 03/55] Haiku fix ZTS build, disabling tls model Closes GH-8047. --- NEWS | 3 +++ TSRM/TSRM.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 3b25cf62d3f27..9502c2a38eabb 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 2022, PHP 8.0.17 +- Core: + . Fixed Haiku ZTS build. (David Carlier) + - Iconv: . Fixed bug GH-7953 (ob_clean() only does not set Content-Encoding). (cmb) diff --git a/TSRM/TSRM.h b/TSRM/TSRM.h index 188ed29f0bc5e..81343f3477409 100644 --- a/TSRM/TSRM.h +++ b/TSRM/TSRM.h @@ -147,7 +147,7 @@ TSRM_API const char *tsrm_api_name(void); # define __has_attribute(x) 0 #endif -#if !__has_attribute(tls_model) || defined(__FreeBSD__) || defined(__MUSL__) +#if !__has_attribute(tls_model) || defined(__FreeBSD__) || defined(__MUSL__) || defined(__HAIKU__) # define TSRM_TLS_MODEL_ATTR #elif __PIC__ # define TSRM_TLS_MODEL_ATTR __attribute__((tls_model("initial-exec"))) From 86c196ba7f73f4bb90530a80631a0cc737a6c684 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Thu, 3 Feb 2022 14:26:57 +0100 Subject: [PATCH 04/55] Fix GH-7980: Unexpected result for iconv_mime_decode We need to reset the shift state right after conversion, to cater to potenially following plain encodings. Also, there is no need to reset the shift for plain encodings, because these are not state-dependent. Closes GH-8025. --- NEWS | 1 + ext/iconv/iconv.c | 10 +++------- ext/iconv/tests/gh7980.phpt | 13 +++++++++++++ 3 files changed, 17 insertions(+), 7 deletions(-) create mode 100644 ext/iconv/tests/gh7980.phpt diff --git a/NEWS b/NEWS index 9502c2a38eabb..a273da6f91927 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,7 @@ PHP NEWS - Iconv: . Fixed bug GH-7953 (ob_clean() only does not set Content-Encoding). (cmb) + . Fixed bug GH-7980 (Unexpected result for iconv_mime_decode). (cmb) - Zlib: . Fixed bug GH-7953 (ob_clean() only does not set Content-Encoding). (cmb) diff --git a/ext/iconv/iconv.c b/ext/iconv/iconv.c index d0693c08f2062..7a66c965e3cbf 100644 --- a/ext/iconv/iconv.c +++ b/ext/iconv/iconv.c @@ -1576,6 +1576,9 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st } err = _php_iconv_appendl(pretval, ZSTR_VAL(decoded_text), ZSTR_LEN(decoded_text), cd); + if (err == PHP_ICONV_ERR_SUCCESS) { + err = _php_iconv_appendl(pretval, NULL, 0, cd); + } zend_string_release_ex(decoded_text, 0); if (err != PHP_ICONV_ERR_SUCCESS) { @@ -1716,13 +1719,6 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st *next_pos = p1; } - if (cd != (iconv_t)(-1)) { - _php_iconv_appendl(pretval, NULL, 0, cd); - } - if (cd_pl != (iconv_t)(-1)) { - _php_iconv_appendl(pretval, NULL, 0, cd_pl); - } - smart_str_0(pretval); out: if (cd != (iconv_t)(-1)) { diff --git a/ext/iconv/tests/gh7980.phpt b/ext/iconv/tests/gh7980.phpt new file mode 100644 index 0000000000000..a2c875a03d9cc --- /dev/null +++ b/ext/iconv/tests/gh7980.phpt @@ -0,0 +1,13 @@ +--TEST-- +Bug GH-7980 (Unexpected result for iconv_mime_decode) +--SKIPIF-- + +--FILE-- +'; +var_dump(iconv_mime_decode($subject, ICONV_MIME_DECODE_STRICT, 'UTF-8')); +?> +--EXPECT-- +string(57) "DSI Chargé de Formation Jean Dupont " From 1d48da6da581c4d1c55f8b6f78cc73bad0136929 Mon Sep 17 00:00:00 2001 From: Brett <6075681+developerbmw@users.noreply.github.com> Date: Tue, 8 Feb 2022 14:37:52 +1300 Subject: [PATCH 05/55] Fixed libpng warning when loading interlaced images We enable interlace transform when reading png. Closes GH-8002. --- NEWS | 3 +++ ext/gd/libgd/gd_png.c | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/NEWS b/NEWS index a273da6f91927..64bb448e262ef 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,9 @@ PHP NEWS - Core: . Fixed Haiku ZTS build. (David Carlier) +- GD: + . Fixed libpng warning when loading interlaced images. (Brett) + - Iconv: . Fixed bug GH-7953 (ob_clean() only does not set Content-Encoding). (cmb) . Fixed bug GH-7980 (Unexpected result for iconv_mime_decode). (cmb) diff --git a/ext/gd/libgd/gd_png.c b/ext/gd/libgd/gd_png.c index 952d65240db17..c7de330b929c4 100644 --- a/ext/gd/libgd/gd_png.c +++ b/ext/gd/libgd/gd_png.c @@ -336,6 +336,11 @@ gdImagePtr gdImageCreateFromPngCtx (gdIOCtx * infile) break; } + /* enable the interlace transform if supported */ +#ifdef PNG_READ_INTERLACING_SUPPORTED + (void)png_set_interlace_handling(png_ptr); +#endif + png_read_update_info(png_ptr, info_ptr); /* allocate space for the PNG image data */ From c035298eb2cf309c486c0652ae5706e961e1fd1f Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 8 Feb 2022 15:45:40 +0300 Subject: [PATCH 06/55] Free cached chunks when the requested memory limit is above real usage --- Zend/zend_alloc.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index 5738c030a5822..6e0ce4b651dc2 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -2660,10 +2660,23 @@ ZEND_API char* ZEND_FASTCALL zend_strndup(const char *s, size_t length) ZEND_API zend_result zend_set_memory_limit_ex(size_t memory_limit) { #if ZEND_MM_LIMIT + zend_mm_heap *heap = AG(mm_heap); + if (memory_limit < ZEND_MM_CHUNK_SIZE) { memory_limit = ZEND_MM_CHUNK_SIZE; } - if (UNEXPECTED(memory_limit < AG(mm_heap)->real_size)) { + if (UNEXPECTED(memory_limit < heap->real_size)) { + if (memory_limit >= heap->real_size - heap->cached_chunks_count * ZEND_MM_CHUNK_SIZE) { + /* free some cached chunks to fit into new memory limit */ + do { + zend_mm_chunk *p = heap->cached_chunks; + heap->cached_chunks = p->next; + zend_mm_chunk_free(heap, p, ZEND_MM_CHUNK_SIZE); + heap->cached_chunks_count--; + heap->real_size -= ZEND_MM_CHUNK_SIZE; + } while (memory_limit < heap->real_size); + return SUCCESS; + } return FAILURE; } AG(mm_heap)->limit = memory_limit; From 3b463749f544a7b538264ee2a9647e4bca92f9b0 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Tue, 8 Feb 2022 09:36:37 +0100 Subject: [PATCH 07/55] Fix GH-8059 use $PHP_EXECUTABLE when $PHP not set --- build/Makefile.global | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build/Makefile.global b/build/Makefile.global index 6941bab6ad412..f93a874ce1b57 100644 --- a/build/Makefile.global +++ b/build/Makefile.global @@ -148,6 +148,9 @@ prof-use: if test ! -z "$(PHP)"; then \ echo Parse $< to generate $@;\ $(PHP) $(top_srcdir)/build/gen_stub.php $<; \ + elif test ! -z "$(PHP_EXECUTABLE)" && test -x "$(PHP_EXECUTABLE)"; then \ + echo Parse $< to generate $@;\ + $(PHP_EXECUTABLE) $(top_srcdir)/build/gen_stub.php $<; \ fi; \ fi; From c03e111e6a39024677b2cc5d30a9baf2fe84dbc5 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Tue, 8 Feb 2022 13:54:35 +0100 Subject: [PATCH 08/55] [ci skip] news --- NEWS | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS b/NEWS index f4ed66db02e27..c1df994e029d3 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,7 @@ PHP NEWS - Core: . Fixed Haiku ZTS build. (David Carlier) + . Fixed bug GH-8059 arginfo not regenerated for extension. (Remi) - GD: . Fixed libpng warning when loading interlaced images. (Brett) From 29fe06fa5919bb0f239677d29f3856d64537eeec Mon Sep 17 00:00:00 2001 From: Till Backhaus Date: Mon, 19 Mar 2018 13:06:04 +0100 Subject: [PATCH 09/55] Fix bug #76109: Implement fpm_scoreboard_copy fpm_scoreboard_copy locks the scoreboard while copying the scoreboard and all proc scoreboards. proc scoreboards are locked one by one while copying each struct. The old implementation (inside fpm_handle_status_request) only briefly locked the scoreboard while copying the scorebard. Closes GH-7931 Co-authored-by: Jakub Zelenka --- NEWS | 4 ++ sapi/fpm/fpm/fpm_scoreboard.c | 57 +++++++++++++++++ sapi/fpm/fpm/fpm_scoreboard.h | 6 ++ sapi/fpm/fpm/fpm_status.c | 112 ++++++++++++++++------------------ 4 files changed, 118 insertions(+), 61 deletions(-) diff --git a/NEWS b/NEWS index 64bb448e262ef..3e1d12d0fc9b0 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,10 @@ PHP NEWS - GD: . Fixed libpng warning when loading interlaced images. (Brett) +- FPM: + . Fixed bug #76109 (Unsafe access to fpm scoreboard). + (Till Backhaus, Jakub Zelenka) + - Iconv: . Fixed bug GH-7953 (ob_clean() only does not set Content-Encoding). (cmb) . Fixed bug GH-7980 (Unexpected result for iconv_mime_decode). (cmb) diff --git a/sapi/fpm/fpm/fpm_scoreboard.c b/sapi/fpm/fpm/fpm_scoreboard.c index 5380d184901bf..ec28af49d7c4b 100644 --- a/sapi/fpm/fpm/fpm_scoreboard.c +++ b/sapi/fpm/fpm/fpm_scoreboard.c @@ -226,6 +226,63 @@ void fpm_scoreboard_release(struct fpm_scoreboard_s *scoreboard) { scoreboard->lock = 0; } +struct fpm_scoreboard_s *fpm_scoreboard_copy(struct fpm_scoreboard_s *scoreboard, int copy_procs) +{ + struct fpm_scoreboard_s *scoreboard_copy; + struct fpm_scoreboard_proc_s *scoreboard_proc_p; + size_t scoreboard_size, scoreboard_nprocs_size; + int i; + void *mem; + + if (!scoreboard) { + scoreboard = fpm_scoreboard_get(); + } + + if (copy_procs) { + scoreboard_size = sizeof(struct fpm_scoreboard_s); + scoreboard_nprocs_size = sizeof(struct fpm_scoreboard_proc_s) * scoreboard->nprocs; + + mem = malloc(scoreboard_size + scoreboard_nprocs_size); + } else { + mem = malloc(sizeof(struct fpm_scoreboard_s)); + } + + if (!mem) { + zlog(ZLOG_ERROR, "scoreboard: failed to allocate memory for copy"); + return NULL; + } + + scoreboard_copy = mem; + + scoreboard = fpm_scoreboard_acquire(scoreboard, FPM_SCOREBOARD_LOCK_NOHANG); + if (!scoreboard) { + free(mem); + zlog(ZLOG_ERROR, "scoreboard: failed to lock (already locked)"); + return NULL; + } + + *scoreboard_copy = *scoreboard; + + if (copy_procs) { + mem += scoreboard_size; + + for (i = 0; i < scoreboard->nprocs; i++, mem += sizeof(struct fpm_scoreboard_proc_s)) { + scoreboard_proc_p = fpm_scoreboard_proc_acquire(scoreboard, i, FPM_SCOREBOARD_LOCK_HANG); + scoreboard_copy->procs[i] = *scoreboard_proc_p; + fpm_scoreboard_proc_release(scoreboard_proc_p); + } + } + + fpm_scoreboard_release(scoreboard); + + return scoreboard_copy; +} + +void fpm_scoreboard_free_copy(struct fpm_scoreboard_s *scoreboard) +{ + free(scoreboard); +} + struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_acquire(struct fpm_scoreboard_s *scoreboard, int child_index, int nohang) /* {{{ */ { struct fpm_scoreboard_proc_s *proc; diff --git a/sapi/fpm/fpm/fpm_scoreboard.h b/sapi/fpm/fpm/fpm_scoreboard.h index 363bdd260547c..e22d6d933a00a 100644 --- a/sapi/fpm/fpm/fpm_scoreboard.h +++ b/sapi/fpm/fpm/fpm_scoreboard.h @@ -15,6 +15,9 @@ #define FPM_SCOREBOARD_ACTION_SET 0 #define FPM_SCOREBOARD_ACTION_INC 1 +#define FPM_SCOREBOARD_LOCK_HANG 0 +#define FPM_SCOREBOARD_LOCK_NOHANG 1 + struct fpm_scoreboard_proc_s { union { atomic_t lock; @@ -87,6 +90,9 @@ void fpm_scoreboard_child_use(struct fpm_child_s *child, pid_t pid); void fpm_scoreboard_proc_free(struct fpm_child_s *child); int fpm_scoreboard_proc_alloc(struct fpm_child_s *child); +struct fpm_scoreboard_s *fpm_scoreboard_copy(struct fpm_scoreboard_s *scoreboard, int copy_procs); +void fpm_scoreboard_free_copy(struct fpm_scoreboard_s *scoreboard); + #ifdef HAVE_TIMES float fpm_scoreboard_get_tick(); #endif diff --git a/sapi/fpm/fpm/fpm_status.c b/sapi/fpm/fpm/fpm_status.c index 0d74f551b7970..b77c7fb700aa0 100644 --- a/sapi/fpm/fpm/fpm_status.c +++ b/sapi/fpm/fpm/fpm_status.c @@ -136,8 +136,8 @@ int fpm_status_export_to_zval(zval *status) int fpm_status_handle_request(void) /* {{{ */ { - struct fpm_scoreboard_s scoreboard, *scoreboard_p; - struct fpm_scoreboard_proc_s proc; + struct fpm_scoreboard_s *scoreboard_p; + struct fpm_scoreboard_proc_s *proc; char *buffer, *time_format, time_buffer[64]; time_t now_epoch; int full, encode; @@ -170,9 +170,16 @@ int fpm_status_handle_request(void) /* {{{ */ if (fpm_status_uri && !strcmp(fpm_status_uri, SG(request_info).request_uri)) { fpm_request_executing(); + /* full status ? */ + _GET_str = zend_string_init(ZEND_STRL("_GET"), 0); + full = (fpm_php_get_string_from_table(_GET_str, "full") != NULL); + short_syntax = short_post = NULL; + full_separator = full_pre = full_syntax = full_post = NULL; + encode = 0; + scoreboard_p = fpm_scoreboard_get(); - if (scoreboard_p->shared) { - scoreboard_p = scoreboard_p->shared; + if (scoreboard_p) { + scoreboard_p = fpm_scoreboard_copy(scoreboard_p->shared ? scoreboard_p->shared : scoreboard_p, full); } if (!scoreboard_p) { zlog(ZLOG_ERROR, "status: unable to find or access status shared memory"); @@ -184,21 +191,9 @@ int fpm_status_handle_request(void) /* {{{ */ return 1; } - if (!fpm_spinlock(&scoreboard_p->lock, 1)) { - zlog(ZLOG_NOTICE, "[pool %s] status: scoreboard already in used.", scoreboard_p->pool); - SG(sapi_headers).http_response_code = 503; - sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1); - sapi_add_header_ex(ZEND_STRL("Expires: Thu, 01 Jan 1970 00:00:00 GMT"), 1, 1); - sapi_add_header_ex(ZEND_STRL("Cache-Control: no-cache, no-store, must-revalidate, max-age=0"), 1, 1); - PUTS("Server busy. Please try again later."); - return 1; - } - /* copy the scoreboard not to bother other processes */ - scoreboard = *scoreboard_p; - fpm_unlock(scoreboard_p->lock); - - if (scoreboard.idle < 0 || scoreboard.active < 0) { - zlog(ZLOG_ERROR, "[pool %s] invalid status values", scoreboard.pool); + if (scoreboard_p->idle < 0 || scoreboard_p->active < 0) { + fpm_scoreboard_free_copy(scoreboard_p); + zlog(ZLOG_ERROR, "[pool %s] invalid status values", scoreboard_p->pool); SG(sapi_headers).http_response_code = 500; sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1); sapi_add_header_ex(ZEND_STRL("Expires: Thu, 01 Jan 1970 00:00:00 GMT"), 1, 1); @@ -214,16 +209,10 @@ int fpm_status_handle_request(void) /* {{{ */ /* handle HEAD */ if (SG(request_info).headers_only) { + fpm_scoreboard_free_copy(scoreboard_p); return 1; } - /* full status ? */ - _GET_str = zend_string_init("_GET", sizeof("_GET")-1, 0); - full = (fpm_php_get_string_from_table(_GET_str, "full") != NULL); - short_syntax = short_post = NULL; - full_separator = full_pre = full_syntax = full_post = NULL; - encode = 0; - /* HTML */ if (fpm_php_get_string_from_table(_GET_str, "html")) { sapi_add_header_ex(ZEND_STRL("Content-Type: text/html"), 1, 1); @@ -429,23 +418,23 @@ int fpm_status_handle_request(void) /* {{{ */ } } - strftime(time_buffer, sizeof(time_buffer) - 1, time_format, localtime(&scoreboard.start_epoch)); + strftime(time_buffer, sizeof(time_buffer) - 1, time_format, localtime(&scoreboard_p->start_epoch)); now_epoch = time(NULL); spprintf(&buffer, 0, short_syntax, - scoreboard.pool, - PM2STR(scoreboard.pm), + scoreboard_p->pool, + PM2STR(scoreboard_p->pm), time_buffer, - (unsigned long) (now_epoch - scoreboard.start_epoch), - scoreboard.requests, - scoreboard.lq, - scoreboard.lq_max, - scoreboard.lq_len, - scoreboard.idle, - scoreboard.active, - scoreboard.idle + scoreboard.active, - scoreboard.active_max, - scoreboard.max_children_reached, - scoreboard.slow_rq); + (unsigned long) (now_epoch - scoreboard_p->start_epoch), + scoreboard_p->requests, + scoreboard_p->lq, + scoreboard_p->lq_max, + scoreboard_p->lq_len, + scoreboard_p->idle, + scoreboard_p->active, + scoreboard_p->idle + scoreboard_p->active, + scoreboard_p->active_max, + scoreboard_p->max_children_reached, + scoreboard_p->slow_rq); PUTS(buffer); efree(buffer); @@ -475,7 +464,7 @@ int fpm_status_handle_request(void) /* {{{ */ if (!scoreboard_p->procs[i].used) { continue; } - proc = scoreboard_p->procs[i]; + proc = &scoreboard_p->procs[i]; if (first) { first = 0; @@ -487,44 +476,44 @@ int fpm_status_handle_request(void) /* {{{ */ query_string = NULL; tmp_query_string = NULL; - if (proc.query_string[0] != '\0') { + if (proc->query_string[0] != '\0') { if (!encode) { - query_string = proc.query_string; + query_string = proc->query_string; } else { - tmp_query_string = php_escape_html_entities_ex((const unsigned char *) proc.query_string, strlen(proc.query_string), 1, ENT_HTML_IGNORE_ERRORS & ENT_COMPAT, NULL, /* double_encode */ 1, /* quiet */ 0); + tmp_query_string = php_escape_html_entities_ex((const unsigned char *) proc->query_string, strlen(proc->query_string), 1, ENT_HTML_IGNORE_ERRORS & ENT_COMPAT, NULL, /* double_encode */ 1, /* quiet */ 0); query_string = ZSTR_VAL(tmp_query_string); } } /* prevent NaN */ - if (proc.cpu_duration.tv_sec == 0 && proc.cpu_duration.tv_usec == 0) { + if (proc->cpu_duration.tv_sec == 0 && proc->cpu_duration.tv_usec == 0) { cpu = 0.; } else { - cpu = (proc.last_request_cpu.tms_utime + proc.last_request_cpu.tms_stime + proc.last_request_cpu.tms_cutime + proc.last_request_cpu.tms_cstime) / fpm_scoreboard_get_tick() / (proc.cpu_duration.tv_sec + proc.cpu_duration.tv_usec / 1000000.) * 100.; + cpu = (proc->last_request_cpu.tms_utime + proc->last_request_cpu.tms_stime + proc->last_request_cpu.tms_cutime + proc->last_request_cpu.tms_cstime) / fpm_scoreboard_get_tick() / (proc->cpu_duration.tv_sec + proc->cpu_duration.tv_usec / 1000000.) * 100.; } - if (proc.request_stage == FPM_REQUEST_ACCEPTING) { - duration = proc.duration; + if (proc->request_stage == FPM_REQUEST_ACCEPTING) { + duration = proc->duration; } else { - timersub(&now, &proc.accepted, &duration); + timersub(&now, &proc->accepted, &duration); } - strftime(time_buffer, sizeof(time_buffer) - 1, time_format, localtime(&proc.start_epoch)); + strftime(time_buffer, sizeof(time_buffer) - 1, time_format, localtime(&proc->start_epoch)); spprintf(&buffer, 0, full_syntax, - (int) proc.pid, - fpm_request_get_stage_name(proc.request_stage), + (int) proc->pid, + fpm_request_get_stage_name(proc->request_stage), time_buffer, - (unsigned long) (now_epoch - proc.start_epoch), - proc.requests, + (unsigned long) (now_epoch - proc->start_epoch), + proc->requests, duration.tv_sec * 1000000UL + duration.tv_usec, - proc.request_method[0] != '\0' ? proc.request_method : "-", - proc.request_uri[0] != '\0' ? proc.request_uri : "-", + proc->request_method[0] != '\0' ? proc->request_method : "-", + proc->request_uri[0] != '\0' ? proc->request_uri : "-", query_string ? "?" : "", query_string ? query_string : "", - proc.content_length, - proc.auth_user[0] != '\0' ? proc.auth_user : "-", - proc.script_filename[0] != '\0' ? proc.script_filename : "-", - proc.request_stage == FPM_REQUEST_ACCEPTING ? cpu : 0., - proc.request_stage == FPM_REQUEST_ACCEPTING ? proc.memory : 0); + proc->content_length, + proc->auth_user[0] != '\0' ? proc->auth_user : "-", + proc->script_filename[0] != '\0' ? proc->script_filename : "-", + proc->request_stage == FPM_REQUEST_ACCEPTING ? cpu : 0., + proc->request_stage == FPM_REQUEST_ACCEPTING ? proc->memory : 0); PUTS(buffer); efree(buffer); @@ -538,6 +527,7 @@ int fpm_status_handle_request(void) /* {{{ */ } } + fpm_scoreboard_free_copy(scoreboard_p); return 1; } From 82bb169a083bb592291d8e6bd5e2198c00eac07b Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 11 Feb 2022 11:08:19 +0300 Subject: [PATCH 10/55] Tracing JIT: Fixed incorrect deoptimization info Fixes oss-fuzz #44294 --- ext/opcache/tests/jit/reg_alloc_008.phpt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 ext/opcache/tests/jit/reg_alloc_008.phpt diff --git a/ext/opcache/tests/jit/reg_alloc_008.phpt b/ext/opcache/tests/jit/reg_alloc_008.phpt new file mode 100644 index 0000000000000..f71578ab4307c --- /dev/null +++ b/ext/opcache/tests/jit/reg_alloc_008.phpt @@ -0,0 +1,17 @@ +--TEST-- +Register Alloction 008: Incorrect deoptimization code +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +--FILE-- + +--EXPECTF-- +Warning: Undefined variable $y in %sreg_alloc_008.php on line 4 From d0f965d078c449d4c6579a69cd7d2d3c0a9250f0 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 11 Feb 2022 11:10:22 +0300 Subject: [PATCH 11/55] Tracing JIT: Fixed incorrect deoptimization info --- ext/opcache/jit/zend_jit_trace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index 8d75d04d47a2e..223792e2eae92 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -3864,7 +3864,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par } info &= ~MAY_BE_GUARD; ssa->var_info[phi->ssa_var].type = info; - SET_STACK_TYPE(stack, i, concrete_type(info), 1); + SET_STACK_TYPE(stack, phi->var, concrete_type(info), 1); } SET_STACK_REG_EX(stack, phi->var, ival->reg, ZREG_LOAD); if (!zend_jit_load_var(&dasm_state, ssa->var_info[phi->ssa_var].type, ssa->vars[phi->ssa_var].var, ival->reg)) { From 0d6b173532d481fdb90d54685bef72d455352b6a Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 11 Feb 2022 12:05:57 +0300 Subject: [PATCH 12/55] JIT: Fix missed type store Fizes oss-fuzz #44376 --- ext/opcache/jit/zend_jit.c | 3 +++ ext/opcache/tests/jit/reg_alloc_009.phpt | 24 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 ext/opcache/tests/jit/reg_alloc_009.phpt diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index fa7953e20f3f2..bec0146afecbf 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -2732,6 +2732,9 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op op2_def_addr = op2_addr; } op1_info = OP1_INFO(); + if (ra && ssa->vars[ssa_op->op1_use].no_val) { + op1_info |= MAY_BE_UNDEF; // requres type assignment + } if (opline->result_type == IS_UNUSED) { res_addr = 0; res_info = -1; diff --git a/ext/opcache/tests/jit/reg_alloc_009.phpt b/ext/opcache/tests/jit/reg_alloc_009.phpt new file mode 100644 index 0000000000000..dfcbfc086f85f --- /dev/null +++ b/ext/opcache/tests/jit/reg_alloc_009.phpt @@ -0,0 +1,24 @@ +--TEST-- +Register Alloction 009: Missing type store +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +--FILE-- +> - $j++; + } +} +test(); +?> +--EXPECTF-- +Warning: Undefined variable $j in %sreg_alloc_009.php on line 4 + +Fatal error: Uncaught ArithmeticError: Bit shift by negative number in %sreg_alloc_009.php:4 +Stack trace: +#0 %sreg_alloc_009.php(7): test() +#1 {main} + thrown in %sreg_alloc_009.php on line 4 From 7434909dc652feca55da7e29db81d1f4cd09b9ad Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 11 Feb 2022 13:03:36 +0300 Subject: [PATCH 13/55] Fix type inference Fixes oss-fuzz #44407 --- ext/opcache/Optimizer/zend_inference.c | 3 +++ ext/opcache/tests/jit/assign_dim_012.phpt | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 ext/opcache/tests/jit/assign_dim_012.phpt diff --git a/ext/opcache/Optimizer/zend_inference.c b/ext/opcache/Optimizer/zend_inference.c index d3a483b889756..db8112d29445b 100644 --- a/ext/opcache/Optimizer/zend_inference.c +++ b/ext/opcache/Optimizer/zend_inference.c @@ -2625,6 +2625,9 @@ static zend_always_inline int _zend_update_type_info( if (t1 & MAY_BE_STRING) { tmp |= MAY_BE_STRING | MAY_BE_NULL; } + if (t1 & MAY_BE_OBJECT) { + tmp |= (MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF); + } if (t1 & (MAY_BE_ARRAY|MAY_BE_FALSE|MAY_BE_NULL|MAY_BE_UNDEF)) { tmp |= (OP1_DATA_INFO() & (MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF)); diff --git a/ext/opcache/tests/jit/assign_dim_012.phpt b/ext/opcache/tests/jit/assign_dim_012.phpt new file mode 100644 index 0000000000000..0753d93618213 --- /dev/null +++ b/ext/opcache/tests/jit/assign_dim_012.phpt @@ -0,0 +1,18 @@ +--TEST-- +JIT ASSIGN_DIM: 012 +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +--FILE-- + +DONE +--EXPECTF-- +DONE From 912608d89bbf9ea1c564052855b8d484aad10319 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 11 Feb 2022 13:44:49 +0300 Subject: [PATCH 14/55] JIT: Fixed register clobbering during overflow handling Fixes oss-fuzz #44535 --- ext/opcache/jit/zend_jit_x86.dasc | 12 +++++------ ext/opcache/tests/jit/assign_dim_op_007.phpt | 21 ++++++++++++++++++++ 2 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 ext/opcache/tests/jit/assign_dim_op_007.phpt diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index e15047ef5d36a..462ba36168485 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -4457,11 +4457,11 @@ static int zend_jit_math_long_long(dasm_State **Dst, (Z_MODE(op2_addr) == IS_CONST_ZVAL && Z_LVAL_P(Z_ZV(op2_addr)) == 1))) { if (opcode == ZEND_ADD) { |.if X64 - | mov64 rax, 0x43e0000000000000 + | mov64 Ra(tmp_reg), 0x43e0000000000000 if (Z_MODE(res_addr) == IS_REG) { - | movd xmm(Z_REG(res_addr)-ZREG_XMM0), rax + | movd xmm(Z_REG(res_addr)-ZREG_XMM0), Ra(tmp_reg) } else { - | SET_ZVAL_LVAL res_addr, rax + | SET_ZVAL_LVAL res_addr, Ra(tmp_reg) } |.else | SET_ZVAL_LVAL res_addr, 0 @@ -4470,11 +4470,11 @@ static int zend_jit_math_long_long(dasm_State **Dst, break; } else if (opcode == ZEND_SUB) { |.if X64 - | mov64 rax, 0xc3e0000000000000 + | mov64 Ra(tmp_reg), 0xc3e0000000000000 if (Z_MODE(res_addr) == IS_REG) { - | movd xmm(Z_REG(res_addr)-ZREG_XMM0), rax + | movd xmm(Z_REG(res_addr)-ZREG_XMM0), Ra(tmp_reg) } else { - | SET_ZVAL_LVAL res_addr, rax + | SET_ZVAL_LVAL res_addr, Ra(tmp_reg) } |.else | SET_ZVAL_LVAL res_addr, 0x00200000 diff --git a/ext/opcache/tests/jit/assign_dim_op_007.phpt b/ext/opcache/tests/jit/assign_dim_op_007.phpt new file mode 100644 index 0000000000000..e8708a1255131 --- /dev/null +++ b/ext/opcache/tests/jit/assign_dim_op_007.phpt @@ -0,0 +1,21 @@ +--TEST-- +JIT ASSIGN_DIM_OP: overflow +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +--FILE-- +member = 9223372036854775807; + $this->member += 1; + } +} +new test(); +?> +DONE +--EXPECT-- +DONE From 73fed0f0285f0b225f10884d19eb26d3cfbd5084 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 11 Feb 2022 15:16:08 +0300 Subject: [PATCH 15/55] Fix emory leak Fixes oss-fuzz #44408 --- Zend/tests/closure_063.phpt | 12 ++++++++++++ Zend/zend_closures.c | 3 ++- 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 Zend/tests/closure_063.phpt diff --git a/Zend/tests/closure_063.phpt b/Zend/tests/closure_063.phpt new file mode 100644 index 0000000000000..b53f370eb4bfc --- /dev/null +++ b/Zend/tests/closure_063.phpt @@ -0,0 +1,12 @@ +--TEST-- +Closure::bindTo leaks with "fake" closure +--FILE-- +bindTo(new stdClass); +?> +DONE +--EXPECT-- +DONE \ No newline at end of file diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index a5ae8cde359e2..b5c0b47553248 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -770,7 +770,8 @@ static void zend_create_closure_ex(zval *res, zend_function *func, zend_class_en ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_entry *scope, zend_class_entry *called_scope, zval *this_ptr) { - zend_create_closure_ex(res, func, scope, called_scope, this_ptr, /* is_fake */ false); + zend_create_closure_ex(res, func, scope, called_scope, this_ptr, + /* is_fake */ (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) != 0); } ZEND_API void zend_create_fake_closure(zval *res, zend_function *func, zend_class_entry *scope, zend_class_entry *called_scope, zval *this_ptr) /* {{{ */ From 52ae6417ca3e62eff796bf3e3b5662fe6a9ee085 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 11 Feb 2022 15:33:31 +0300 Subject: [PATCH 16/55] Fixed GH-8044 (var_export/debug_zval_dump HT_ASSERT_RC1 debug failure for SplFixedArray) --- ext/spl/spl_fixedarray.c | 6 ++++++ ext/spl/tests/fixedarray_022.phpt | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 ext/spl/tests/fixedarray_022.phpt diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index 693d3296acaec..ec53935ac9d2e 100644 --- a/ext/spl/spl_fixedarray.c +++ b/ext/spl/spl_fixedarray.c @@ -207,6 +207,12 @@ static HashTable* spl_fixedarray_object_get_properties(zend_object *obj) if (!spl_fixedarray_empty(&intern->array)) { zend_long j = zend_hash_num_elements(ht); + if (GC_REFCOUNT(ht) > 1) { + intern->std.properties = zend_array_dup(ht); + if (!(GC_FLAGS(ht) & GC_IMMUTABLE)) { + GC_DELREF(ht); + } + } for (zend_long i = 0; i < intern->array.size; i++) { zend_hash_index_update(ht, i, &intern->array.elements[i]); Z_TRY_ADDREF(intern->array.elements[i]); diff --git a/ext/spl/tests/fixedarray_022.phpt b/ext/spl/tests/fixedarray_022.phpt new file mode 100644 index 0000000000000..c1cff1a926582 --- /dev/null +++ b/ext/spl/tests/fixedarray_022.phpt @@ -0,0 +1,20 @@ +--TEST-- +SPL: FixedArray: Bug GH-8044 (var_export/debug_zval_dump HT_ASSERT_RC1 debug failure for SplFixedArray) +--FILE-- + +--EXPECTF-- +Warning: var_export does not handle circular references in %s on line 5 +SplFixedArray::__set_state(array( + 0 => NULL, +)) +object(SplFixedArray)#2 (1) refcount(4){ + [0]=> + *RECURSION* +} From dce5e561a63fc970de722636ad8c09e9b079e8ae Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 31 Jan 2022 15:43:24 +0100 Subject: [PATCH 17/55] Fix #81708: UAF due to php_filter_float() failing for ints We must only release the zval, if we actually assign a new zval. --- ext/filter/logical_filters.c | 2 +- ext/filter/tests/bug81708.phpt | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 ext/filter/tests/bug81708.phpt diff --git a/ext/filter/logical_filters.c b/ext/filter/logical_filters.c index fa6ae65ac5868..e5e87c01568a4 100644 --- a/ext/filter/logical_filters.c +++ b/ext/filter/logical_filters.c @@ -435,10 +435,10 @@ void php_filter_float(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ switch (is_numeric_string(num, p - num, &lval, &dval, 0)) { case IS_LONG: - zval_ptr_dtor(value); if ((min_range_set && (lval < min_range)) || (max_range_set && (lval > max_range))) { goto error; } + zval_ptr_dtor(value); ZVAL_DOUBLE(value, (double)lval); break; case IS_DOUBLE: diff --git a/ext/filter/tests/bug81708.phpt b/ext/filter/tests/bug81708.phpt new file mode 100644 index 0000000000000..d0036af136824 --- /dev/null +++ b/ext/filter/tests/bug81708.phpt @@ -0,0 +1,20 @@ +--TEST-- +Bug #81708 (UAF due to php_filter_float() failing for ints) +--SKIPIF-- + +--INI-- +opcache.enable_cli=0 +--FILE-- + ['min_range' => -1, 'max_range' => 1]] +); +var_dump($input); +?> +--EXPECT-- +string(3) "+11" From 82f1bf1b6bc3a43aba62214870e6d0931e93a6d9 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 31 Jan 2022 15:43:24 +0100 Subject: [PATCH 18/55] Fix #81708: UAF due to php_filter_float() failing for ints We must only release the zval, if we actually assign a new zval. --- ext/filter/logical_filters.c | 2 +- ext/filter/tests/bug81708.phpt | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 ext/filter/tests/bug81708.phpt diff --git a/ext/filter/logical_filters.c b/ext/filter/logical_filters.c index 1bf7c00d13c68..95f7a99e34b14 100644 --- a/ext/filter/logical_filters.c +++ b/ext/filter/logical_filters.c @@ -436,10 +436,10 @@ void php_filter_float(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ switch (is_numeric_string(num, p - num, &lval, &dval, 0)) { case IS_LONG: - zval_ptr_dtor(value); if ((min_range_set && (lval < min_range)) || (max_range_set && (lval > max_range))) { goto error; } + zval_ptr_dtor(value); ZVAL_DOUBLE(value, (double)lval); break; case IS_DOUBLE: diff --git a/ext/filter/tests/bug81708.phpt b/ext/filter/tests/bug81708.phpt new file mode 100644 index 0000000000000..d0036af136824 --- /dev/null +++ b/ext/filter/tests/bug81708.phpt @@ -0,0 +1,20 @@ +--TEST-- +Bug #81708 (UAF due to php_filter_float() failing for ints) +--SKIPIF-- + +--INI-- +opcache.enable_cli=0 +--FILE-- + ['min_range' => -1, 'max_range' => 1]] +); +var_dump($input); +?> +--EXPECT-- +string(3) "+11" From 93a8d5cd1721ccb5c7ae78e227d36b580e03efc1 Mon Sep 17 00:00:00 2001 From: Kamil Tekiela Date: Tue, 8 Feb 2022 12:08:26 +0000 Subject: [PATCH 19/55] Fix bug GH-8058 - mysqlnd segfault when prepare fails Closes GH-8061 --- NEWS | 3 + ext/mysqli/tests/gh8058.phpt | 39 ++++++++++++ .../tests/mysqli_stmt_affected_rows.phpt | 11 +--- ext/mysqlnd/mysqlnd_ps.c | 60 +++++-------------- 4 files changed, 59 insertions(+), 54 deletions(-) create mode 100644 ext/mysqli/tests/gh8058.phpt diff --git a/NEWS b/NEWS index 3e1d12d0fc9b0..91fce7ad7342a 100644 --- a/NEWS +++ b/NEWS @@ -16,6 +16,9 @@ PHP NEWS . Fixed bug GH-7953 (ob_clean() only does not set Content-Encoding). (cmb) . Fixed bug GH-7980 (Unexpected result for iconv_mime_decode). (cmb) +- MySQLnd: + . Fixed bug GH-8058 (NULL pointer dereference in mysqlnd package). (Kamil Tekiela) + - Zlib: . Fixed bug GH-7953 (ob_clean() only does not set Content-Encoding). (cmb) diff --git a/ext/mysqli/tests/gh8058.phpt b/ext/mysqli/tests/gh8058.phpt new file mode 100644 index 0000000000000..8f47e372e73e3 --- /dev/null +++ b/ext/mysqli/tests/gh8058.phpt @@ -0,0 +1,39 @@ +--TEST-- +GH-8058 (NULL pointer dereference in mysqlnd package (#81706)) +--SKIPIF-- + +--FILE-- +prepare("select 1,2,3"); +$stmt->bind_result($a,$a,$a); +$stmt->prepare(""); +$stmt->prepare("select ".str_repeat("'A',", 0x1201)."1"); +unset($stmt); // trigger dtor + +// There should be no memory leak +$stmt = $mysqli->prepare("select 1,2,3"); +$stmt->bind_result($a,$a,$a); +$stmt->prepare(""); +$stmt->prepare("select 1"); +unset($stmt); // trigger dtor + +mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); +$stmt = $mysqli->prepare("select 1,2,3"); +try { + // We expect an exception to be thrown + $stmt->prepare(""); +} catch (mysqli_sql_exception $e) { + var_dump($e->getMessage()); +} +?> +--EXPECT-- +string(15) "Query was empty" diff --git a/ext/mysqli/tests/mysqli_stmt_affected_rows.phpt b/ext/mysqli/tests/mysqli_stmt_affected_rows.phpt index de4f73bc18ce6..ed682b7cca54b 100644 --- a/ext/mysqli/tests/mysqli_stmt_affected_rows.phpt +++ b/ext/mysqli/tests/mysqli_stmt_affected_rows.phpt @@ -196,18 +196,13 @@ require_once('skipifconnectfailure.inc'); /* stmt_affected_rows is not really meant for SELECT! */ if (mysqli_stmt_prepare($stmt, 'SELECT unknown_column FROM this_table_does_not_exist') || mysqli_stmt_execute($stmt)) - printf("[041] The invalid SELECT statement is issued on purpose\n"); + printf("[041] Expecting SELECT statement to fail on purpose\n"); if (-1 !== ($tmp = mysqli_stmt_affected_rows($stmt))) printf("[042] Expecting int/-1, got %s/%s\n", gettype($tmp), $tmp); - if ($IS_MYSQLND) { - if (false !== ($tmp = mysqli_stmt_store_result($stmt))) - printf("[043] Expecting boolean/false, got %s\%s\n", gettype($tmp), $tmp); - } else { - if (true !== ($tmp = mysqli_stmt_store_result($stmt))) - printf("[043] Libmysql does not care if the previous statement was bogus, expecting boolean/true, got %s\%s\n", gettype($tmp), $tmp); - } + if (true !== ($tmp = mysqli_stmt_store_result($stmt))) + printf("[043] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp); if (0 !== ($tmp = mysqli_stmt_num_rows($stmt))) printf("[044] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp); diff --git a/ext/mysqlnd/mysqlnd_ps.c b/ext/mysqlnd/mysqlnd_ps.c index f3dee49d88f33..1eac55a03fc89 100644 --- a/ext/mysqlnd/mysqlnd_ps.c +++ b/ext/mysqlnd/mysqlnd_ps.c @@ -391,12 +391,10 @@ mysqlnd_stmt_prepare_read_eof(MYSQLND_STMT * s) /* {{{ mysqlnd_stmt::prepare */ static enum_func_status -MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * const s, const char * const query, const size_t query_len) +MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * s, const char * const query, const size_t query_len) { MYSQLND_STMT_DATA * stmt = s? s->data : NULL; MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL; - MYSQLND_STMT * s_to_prepare = s; - MYSQLND_STMT_DATA * stmt_to_prepare = stmt; DBG_ENTER("mysqlnd_stmt::prepare"); if (!stmt || !conn) { @@ -412,25 +410,15 @@ MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * const s, const char * const SET_EMPTY_ERROR(conn->error_info); if (stmt->state > MYSQLND_STMT_INITTED) { - /* See if we have to clean the wire */ - if (stmt->state == MYSQLND_STMT_WAITING_USE_OR_STORE) { - /* Do implicit use_result and then flush the result */ - stmt->default_rset_handler = s->m->use_result; - stmt->default_rset_handler(s); - } - /* No 'else' here please :) */ - if (stmt->state > MYSQLND_STMT_WAITING_USE_OR_STORE && stmt->result) { - stmt->result->m.skip_result(stmt->result); - } /* - Create a new test statement, which we will prepare, but if anything - fails, we will scrap it. + Create a new prepared statement and destroy the previous one. */ - s_to_prepare = conn->m->stmt_init(conn); - if (!s_to_prepare) { + s->m->dtor(s, TRUE); + s = conn->m->stmt_init(conn); + if (!s) { goto fail; } - stmt_to_prepare = s_to_prepare->data; + stmt = s->data; } { @@ -444,13 +432,13 @@ MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * const s, const char * const } } - if (FAIL == mysqlnd_stmt_read_prepare_response(s_to_prepare)) { + if (FAIL == mysqlnd_stmt_read_prepare_response(s)) { goto fail; } - if (stmt_to_prepare->param_count) { - if (FAIL == mysqlnd_stmt_skip_metadata(s_to_prepare) || - FAIL == mysqlnd_stmt_prepare_read_eof(s_to_prepare)) + if (stmt->param_count) { + if (FAIL == mysqlnd_stmt_skip_metadata(s) || + FAIL == mysqlnd_stmt_prepare_read_eof(s)) { goto fail; } @@ -461,51 +449,31 @@ MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * const s, const char * const Beware that SHOW statements bypass the PS framework and thus they send no metadata at prepare. */ - if (stmt_to_prepare->field_count) { - MYSQLND_RES * result = conn->m->result_init(stmt_to_prepare->field_count); + if (stmt->field_count) { + MYSQLND_RES * result = conn->m->result_init(stmt->field_count); if (!result) { SET_OOM_ERROR(conn->error_info); goto fail; } /* Allocate the result now as it is needed for the reading of metadata */ - stmt_to_prepare->result = result; + stmt->result = result; result->conn = conn->m->get_reference(conn); result->type = MYSQLND_RES_PS_BUF; if (FAIL == result->m.read_result_metadata(result, conn) || - FAIL == mysqlnd_stmt_prepare_read_eof(s_to_prepare)) + FAIL == mysqlnd_stmt_prepare_read_eof(s)) { goto fail; } } - if (stmt_to_prepare != stmt) { - /* swap */ - size_t real_size = sizeof(MYSQLND_STMT) + mysqlnd_plugin_count() * sizeof(void *); - char * tmp_swap = mnd_malloc(real_size); - memcpy(tmp_swap, s, real_size); - memcpy(s, s_to_prepare, real_size); - memcpy(s_to_prepare, tmp_swap, real_size); - mnd_free(tmp_swap); - { - MYSQLND_STMT_DATA * tmp_swap_data = stmt_to_prepare; - stmt_to_prepare = stmt; - stmt = tmp_swap_data; - } - s_to_prepare->m->dtor(s_to_prepare, TRUE); - } stmt->state = MYSQLND_STMT_PREPARED; DBG_INF("PASS"); DBG_RETURN(PASS); fail: - if (stmt_to_prepare != stmt && s_to_prepare) { - s_to_prepare->m->dtor(s_to_prepare, TRUE); - } - stmt->state = MYSQLND_STMT_INITTED; - DBG_INF("FAIL"); DBG_RETURN(FAIL); } From d13ceb74fa48a12ff29ca3d291d568a0f198249b Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Mon, 14 Feb 2022 16:23:06 +0000 Subject: [PATCH 20/55] Add fix to NEWS --- NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS b/NEWS index b4d1e4b0378ec..076b2cd2abf92 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 7.4.28 +- Filter: + . Fix #81708: UAF due to php_filter_float() failing for ints + 16 Dec 2021, PHP 7.4.27 From 0fab520ded1babcdf5c54fb4b4d2642de2c7cbfe Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Mon, 14 Feb 2022 17:58:26 -0500 Subject: [PATCH 21/55] Fix zend_register_internal_class_ex alias generation (#8091) This wouldn't work for creating aliases in a namespace. It would create the class alias "MyNS_ClassName" instead of "MyNS\\ClassName" --- build/gen_stub.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 486ff679499fc..348cc9e82d277 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -1748,7 +1748,7 @@ function (Name $item) { } if ($this->alias) { - $code .= "\tzend_register_class_alias(\"" . str_replace("\\", "_", $this->alias) . "\", class_entry);\n"; + $code .= "\tzend_register_class_alias(\"" . str_replace("\\", "\\\\", $this->alias) . "\", class_entry);\n"; } foreach ($this->enumCaseInfos as $enumCase) { From 325bcf9f1d0d7c879f441cbbe9a8a28e30f4ea86 Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Tue, 15 Feb 2022 13:27:37 +0000 Subject: [PATCH 22/55] Prepare for 7.4.29 --- NEWS | 5 ++++- configure.ac | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 076b2cd2abf92..fa117f5185fa4 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 7.4.28 +?? ??? ????, PHP 7.4.29 + + +17 Feb 2022, PHP 7.4.28 - Filter: . Fix #81708: UAF due to php_filter_float() failing for ints diff --git a/configure.ac b/configure.ac index 7155ff432f400..6f829c0e7820a 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],[7.4.27-dev],[https://bugs.php.net],[php],[https://www.php.net]) +AC_INIT([PHP],[7.4.29-dev],[https://bugs.php.net],[php],[https://www.php.net]) AC_CONFIG_SRCDIR([main/php_version.h]) AC_CONFIG_AUX_DIR([build]) AC_PRESERVE_HELP_ORDER From e98a7a68b7b8b5b7974134f8046777bd72f141e4 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 15 Feb 2022 10:15:28 +0100 Subject: [PATCH 23/55] Fix bugtracker URL The php-src bugtracker is now on Github. Closes GH-8102. --- sapi/fpm/fpm/fpm_children.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sapi/fpm/fpm/fpm_children.c b/sapi/fpm/fpm/fpm_children.c index a24e06fc483be..0aab23043a943 100644 --- a/sapi/fpm/fpm/fpm_children.c +++ b/sapi/fpm/fpm/fpm_children.c @@ -299,7 +299,7 @@ void fpm_children_bury() /* {{{ */ } } } else { - zlog(ZLOG_ALERT, "oops, unknown child (%d) exited %s. Please open a bug report (https://bugs.php.net).", pid, buf); + zlog(ZLOG_ALERT, "oops, unknown child (%d) exited %s. Please open a bug report (https://github.com/php/php-src/issues).", pid, buf); } } } From bfe9531dc1b8ad235108d4f310f57df0c75d6bb7 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 16 Feb 2022 19:01:44 +0100 Subject: [PATCH 24/55] Initialize int_codepoint in parse_code_point_param() This is being passed to convert_cp(), and passing an uninitialized value to a function is undefined behavior. Clang 14 makes use of noundef facts aggressively and miscompiles this code if not initialized. --- ext/intl/uchar/uchar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/intl/uchar/uchar.c b/ext/intl/uchar/uchar.c index 0f44b454b4499..58f9615de7050 100644 --- a/ext/intl/uchar/uchar.c +++ b/ext/intl/uchar/uchar.c @@ -38,7 +38,7 @@ static inline int convert_cp(UChar32* pcp, zend_string *string_codepoint, zend_l static zend_never_inline int parse_code_point_param(INTERNAL_FUNCTION_PARAMETERS, UChar32 *cp) { zend_string *string_codepoint; - zend_long int_codepoint; + zend_long int_codepoint = 0; ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_STR_OR_LONG(string_codepoint, int_codepoint) ZEND_PARSE_PARAMETERS_END_EX(return FAILURE); From 8f5480e7ebbb94c46baa4ca8c7d4826f9ae614af Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 17 Feb 2022 19:16:15 +0300 Subject: [PATCH 25/55] Release lock and protect SHM before replaying warnings --- ext/opcache/ZendAccelerator.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 6883979e7d131..c195ad7d2cbcc 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -2195,6 +2195,9 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type) zend_hash_index_del(EG(zend_constants), new_const_num); } } + persistent_script->dynamic_members.last_used = ZCG(request_time); + SHM_PROTECT(); + HANDLE_UNBLOCK_INTERRUPTIONS(); } else { #if !ZEND_WIN32 @@ -2231,16 +2234,16 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type) } } } + + persistent_script->dynamic_members.last_used = ZCG(request_time); + SHM_PROTECT(); + HANDLE_UNBLOCK_INTERRUPTIONS(); + replay_warnings(persistent_script); zend_file_handle_dtor(file_handle); from_shared_memory = 1; } - persistent_script->dynamic_members.last_used = ZCG(request_time); - - SHM_PROTECT(); - HANDLE_UNBLOCK_INTERRUPTIONS(); - /* Fetch jit auto globals used in the script before execution */ if (persistent_script->ping_auto_globals_mask) { zend_accel_set_auto_globals(persistent_script->ping_auto_globals_mask); From 7e8257fbd29193e2087cb90ea74afa3ec4cd7c64 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 18 Feb 2022 11:35:43 +0300 Subject: [PATCH 26/55] Disable ASSIGN optimization for values inferred for fatal errors. --- Zend/Optimizer/dfa_pass.c | 2 ++ ext/opcache/tests/jit/assign_051.phpt | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 ext/opcache/tests/jit/assign_051.phpt diff --git a/Zend/Optimizer/dfa_pass.c b/Zend/Optimizer/dfa_pass.c index d0b52fbfcd1bb..5f7d027a73bf6 100644 --- a/Zend/Optimizer/dfa_pass.c +++ b/Zend/Optimizer/dfa_pass.c @@ -1356,6 +1356,7 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx if (src_var >= 0 && !(ssa->var_info[src_var].type & MAY_BE_REF) + && (ssa->var_info[src_var].type & (MAY_BE_UNDEF|MAY_BE_ANY)) && ssa->vars[src_var].definition >= 0 && ssa->ops[ssa->vars[src_var].definition].result_def == src_var && ssa->ops[ssa->vars[src_var].definition].result_use < 0 @@ -1513,6 +1514,7 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx if ((opline->op2_type & (IS_TMP_VAR|IS_VAR)) && src_var >= 0 && !(ssa->var_info[src_var].type & MAY_BE_REF) + && (ssa->var_info[src_var].type & (MAY_BE_UNDEF|MAY_BE_ANY)) && ssa->vars[src_var].definition >= 0 && ssa->ops[ssa->vars[src_var].definition].result_def == src_var && ssa->ops[ssa->vars[src_var].definition].result_use < 0 diff --git a/ext/opcache/tests/jit/assign_051.phpt b/ext/opcache/tests/jit/assign_051.phpt new file mode 100644 index 0000000000000..88264161d4af5 --- /dev/null +++ b/ext/opcache/tests/jit/assign_051.phpt @@ -0,0 +1,23 @@ +--TEST-- +JIT ASSIGN: incorrect assignment optimization +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +opcache.protect_memory=1 +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught Error: Undefined constant "y" in %sassign_051.php:3 +Stack trace: +#0 %sassign_051.php(7): foo(0) +#1 {main} + thrown in %sassign_051.php on line 3 From 84a638a346f918e1ed6afc23f8ea1b7b7b90df1b Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 18 Feb 2022 12:20:40 +0300 Subject: [PATCH 27/55] Fix memory leak Fixes oss-fuzz #44685 --- .../resume_running_generator_error_002.phpt | 17 +++++++++++++++++ Zend/zend_generators.c | 1 + 2 files changed, 18 insertions(+) create mode 100644 Zend/tests/generators/errors/resume_running_generator_error_002.phpt diff --git a/Zend/tests/generators/errors/resume_running_generator_error_002.phpt b/Zend/tests/generators/errors/resume_running_generator_error_002.phpt new file mode 100644 index 0000000000000..e71e32a886dcc --- /dev/null +++ b/Zend/tests/generators/errors/resume_running_generator_error_002.phpt @@ -0,0 +1,17 @@ +--TEST-- +Memory leak when resume an already running generator +--FILE-- +send($g); +} +$gen = gen(); +try { + $gen->send($gen); +} catch (Throwable $e) { + echo $e->getMessage() . "\n"; +} +?> +--EXPECT-- +Cannot resume an already running generator diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 68c1865c0002e..2e6e22effab9d 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -924,6 +924,7 @@ ZEND_METHOD(Generator, send) root = zend_generator_get_current(generator); /* Put sent value in the target VAR slot, if it is used */ if (root->send_target) { + zval_ptr_dtor(root->send_target); ZVAL_COPY(root->send_target, value); } From 3198b8787bdbe08a893faf1164c48b9bd0f86562 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 18 Feb 2022 17:15:07 +0300 Subject: [PATCH 28/55] JIT: Fix register allocation Fixes oss-fuzz #44689 --- ext/opcache/jit/zend_jit.c | 8 ++++++-- ext/opcache/tests/jit/reg_alloc_010.phpt | 24 ++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 ext/opcache/tests/jit/reg_alloc_010.phpt diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index bec0146afecbf..920020fb2d01b 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -145,8 +145,8 @@ static zend_bool zend_ssa_is_last_use(const zend_op_array *op_array, const zend_ } while (phi); } - next_use = zend_ssa_next_use(ssa->ops, var, use); - if (next_use < 0) { + if (ssa->cfg.blocks[ssa->cfg.map[use]].loop_header > 0 + || (ssa->cfg.blocks[ssa->cfg.map[use]].flags & ZEND_BB_LOOP_HEADER)) { int b = ssa->cfg.map[use]; int prev_use = ssa->vars[var].use_chain; @@ -158,6 +158,10 @@ static zend_bool zend_ssa_is_last_use(const zend_op_array *op_array, const zend_ } prev_use = zend_ssa_next_use(ssa->ops, var, prev_use); } + } + + next_use = zend_ssa_next_use(ssa->ops, var, use); + if (next_use < 0) { return 1; } else if (zend_ssa_is_no_val_use(op_array->opcodes + next_use, ssa->ops + next_use, var)) { return 1; diff --git a/ext/opcache/tests/jit/reg_alloc_010.phpt b/ext/opcache/tests/jit/reg_alloc_010.phpt new file mode 100644 index 0000000000000..d14b107295346 --- /dev/null +++ b/ext/opcache/tests/jit/reg_alloc_010.phpt @@ -0,0 +1,24 @@ +--TEST-- +Register Alloction 010: Missed store +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +--FILE-- + +DONE +--EXPECTF-- +Warning: Undefined variable $cnt in %sreg_alloc_010.php on line 3 + +Warning: Undefined variable $cnt in %sreg_alloc_010.php on line 3 +DONE \ No newline at end of file From 19063a84f0e815b3efb65d8e5349247ecb291e17 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 17 Feb 2022 14:48:18 +0100 Subject: [PATCH 29/55] Fix null static_variable_ptr for uncalled fake closures Closes GH-8083 Closes GH-8109 --- NEWS | 2 ++ Zend/tests/gh8083.phpt | 22 ++++++++++++++++++++++ Zend/zend_closures.c | 7 +++++++ 3 files changed, 31 insertions(+) create mode 100644 Zend/tests/gh8083.phpt diff --git a/NEWS b/NEWS index d57dd9c37e884..cea996c4ebdf6 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,8 @@ PHP NEWS - Core: . Fixed Haiku ZTS build. (David Carlier) . Fixed bug GH-8059 arginfo not regenerated for extension. (Remi) + . Fixed bug GH-8083 Segfault when dumping uncalled fake closure with static + variables. (ilutov) - GD: . Fixed libpng warning when loading interlaced images. (Brett) diff --git a/Zend/tests/gh8083.phpt b/Zend/tests/gh8083.phpt new file mode 100644 index 0000000000000..a98de47cbf375 --- /dev/null +++ b/Zend/tests/gh8083.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-8083 (var_dump() on closure with static variable segfaults) +--FILE-- + +--EXPECT-- +object(Closure)#1 (1) { + ["static"]=> + array(1) { + ["i"]=> + NULL + } +} diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index b5c0b47553248..0dab5537a3752 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -697,6 +697,13 @@ static void zend_create_closure_ex(zval *res, zend_function *func, zend_class_en } ZEND_MAP_PTR_INIT(closure->func.op_array.static_variables_ptr, &closure->func.op_array.static_variables); + } else if (func->op_array.static_variables) { + HashTable *ht = ZEND_MAP_PTR_GET(func->op_array.static_variables_ptr); + + if (!ht) { + ht = zend_array_dup(func->op_array.static_variables); + ZEND_MAP_PTR_SET(closure->func.op_array.static_variables_ptr, ht); + } } /* Runtime cache is scope-dependent, so we cannot reuse it if the scope changed */ From fb70460d8e7593e32abdaaf8ae8849345d49c8fd Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Fri, 18 Feb 2022 13:21:22 +0100 Subject: [PATCH 30/55] Fix GH-7958: Nested CallbackFilterIterator is leaking memory We implement `zend_object_iterator_funcs.get_gc` for user iterators to avoid the memory leak. Closes GH-8107. --- NEWS | 1 + Zend/tests/gh7958.phpt | 43 ++++++++++++++++++++++++++++++++++++++++++ Zend/zend_interfaces.c | 10 +++++++++- Zend/zend_interfaces.h | 1 + 4 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 Zend/tests/gh7958.phpt diff --git a/NEWS b/NEWS index cea996c4ebdf6..e25f3378ee165 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,7 @@ PHP NEWS . Fixed bug GH-8059 arginfo not regenerated for extension. (Remi) . Fixed bug GH-8083 Segfault when dumping uncalled fake closure with static variables. (ilutov) + . Fixed bug GH-7958 (Nested CallbackFilterIterator is leaking memory). (cmb) - GD: . Fixed libpng warning when loading interlaced images. (Brett) diff --git a/Zend/tests/gh7958.phpt b/Zend/tests/gh7958.phpt new file mode 100644 index 0000000000000..d9f3b8940a4a4 --- /dev/null +++ b/Zend/tests/gh7958.phpt @@ -0,0 +1,43 @@ +--TEST-- +GH-7958 (Nested CallbackFilterIterator is leaking memory) +--FILE-- +iterator = new ArrayIterator($data); + echo '-- c ' . spl_object_id($this) . "\n"; + } + + public function __destruct() + { + echo '-- d ' . spl_object_id($this) . "\n"; + } + + public function filter() + { + $this->iterator = new \CallbackFilterIterator($this->iterator, fn() => true); + $this->iterator->rewind(); + } +} + +$action = new Action(['a', 'b']); +$action->filter(); +$action->filter(); +print_r(iterator_to_array($action->iterator)); +$action = null; +gc_collect_cycles(); +echo "==DONE==\n"; +?> +--EXPECT-- +-- c 1 +Array +( + [0] => a + [1] => b +) +-- d 1 +==DONE== diff --git a/Zend/zend_interfaces.c b/Zend/zend_interfaces.c index 54a2d61c38c29..b032d1d4e0b4c 100644 --- a/Zend/zend_interfaces.c +++ b/Zend/zend_interfaces.c @@ -182,6 +182,14 @@ ZEND_API void zend_user_it_rewind(zend_object_iterator *_iter) } /* }}} */ +ZEND_API HashTable *zend_user_it_get_gc(zend_object_iterator *_iter, zval **table, int *n) +{ + zend_user_iterator *iter = (zend_user_iterator*)_iter; + *table = &iter->it.data; + *n = 1; + return NULL; +} + static const zend_object_iterator_funcs zend_interface_iterator_funcs_iterator = { zend_user_it_dtor, zend_user_it_valid, @@ -190,7 +198,7 @@ static const zend_object_iterator_funcs zend_interface_iterator_funcs_iterator = zend_user_it_move_forward, zend_user_it_rewind, zend_user_it_invalidate_current, - NULL, /* get_gc */ + zend_user_it_get_gc, }; /* {{{ zend_user_it_get_iterator */ diff --git a/Zend/zend_interfaces.h b/Zend/zend_interfaces.h index 2799e2c438154..a8351ee9a7823 100644 --- a/Zend/zend_interfaces.h +++ b/Zend/zend_interfaces.h @@ -55,6 +55,7 @@ ZEND_API void zend_user_it_get_current_key(zend_object_iterator *_iter, zval *ke ZEND_API zval *zend_user_it_get_current_data(zend_object_iterator *_iter); ZEND_API void zend_user_it_move_forward(zend_object_iterator *_iter); ZEND_API void zend_user_it_invalidate_current(zend_object_iterator *_iter); +ZEND_API HashTable *zend_user_it_get_gc(zend_object_iterator *_iter, zval **table, int *n); ZEND_API void zend_user_it_new_iterator(zend_class_entry *ce, zval *object, zval *iterator); ZEND_API zend_object_iterator *zend_user_it_get_new_iterator(zend_class_entry *ce, zval *object, int by_ref); From ef80dcb80b9fd742f43844ec07588fc25896c507 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 21 Feb 2022 16:27:53 +0100 Subject: [PATCH 31/55] Fix GH-8074: Wrong type inference of range() result If either the first or second operand of `range()` may be a string, we must not exclude the possibility that the result may be an array of longs. Closes GH-8131. --- NEWS | 3 +++ ext/opcache/Optimizer/zend_func_info.c | 2 +- ext/opcache/tests/opt/gh8074.phpt | 17 +++++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 ext/opcache/tests/opt/gh8074.phpt diff --git a/NEWS b/NEWS index 91fce7ad7342a..022cd11a62495 100644 --- a/NEWS +++ b/NEWS @@ -19,6 +19,9 @@ PHP NEWS - MySQLnd: . Fixed bug GH-8058 (NULL pointer dereference in mysqlnd package). (Kamil Tekiela) +- OPcache: + . Fixed bug GH-8074 (Wrong type inference of range() result). (cmb) + - Zlib: . Fixed bug GH-7953 (ob_clean() only does not set Content-Encoding). (cmb) diff --git a/ext/opcache/Optimizer/zend_func_info.c b/ext/opcache/Optimizer/zend_func_info.c index 84c9d20966cae..143717176b8d5 100644 --- a/ext/opcache/Optimizer/zend_func_info.c +++ b/ext/opcache/Optimizer/zend_func_info.c @@ -78,7 +78,7 @@ static uint32_t zend_range_info(const zend_call_info *call_info, const zend_ssa || (t3 & (MAY_BE_DOUBLE|MAY_BE_STRING))) { tmp |= MAY_BE_ARRAY_OF_DOUBLE; } - if ((t1 & (MAY_BE_ANY-(MAY_BE_STRING|MAY_BE_DOUBLE))) && (t2 & (MAY_BE_ANY-(MAY_BE_STRING|MAY_BE_DOUBLE)))) { + if ((t1 & (MAY_BE_ANY-MAY_BE_DOUBLE)) && (t2 & (MAY_BE_ANY-MAY_BE_DOUBLE))) { if ((t3 & MAY_BE_ANY) != MAY_BE_DOUBLE) { tmp |= MAY_BE_ARRAY_OF_LONG; } diff --git a/ext/opcache/tests/opt/gh8074.phpt b/ext/opcache/tests/opt/gh8074.phpt new file mode 100644 index 0000000000000..86ec3449c476c --- /dev/null +++ b/ext/opcache/tests/opt/gh8074.phpt @@ -0,0 +1,17 @@ +--TEST-- +GH-8074 (Wrong type inference of range() result) +--FILE-- + +--EXPECT-- +int(2) +int(3) From 8a8533d263d981b9c24de7f0e54adb8441da72e0 Mon Sep 17 00:00:00 2001 From: Alex Dowad Date: Tue, 22 Feb 2022 22:11:49 +0200 Subject: [PATCH 32/55] mb_check_encoding($str, '7bit') rejects strings with bytes over 0x7F This was the old behavior of mb_check_encoding() before 3e7acf901d, but yours truly broke it. If only we had more thorough tests at that time, this might not have slipped through the cracks. Thanks to divinity76 for the report. --- ext/mbstring/libmbfl/filters/mbfilter_7bit.c | 2 +- ext/mbstring/tests/other_encodings.phpt | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ext/mbstring/libmbfl/filters/mbfilter_7bit.c b/ext/mbstring/libmbfl/filters/mbfilter_7bit.c index dbf8993128472..a3a90c96f7a4a 100644 --- a/ext/mbstring/libmbfl/filters/mbfilter_7bit.c +++ b/ext/mbstring/libmbfl/filters/mbfilter_7bit.c @@ -67,7 +67,7 @@ const struct mbfl_convert_vtbl vtbl_7bit_8bit = { int mbfl_filt_conv_7bit_any(int c, mbfl_convert_filter *filter) { - return (*filter->output_function)(c, filter->data); + return (*filter->output_function)(c < 0x80 ? c : MBFL_BAD_INPUT, filter->data); } diff --git a/ext/mbstring/tests/other_encodings.phpt b/ext/mbstring/tests/other_encodings.phpt index 321eccb247b6f..0cdaad43d8826 100644 --- a/ext/mbstring/tests/other_encodings.phpt +++ b/ext/mbstring/tests/other_encodings.phpt @@ -14,10 +14,11 @@ mb_substitute_character(0x25); var_dump(mb_convert_encoding("ABC", "7bit", "ASCII")); var_dump(mb_convert_encoding("\x80", "7bit", "ASCII")); var_dump(mb_convert_encoding("ABC", "8bit", "7bit")); +var_dump(mb_check_encoding(chr(255), '7bit')); echo "7bit done\n"; // "8bit" -var_dump(mb_convert_encoding("\x01\x00", "8bit", "UTF-16BE")); // codepoints over 0xFF are illegal or '8-bit' +var_dump(mb_convert_encoding("\x01\x00", "8bit", "UTF-16BE")); // codepoints over 0xFF are illegal for '8-bit' echo "8bit done\n"; // UCS-2 @@ -41,6 +42,7 @@ echo "UCS-4 done\n"; string(3) "ABC" string(1) "%" string(3) "ABC" +bool(false) 7bit done string(1) "%" 8bit done From 41461cf812d65f6b933ca01e12fcc0d29c713276 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Wed, 9 Feb 2022 19:01:05 +0100 Subject: [PATCH 33/55] Migrate CI to GitHub actions --- .github/actions/apt-x64/action.yml | 68 ++++++++ .github/actions/brew/action.yml | 34 ++++ .github/actions/configure-macos/action.yml | 71 ++++++++ .github/actions/configure-x64/action.yml | 81 +++++++++ .github/actions/install-linux/action.yml | 14 ++ .github/actions/mssql/action.yml | 14 ++ .github/actions/setup-x64/action.yml | 30 ++++ .github/actions/test-linux/action.yml | 27 +++ .github/actions/test-macos/action.yml | 20 +++ .github/scripts/setup-slapd.sh | 185 +++++++++++++++++++++ .github/workflows/push.yml | 82 +++++++++ azure-pipelines.yml | 21 +-- 12 files changed, 631 insertions(+), 16 deletions(-) create mode 100644 .github/actions/apt-x64/action.yml create mode 100644 .github/actions/brew/action.yml create mode 100644 .github/actions/configure-macos/action.yml create mode 100644 .github/actions/configure-x64/action.yml create mode 100644 .github/actions/install-linux/action.yml create mode 100644 .github/actions/mssql/action.yml create mode 100644 .github/actions/setup-x64/action.yml create mode 100644 .github/actions/test-linux/action.yml create mode 100644 .github/actions/test-macos/action.yml create mode 100755 .github/scripts/setup-slapd.sh create mode 100644 .github/workflows/push.yml diff --git a/.github/actions/apt-x64/action.yml b/.github/actions/apt-x64/action.yml new file mode 100644 index 0000000000000..c21a34534aea8 --- /dev/null +++ b/.github/actions/apt-x64/action.yml @@ -0,0 +1,68 @@ +name: apt +runs: + using: composite + steps: + - shell: bash + run: | + set -x + sudo apt-get update + sudo apt-get install \ + bison \ + re2c \ + locales \ + ldap-utils \ + openssl \ + slapd \ + language-pack-de \ + libgmp-dev \ + libicu-dev \ + libtidy-dev \ + libenchant-dev \ + libaspell-dev \ + libpspell-dev \ + libsasl2-dev \ + libxpm-dev \ + libzip-dev \ + libsqlite3-dev \ + libwebp-dev \ + libonig-dev \ + libkrb5-dev \ + libgssapi-krb5-2 \ + libcurl4-openssl-dev \ + libxml2-dev \ + libxslt1-dev \ + libpq-dev \ + libreadline-dev \ + libldap2-dev \ + libsodium-dev \ + libargon2-0-dev \ + libmm-dev \ + libsnmp-dev \ + postgresql \ + postgresql-contrib \ + snmpd \ + snmp-mibs-downloader \ + freetds-dev \ + unixodbc-dev \ + llvm \ + libc-client-dev \ + dovecot-core \ + dovecot-pop3d \ + dovecot-imapd \ + sendmail \ + firebird-dev \ + liblmdb-dev \ + libtokyocabinet-dev \ + libdb-dev \ + libqdbm-dev \ + libjpeg-dev \ + libpng-dev \ + libfreetype6-dev + mkdir /opt/oracle + wget https://download.oracle.com/otn_software/linux/instantclient/instantclient-basiclite-linuxx64.zip + unzip instantclient-basiclite-linuxx64.zip + wget https://download.oracle.com/otn_software/linux/instantclient/instantclient-sdk-linuxx64.zip + unzip instantclient-sdk-linuxx64.zip + mv instantclient_*_* /opt/oracle/instantclient + # Interferes with libldap2 headers. + rm /opt/oracle/instantclient/sdk/include/ldap.h diff --git a/.github/actions/brew/action.yml b/.github/actions/brew/action.yml new file mode 100644 index 0000000000000..36b76392048d4 --- /dev/null +++ b/.github/actions/brew/action.yml @@ -0,0 +1,34 @@ +name: brew +runs: + using: composite + steps: + - shell: bash + run: | + set -x + brew install \ + pkg-config \ + autoconf \ + bison \ + re2c + brew install \ + openssl@1.1 \ + krb5 \ + bzip2 \ + enchant \ + libffi \ + libpng \ + webp \ + freetype \ + intltool \ + icu4c \ + libiconv \ + zlib \ + t1lib \ + gd \ + libzip \ + gmp \ + tidyp \ + libxml2 \ + libxslt \ + postgresql + brew link icu4c gettext --force diff --git a/.github/actions/configure-macos/action.yml b/.github/actions/configure-macos/action.yml new file mode 100644 index 0000000000000..852d8f62b68e1 --- /dev/null +++ b/.github/actions/configure-macos/action.yml @@ -0,0 +1,71 @@ +name: ./configure +inputs: + configurationParameters: + default: '' + required: false +runs: + using: composite + steps: + - shell: bash + run: | + set -x + export PATH="/usr/local/opt/bison/bin:$PATH" + export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/opt/openssl@1.1/lib/pkgconfig" + export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/opt/krb5/lib/pkgconfig" + export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/opt/libffi/lib/pkgconfig" + export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/opt/libxml2/lib/pkgconfig" + export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/opt/libxslt/lib/pkgconfig" + export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/opt/zlib/lib/pkgconfig" + export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/opt/icu4c/lib/pkgconfig" + ./buildconf --force + ./configure \ + --enable-option-checking=fatal \ + --prefix=/usr/local \ + --enable-fpm \ + --with-pdo-mysql=mysqlnd \ + --with-mysqli=mysqlnd \ + --with-pgsql=/usr/local/opt/libpq \ + --with-pdo-pgsql=/usr/local/opt/libpq \ + --with-pdo-sqlite \ + --without-pear \ + --enable-gd \ + --with-jpeg \ + --with-webp \ + --with-freetype \ + --enable-exif \ + --with-zip \ + --with-zlib \ + --enable-soap \ + --enable-xmlreader \ + --with-xsl \ + --with-tidy=/usr/local/opt/tidyp \ + --with-libxml \ + --enable-sysvsem \ + --enable-sysvshm \ + --enable-shmop \ + --enable-pcntl \ + --with-readline=/usr/local/opt/readline \ + --enable-mbstring \ + --with-curl \ + --with-gettext=/usr/local/opt/gettext \ + --enable-sockets \ + --with-bz2=/usr/local/opt/bzip2 \ + --with-openssl \ + --with-gmp=/usr/local/opt/gmp \ + --with-iconv=/usr/local/opt/libiconv \ + --enable-bcmath \ + --enable-calendar \ + --enable-ftp \ + --with-pspell=/usr/local/opt/aspell \ + --with-kerberos \ + --enable-sysvmsg \ + --with-ffi \ + --enable-zend-test \ + --enable-intl \ + --with-mhash \ + --with-sodium \ + --enable-dba \ + --enable-werror \ + --with-config-file-path=/etc \ + --with-config-file-scan-dir=/etc/php.d \ + ${{ inputs.configurationParameters }} diff --git a/.github/actions/configure-x64/action.yml b/.github/actions/configure-x64/action.yml new file mode 100644 index 0000000000000..73ce6322d25af --- /dev/null +++ b/.github/actions/configure-x64/action.yml @@ -0,0 +1,81 @@ +name: ./configure +inputs: + configurationParameters: + default: '' + required: false +runs: + using: composite + steps: + - shell: bash + run: | + set -x + ./buildconf --force + ./configure \ + --enable-option-checking=fatal \ + --prefix=/usr \ + --enable-phpdbg \ + --enable-fpm \ + --with-pdo-mysql=mysqlnd \ + --with-mysqli=mysqlnd \ + --with-pgsql \ + --with-pdo-pgsql \ + --with-pdo-sqlite \ + --enable-intl \ + --without-pear \ + --enable-gd \ + --with-jpeg \ + --with-webp \ + --with-freetype \ + --with-xpm \ + --enable-exif \ + --with-zip \ + --with-zlib \ + --with-zlib-dir=/usr \ + --enable-soap \ + --enable-xmlreader \ + --with-xsl \ + --with-tidy \ + --enable-sysvsem \ + --enable-sysvshm \ + --enable-shmop \ + --enable-pcntl \ + --with-readline \ + --enable-mbstring \ + --with-curl \ + --with-gettext \ + --enable-sockets \ + --with-bz2 \ + --with-openssl \ + --with-gmp \ + --enable-bcmath \ + --enable-calendar \ + --enable-ftp \ + --with-pspell=/usr \ + --with-enchant=/usr \ + --with-kerberos \ + --enable-sysvmsg \ + --with-ffi \ + --enable-zend-test \ + --with-ldap \ + --with-ldap-sasl \ + --with-password-argon2 \ + --with-mhash \ + --with-sodium \ + --enable-dba \ + --with-cdb \ + --enable-flatfile \ + --enable-inifile \ + --with-tcadb \ + --with-lmdb \ + --with-qdbm \ + --with-snmp \ + --with-unixODBC \ + --with-imap \ + --with-kerberos \ + --with-imap-ssl \ + --with-pdo-odbc=unixODBC,/usr \ + --with-pdo-oci=shared,instantclient,/opt/oracle/instantclient \ + --with-oci8=shared,instantclient,/opt/oracle/instantclient \ + --with-config-file-path=/etc \ + --with-config-file-scan-dir=/etc/php.d \ + ${{ inputs.configurationParameters }} diff --git a/.github/actions/install-linux/action.yml b/.github/actions/install-linux/action.yml new file mode 100644 index 0000000000000..6db48f0ec3e1d --- /dev/null +++ b/.github/actions/install-linux/action.yml @@ -0,0 +1,14 @@ +name: Install +runs: + using: composite + steps: + - shell: bash + run: | + set -x + sudo make install + sudo mkdir /etc/php.d + sudo chmod 777 /etc/php.d + echo mysqli.default_socket=/var/run/mysqld/mysqld.sock > /etc/php.d/mysqli.ini + echo pdo_mysql.default_socket=/var/run/mysqld/mysqld.sock > /etc/php.d/pdo_mysql.ini + echo opcache.enable_cli=1 >> /etc/php.d/opcache.ini + echo opcache.protect_memory=1 >> /etc/php.d/opcache.ini diff --git a/.github/actions/mssql/action.yml b/.github/actions/mssql/action.yml new file mode 100644 index 0000000000000..894380644c1ea --- /dev/null +++ b/.github/actions/mssql/action.yml @@ -0,0 +1,14 @@ +name: Create mssql container +runs: + using: composite + steps: + - shell: bash + run: | + set -x + docker run \ + -e "ACCEPT_EULA=Y" \ + -e "SA_PASSWORD=" \ + -p 1433:1433 \ + --name sql1 \ + -h sql1 \ + -d mcr.microsoft.com/mssql/server:2019-CU8-ubuntu-16.04 diff --git a/.github/actions/setup-x64/action.yml b/.github/actions/setup-x64/action.yml new file mode 100644 index 0000000000000..6cec51d4c8079 --- /dev/null +++ b/.github/actions/setup-x64/action.yml @@ -0,0 +1,30 @@ +name: Setup +runs: + using: composite + steps: + - shell: bash + run: | + set -x + + sudo service mysql start + sudo service postgresql start + sudo service slapd start + mysql -uroot -proot -e "CREATE DATABASE IF NOT EXISTS test" + # Ensure local_infile tests can run. + mysql -uroot -proot -e "SET GLOBAL local_infile = true" + sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'postgres';" + sudo -u postgres psql -c "CREATE DATABASE test;" + docker exec sql1 /opt/mssql-tools/bin/sqlcmd -S 127.0.0.1 -U SA -P "" -Q "create login pdo_test with password='password', check_policy=off; create user pdo_test for login pdo_test; grant alter, control to pdo_test;" + sudo locale-gen de_DE + + ./.github/scripts/setup-slapd.sh + + sudo cp ext/snmp/tests/snmpd.conf /etc/snmp + sudo cp ext/snmp/tests/bigtest /etc/snmp + sudo service snmpd restart + + sudo groupadd -g 5000 vmail + sudo useradd -m -d /var/vmail -s /bin/false -u 5000 -g vmail vmail + sudo cp ext/imap/tests/setup/dovecot.conf /etc/dovecot/dovecot.conf + sudo cp ext/imap/tests/setup/dovecotpass /etc/dovecot/dovecotpass + sudo service dovecot restart diff --git a/.github/actions/test-linux/action.yml b/.github/actions/test-linux/action.yml new file mode 100644 index 0000000000000..c7dab609820dd --- /dev/null +++ b/.github/actions/test-linux/action.yml @@ -0,0 +1,27 @@ +name: Test +inputs: + runTestsParameters: + default: '' + required: false +runs: + using: composite + steps: + - shell: bash + run: | + set -x + export MYSQL_TEST_USER=root + export MYSQL_TEST_PASSWD=root + export PDO_MYSQL_TEST_DSN="mysql:host=localhost;dbname=test" + export PDO_MYSQL_TEST_USER=root + export PDO_MYSQL_TEST_PASS=root + export PDO_DBLIB_TEST_DSN="dblib:host=127.0.0.1;dbname=master;version=7.0" + export PDO_DBLIB_TEST_USER="pdo_test" + export PDO_DBLIB_TEST_PASS="password" + export SKIP_IO_CAPTURE_TESTS=1 + sapi/cli/php run-tests.php -P -q ${{ inputs.runTestsParameters }} \ + -j$(/usr/bin/nproc) \ + -g FAIL,XFAIL,BORK,WARN,LEAK,XLEAK,SKIP \ + --offline \ + --show-diff \ + --show-slow 1000 \ + --set-timeout 120 diff --git a/.github/actions/test-macos/action.yml b/.github/actions/test-macos/action.yml new file mode 100644 index 0000000000000..99ac49b268c76 --- /dev/null +++ b/.github/actions/test-macos/action.yml @@ -0,0 +1,20 @@ +name: Test +inputs: + runTestsParameters: + default: '' + required: false +runs: + using: composite + steps: + - shell: bash + run: | + set -x + export SKIP_IO_CAPTURE_TESTS=1 + export CI_NO_IPV6=1 + sapi/cli/php run-tests.php -P -q ${{ inputs.runTestsParameters }} \ + -j$(sysctl -n hw.ncpu) \ + -g FAIL,XFAIL,BORK,WARN,LEAK,XLEAK,SKIP \ + --offline \ + --show-diff \ + --show-slow 1000 \ + --set-timeout 120 diff --git a/.github/scripts/setup-slapd.sh b/.github/scripts/setup-slapd.sh new file mode 100755 index 0000000000000..7ea3cb33b3d0e --- /dev/null +++ b/.github/scripts/setup-slapd.sh @@ -0,0 +1,185 @@ +#!/bin/sh +set -ev + +# Create TLS certificate +sudo mkdir -p /etc/ldap/ssl + +alt_names() { + ( + ( + (hostname && hostname -a && hostname -A && hostname -f) | + xargs -n 1 | + sort -u | + sed -e 's/\(\S\+\)/DNS:\1/g' + ) && ( + (hostname -i && hostname -I && echo "127.0.0.1 ::1") | + xargs -n 1 | + sort -u | + sed -e 's/\(\S\+\)/IP:\1/g' + ) + ) | paste -d, -s +} + +sudo openssl req -newkey rsa:4096 -x509 -nodes -days 3650 \ + -out /etc/ldap/ssl/server.crt -keyout /etc/ldap/ssl/server.key \ + -subj "/C=US/ST=Arizona/L=Localhost/O=localhost/CN=localhost" \ + -addext "subjectAltName = `alt_names`" + +sudo chown -R openldap:openldap /etc/ldap/ssl + +# Display the TLS certificate (should be world readable) +openssl x509 -noout -text -in /etc/ldap/ssl/server.crt + +# Point to the certificate generated +if ! grep -q 'TLS_CACERT \/etc\/ldap\/ssl\/server.crt' /etc/ldap/ldap.conf; then + sudo sed -e 's|^\s*TLS_CACERT|# TLS_CACERT|' -i /etc/ldap/ldap.conf + echo 'TLS_CACERT /etc/ldap/ssl/server.crt' | sudo tee -a /etc/ldap/ldap.conf +fi + +# Configure LDAP protocols to serve. +sudo sed -e 's|^\s*SLAPD_SERVICES\s*=.*$|SLAPD_SERVICES="ldap:/// ldaps:/// ldapi:///"|' -i /etc/default/slapd + +# Configure LDAP database. +DBDN=`sudo ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -b cn=config '(&(olcRootDN=*)(olcSuffix=*))' dn | grep -i '^dn:' | sed -e 's/^dn:\s*//'`; + +sudo ldapadd -Q -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/ppolicy.ldif + +sudo service slapd restart + +sudo ldapmodify -Q -Y EXTERNAL -H ldapi:/// << EOF +dn: $DBDN +changetype: modify +replace: olcSuffix +olcSuffix: dc=my-domain,dc=com +- +replace: olcRootDN +olcRootDN: cn=Manager,dc=my-domain,dc=com +- +replace: olcRootPW +olcRootPW: secret + +dn: cn=config +changetype: modify +add: olcTLSCACertificateFile +olcTLSCACertificateFile: /etc/ldap/ssl/server.crt +- +add: olcTLSCertificateFile +olcTLSCertificateFile: /etc/ldap/ssl/server.crt +- +add: olcTLSCertificateKeyFile +olcTLSCertificateKeyFile: /etc/ldap/ssl/server.key +- +add: olcTLSVerifyClient +olcTLSVerifyClient: never +- +add: olcAuthzRegexp +olcAuthzRegexp: uid=usera,cn=digest-md5,cn=auth cn=usera,dc=my-domain,dc=com +- +replace: olcLogLevel +olcLogLevel: -1 + +dn: cn=module{0},cn=config +changetype: modify +add: olcModuleLoad +olcModuleLoad: sssvlv +- +add: olcModuleLoad +olcModuleLoad: ppolicy +- +add: olcModuleLoad +olcModuleLoad: dds +EOF + +sudo service slapd restart + +sudo ldapadd -Q -Y EXTERNAL -H ldapi:/// << EOF +dn: olcOverlay=sssvlv,$DBDN +objectClass: olcOverlayConfig +objectClass: olcSssVlvConfig +olcOverlay: sssvlv +olcSssVlvMax: 10 +olcSssVlvMaxKeys: 5 + +dn: olcOverlay=ppolicy,$DBDN +objectClass: olcOverlayConfig +objectClass: olcPPolicyConfig +olcOverlay: ppolicy +### This would clutter our DIT and make tests to fail, while ppolicy does not +### seem to work as we expect (it does not seem to provide expected controls) +## olcPPolicyDefault: cn=default,ou=pwpolicies,dc=my-domain,dc=com +## olcPPolicyHashCleartext: FALSE +## olcPPolicyUseLockout: TRUE + +dn: olcOverlay=dds,$DBDN +objectClass: olcOverlayConfig +objectClass: olcDdsConfig +olcOverlay: dds +EOF + +sudo service slapd restart + +sudo ldapmodify -Q -Y EXTERNAL -H ldapi:/// << EOF +dn: $DBDN +changetype: modify +add: olcDbIndex +olcDbIndex: entryExpireTimestamp eq +EOF + +sudo service slapd restart + +ldapadd -H ldapi:/// -D cn=Manager,dc=my-domain,dc=com -w secret <- + --${{ matrix.debug && 'enable' || 'disable' }}-debug + --${{ matrix.zts && 'enable' || 'disable' }}-zts + - name: make + run: make -j$(/usr/bin/nproc) >/dev/null + - name: make install + uses: ./.github/actions/install-linux + - name: Setup + uses: ./.github/actions/setup-x64 + - name: Test + uses: ./.github/actions/test-linux + - name: Test Tracing JIT + uses: ./.github/actions/test-linux + with: + runTestsParameters: -d zend_extension=opcache.so -d opcache.jit_buffer_size=16M + MACOS_DEBUG_NTS: + runs-on: macos-10.15 + steps: + - name: git checkout + uses: actions/checkout@v2 + - name: brew + uses: ./.github/actions/brew + - name: ./configure + uses: ./.github/actions/configure-macos + with: + configurationParameters: --enable-debug --disable-zts + - name: make + run: |- + export PATH="/usr/local/opt/bison/bin:$PATH" + make -j$(sysctl -n hw.logicalcpu) >/dev/null + - name: make install + run: sudo make install + - name: Test + uses: ./.github/actions/test-macos + - name: Test Tracing JIT + uses: ./.github/actions/test-macos + with: + runTestsParameters: >- + -d zend_extension=opcache.so + -d opcache.protect_memory=1 + -d opcache.jit_buffer_size=16M diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 4f871281fd5c6..a8fc6bcbb70bc 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -22,22 +22,11 @@ schedules: - master jobs: - - template: azure/job.yml - parameters: - configurationName: DEBUG_NTS - configurationParameters: '--enable-debug --disable-zts' - - template: azure/job.yml - parameters: - configurationName: RELEASE_ZTS - configurationParameters: '--disable-debug --enable-zts' - - template: azure/i386/job.yml - parameters: - configurationName: I386_DEBUG_ZTS - configurationParameters: '--enable-debug --enable-zts' - - template: azure/macos/job.yml - parameters: - configurationName: MACOS_DEBUG_NTS - configurationParameters: '--enable-debug --disable-zts' + # Azure pipelines don't work atm + # - template: azure/i386/job.yml + # parameters: + # configurationName: I386_DEBUG_ZTS + # configurationParameters: '--enable-debug --enable-zts' - ${{ if eq(variables['Build.Reason'], 'Schedule') }}: - template: azure/job.yml parameters: From bbc111ed3f6062fa1c1bb30865e8c4a9e1ff90ba Mon Sep 17 00:00:00 2001 From: Alex Dowad Date: Wed, 23 Feb 2022 22:56:55 +0200 Subject: [PATCH 34/55] Add NEWS entry for recent MBString bugfix (re: '7bit' encoding) Thanks to Kamil Tekiela for mentioning that this should be done. --- NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS b/NEWS index 7ab4801312689..75da613024740 100644 --- a/NEWS +++ b/NEWS @@ -21,6 +21,9 @@ PHP NEWS . Fixed bug GH-7953 (ob_clean() only does not set Content-Encoding). (cmb) . Fixed bug GH-7980 (Unexpected result for iconv_mime_decode). (cmb) +- MBString: + . Fixed bug GH-8128 (mb_check_encoding wrong result for 7bit). (alexdowad) + - MySQLnd: . Fixed bug GH-8058 (NULL pointer dereference in mysqlnd package). (Kamil Tekiela) From 1e8d35adaba196caa0173de136888952efa7c461 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Wed, 23 Feb 2022 20:25:29 +0100 Subject: [PATCH 35/55] GitHub actions test with firebird, dblib and werror --- .github/actions/configure-x64/action.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/actions/configure-x64/action.yml b/.github/actions/configure-x64/action.yml index 73ce6322d25af..f9b774218f4ef 100644 --- a/.github/actions/configure-x64/action.yml +++ b/.github/actions/configure-x64/action.yml @@ -78,4 +78,7 @@ runs: --with-oci8=shared,instantclient,/opt/oracle/instantclient \ --with-config-file-path=/etc \ --with-config-file-scan-dir=/etc/php.d \ + --with-pdo-firebird \ + --with-pdo-dblib \ + --enable-werror \ ${{ inputs.configurationParameters }} From e80ec3fe165a9db44561e9943e0d3020b33e245f Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Wed, 23 Feb 2022 22:46:10 +0100 Subject: [PATCH 36/55] Mark failing JIT test with XFAIL --- ext/opcache/tests/jit/assign_dim_op_007.phpt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/opcache/tests/jit/assign_dim_op_007.phpt b/ext/opcache/tests/jit/assign_dim_op_007.phpt index e8708a1255131..cf7125c2a4554 100644 --- a/ext/opcache/tests/jit/assign_dim_op_007.phpt +++ b/ext/opcache/tests/jit/assign_dim_op_007.phpt @@ -5,6 +5,8 @@ opcache.enable=1 opcache.enable_cli=1 opcache.file_update_protection=0 opcache.jit_buffer_size=1M +--XFAIL-- +See https://github.com/php/php-src/issues/8147 --FILE-- Date: Wed, 23 Feb 2022 19:23:00 -0500 Subject: [PATCH 37/55] Fixes infinite recursion introduced by patch to SplFixedArray (#8105) Closes GH-8079 Track whether the spl_fixedarray was modified since the last call to get_properties --- ext/spl/spl_fixedarray.c | 25 +++++++++++++++++++++ ext/spl/tests/fixedarray_023.phpt | 36 +++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 ext/spl/tests/fixedarray_023.phpt diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index ec53935ac9d2e..cdf628cfb4ee6 100644 --- a/ext/spl/spl_fixedarray.c +++ b/ext/spl/spl_fixedarray.c @@ -42,6 +42,8 @@ ZEND_GET_MODULE(spl_fixedarray) typedef struct _spl_fixedarray { zend_long size; zval *elements; + /* True if this was modified after the last call to get_properties or the hash table wasn't rebuilt. */ + bool should_rebuild_properties; } spl_fixedarray; typedef struct _spl_fixedarray_object { @@ -104,6 +106,7 @@ static void spl_fixedarray_init(spl_fixedarray *array, zend_long size) array->size = 0; /* reset size in case ecalloc() fails */ array->elements = safe_emalloc(size, sizeof(zval), 0); array->size = size; + array->should_rebuild_properties = true; spl_fixedarray_init_elems(array, 0, size); } else { spl_fixedarray_default_ctor(array); @@ -166,6 +169,7 @@ static void spl_fixedarray_resize(spl_fixedarray *array, zend_long size) /* nothing to do */ return; } + array->should_rebuild_properties = true; /* first initialization */ if (array->size == 0) { @@ -205,6 +209,22 @@ static HashTable* spl_fixedarray_object_get_properties(zend_object *obj) HashTable *ht = zend_std_get_properties(obj); if (!spl_fixedarray_empty(&intern->array)) { + /* + * Usually, the reference count of the hash table is 1, + * except during cyclic reference cycles. + * + * Maintain the DEBUG invariant that a hash table isn't modified during iteration, + * and avoid unnecessary work rebuilding a hash table for unmodified properties. + * + * See https://github.com/php/php-src/issues/8079 and ext/spl/tests/fixedarray_022.phpt + * Also see https://github.com/php/php-src/issues/8044 for alternate considered approaches. + */ + if (!intern->array.should_rebuild_properties) { + /* Return the same hash table so that recursion cycle detection works in internal functions. */ + return ht; + } + intern->array.should_rebuild_properties = false; + zend_long j = zend_hash_num_elements(ht); if (GC_REFCOUNT(ht) > 1) { @@ -354,6 +374,9 @@ static zval *spl_fixedarray_object_read_dimension(zend_object *object, zval *off } return &EG(uninitialized_zval); } + if (type != BP_VAR_IS && type != BP_VAR_R) { + intern->array.should_rebuild_properties = true; + } return spl_fixedarray_object_read_dimension_helper(intern, offset); } @@ -378,6 +401,7 @@ static void spl_fixedarray_object_write_dimension_helper(spl_fixedarray_object * zend_throw_exception(spl_ce_RuntimeException, "Index invalid or out of range", 0); return; } else { + intern->array.should_rebuild_properties = true; /* Fix #81429 */ zval *ptr = &(intern->array.elements[index]); zval tmp; @@ -425,6 +449,7 @@ static void spl_fixedarray_object_unset_dimension_helper(spl_fixedarray_object * zend_throw_exception(spl_ce_RuntimeException, "Index invalid or out of range", 0); return; } else { + intern->array.should_rebuild_properties = true; zval_ptr_dtor(&(intern->array.elements[index])); ZVAL_NULL(&intern->array.elements[index]); } diff --git a/ext/spl/tests/fixedarray_023.phpt b/ext/spl/tests/fixedarray_023.phpt new file mode 100644 index 0000000000000..1d60a2ce6d9f7 --- /dev/null +++ b/ext/spl/tests/fixedarray_023.phpt @@ -0,0 +1,36 @@ +--TEST-- +SPL: FixedArray: Infinite loop in var_export bugfix +--FILE-- + +--EXPECTF-- +Warning: var_export does not handle circular references in %s on line 8 + +Warning: var_export does not handle circular references in %s on line 8 +SplFixedArray::__set_state(array( + 0 => NAN, + 1 => 0.0, + 2 => NULL, + 3 => NULL, +)) +object(SplFixedArray)#2 (4) refcount(6){ + [0]=> + float(NAN) + [1]=> + float(-0) + [2]=> + *RECURSION* + [3]=> + *RECURSION* +} \ No newline at end of file From 33cd61c9045ae8675448456cdda6fb244b2efa01 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 23 Feb 2022 14:14:46 +0100 Subject: [PATCH 38/55] Fix GH-8140: Wrong first class callable by name optimization When optimizing by name function calls, we must not replace `CALLABLE_CONVERT` opcodes, but have to keep them. Closes GH-8144. --- NEWS | 1 + Zend/Optimizer/optimize_func_calls.c | 8 ++++++-- ext/opcache/tests/opt/gh8140a.phpt | 16 ++++++++++++++++ ext/opcache/tests/opt/gh8140b.phpt | 14 ++++++++++++++ 4 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 ext/opcache/tests/opt/gh8140a.phpt create mode 100644 ext/opcache/tests/opt/gh8140b.phpt diff --git a/NEWS b/NEWS index 75da613024740..ea8ee5879e72b 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,7 @@ PHP NEWS variables. (ilutov) . Fixed bug GH-7958 (Nested CallbackFilterIterator is leaking memory). (cmb) . Fixed bug GH-8074 (Wrong type inference of range() result). (cmb) + . Fixed bug GH-8140 (Wrong first class callable by name optimization). (cmb) - GD: . Fixed libpng warning when loading interlaced images. (Brett) diff --git a/Zend/Optimizer/optimize_func_calls.c b/Zend/Optimizer/optimize_func_calls.c index e2e16f90b8654..351010177f630 100644 --- a/Zend/Optimizer/optimize_func_calls.c +++ b/Zend/Optimizer/optimize_func_calls.c @@ -200,14 +200,18 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx) fcall->op1.num = zend_vm_calc_used_stack(fcall->extended_value, call_stack[call].func); literal_dtor(&ZEND_OP2_LITERAL(fcall)); fcall->op2.constant = fcall->op2.constant + 1; - opline->opcode = zend_get_call_op(fcall, call_stack[call].func); + if (opline->opcode != ZEND_CALLABLE_CONVERT) { + opline->opcode = zend_get_call_op(fcall, call_stack[call].func); + } } else if (fcall->opcode == ZEND_INIT_NS_FCALL_BY_NAME) { fcall->opcode = ZEND_INIT_FCALL; fcall->op1.num = zend_vm_calc_used_stack(fcall->extended_value, call_stack[call].func); literal_dtor(&op_array->literals[fcall->op2.constant]); literal_dtor(&op_array->literals[fcall->op2.constant + 2]); fcall->op2.constant = fcall->op2.constant + 1; - opline->opcode = zend_get_call_op(fcall, call_stack[call].func); + if (opline->opcode != ZEND_CALLABLE_CONVERT) { + opline->opcode = zend_get_call_op(fcall, call_stack[call].func); + } } else if (fcall->opcode == ZEND_INIT_STATIC_METHOD_CALL || fcall->opcode == ZEND_INIT_METHOD_CALL || fcall->opcode == ZEND_NEW) { diff --git a/ext/opcache/tests/opt/gh8140a.phpt b/ext/opcache/tests/opt/gh8140a.phpt new file mode 100644 index 0000000000000..03f097c77c5ce --- /dev/null +++ b/ext/opcache/tests/opt/gh8140a.phpt @@ -0,0 +1,16 @@ +--TEST-- +GH-8140 (Wrong first class callable by name optimization) +--FILE-- + +--EXPECT-- +Hello, world! diff --git a/ext/opcache/tests/opt/gh8140b.phpt b/ext/opcache/tests/opt/gh8140b.phpt new file mode 100644 index 0000000000000..60da3a79e1408 --- /dev/null +++ b/ext/opcache/tests/opt/gh8140b.phpt @@ -0,0 +1,14 @@ +--TEST-- +GH-8140 (Wrong first class callable by name optimization) +--FILE-- + +--EXPECT-- +Hello, world! From 8b8cf8f8f507c503282465264e2f9e0f72ef4b03 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 28 Feb 2022 10:58:14 +0300 Subject: [PATCH 39/55] JIT: Fix register clobbering --- ext/opcache/jit/zend_jit_arm64.dasc | 20 ++++++++++---------- ext/opcache/tests/jit/assign_dim_op_007.phpt | 2 -- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/ext/opcache/jit/zend_jit_arm64.dasc b/ext/opcache/jit/zend_jit_arm64.dasc index 6d6bc471ec27e..31b5260605430 100644 --- a/ext/opcache/jit/zend_jit_arm64.dasc +++ b/ext/opcache/jit/zend_jit_arm64.dasc @@ -3816,7 +3816,7 @@ static int zend_jit_inc_dec(dasm_State **Dst, const zend_op *opline, uint32_t op | LOAD_64BIT_VAL TMP1, val | fmov Rd(Z_REG(op1_def_addr)-ZREG_V0), TMP1 } else { - | SET_ZVAL_LVAL op1_def_addr, val, REG0, TMP1 + | SET_ZVAL_LVAL op1_def_addr, val, TMP2, TMP1 } } else { uint64_t val = 0xc3e0000000000000; @@ -3824,7 +3824,7 @@ static int zend_jit_inc_dec(dasm_State **Dst, const zend_op *opline, uint32_t op | LOAD_64BIT_VAL TMP1, val | fmov Rd(Z_REG(op1_def_addr)-ZREG_V0), TMP1 } else { - | SET_ZVAL_LVAL op1_def_addr, val, REG0, TMP1 + | SET_ZVAL_LVAL op1_def_addr, val, TMP2, TMP1 } } if (Z_MODE(op1_def_addr) == IS_MEM_ZVAL) { @@ -4155,7 +4155,7 @@ static int zend_jit_math_long_long(dasm_State **Dst, | LOAD_64BIT_VAL TMP1, val | fmov Rd(Z_REG(res_addr)-ZREG_V0), TMP1 } else { - | SET_ZVAL_LVAL res_addr, val, REG0, TMP1 + | SET_ZVAL_LVAL res_addr, val, TMP2, TMP1 } break; } else if (opcode == ZEND_SUB) { @@ -4164,7 +4164,7 @@ static int zend_jit_math_long_long(dasm_State **Dst, | LOAD_64BIT_VAL TMP1, val | fmov Rd(Z_REG(res_addr)-ZREG_V0), TMP1 } else { - | SET_ZVAL_LVAL res_addr, val, REG0, TMP1 + | SET_ZVAL_LVAL res_addr, val, TMP2, TMP1 } break; } @@ -12942,20 +12942,20 @@ static int zend_jit_incdec_obj(dasm_State **Dst, |3: if (opline->opcode == ZEND_PRE_INC_OBJ || opline->opcode == ZEND_POST_INC_OBJ) { uint64_t val = 0x43e0000000000000; - | LOAD_64BIT_VAL REG0, val - | SET_ZVAL_LVAL_FROM_REG var_addr, REG0, TMP1 + | LOAD_64BIT_VAL TMP2, val + | SET_ZVAL_LVAL_FROM_REG var_addr, TMP2, TMP1 | SET_ZVAL_TYPE_INFO var_addr, IS_DOUBLE, TMP1w, TMP2 if (opline->opcode == ZEND_PRE_INC_OBJ && opline->result_type != IS_UNUSED) { - | SET_ZVAL_LVAL_FROM_REG res_addr, REG0, TMP1 + | SET_ZVAL_LVAL_FROM_REG res_addr, TMP2, TMP1 | SET_ZVAL_TYPE_INFO res_addr, IS_DOUBLE, TMP1w, TMP2 } } else { uint64_t val = 0xc3e0000000000000; - | LOAD_64BIT_VAL REG0, val - | SET_ZVAL_LVAL_FROM_REG var_addr, REG0, TMP1 + | LOAD_64BIT_VAL TMP2, val + | SET_ZVAL_LVAL_FROM_REG var_addr, TMP2, TMP1 | SET_ZVAL_TYPE_INFO var_addr, IS_DOUBLE, TMP1w, TMP2 if (opline->opcode == ZEND_PRE_DEC_OBJ && opline->result_type != IS_UNUSED) { - | SET_ZVAL_LVAL_FROM_REG res_addr, REG0, TMP1 + | SET_ZVAL_LVAL_FROM_REG res_addr, TMP2, TMP1 | SET_ZVAL_TYPE_INFO res_addr, IS_DOUBLE, TMP1w, TMP2 } } diff --git a/ext/opcache/tests/jit/assign_dim_op_007.phpt b/ext/opcache/tests/jit/assign_dim_op_007.phpt index cf7125c2a4554..e8708a1255131 100644 --- a/ext/opcache/tests/jit/assign_dim_op_007.phpt +++ b/ext/opcache/tests/jit/assign_dim_op_007.phpt @@ -5,8 +5,6 @@ opcache.enable=1 opcache.enable_cli=1 opcache.file_update_protection=0 opcache.jit_buffer_size=1M ---XFAIL-- -See https://github.com/php/php-src/issues/8147 --FILE-- Date: Mon, 28 Feb 2022 11:44:22 +0300 Subject: [PATCH 40/55] Fixed incorrect DCE for FREE Fixes oss-fuzz #44863 --- ext/opcache/Optimizer/dce.c | 4 +++- ext/opcache/tests/opt/dce_013.phpt | 12 ++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 ext/opcache/tests/opt/dce_013.phpt diff --git a/ext/opcache/Optimizer/dce.c b/ext/opcache/Optimizer/dce.c index 47f5f271062e2..f945856dfb293 100644 --- a/ext/opcache/Optimizer/dce.c +++ b/ext/opcache/Optimizer/dce.c @@ -391,7 +391,9 @@ static zend_bool dce_instr(context *ctx, zend_op *opline, zend_ssa_op *ssa_op) { } /* We mark FREEs as dead, but they're only really dead if the destroyed var is dead */ - if (opline->opcode == ZEND_FREE && may_be_refcounted(ssa->var_info[ssa_op->op1_use].type) + if (opline->opcode == ZEND_FREE + && ((ssa->var_info[ssa_op->op1_use].type & (MAY_BE_REF|MAY_BE_ANY|MAY_BE_UNDEF)) == 0 + || may_be_refcounted(ssa->var_info[ssa_op->op1_use].type)) && !is_var_dead(ctx, ssa_op->op1_use)) { return 0; } diff --git a/ext/opcache/tests/opt/dce_013.phpt b/ext/opcache/tests/opt/dce_013.phpt new file mode 100644 index 0000000000000..ac5211498f6d1 --- /dev/null +++ b/ext/opcache/tests/opt/dce_013.phpt @@ -0,0 +1,12 @@ +--TEST-- +Incorrect DCE of FREE +--FILE-- + +DONE +--EXPECT-- +DONE From 0d266a24d61dd93bba4ed8837163f099b0ee0374 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 16 Feb 2022 12:32:17 +0100 Subject: [PATCH 41/55] Fix GH-8080: ReflectionClass::getConstants() depends on def. order When we need to evaluate constant ASTs, we always have to do that in the scope where the constant has been defined, which may be a parent of the `ReflectionClass`'s scope. Closes GH-8106. --- NEWS | 4 ++++ ext/reflection/php_reflection.c | 4 ++-- ext/reflection/tests/gh8080.phpt | 31 +++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 ext/reflection/tests/gh8080.phpt diff --git a/NEWS b/NEWS index 022cd11a62495..7d8806639f1ba 100644 --- a/NEWS +++ b/NEWS @@ -22,6 +22,10 @@ PHP NEWS - OPcache: . Fixed bug GH-8074 (Wrong type inference of range() result). (cmb) +- Reflection: + . Fixed bug GH-8080 (ReflectionClass::getConstants() depends on def. order). + (cmb) + - Zlib: . Fixed bug GH-7953 (ob_clean() only does not set Content-Encoding). (cmb) diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index c2c379be2823a..0210fa5ef3fd5 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -4454,7 +4454,7 @@ ZEND_METHOD(ReflectionClass, getConstants) array_init(return_value); ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, key, constant) { - if (UNEXPECTED(zval_update_constant_ex(&constant->value, ce) != SUCCESS)) { + if (UNEXPECTED(zval_update_constant_ex(&constant->value, constant->ce) != SUCCESS)) { RETURN_THROWS(); } @@ -4511,7 +4511,7 @@ ZEND_METHOD(ReflectionClass, getConstant) GET_REFLECTION_OBJECT_PTR(ce); ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) { - if (UNEXPECTED(zval_update_constant_ex(&c->value, ce) != SUCCESS)) { + if (UNEXPECTED(zval_update_constant_ex(&c->value, c->ce) != SUCCESS)) { RETURN_THROWS(); } } ZEND_HASH_FOREACH_END(); diff --git a/ext/reflection/tests/gh8080.phpt b/ext/reflection/tests/gh8080.phpt new file mode 100644 index 0000000000000..c9c861051ab85 --- /dev/null +++ b/ext/reflection/tests/gh8080.phpt @@ -0,0 +1,31 @@ +--TEST-- +GH-8080 (ReflectionClass::getConstants() depends on def. order) +--FILE-- + 'Test', + ]; + private const TEST = 'test'; +} + +class B extends A {} + +$r = new ReflectionClass(B::class); +var_dump( + $r->getConstants(), + $r->getConstant("LIST") +); +?> +--EXPECT-- +array(1) { + ["LIST"]=> + array(1) { + ["test"]=> + string(4) "Test" + } +} +array(1) { + ["test"]=> + string(4) "Test" +} From ac8a53cab1297f8546146f93f3fa7897e396b047 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 28 Feb 2022 13:48:53 +0300 Subject: [PATCH 42/55] JIT: Fix register allocator Fixes oss-fuzz #44916 --- ext/opcache/jit/zend_jit_trace.c | 16 +++++++++++++++ ext/opcache/jit/zend_jit_x86.dasc | 8 ++++++++ ext/opcache/tests/jit/reg_alloc_011.phpt | 25 ++++++++++++++++++++++++ 3 files changed, 49 insertions(+) create mode 100644 ext/opcache/tests/jit/reg_alloc_011.phpt diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index 223792e2eae92..5244b1eaa315b 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -6389,6 +6389,22 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par if (p->stop == ZEND_JIT_TRACE_STOP_LOOP || p->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL || p->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET) { + if (ra) { + zend_ssa_phi *phi = ssa->blocks[1].phis; + + while (phi) { + if (ra[phi->ssa_var] + && ra[phi->sources[1]] + && STACK_MEM_TYPE(stack, phi->var) != STACK_TYPE(stack, phi->var) + && (ra[phi->ssa_var]->flags & (ZREG_LOAD|ZREG_STORE)) == 0 + && (ra[phi->sources[1]]->flags & (ZREG_LOAD|ZREG_STORE)) == 0) { + /* Store actual type to memory to avoid deoptimization mistakes */ + /* TODO: Alternatively, we may try to update alredy generated deoptimization info */ + zend_jit_store_var_type(&dasm_state, phi->var, STACK_TYPE(stack, phi->var)); + } + phi = phi->next; + } + } if (p->stop != ZEND_JIT_TRACE_STOP_RECURSIVE_RET) { if ((t->flags & ZEND_JIT_TRACE_USES_INITIAL_IP) && !zend_jit_set_ip(&dasm_state, p->opline)) { diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 462ba36168485..0539165687afb 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -3867,6 +3867,14 @@ static int zend_jit_store_var(dasm_State **Dst, uint32_t info, int var, zend_reg return zend_jit_spill_store(Dst, src, dst, info, set_type); } +static int zend_jit_store_var_type(dasm_State **Dst, int var, uint8_t type) +{ + zend_jit_addr dst = ZEND_ADDR_MEM_ZVAL(ZREG_FP, EX_NUM_TO_VAR(var)); + + | SET_ZVAL_TYPE_INFO dst, type + return 1; +} + static int zend_jit_store_var_if_necessary(dasm_State **Dst, int var, zend_jit_addr src, uint32_t info) { if (Z_MODE(src) == IS_REG && Z_STORE(src)) { diff --git a/ext/opcache/tests/jit/reg_alloc_011.phpt b/ext/opcache/tests/jit/reg_alloc_011.phpt new file mode 100644 index 0000000000000..f628adf7795ae --- /dev/null +++ b/ext/opcache/tests/jit/reg_alloc_011.phpt @@ -0,0 +1,25 @@ +--TEST-- +Register Alloction 011: Missed type store +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +--FILE-- + +DONE +--EXPECTF-- +DONE \ No newline at end of file From 0a5162b2b61fc9a11d2a6df3afce2d340bb3c4ab Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 28 Feb 2022 13:55:25 +0300 Subject: [PATCH 43/55] Allow setting full type info --- ext/opcache/jit/zend_jit_arm64.dasc | 2 +- ext/opcache/jit/zend_jit_x86.dasc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/opcache/jit/zend_jit_arm64.dasc b/ext/opcache/jit/zend_jit_arm64.dasc index 2b6394d68551b..b29a69aa65075 100644 --- a/ext/opcache/jit/zend_jit_arm64.dasc +++ b/ext/opcache/jit/zend_jit_arm64.dasc @@ -3560,7 +3560,7 @@ static int zend_jit_store_var(dasm_State **Dst, uint32_t info, int var, zend_reg return zend_jit_spill_store(Dst, src, dst, info, set_type); } -static int zend_jit_store_var_type(dasm_State **Dst, int var, uint8_t type) +static int zend_jit_store_var_type(dasm_State **Dst, int var, uint32_t type) { zend_jit_addr dst = ZEND_ADDR_MEM_ZVAL(ZREG_FP, EX_NUM_TO_VAR(var)); diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index c073c5d873d72..ea9c7ba6eedd8 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -3900,7 +3900,7 @@ static int zend_jit_store_var(dasm_State **Dst, uint32_t info, int var, zend_reg return zend_jit_spill_store(Dst, src, dst, info, set_type); } -static int zend_jit_store_var_type(dasm_State **Dst, int var, uint8_t type) +static int zend_jit_store_var_type(dasm_State **Dst, int var, uint32_t type) { zend_jit_addr dst = ZEND_ADDR_MEM_ZVAL(ZREG_FP, EX_NUM_TO_VAR(var)); From 70f7e7d83fe213712a0828ae4872daaed03a2544 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 28 Feb 2022 15:43:03 +0300 Subject: [PATCH 44/55] JIT: Fix memory leak Fixes oss-fuzz #44920 --- ext/opcache/jit/zend_jit_disasm_x86.c | 1 + ext/opcache/jit/zend_jit_helpers.c | 14 +++++++++ ext/opcache/jit/zend_jit_x86.dasc | 28 +++++++++++++++--- ext/opcache/tests/jit/assign_obj_op_002.phpt | 31 ++++++++++++++++++++ 4 files changed, 70 insertions(+), 4 deletions(-) create mode 100644 ext/opcache/tests/jit/assign_obj_op_002.phpt diff --git a/ext/opcache/jit/zend_jit_disasm_x86.c b/ext/opcache/jit/zend_jit_disasm_x86.c index 1258165815594..504c2efaec663 100644 --- a/ext/opcache/jit/zend_jit_disasm_x86.c +++ b/ext/opcache/jit/zend_jit_disasm_x86.c @@ -461,6 +461,7 @@ static int zend_jit_disasm_init(void) REGISTER_HELPER(zend_jit_post_inc_typed_ref); REGISTER_HELPER(zend_jit_post_dec_typed_ref); REGISTER_HELPER(zend_jit_assign_op_to_typed_ref); + REGISTER_HELPER(zend_jit_assign_op_to_typed_ref_tmp); REGISTER_HELPER(zend_jit_only_vars_by_reference); REGISTER_HELPER(zend_jit_invalid_array_access); REGISTER_HELPER(zend_jit_invalid_property_read); diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index 2eb3bb3cc1880..dd01532b5b705 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -2259,6 +2259,20 @@ static void ZEND_FASTCALL zend_jit_assign_op_to_typed_ref(zend_reference *ref, z } } +static void ZEND_FASTCALL zend_jit_assign_op_to_typed_ref_tmp(zend_reference *ref, zval *val, binary_op_type binary_op) +{ + zval z_copy; + + binary_op(&z_copy, &ref->val, val); + if (EXPECTED(zend_verify_ref_assignable_zval(ref, &z_copy, ZEND_CALL_USES_STRICT_TYPES(EG(current_execute_data))))) { + zval_ptr_dtor(&ref->val); + ZVAL_COPY_VALUE(&ref->val, &z_copy); + } else { + zval_ptr_dtor(&z_copy); + } + zval_ptr_dtor_nogc(val); +} + static void ZEND_FASTCALL zend_jit_only_vars_by_reference(zval *arg) { ZVAL_NEW_REF(arg, arg); diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 0539165687afb..b0635a77029bc 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -6776,7 +6776,12 @@ static int zend_jit_assign_dim_op(dasm_State **Dst, const zend_op *opline, uint3 | PUSH_ADDR binary_op, r0 |.endif | SET_EX_OPLINE opline, r0 - | EXT_CALL zend_jit_assign_op_to_typed_ref, r0 + if (((opline+1)->op1_type & (IS_TMP_VAR|IS_VAR)) + && (op1_data_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE))) { + | EXT_CALL zend_jit_assign_op_to_typed_ref_tmp, r0 + } else { + | EXT_CALL zend_jit_assign_op_to_typed_ref, r0 + } |.if not(X64) | add r4, 12 |.endif @@ -6900,7 +6905,12 @@ static int zend_jit_assign_op(dasm_State **Dst, const zend_op *opline, uint32_t | PUSH_ADDR binary_op, r0 |.endif | SET_EX_OPLINE opline, r0 - | EXT_CALL zend_jit_assign_op_to_typed_ref, r0 + if ((opline->op2_type & (IS_TMP_VAR|IS_VAR)) + && (op2_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE))) { + | EXT_CALL zend_jit_assign_op_to_typed_ref_tmp, r0 + } else { + | EXT_CALL zend_jit_assign_op_to_typed_ref, r0 + } |.if not(X64) | add r4, 12 |.endif @@ -13974,7 +13984,12 @@ static int zend_jit_assign_obj_op(dasm_State **Dst, | sub r4, 12 | PUSH_ADDR binary_op, r0 |.endif - | EXT_CALL zend_jit_assign_op_to_typed_ref, r0 + if (((opline+1)->op1_type & (IS_TMP_VAR|IS_VAR)) + && (val_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE))) { + | EXT_CALL zend_jit_assign_op_to_typed_ref_tmp, r0 + } else { + | EXT_CALL zend_jit_assign_op_to_typed_ref, r0 + } |.if not(X64) | add r4, 12 |.endif @@ -14044,7 +14059,12 @@ static int zend_jit_assign_obj_op(dasm_State **Dst, | sub r4, 12 | PUSH_ADDR binary_op, r0 |.endif - | EXT_CALL zend_jit_assign_op_to_typed_ref, r0 + if (((opline+1)->op1_type & (IS_TMP_VAR|IS_VAR)) + && (val_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE))) { + | EXT_CALL zend_jit_assign_op_to_typed_ref_tmp, r0 + } else { + | EXT_CALL zend_jit_assign_op_to_typed_ref, r0 + } |.if not(X64) | add r4, 12 |.endif diff --git a/ext/opcache/tests/jit/assign_obj_op_002.phpt b/ext/opcache/tests/jit/assign_obj_op_002.phpt new file mode 100644 index 0000000000000..3d6ac3f897bff --- /dev/null +++ b/ext/opcache/tests/jit/assign_obj_op_002.phpt @@ -0,0 +1,31 @@ +--TEST-- +JIT ASSIGN_OBJ_OP: memory leak +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +--FILE-- +prop .= $a->prop . "leak"; + return "test"; + } +} + +$a = new A; +$prop = &$a->prop; +$a->prop = new B; +var_dump($a); +?> +--EXPECT-- +object(A)#1 (1) { + ["prop"]=> + &string(4) "test" +} From aced867a952c189a3968a9ecf3e6ca28facc2153 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 28 Feb 2022 18:25:49 +0300 Subject: [PATCH 45/55] Fix typr inference Fixes oss-fuzz #45020 --- Zend/Optimizer/zend_inference.c | 1 + ext/opcache/tests/jit/assign_dim_013.phpt | 26 +++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 ext/opcache/tests/jit/assign_dim_013.phpt diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index 99e037829e875..6c5d96bd83158 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -2661,6 +2661,7 @@ static zend_always_inline int _zend_update_type_info( case ZEND_ASSIGN_DIM: if (opline->op1_type == IS_CV) { tmp = assign_dim_result_type(t1, t2, OP1_DATA_INFO(), opline->op2_type); + tmp |= ssa->var_info[ssa_op->op1_def].type & (MAY_BE_ARRAY_PACKED|MAY_BE_ARRAY_NUMERIC_HASH|MAY_BE_ARRAY_STRING_HASH); UPDATE_SSA_TYPE(tmp, ssa_op->op1_def); COPY_SSA_OBJ_TYPE(ssa_op->op1_use, ssa_op->op1_def); } diff --git a/ext/opcache/tests/jit/assign_dim_013.phpt b/ext/opcache/tests/jit/assign_dim_013.phpt new file mode 100644 index 0000000000000..49907b358a21a --- /dev/null +++ b/ext/opcache/tests/jit/assign_dim_013.phpt @@ -0,0 +1,26 @@ +--TEST-- +JIT ASSIGN_DIM: 013 +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +--FILE-- +y = set_error_handler(function(){}); + foreach($obj as $y) { + } + $arr = ['' => y]; + } +} +test(); +?> +--EXPECTF-- +Fatal error: Uncaught Error: Undefined constant "y" in %sassign_dim_013.php:8 +Stack trace: +#0 %sassign_dim_013.php(11): test() +#1 {main} + thrown in %sassign_dim_013.php on line 8 \ No newline at end of file From bb0b4eb996c86b927df86f6bdb1e8ac0749e5333 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 1 Mar 2022 00:00:22 +0300 Subject: [PATCH 46/55] Fix infiniry recursion during serialize() of "tricky" object Fixes oss-fuzz #44954 --- .../serialize/serialization_objects_016.phpt | 32 +++++++++++++++++++ ext/standard/var.c | 6 +++- 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 ext/standard/tests/serialize/serialization_objects_016.phpt diff --git a/ext/standard/tests/serialize/serialization_objects_016.phpt b/ext/standard/tests/serialize/serialization_objects_016.phpt new file mode 100644 index 0000000000000..92b83f5f3c9df --- /dev/null +++ b/ext/standard/tests/serialize/serialization_objects_016.phpt @@ -0,0 +1,32 @@ +--TEST-- +Object serialization / unserialization: circular object with rc=1 +--FILE-- +y=$t; +$y=(array)$t; +unset($t); +var_dump($y); +$s=serialize($y); +var_dump($s); +$x=unserialize($s); +var_dump($x); +vaR_dump(serialize($x)); +?> +--EXPECTF-- +array(1) { + ["y"]=> + object(stdClass)#%d (1) { + ["y"]=> + *RECURSION* + } +} +string(45) "a:1:{s:1:"y";O:8:"stdClass":1:{s:1:"y";r:2;}}" +array(1) { + ["y"]=> + object(stdClass)#%d (1) { + ["y"]=> + *RECURSION* + } +} +string(45) "a:1:{s:1:"y";O:8:"stdClass":1:{s:1:"y";r:2;}}" diff --git a/ext/standard/var.c b/ext/standard/var.c index ef4b019fb6e76..c429763eb9c86 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -662,7 +662,11 @@ static inline zend_long php_add_var_hash(php_serialize_data_t data, zval *var) / data->n += 1; - if (!is_ref && (Z_TYPE_P(var) != IS_OBJECT || Z_REFCOUNT_P(var) == 1)) { + if (is_ref) { + /* pass */ + } else if (Z_TYPE_P(var) != IS_OBJECT) { + return 0; + } else if (Z_REFCOUNT_P(var) == 1 && (Z_OBJ_P(var)->properties == NULL || GC_REFCOUNT(Z_OBJ_P(var)->properties) == 1)) { return 0; } From 01702a851b3902ac043d634f8cd7452edb26df1b Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 1 Mar 2022 01:33:22 +0300 Subject: [PATCH 47/55] Fix use after free Fixes oss-fuzz #44885 --- .../resume_running_generator_error_003.phpt | 24 +++++++++++++++++++ Zend/zend_generators.c | 3 +-- 2 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 Zend/tests/generators/errors/resume_running_generator_error_003.phpt diff --git a/Zend/tests/generators/errors/resume_running_generator_error_003.phpt b/Zend/tests/generators/errors/resume_running_generator_error_003.phpt new file mode 100644 index 0000000000000..c72f9ba87258c --- /dev/null +++ b/Zend/tests/generators/errors/resume_running_generator_error_003.phpt @@ -0,0 +1,24 @@ +--TEST-- +Use-after-free when resume an already running generator +--FILE-- +send($y); +} +$gen=gen(); +try { + $gen->send($gen); +}catch(y) { +} +?> +--EXPECTF-- +Warning: Undefined variable $y in %sresume_running_generator_error_003.php on line 4 + +Fatal error: Uncaught Error: Cannot resume an already running generator in %sresume_running_generator_error_003.php:4 +Stack trace: +#0 %sresume_running_generator_error_003.php(4): Generator->send(NULL) +#1 [internal function]: gen() +#2 %sresume_running_generator_error_003.php(8): Generator->send(Object(Generator)) +#3 {main} + thrown in %sresume_running_generator_error_003.php on line 4 diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 2e6e22effab9d..66d3bb3b62424 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -923,8 +923,7 @@ ZEND_METHOD(Generator, send) root = zend_generator_get_current(generator); /* Put sent value in the target VAR slot, if it is used */ - if (root->send_target) { - zval_ptr_dtor(root->send_target); + if (root->send_target && !(root->flags & ZEND_GENERATOR_CURRENTLY_RUNNING)) { ZVAL_COPY(root->send_target, value); } From 5507201a389f3ac0e3e25d5e805a5d54208a1410 Mon Sep 17 00:00:00 2001 From: Gabriel Caruso Date: Tue, 1 Mar 2022 11:30:01 +0100 Subject: [PATCH 48/55] Prepare for PHP 8.0.18 --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 7d8806639f1ba..19ef33896c5c4 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,6 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? 2022, PHP 8.0.17 +?? ??? 2022, PHP 8.0.18 - Core: . Fixed Haiku ZTS build. (David Carlier) From 05f2fb3af33e564c5da3aaca7e525d97af640a9d Mon Sep 17 00:00:00 2001 From: Gabriel Caruso Date: Tue, 1 Mar 2022 11:32:28 +0100 Subject: [PATCH 49/55] Fix NEWS format --- NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS b/NEWS index 19ef33896c5c4..c74365d2e079f 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 2022, PHP 8.0.18 + +17 Mar 2022, PHP 8.0.17 + - Core: . Fixed Haiku ZTS build. (David Carlier) From e6cf583160f2054da92426e69143e80ee28e8e16 Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Sat, 12 Feb 2022 01:26:23 +0100 Subject: [PATCH 50/55] Fix GH-8082: Prevent leaking memory on observed transient run_time_caches This is achieved by tracking the observers on the run_time_cache (with a fixed amount of slots, 2 for each observer). That way round, if the run_time_cache is freed all associated observer data is as well. This approach has been chosen, as to avoid any ABI or API breakage. Future versions may for example choose to provide a hookable API for run_time_cache freeing or similar. --- NEWS | 2 + Zend/zend.c | 2 - Zend/zend_extensions.c | 11 +- Zend/zend_extensions.h | 1 + Zend/zend_observer.c | 200 +++++++++---------- Zend/zend_observer.h | 1 + ext/zend_test/tests/observer_bug81430_1.phpt | 2 +- ext/zend_test/tests/observer_bug81430_2.phpt | 2 +- main/main.c | 3 + 9 files changed, 111 insertions(+), 113 deletions(-) diff --git a/NEWS b/NEWS index c74365d2e079f..9b35952df519b 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,8 @@ PHP NEWS - Core: . Fixed Haiku ZTS build. (David Carlier) + . Fixed bug GH-8082 (op_arrays with temporary run_time_cache leak memory + when observed). (Bob) - GD: . Fixed libpng warning when loading interlaced images. (Brett) diff --git a/Zend/zend.c b/Zend/zend.c index cbd5aef42b9fe..cb245bb7704ee 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -1215,8 +1215,6 @@ ZEND_API void zend_deactivate(void) /* {{{ */ /* we're no longer executing anything */ EG(current_execute_data) = NULL; - zend_observer_deactivate(); - zend_try { shutdown_scanner(); } zend_end_try(); diff --git a/Zend/zend_extensions.c b/Zend/zend_extensions.c index 4d4b1ffe09b41..c3efc0719bc94 100644 --- a/Zend/zend_extensions.c +++ b/Zend/zend_extensions.c @@ -267,8 +267,17 @@ ZEND_API int zend_get_resource_handle(const char *module_name) ZEND_API int zend_get_op_array_extension_handle(const char *module_name) { + int handle = zend_op_array_extension_handles++; zend_add_system_entropy(module_name, "zend_get_op_array_extension_handle", &zend_op_array_extension_handles, sizeof(int)); - return zend_op_array_extension_handles++; + return handle; +} + +ZEND_API int zend_get_op_array_extension_handles(const char *module_name, int handles) +{ + int handle = zend_op_array_extension_handles; + zend_op_array_extension_handles += handles; + zend_add_system_entropy(module_name, "zend_get_op_array_extension_handle", &zend_op_array_extension_handles, sizeof(int)); + return handle; } ZEND_API zend_extension *zend_get_extension(const char *extension_name) diff --git a/Zend/zend_extensions.h b/Zend/zend_extensions.h index 9f96d3b0fadba..195d508c3f358 100644 --- a/Zend/zend_extensions.h +++ b/Zend/zend_extensions.h @@ -115,6 +115,7 @@ extern ZEND_API int zend_op_array_extension_handles; ZEND_API int zend_get_resource_handle(const char *module_name); ZEND_API int zend_get_op_array_extension_handle(const char *module_name); +ZEND_API int zend_get_op_array_extension_handles(const char *module_name, int handles); ZEND_API void zend_extension_dispatch_message(int message, void *arg); END_EXTERN_C() diff --git a/Zend/zend_observer.c b/Zend/zend_observer.c index b970acd85c8e5..f347738107850 100644 --- a/Zend/zend_observer.c +++ b/Zend/zend_observer.c @@ -31,28 +31,36 @@ #define ZEND_OBSERVABLE_FN(fn_flags) \ (!(fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) -typedef struct _zend_observer_fcall_data { - // points after the last handler - zend_observer_fcall_handlers *end; - // a variadic array using "struct hack" - zend_observer_fcall_handlers handlers[1]; -} zend_observer_fcall_data; - zend_llist zend_observers_fcall_list; zend_llist zend_observer_error_callbacks; int zend_observer_fcall_op_array_extension; -ZEND_TLS zend_arena *fcall_handlers_arena; ZEND_TLS zend_execute_data *first_observed_frame; ZEND_TLS zend_execute_data *current_observed_frame; // Call during minit/startup ONLY -ZEND_API void zend_observer_fcall_register(zend_observer_fcall_init init) { - if (!ZEND_OBSERVER_ENABLED) { - /* We don't want to get an extension handle unless an ext installs an observer */ +ZEND_API void zend_observer_fcall_register(zend_observer_fcall_init init) +{ + zend_llist_add_element(&zend_observers_fcall_list, &init); +} + +// Called by engine before MINITs +ZEND_API void zend_observer_startup(void) +{ + zend_llist_init(&zend_observers_fcall_list, sizeof(zend_observer_fcall_init), NULL, 1); + zend_llist_init(&zend_observer_error_callbacks, sizeof(zend_observer_error_cb), NULL, 1); + + zend_observer_fcall_op_array_extension = -1; +} + +ZEND_API void zend_observer_post_startup(void) +{ + if (zend_observers_fcall_list.count) { + /* We don't want to get an extension handle unless an ext installs an observer + * Allocate each a begin and an end pointer */ zend_observer_fcall_op_array_extension = - zend_get_op_array_extension_handle("Zend Observer"); + zend_get_op_array_extension_handles("Zend Observer", (int) zend_observers_fcall_list.count * 2); /* ZEND_CALL_TRAMPOLINE has SPEC(OBSERVER) but zend_init_call_trampoline_op() * is called before any extensions have registered as an observer. So we @@ -62,123 +70,98 @@ ZEND_API void zend_observer_fcall_register(zend_observer_fcall_init init) { /* ZEND_HANDLE_EXCEPTION also has SPEC(OBSERVER) and no observer extensions * exist when zend_init_exception_op() is called. */ ZEND_VM_SET_OPCODE_HANDLER(EG(exception_op)); - ZEND_VM_SET_OPCODE_HANDLER(EG(exception_op)+1); - ZEND_VM_SET_OPCODE_HANDLER(EG(exception_op)+2); + ZEND_VM_SET_OPCODE_HANDLER(EG(exception_op) + 1); + ZEND_VM_SET_OPCODE_HANDLER(EG(exception_op) + 2); } - zend_llist_add_element(&zend_observers_fcall_list, &init); -} - -// Called by engine before MINITs -ZEND_API void zend_observer_startup(void) { - zend_llist_init(&zend_observers_fcall_list, sizeof(zend_observer_fcall_init), NULL, 1); - zend_llist_init(&zend_observer_error_callbacks, sizeof(zend_observer_error_cb), NULL, 1); - - zend_observer_fcall_op_array_extension = -1; } -ZEND_API void zend_observer_activate(void) { - if (ZEND_OBSERVER_ENABLED) { - fcall_handlers_arena = zend_arena_create(4096); - } else { - fcall_handlers_arena = NULL; - } +ZEND_API void zend_observer_activate(void) +{ first_observed_frame = NULL; current_observed_frame = NULL; } -ZEND_API void zend_observer_deactivate(void) { - if (fcall_handlers_arena) { - zend_arena_destroy(fcall_handlers_arena); - } +ZEND_API void zend_observer_deactivate(void) +{ + // now empty and unused, but kept for ABI compatibility } -ZEND_API void zend_observer_shutdown(void) { +ZEND_API void zend_observer_shutdown(void) +{ zend_llist_destroy(&zend_observers_fcall_list); zend_llist_destroy(&zend_observer_error_callbacks); } -static void zend_observer_fcall_install(zend_execute_data *execute_data) { - zend_llist_element *element; +static void zend_observer_fcall_install(zend_execute_data *execute_data) +{ zend_llist *list = &zend_observers_fcall_list; zend_function *function = execute_data->func; zend_op_array *op_array = &function->op_array; - if (fcall_handlers_arena == NULL) { - return; - } - ZEND_ASSERT(function->type != ZEND_INTERNAL_FUNCTION); - zend_llist handlers_list; - zend_llist_init(&handlers_list, sizeof(zend_observer_fcall_handlers), NULL, 0); - for (element = list->head; element; element = element->next) { + ZEND_ASSERT(RUN_TIME_CACHE(op_array)); + zend_observer_fcall_begin_handler *begin_handlers = (zend_observer_fcall_begin_handler *)&ZEND_OBSERVER_DATA(op_array); + zend_observer_fcall_end_handler *end_handlers = (zend_observer_fcall_end_handler *)begin_handlers + list->count, *end_handlers_start = end_handlers; + + *begin_handlers = ZEND_OBSERVER_NOT_OBSERVED; + *end_handlers = ZEND_OBSERVER_NOT_OBSERVED; + + for (zend_llist_element *element = list->head; element; element = element->next) { zend_observer_fcall_init init; memcpy(&init, element->data, sizeof init); zend_observer_fcall_handlers handlers = init(execute_data); - if (handlers.begin || handlers.end) { - zend_llist_add_element(&handlers_list, &handlers); + if (handlers.begin) { + *(begin_handlers++) = handlers.begin; } - } - - ZEND_ASSERT(RUN_TIME_CACHE(op_array)); - void *ext; - if (handlers_list.count) { - size_t size = sizeof(zend_observer_fcall_data) + (handlers_list.count - 1) * sizeof(zend_observer_fcall_handlers); - zend_observer_fcall_data *fcall_data = zend_arena_alloc(&fcall_handlers_arena, size); - zend_observer_fcall_handlers *handlers = fcall_data->handlers; - for (element = handlers_list.head; element; element = element->next) { - memcpy(handlers++, element->data, sizeof *handlers); + if (handlers.end) { + *(end_handlers++) = handlers.end; } - fcall_data->end = handlers; - ext = fcall_data; - } else { - ext = ZEND_OBSERVER_NOT_OBSERVED; } - - ZEND_OBSERVER_DATA(op_array) = ext; - zend_llist_destroy(&handlers_list); + + // end handlers are executed in reverse order + for (--end_handlers; end_handlers_start < end_handlers; --end_handlers, ++end_handlers_start) { + zend_observer_fcall_end_handler tmp = *end_handlers; + *end_handlers = *end_handlers_start; + *end_handlers_start = tmp; + } } static void ZEND_FASTCALL _zend_observe_fcall_begin(zend_execute_data *execute_data) { - zend_op_array *op_array; - uint32_t fn_flags; - zend_observer_fcall_data *fcall_data; - zend_observer_fcall_handlers *handlers, *end; - if (!ZEND_OBSERVER_ENABLED) { return; } - op_array = &execute_data->func->op_array; - fn_flags = op_array->fn_flags; + zend_op_array *op_array = &execute_data->func->op_array; + uint32_t fn_flags = op_array->fn_flags; if (!ZEND_OBSERVABLE_FN(fn_flags)) { return; } - fcall_data = ZEND_OBSERVER_DATA(op_array); - if (!fcall_data) { + zend_observer_fcall_begin_handler *handler = (zend_observer_fcall_begin_handler *)&ZEND_OBSERVER_DATA(op_array); + if (!*handler) { zend_observer_fcall_install(execute_data); - fcall_data = ZEND_OBSERVER_DATA(op_array); } - ZEND_ASSERT(fcall_data); - if (fcall_data == ZEND_OBSERVER_NOT_OBSERVED) { - return; - } + zend_observer_fcall_begin_handler *possible_handlers_end = handler + zend_observers_fcall_list.count; - if (first_observed_frame == NULL) { - first_observed_frame = execute_data; + zend_observer_fcall_end_handler *end_handler = (zend_observer_fcall_end_handler *)possible_handlers_end; + if (*end_handler != ZEND_OBSERVER_NOT_OBSERVED) { + if (first_observed_frame == NULL) { + first_observed_frame = execute_data; + } + current_observed_frame = execute_data; } - current_observed_frame = execute_data; - end = fcall_data->end; - for (handlers = fcall_data->handlers; handlers != end; ++handlers) { - if (handlers->begin) { - handlers->begin(execute_data); - } + if (*handler == ZEND_OBSERVER_NOT_OBSERVED) { + return; } + + do { + (*handler)(execute_data); + } while (++handler != possible_handlers_end && *handler != NULL); } ZEND_API void ZEND_FASTCALL zend_observer_generator_resume(zend_execute_data *execute_data) @@ -194,43 +177,48 @@ ZEND_API void ZEND_FASTCALL zend_observer_fcall_begin(zend_execute_data *execute } } -ZEND_API void ZEND_FASTCALL zend_observer_fcall_end( - zend_execute_data *execute_data, - zval *return_value) +static inline bool zend_observer_is_skipped_frame(zend_execute_data *execute_data) { + zend_function *func = execute_data->func; + + if (!func || func->type == ZEND_INTERNAL_FUNCTION || !ZEND_OBSERVABLE_FN(func->common.fn_flags)) { + return true; + } + + zend_observer_fcall_end_handler end_handler = (&ZEND_OBSERVER_DATA(&func->op_array))[zend_observers_fcall_list.count]; + if (end_handler == NULL || end_handler == ZEND_OBSERVER_NOT_OBSERVED) { + return true; + } + + return false; +} + +ZEND_API void ZEND_FASTCALL zend_observer_fcall_end(zend_execute_data *execute_data, zval *return_value) { zend_function *func = execute_data->func; - zend_observer_fcall_data *fcall_data; - zend_observer_fcall_handlers *handlers, *end; if (!ZEND_OBSERVER_ENABLED || !ZEND_OBSERVABLE_FN(func->common.fn_flags)) { return; } - fcall_data = (zend_observer_fcall_data*)ZEND_OBSERVER_DATA(&func->op_array); + zend_observer_fcall_end_handler *handler = (zend_observer_fcall_end_handler *)&ZEND_OBSERVER_DATA(&func->op_array) + zend_observers_fcall_list.count; // TODO: Fix exceptions from generators // ZEND_ASSERT(fcall_data); - if (!fcall_data || fcall_data == ZEND_OBSERVER_NOT_OBSERVED) { + if (!*handler || *handler == ZEND_OBSERVER_NOT_OBSERVED) { return; } - handlers = fcall_data->end; - end = fcall_data->handlers; - while (handlers-- != end) { - if (handlers->end) { - handlers->end(execute_data, return_value); - } - } + zend_observer_fcall_end_handler *possible_handlers_end = handler + zend_observers_fcall_list.count; + do { + (*handler)(execute_data, return_value); + } while (++handler != possible_handlers_end && *handler != NULL); if (first_observed_frame == execute_data) { first_observed_frame = NULL; current_observed_frame = NULL; } else { zend_execute_data *ex = execute_data->prev_execute_data; - while (ex && (!ex->func || ex->func->type == ZEND_INTERNAL_FUNCTION - || !ZEND_OBSERVABLE_FN(ex->func->common.fn_flags) - || !ZEND_OBSERVER_DATA(&ex->func->op_array) - || ZEND_OBSERVER_DATA(&ex->func->op_array) == ZEND_OBSERVER_NOT_OBSERVED)) { + while (ex && zend_observer_is_skipped_frame(ex)) { ex = ex->prev_execute_data; } current_observed_frame = ex; @@ -246,7 +234,6 @@ ZEND_API void zend_observer_fcall_end_all(void) } ex = ex->prev_execute_data; } - current_observed_frame = NULL; } ZEND_API void zend_observer_error_register(zend_observer_error_cb cb) @@ -256,11 +243,8 @@ ZEND_API void zend_observer_error_register(zend_observer_error_cb cb) void zend_observer_error_notify(int type, const char *error_filename, uint32_t error_lineno, zend_string *message) { - zend_llist_element *element; - zend_observer_error_cb callback; - - for (element = zend_observer_error_callbacks.head; element; element = element->next) { - callback = *(zend_observer_error_cb *) (element->data); + for (zend_llist_element *element = zend_observer_error_callbacks.head; element; element = element->next) { + zend_observer_error_cb callback = *(zend_observer_error_cb *) (element->data); callback(type, error_filename, error_lineno, message); } } diff --git a/Zend/zend_observer.h b/Zend/zend_observer.h index cb29729ec45da..2a2fce0761127 100644 --- a/Zend/zend_observer.h +++ b/Zend/zend_observer.h @@ -56,6 +56,7 @@ typedef zend_observer_fcall_handlers (*zend_observer_fcall_init)(zend_execute_da ZEND_API void zend_observer_fcall_register(zend_observer_fcall_init); ZEND_API void zend_observer_startup(void); // Called by engine before MINITs +ZEND_API void zend_observer_post_startup(void); // Called by engine after MINITs ZEND_API void zend_observer_activate(void); ZEND_API void zend_observer_deactivate(void); ZEND_API void zend_observer_shutdown(void); diff --git a/ext/zend_test/tests/observer_bug81430_1.phpt b/ext/zend_test/tests/observer_bug81430_1.phpt index cac53ef70cbbb..1d1e3c4256e0e 100644 --- a/ext/zend_test/tests/observer_bug81430_1.phpt +++ b/ext/zend_test/tests/observer_bug81430_1.phpt @@ -1,7 +1,7 @@ --TEST-- Bug #81430 (Attribute instantiation frame accessing invalid frame pointer) --EXTENSIONS-- -zend_test +zend-test --INI-- memory_limit=20M zend_test.observer.enabled=1 diff --git a/ext/zend_test/tests/observer_bug81430_2.phpt b/ext/zend_test/tests/observer_bug81430_2.phpt index 4d56248a80f34..a575fb9d7a038 100644 --- a/ext/zend_test/tests/observer_bug81430_2.phpt +++ b/ext/zend_test/tests/observer_bug81430_2.phpt @@ -1,7 +1,7 @@ --TEST-- Bug #81430 (Attribute instantiation leaves dangling execute_data pointer) --EXTENSIONS-- -zend_test +zend-test --INI-- memory_limit=20M zend_test.observer.enabled=1 diff --git a/main/main.c b/main/main.c index 073d260ac6898..7bd5400760f05 100644 --- a/main/main.c +++ b/main/main.c @@ -2280,6 +2280,9 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod module->version = PHP_VERSION; module->info_func = PHP_MINFO(php_core); } + + /* freeze the list of observer fcall_init handlers */ + zend_observer_post_startup(); /* Extensions that add engine hooks after this point do so at their own peril */ zend_finalize_system_id(); From 408efb7985f7832c51037029b76e284f80d7066c Mon Sep 17 00:00:00 2001 From: Patrick Allaert Date: Wed, 2 Mar 2022 17:29:59 +0100 Subject: [PATCH 51/55] Update NEWS for PHP 8.1.4RC1 --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 5474de448427d..5bc1cfc9af9b5 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,6 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.1.4 +03 Mar 2022, PHP 8.1.4RC1 - Core: . Fixed Haiku ZTS build. (David Carlier) From c8d5f4dcd18fabcbf54aaad7f64fb5ca2edf7b70 Mon Sep 17 00:00:00 2001 From: Patrick Allaert Date: Wed, 2 Mar 2022 17:30:42 +0100 Subject: [PATCH 52/55] Update versions for PHP 8.1.4RC1 --- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Zend/zend.h b/Zend/zend.h index 67afd49421fd9..549e76f751117 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.1.4-dev" +#define ZEND_VERSION "4.1.4RC1" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index 57e01def67e0e..06ea8b245599f 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.4-dev],[https://bugs.php.net],[php],[https://www.php.net]) +AC_INIT([PHP],[8.1.4RC1],[https://bugs.php.net],[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 fd5b1b0854a9b..f3bfa979f9e1e 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -3,6 +3,6 @@ #define PHP_MAJOR_VERSION 8 #define PHP_MINOR_VERSION 1 #define PHP_RELEASE_VERSION 4 -#define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.1.4-dev" +#define PHP_EXTRA_VERSION "RC1" +#define PHP_VERSION "8.1.4RC1" #define PHP_VERSION_ID 80104 From 0b50df23812f4cf02f126712885bed7fe1a10dae Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Tue, 15 Mar 2022 14:55:37 -0500 Subject: [PATCH 53/55] Fix versions in PHP-8.1.4 branch --- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Zend/zend.h b/Zend/zend.h index 549e76f751117..67afd49421fd9 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.1.4RC1" +#define ZEND_VERSION "4.1.4-dev" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index 06ea8b245599f..57e01def67e0e 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.4RC1],[https://bugs.php.net],[php],[https://www.php.net]) +AC_INIT([PHP],[8.1.4-dev],[https://bugs.php.net],[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 f3bfa979f9e1e..fd5b1b0854a9b 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -3,6 +3,6 @@ #define PHP_MAJOR_VERSION 8 #define PHP_MINOR_VERSION 1 #define PHP_RELEASE_VERSION 4 -#define PHP_EXTRA_VERSION "RC1" -#define PHP_VERSION "8.1.4RC1" +#define PHP_EXTRA_VERSION "-dev" +#define PHP_VERSION "8.1.4-dev" #define PHP_VERSION_ID 80104 From 964f494ad13c3cc9b4a17704ca1e5ba3cdb3e0c5 Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Tue, 15 Mar 2022 14:57:42 -0500 Subject: [PATCH 54/55] Prepare for PHP 8.1.4 GA --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 5bc1cfc9af9b5..0c5927890fb08 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,6 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -03 Mar 2022, PHP 8.1.4RC1 +17 Mar 2022, PHP 8.1.4 - Core: . Fixed Haiku ZTS build. (David Carlier) From 70c7d9b602805f3a3543f29af1902d6eaa8d8a54 Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Tue, 15 Mar 2022 15:02:24 -0500 Subject: [PATCH 55/55] Update versions for PHP 8.1.4 --- Zend/zend.h | 2 +- configure.ac | 2 +- main/php_version.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Zend/zend.h b/Zend/zend.h index 67afd49421fd9..7f152a8591e5b 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.1.4-dev" +#define ZEND_VERSION "4.1.4" #define ZEND_ENGINE_3 diff --git a/configure.ac b/configure.ac index 57e01def67e0e..b54abe326b8c6 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.4-dev],[https://bugs.php.net],[php],[https://www.php.net]) +AC_INIT([PHP],[8.1.4],[https://bugs.php.net],[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 fd5b1b0854a9b..d87c013026ff2 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -3,6 +3,6 @@ #define PHP_MAJOR_VERSION 8 #define PHP_MINOR_VERSION 1 #define PHP_RELEASE_VERSION 4 -#define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.1.4-dev" +#define PHP_EXTRA_VERSION "" +#define PHP_VERSION "8.1.4" #define PHP_VERSION_ID 80104