diff --git a/.editorconfig b/.editorconfig index 155d834fedfe8..7911bf8490b63 100644 --- a/.editorconfig +++ b/.editorconfig @@ -9,7 +9,7 @@ end_of_line = lf charset = utf-8 tab_width = 4 -[{*.{awk,bat,c,cpp,d,h,l,re,skl,w32,y},Makefile*}] +[{*.{awk,bat,c,cpp,d,dasc,h,l,re,skl,w32,y},Makefile*}] indent_size = 4 indent_style = tab diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 4d347323e89b3..16b99af3f730d 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -153,3 +153,34 @@ jobs: -d opcache.jit=1205 - name: Verify generated files are up to date uses: ./.github/actions/verify-generated-files + COVERAGE_DEBUG_NTS: + runs-on: ubuntu-20.04 + steps: + - name: git checkout + uses: actions/checkout@v2 + - name: Create mssql container + uses: ./.github/actions/mssql + - name: apt + uses: ./.github/actions/apt-x64 + - name: Install gcovr + run: sudo -H pip install gcovr + - name: ./configure + uses: ./.github/actions/configure-x64 + with: + configurationParameters: --enable-debug --disable-zts --enable-gcov + - 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 + # We only test with OpCache, the difference in coverage is negligible + - name: Test OpCache + uses: ./.github/actions/test-linux + with: + runTestsParameters: >- + -d zend_extension=opcache.so + -d opcache.enable_cli=1 + - name: Upload Test Coverage to Codecov.io + if: always() + run: bash <(curl -s https://codecov.io/bash) diff --git a/NEWS b/NEWS index e54603c47ab73..bdd499c83068e 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,50 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.1.8 +04 Aug 2022, PHP 8.1.9 + +- CLI: + . Fixed potential overflow for the builtin server via the PHP_CLI_SERVER_WORKERS + environment variable. (yiyuaner) + . Fixed GH-8952 (Intentionally closing std handles no longer possible). + (Arnaud, cmb) + +- Core: + . Fixed bug GH-8923 (error_log on Windows can hold the file write lock). (cmb) + . Fixed bug GH-8995 (WeakMap object reference offset causing TypeError). + (Tobias Bachert) + +- Date: + . Fixed bug #80047 (DatePeriod doesn't warn with custom DateTimeImmutable). + (Derick) + +- FPM: + . Fixed zlog message prepend, free on incorrect address. (Heiko Weber) + . Fixed possible double free on configuration loading failure. (Heiko Weber). + +- GD: + . Fixed bug GH-8848 (imagecopyresized() error refers to the wrong argument). + (cmb) + +- Intl: + . Fixed build for ICU 69.x and onwards. (David Carlier) + +- OPcache: + . Fixed bug GH-8847 (PHP hanging infinitly at 100% cpu when check php + syntaxe of a valid file). (Dmitry) + . Fixed bug GH-8030 (Segfault with JIT and large match/switch statements). + (Arnaud) + +- Reflection: + . Fixed bug GH-8943 (Fixed Reflection::getModifiersNames() with readonly + modifier). (Pierrick) + +- Standard: + . Fixed the crypt_sha256/512 api build with clang > 12. (David Carlier) + . Uses CCRandomGenerateBytes instead of arc4random_buf on macOs. (David Carlier). + . Fixed bug GH-9017 (php_stream_sock_open_from_socket could return NULL). + (Heiko Weber) + +07 Jul 2022, PHP 8.1.8 - Core: . Fixed bug GH-8338 (Intel CET is disabled unintentionally). (Chen, Hu) @@ -10,6 +54,8 @@ PHP NEWS . Fixed bug GH-8655 (Casting an object to array does not unwrap refcount=1 references). (Nicolas Grekas) . Fixed potential use after free in php_binary_init(). (Heiko Weber) + . Fixed bug GH-7942 (Indirect mutation of readonly properties through + references). (ilutov) - CLI: . Fixed GH-8827 (Intentionally closing std handles no longer possible). (cmb) @@ -30,12 +76,16 @@ PHP NEWS . Fixed bug #78139 (timezone_open accepts invalid timezone string argument). (Derick) -- GD: - . Fixed imagecreatefromavif() memory leak. (cmb) +- Fileinfo: + . Fixed bug #81723 (Heap buffer overflow in finfo_buffer). (CVE-2022-31627) + (cmb) - FPM: . Fixed bug #67764 (fpm: syslog.ident don't work). (Jakub Zelenka) +- GD: + . Fixed imagecreatefromavif() memory leak. (cmb) + - MBString: . mb_detect_encoding recognizes all letters in Czech alphabet (alexdowad) . mb_detect_encoding recognizes all letters in Hungarian alphabet (alexdowad) @@ -59,9 +109,6 @@ PHP NEWS - PDO_ODBC: . Fixed handling of single-key connection strings. (Calvin Buckley) -- SPL: - . Fixed bug GH-8563 (Different results for seek() on SplFileObject and SplTempFileObject). (Girgias) - - Zip: . Fixed bug GH-8781 (ZipArchive::close deletes zip file without updating stat cache). (Remi) diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index 867d2a5ddb578..5c72ad4a130a8 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -1936,6 +1936,9 @@ static uint32_t assign_dim_array_result_type( value_type |= MAY_BE_NULL; } if (dim_op_type == IS_UNUSED) { + if (arr_type & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) { + tmp |= MAY_BE_ARRAY_PACKED; + } tmp |= MAY_BE_HASH_ONLY(arr_type) ? MAY_BE_ARRAY_NUMERIC_HASH : MAY_BE_ARRAY_KEY_LONG; } else { if (dim_type & (MAY_BE_LONG|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_RESOURCE|MAY_BE_DOUBLE)) { @@ -3348,7 +3351,12 @@ static zend_always_inline int _zend_update_type_info( ZEND_ASSERT(j < 0 && "There should only be one use"); } } - if (((tmp & MAY_BE_ARRAY) && (tmp & MAY_BE_ARRAY_KEY_ANY)) || opline->opcode == ZEND_FETCH_DIM_FUNC_ARG) { + if (((tmp & MAY_BE_ARRAY) && (tmp & MAY_BE_ARRAY_KEY_ANY)) + || opline->opcode == ZEND_FETCH_DIM_FUNC_ARG + || opline->opcode == ZEND_FETCH_DIM_R + || opline->opcode == ZEND_FETCH_DIM_IS + || opline->opcode == ZEND_FETCH_DIM_UNSET + || opline->opcode == ZEND_FETCH_LIST_R) { UPDATE_SSA_TYPE(tmp, ssa_op->op1_def); } else { /* invalid key type */ diff --git a/Zend/tests/readonly_props/array_append_initialization.phpt b/Zend/tests/readonly_props/array_append_initialization.phpt index 079fecb8b3373..d9b3e8c074438 100644 --- a/Zend/tests/readonly_props/array_append_initialization.phpt +++ b/Zend/tests/readonly_props/array_append_initialization.phpt @@ -19,7 +19,11 @@ function init() { var_dump($c->a); } -(new C)->init(); +try { + (new C)->init(); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} try { init(); @@ -29,8 +33,5 @@ try { ?> --EXPECT-- -array(1) { - [0]=> - int(1) -} -Cannot initialize readonly property C::$a from global scope +Cannot indirectly modify readonly property C::$a +Cannot indirectly modify readonly property C::$a diff --git a/Zend/tests/readonly_props/gh7942.phpt b/Zend/tests/readonly_props/gh7942.phpt new file mode 100644 index 0000000000000..89db53439a2f2 --- /dev/null +++ b/Zend/tests/readonly_props/gh7942.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-7942: Disallow assigning reference to unset readonly property +--FILE-- +bar = &$bar; + } +} + +try { + $i = 42; + new Foo($i); +} catch (Error $e) { + echo $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Cannot indirectly modify readonly property Foo::$bar diff --git a/Zend/tests/readonly_props/variation.phpt b/Zend/tests/readonly_props/variation.phpt new file mode 100644 index 0000000000000..a8ea4be60887e --- /dev/null +++ b/Zend/tests/readonly_props/variation.phpt @@ -0,0 +1,118 @@ +--TEST-- +Readonly variations +--FILE-- +prop = 1; + } + + public function r() { + echo $this->prop; + } + + public function w() { + $this->prop = 1; + echo 'done'; + } + + public function rw() { + $this->prop += 1; + echo 'done'; + } + + public function im() { + $this->prop[] = 1; + echo 'done'; + } + + public function is() { + echo (int) isset($this->prop); + } + + public function us() { + unset($this->prop); + echo 'done'; + } +} + +function r($test) { + echo $test->prop; +} + +function w($test) { + $test->prop = 0; + echo 'done'; +} + +function rw($test) { + $test->prop += 1; + echo 'done'; +} + +function im($test) { + $test->prop[] = 1; + echo 'done'; +} + +function is($test) { + echo (int) isset($test->prop); +} + +function us($test) { + unset($test->prop); + echo 'done'; +} + +foreach ([true, false] as $init) { + foreach ([true, false] as $scope) { + foreach (['r', 'w', 'rw', 'im', 'is', 'us'] as $op) { + $test = new Test(); + if ($init) { + $test->init(); + } + + echo 'Init: ' . ((int) $init) . ', scope: ' . ((int) $scope) . ', op: ' . $op . ": "; + try { + if ($scope) { + $test->{$op}(); + } else { + $op($test); + } + } catch (Error $e) { + echo $e->getMessage(); + } + echo "\n"; + } + } +} + +?> +--EXPECT-- +Init: 1, scope: 1, op: r: 1 +Init: 1, scope: 1, op: w: Cannot modify readonly property Test::$prop +Init: 1, scope: 1, op: rw: Cannot modify readonly property Test::$prop +Init: 1, scope: 1, op: im: Cannot modify readonly property Test::$prop +Init: 1, scope: 1, op: is: 1 +Init: 1, scope: 1, op: us: Cannot unset readonly property Test::$prop +Init: 1, scope: 0, op: r: 1 +Init: 1, scope: 0, op: w: Cannot modify readonly property Test::$prop +Init: 1, scope: 0, op: rw: Cannot modify readonly property Test::$prop +Init: 1, scope: 0, op: im: Cannot modify readonly property Test::$prop +Init: 1, scope: 0, op: is: 1 +Init: 1, scope: 0, op: us: Cannot unset readonly property Test::$prop +Init: 0, scope: 1, op: r: Typed property Test::$prop must not be accessed before initialization +Init: 0, scope: 1, op: w: done +Init: 0, scope: 1, op: rw: Typed property Test::$prop must not be accessed before initialization +Init: 0, scope: 1, op: im: Cannot indirectly modify readonly property Test::$prop +Init: 0, scope: 1, op: is: 0 +Init: 0, scope: 1, op: us: done +Init: 0, scope: 0, op: r: Typed property Test::$prop must not be accessed before initialization +Init: 0, scope: 0, op: w: Cannot initialize readonly property Test::$prop from global scope +Init: 0, scope: 0, op: rw: Typed property Test::$prop must not be accessed before initialization +Init: 0, scope: 0, op: im: Cannot indirectly modify readonly property Test::$prop +Init: 0, scope: 0, op: is: 0 +Init: 0, scope: 0, op: us: Cannot unset readonly property Test::$prop from global scope diff --git a/Zend/tests/readonly_props/variation_nested.phpt b/Zend/tests/readonly_props/variation_nested.phpt new file mode 100644 index 0000000000000..72a7925da9905 --- /dev/null +++ b/Zend/tests/readonly_props/variation_nested.phpt @@ -0,0 +1,77 @@ +--TEST-- +Readonly nested variations +--FILE-- +prop = new Inner(); + } +} + +function r($test) { + echo $test->prop->prop; +} + +function w($test) { + $test->prop->prop = 0; + echo 'done'; +} + +function rw($test) { + $test->prop->prop += 1; + echo 'done'; +} + +function im($test) { + $test->prop->array[] = 1; + echo 'done'; +} + +function is($test) { + echo (int) isset($test->prop->prop); +} + +function us($test) { + unset($test->prop->prop); + echo 'done'; +} + +foreach ([true, false] as $init) { + foreach (['r', 'w', 'rw', 'im', 'is', 'us'] as $op) { + $test = new Test(); + if ($init) { + $test->init(); + } + + echo 'Init: ' . ((int) $init) . ', op: ' . $op . ": "; + try { + $op($test); + } catch (Error $e) { + echo $e->getMessage(); + } + echo "\n"; + } +} + +?> +--EXPECT-- +Init: 1, op: r: 1 +Init: 1, op: w: done +Init: 1, op: rw: done +Init: 1, op: im: done +Init: 1, op: is: 1 +Init: 1, op: us: done +Init: 0, op: r: Typed property Test::$prop must not be accessed before initialization +Init: 0, op: w: Cannot indirectly modify readonly property Test::$prop +Init: 0, op: rw: Typed property Test::$prop must not be accessed before initialization +Init: 0, op: im: Cannot indirectly modify readonly property Test::$prop +Init: 0, op: is: 0 +Init: 0, op: us: done diff --git a/Zend/tests/weakrefs/weakmap_object_reference.phpt b/Zend/tests/weakrefs/weakmap_object_reference.phpt new file mode 100644 index 0000000000000..b291092fdb7f5 --- /dev/null +++ b/Zend/tests/weakrefs/weakmap_object_reference.phpt @@ -0,0 +1,32 @@ +--TEST-- +WeakMap object reference offset +--FILE-- + +--EXPECT-- +int(1) +object(WeakMap)#1 (1) { + [0]=> + array(2) { + ["key"]=> + object(stdClass)#2 (0) { + } + ["value"]=> + int(1) + } +} +bool(true) +bool(true) +int(1) diff --git a/Zend/zend.h b/Zend/zend.h index 902d340427a03..0734388f720d7 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.1.8-dev" +#define ZEND_VERSION "4.1.9" #define ZEND_ENGINE_3 diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index ccd10d85c4f95..05bd59e5169db 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -849,6 +849,12 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_readonly_property_modification_error( ZSTR_VAL(info->ce->name), zend_get_unmangled_property_name(info->name)); } +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_readonly_property_indirect_modification_error(zend_property_info *info) +{ + zend_throw_error(NULL, "Cannot indirectly modify readonly property %s::$%s", + ZSTR_VAL(info->ce->name), zend_get_unmangled_property_name(info->name)); +} + static zend_class_entry *resolve_single_class_type(zend_string *name, zend_class_entry *self_ce) { if (zend_string_equals_literal_ci(name, "self")) { return self_ce; diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index d13087a5b0264..0a80daf25092e 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -74,6 +74,7 @@ ZEND_API ZEND_COLD zval* ZEND_FASTCALL zend_undefined_index_write(HashTable *ht, ZEND_API ZEND_COLD void zend_wrong_string_offset_error(void); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_readonly_property_modification_error(zend_property_info *info); +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_readonly_property_indirect_modification_error(zend_property_info *info); ZEND_API bool zend_verify_scalar_type_hint(uint32_t type_mask, zval *arg, bool strict, bool is_internal_arg); ZEND_API ZEND_COLD void zend_verify_arg_error( diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 966ba0dd6ed72..5fa80c1adc5e5 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -604,6 +604,17 @@ ZEND_API zval *zend_std_read_property(zend_object *zobj, zend_string *name, int } } goto exit; + } else { + if (prop_info && UNEXPECTED(prop_info->flags & ZEND_ACC_READONLY)) { + if (type == BP_VAR_W || type == BP_VAR_RW) { + zend_readonly_property_indirect_modification_error(prop_info); + retval = &EG(uninitialized_zval); + goto exit; + } else if (type == BP_VAR_UNSET) { + retval = &EG(uninitialized_zval); + goto exit; + } + } } if (UNEXPECTED(Z_PROP_FLAG_P(retval) == IS_PROP_UNINIT)) { /* Skip __get() for uninitialized typed properties */ @@ -1024,9 +1035,9 @@ ZEND_API zval *zend_std_get_property_ptr_ptr(zend_object *zobj, zend_string *nam ZVAL_NULL(retval); zend_error(E_WARNING, "Undefined property: %s::$%s", ZSTR_VAL(zobj->ce->name), ZSTR_VAL(name)); } - } else if (prop_info && UNEXPECTED(prop_info->flags & ZEND_ACC_READONLY) - && !verify_readonly_initialization_access(prop_info, zobj->ce, name, "initialize")) { - retval = &EG(error_zval); + } else if (prop_info && UNEXPECTED(prop_info->flags & ZEND_ACC_READONLY)) { + /* Readonly property, delegate to read_property + write_property. */ + retval = NULL; } } else { /* we do have getter - fail and let it try again with usual get/set */ diff --git a/Zend/zend_weakrefs.c b/Zend/zend_weakrefs.c index 226eb96a75520..791aa9ad27887 100644 --- a/Zend/zend_weakrefs.c +++ b/Zend/zend_weakrefs.c @@ -310,6 +310,7 @@ static zval *zend_weakmap_read_dimension(zend_object *object, zval *offset, int return NULL; } + ZVAL_DEREF(offset); if (Z_TYPE_P(offset) != IS_OBJECT) { zend_type_error("WeakMap key must be an object"); return NULL; @@ -340,6 +341,7 @@ static void zend_weakmap_write_dimension(zend_object *object, zval *offset, zval return; } + ZVAL_DEREF(offset); if (Z_TYPE_P(offset) != IS_OBJECT) { zend_type_error("WeakMap key must be an object"); return; @@ -367,6 +369,7 @@ static void zend_weakmap_write_dimension(zend_object *object, zval *offset, zval /* int return and check_empty due to Object Handler API */ static int zend_weakmap_has_dimension(zend_object *object, zval *offset, int check_empty) { + ZVAL_DEREF(offset); if (Z_TYPE_P(offset) != IS_OBJECT) { zend_type_error("WeakMap key must be an object"); return 0; @@ -386,6 +389,7 @@ static int zend_weakmap_has_dimension(zend_object *object, zval *offset, int che static void zend_weakmap_unset_dimension(zend_object *object, zval *offset) { + ZVAL_DEREF(offset); if (Z_TYPE_P(offset) != IS_OBJECT) { zend_type_error("WeakMap key must be an object"); return; diff --git a/azure-pipelines.yml b/azure-pipelines.yml index abb7c3f970923..03ce1779c8dbe 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -51,11 +51,6 @@ jobs: --enable-debug --enable-zts --enable-address-sanitizer --enable-undefined-sanitizer CFLAGS='-fno-sanitize-recover' timeoutInMinutes: 90 - - template: azure/coverage_job.yml - parameters: - configurationName: COVERAGE_DEBUG_ZTS - configurationParameters: '--enable-debug --disable-zts' - timeoutInMinutes: 90 - template: azure/opcache_variation_job.yml parameters: configurationName: DEBUG_NTS_OPCACHE diff --git a/azure/coverage_job.yml b/azure/coverage_job.yml deleted file mode 100644 index a68b7af4f4aa1..0000000000000 --- a/azure/coverage_job.yml +++ /dev/null @@ -1,49 +0,0 @@ -parameters: - configurationName: '' - configurationParameters: '' - runTestsParameters: '' - timeoutInMinutes: 60 - -jobs: - - job: ${{ parameters.configurationName }} - timeoutInMinutes: ${{ parameters.timeoutInMinutes }} - pool: - vmImage: 'ubuntu-20.04' - steps: - - template: mssql.yml - - template: apt.yml - - script: | - sudo -H pip install gcovr - displayName: 'Install gcovr' - - template: configure.yml - parameters: - configurationParameters: --enable-gcov ${{ parameters.configurationParameters }} - - script: make -j$(/usr/bin/nproc) >/dev/null - displayName: 'Make Build' - - template: install.yml - - template: setup.yml - - template: test.yml - parameters: - configurationName: ${{ parameters.configurationName }} - runTestsParameters: ${{ parameters.runTestsParameters }} - - template: test.yml - parameters: - configurationName: ${{ parameters.configurationName }} - runTestsName: 'OpCache' - runTestsParameters: >- - ${{ parameters.runTestsParameters }} - -d zend_extension=opcache.so - - script: bash <(curl -s https://codecov.io/bash) - displayName: 'Upload ${{ parameters.configurationName }} Test Coverage to Codecov.io' - condition: or(succeeded(), failed()) - - script: | - make gcovr-xml - mv gcovr.xml coverage.xml - displayName: 'Generate ${{ parameters.configurationName }} Test Coverage Cobertura XML Report' - condition: or(succeeded(), failed()) - - task: PublishCodeCoverageResults@1 - inputs: - codeCoverageTool: 'Cobertura' - summaryFileLocation: coverage.xml - displayName: 'Publish ${{ parameters.configurationName }} Test Coverage' - condition: or(succeeded(), failed()) diff --git a/configure.ac b/configure.ac index b95e3232aef0d..5d45519dc72f3 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.8-dev],[https://bugs.php.net],[php],[https://www.php.net]) +AC_INIT([PHP],[8.1.9],[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/ext/bz2/bz2_filter.c b/ext/bz2/bz2_filter.c index 4c573638366f1..9b3480b4a5ca9 100644 --- a/ext/bz2/bz2_filter.c +++ b/ext/bz2/bz2_filter.c @@ -366,7 +366,7 @@ static php_stream_filter *php_bz2_filter_create(const char *filtername, zval *fi /* How much memory to allocate (1 - 9) x 100kb */ zend_long blocks = zval_get_long(tmpzval); if (blocks < 1 || blocks > 9) { - php_error_docref(NULL, E_WARNING, "Invalid parameter given for number of blocks to allocate. (" ZEND_LONG_FMT ")", blocks); + php_error_docref(NULL, E_WARNING, "Invalid parameter given for number of blocks to allocate (" ZEND_LONG_FMT ")", blocks); } else { blockSize100k = (int) blocks; } @@ -376,7 +376,7 @@ static php_stream_filter *php_bz2_filter_create(const char *filtername, zval *fi /* Work Factor (0 - 250) */ zend_long work = zval_get_long(tmpzval); if (work < 0 || work > 250) { - php_error_docref(NULL, E_WARNING, "Invalid parameter given for work factor. (" ZEND_LONG_FMT ")", work); + php_error_docref(NULL, E_WARNING, "Invalid parameter given for work factor (" ZEND_LONG_FMT ")", work); } else { workFactor = (int) work; } diff --git a/ext/bz2/tests/bug72447.phpt b/ext/bz2/tests/bug72447.phpt index 7cbd43a443802..11f3bd9136b54 100644 --- a/ext/bz2/tests/bug72447.phpt +++ b/ext/bz2/tests/bug72447.phpt @@ -16,4 +16,4 @@ fclose($fp); unlink('testfile'); ?> --EXPECTF-- -Warning: stream_filter_append(): Invalid parameter given for number of blocks to allocate. (0) in %s%ebug72447.php on line %d +Warning: stream_filter_append(): Invalid parameter given for number of blocks to allocate (0) in %s%ebug72447.php on line %d diff --git a/ext/date/php_date.c b/ext/date/php_date.c index c22b9159fd8a5..3e5de97c6636c 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -1475,6 +1475,17 @@ static int date_period_it_has_more(zend_object_iterator *iter) } /* }}} */ +static zend_class_entry *get_base_date_class(zend_class_entry *start_ce) +{ + zend_class_entry *tmp = start_ce; + + while (tmp != date_ce_date && tmp != date_ce_immutable && tmp->parent) { + tmp = tmp->parent; + } + + return tmp; +} + /* {{{ date_period_it_current_data */ static zval *date_period_it_current_data(zend_object_iterator *iter) { @@ -1484,7 +1495,7 @@ static zval *date_period_it_current_data(zend_object_iterator *iter) php_date_obj *newdateobj; /* Create new object */ - php_date_instantiate(object->start_ce, &iterator->current); + php_date_instantiate(get_base_date_class(object->start_ce), &iterator->current); newdateobj = Z_PHPDATE_P(&iterator->current); newdateobj->time = timelib_time_ctor(); *newdateobj->time = *it_time; diff --git a/ext/date/tests/bug80047.phpt b/ext/date/tests/bug80047.phpt new file mode 100644 index 0000000000000..30f66375da884 --- /dev/null +++ b/ext/date/tests/bug80047.phpt @@ -0,0 +1,39 @@ +--TEST-- +Bug #80047: DatePeriod doesn't support custom DateTimeImmutable +--INI-- +date.timezone=UTC +--FILE-- + +--EXPECT-- +DateTime +DateTime +DateTime +DateTimeImmutable +DateTimeImmutable +DateTimeImmutable +DateTimeImmutable diff --git a/ext/dba/dba_lmdb.c b/ext/dba/dba_lmdb.c index d78ba0f891fb3..4eb7cdd32c489 100644 --- a/ext/dba/dba_lmdb.c +++ b/ext/dba/dba_lmdb.c @@ -254,6 +254,7 @@ DBA_DELETE_FUNC(lmdb) php_error_docref1(NULL, key, E_WARNING, "%s", mdb_strerror(rc)); + mdb_txn_abort(LMDB_IT(txn)); return FAILURE; } diff --git a/ext/fileinfo/libmagic.patch b/ext/fileinfo/libmagic.patch index 27124692a00a9..3373ae451989e 100644 --- a/ext/fileinfo/libmagic.patch +++ b/ext/fileinfo/libmagic.patch @@ -1,6 +1,6 @@ -diff -ur libmagic.orig/apprentice.c libmagic/apprentice.c +diff -u libmagic.orig/apprentice.c libmagic/apprentice.c --- libmagic.orig/apprentice.c 2021-02-23 01:51:11.000000000 +0100 -+++ libmagic/apprentice.c 2021-04-06 21:34:57.332978922 +0200 ++++ libmagic/apprentice.c 2022-06-16 13:39:41.570984700 +0200 @@ -29,6 +29,8 @@ * apprentice - make one pass through /etc/magic, learning its secrets. */ @@ -925,9 +925,9 @@ diff -ur libmagic.orig/apprentice.c libmagic/apprentice.c m->str_range = swap4(m->str_range); m->str_flags = swap4(m->str_flags); } -diff -ur libmagic.orig/ascmagic.c libmagic/ascmagic.c +diff -u libmagic.orig/ascmagic.c libmagic/ascmagic.c --- libmagic.orig/ascmagic.c 2021-02-23 01:49:06.000000000 +0100 -+++ libmagic/ascmagic.c 2021-04-06 21:34:57.332978922 +0200 ++++ libmagic/ascmagic.c 2022-06-16 13:39:41.570984700 +0200 @@ -96,7 +96,7 @@ rv = file_ascmagic_with_encoding(ms, &bb, ubuf, ulen, code, type, text); @@ -956,9 +956,9 @@ diff -ur libmagic.orig/ascmagic.c libmagic/ascmagic.c return rv; } -diff -ur libmagic.orig/buffer.c libmagic/buffer.c +diff -u libmagic.orig/buffer.c libmagic/buffer.c --- libmagic.orig/buffer.c 2021-02-23 01:49:26.000000000 +0100 -+++ libmagic/buffer.c 2021-04-06 21:34:57.332978922 +0200 ++++ libmagic/buffer.c 2021-09-21 13:27:27.982716100 +0200 @@ -31,19 +31,23 @@ #endif /* lint */ @@ -1012,9 +1012,9 @@ diff -ur libmagic.orig/buffer.c libmagic/buffer.c b->ebuf = NULL; goto out; } -diff -ur libmagic.orig/cdf.c libmagic/cdf.c +diff -u libmagic.orig/cdf.c libmagic/cdf.c --- libmagic.orig/cdf.c 2021-02-23 01:49:06.000000000 +0100 -+++ libmagic/cdf.c 2021-04-06 21:34:57.332978922 +0200 ++++ libmagic/cdf.c 2021-09-21 13:27:27.983695600 +0200 @@ -43,7 +43,17 @@ #include #endif @@ -1247,9 +1247,9 @@ diff -ur libmagic.orig/cdf.c libmagic/cdf.c } #endif -diff -ur libmagic.orig/cdf.h libmagic/cdf.h +diff -u libmagic.orig/cdf.h libmagic/cdf.h --- libmagic.orig/cdf.h 2021-02-23 01:49:06.000000000 +0100 -+++ libmagic/cdf.h 2021-04-06 21:34:57.332978922 +0200 ++++ libmagic/cdf.h 2021-09-21 13:27:27.984674900 +0200 @@ -35,10 +35,10 @@ #ifndef _H_CDF_ #define _H_CDF_ @@ -1264,9 +1264,9 @@ diff -ur libmagic.orig/cdf.h libmagic/cdf.h #endif #ifdef __DJGPP__ #define timespec timeval -diff -ur libmagic.orig/cdf_time.c libmagic/cdf_time.c +diff -u libmagic.orig/cdf_time.c libmagic/cdf_time.c --- libmagic.orig/cdf_time.c 2021-02-23 01:49:06.000000000 +0100 -+++ libmagic/cdf_time.c 2021-04-06 21:34:57.336978894 +0200 ++++ libmagic/cdf_time.c 2021-09-21 13:27:27.985654400 +0200 @@ -23,6 +23,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. @@ -1293,9 +1293,9 @@ diff -ur libmagic.orig/cdf_time.c libmagic/cdf_time.c if (ptr != NULL) return buf; (void)snprintf(buf, 26, "*Bad* %#16.16" INT64_T_FORMAT "x\n", -diff -ur libmagic.orig/compress.c libmagic/compress.c +diff -u libmagic.orig/compress.c libmagic/compress.c --- libmagic.orig/compress.c 2021-02-23 01:49:07.000000000 +0100 -+++ libmagic/compress.c 2021-04-06 21:34:57.336978894 +0200 ++++ libmagic/compress.c 2022-06-16 13:39:41.586609800 +0200 @@ -51,7 +51,7 @@ #ifndef HAVE_SIG_T typedef void (*sig_t)(int); @@ -1430,9 +1430,9 @@ diff -ur libmagic.orig/compress.c libmagic/compress.c } #endif +#endif -diff -ur libmagic.orig/der.c libmagic/der.c +diff -u libmagic.orig/der.c libmagic/der.c --- libmagic.orig/der.c 2021-02-23 01:49:06.000000000 +0100 -+++ libmagic/der.c 2021-04-06 21:34:57.336978894 +0200 ++++ libmagic/der.c 2022-06-16 13:39:41.586609800 +0200 @@ -54,7 +54,9 @@ #include "magic.h" #include "der.h" @@ -1443,9 +1443,9 @@ diff -ur libmagic.orig/der.c libmagic/der.c #include #include #endif -diff -ur libmagic.orig/elfclass.h libmagic/elfclass.h +diff -u libmagic.orig/elfclass.h libmagic/elfclass.h --- libmagic.orig/elfclass.h 2021-02-23 01:49:06.000000000 +0100 -+++ libmagic/elfclass.h 2021-04-06 21:34:57.336978894 +0200 ++++ libmagic/elfclass.h 2021-09-21 13:27:27.989571700 +0200 @@ -41,7 +41,7 @@ return toomany(ms, "program headers", phnum); flags |= FLAGS_IS_CORE; @@ -1473,9 +1473,9 @@ diff -ur libmagic.orig/elfclass.h libmagic/elfclass.h CAST(size_t, elf_getu16(swap, elfhdr.e_shentsize)), fsize, elf_getu16(swap, elfhdr.e_machine), CAST(int, elf_getu16(swap, elfhdr.e_shstrndx)), -diff -ur libmagic.orig/encoding.c libmagic/encoding.c +diff -u libmagic.orig/encoding.c libmagic/encoding.c --- libmagic.orig/encoding.c 2021-02-23 01:49:06.000000000 +0100 -+++ libmagic/encoding.c 2021-04-06 21:34:57.336978894 +0200 ++++ libmagic/encoding.c 2022-06-16 13:39:41.586609800 +0200 @@ -98,14 +98,14 @@ nbytes = ms->encoding_max; @@ -1514,9 +1514,9 @@ diff -ur libmagic.orig/encoding.c libmagic/encoding.c } \ if (u < 3) \ return 0; \ -diff -ur libmagic.orig/file.h libmagic/file.h +diff -u libmagic.orig/file.h libmagic/file.h --- libmagic.orig/file.h 2021-02-23 01:49:06.000000000 +0100 -+++ libmagic/file.h 2021-04-06 21:34:57.336978894 +0200 ++++ libmagic/file.h 2022-06-16 13:39:41.586609800 +0200 @@ -33,17 +33,14 @@ #ifndef __file_h__ #define __file_h__ @@ -1775,9 +1775,9 @@ diff -ur libmagic.orig/file.h libmagic/file.h +#endif + #endif /* __file_h__ */ -diff -ur libmagic.orig/fsmagic.c libmagic/fsmagic.c +diff -u libmagic.orig/fsmagic.c libmagic/fsmagic.c --- libmagic.orig/fsmagic.c 2021-02-23 01:49:06.000000000 +0100 -+++ libmagic/fsmagic.c 2021-04-06 21:34:57.336978894 +0200 ++++ libmagic/fsmagic.c 2021-09-21 13:27:27.992511000 +0200 @@ -66,26 +66,10 @@ # define minor(dev) ((dev) & 0xff) #endif @@ -2068,9 +2068,9 @@ diff -ur libmagic.orig/fsmagic.c libmagic/fsmagic.c #ifdef S_IFSOCK #ifndef __COHERENT__ case S_IFSOCK: -diff -ur libmagic.orig/funcs.c libmagic/funcs.c +diff -u libmagic.orig/funcs.c libmagic/funcs.c --- libmagic.orig/funcs.c 2021-02-23 01:49:06.000000000 +0100 -+++ libmagic/funcs.c 2021-04-06 21:34:57.336978894 +0200 ++++ libmagic/funcs.c 2022-06-16 13:39:41.586609800 +0200 @@ -51,6 +51,13 @@ #define SIZE_MAX ((size_t)~0) #endif @@ -2388,9 +2388,9 @@ diff -ur libmagic.orig/funcs.c libmagic/funcs.c protected char * file_strtrim(char *str) -diff -ur libmagic.orig/magic.c libmagic/magic.c +diff -u libmagic.orig/magic.c libmagic/magic.c --- libmagic.orig/magic.c 2021-02-23 01:49:06.000000000 +0100 -+++ libmagic/magic.c 2021-04-06 21:34:57.336978894 +0200 ++++ libmagic/magic.c 2022-06-16 13:39:41.586609800 +0200 @@ -25,11 +25,6 @@ * SUCH DAMAGE. */ @@ -2867,9 +2867,9 @@ diff -ur libmagic.orig/magic.c libmagic/magic.c return NULL; } return file_getbuffer(ms); -diff -ur libmagic.orig/magic.h libmagic/magic.h ---- libmagic.orig/magic.h 2021-04-06 22:37:37.647426536 +0200 -+++ libmagic/magic.h 2021-04-06 21:34:57.336978894 +0200 +diff -u libmagic.orig/magic.h libmagic/magic.h +--- libmagic.orig/magic.h 2022-06-30 17:16:06.144009900 +0200 ++++ libmagic/magic.h 2022-06-16 13:39:41.586609800 +0200 @@ -126,6 +126,7 @@ const char *magic_getpath(const char *, int); @@ -2878,9 +2878,9 @@ diff -ur libmagic.orig/magic.h libmagic/magic.h const char *magic_descriptor(magic_t, int); const char *magic_buffer(magic_t, const void *, size_t); -diff -ur libmagic.orig/print.c libmagic/print.c +diff -u libmagic.orig/print.c libmagic/print.c --- libmagic.orig/print.c 2021-02-23 01:49:07.000000000 +0100 -+++ libmagic/print.c 2021-04-06 21:34:57.340978869 +0200 ++++ libmagic/print.c 2021-09-21 13:27:27.998388700 +0200 @@ -28,6 +28,7 @@ /* * print.c - debugging printout routines @@ -2943,9 +2943,9 @@ diff -ur libmagic.orig/print.c libmagic/print.c if (pp == NULL) goto out; -diff -ur libmagic.orig/readcdf.c libmagic/readcdf.c +diff -u libmagic.orig/readcdf.c libmagic/readcdf.c --- libmagic.orig/readcdf.c 2021-02-23 01:49:08.000000000 +0100 -+++ libmagic/readcdf.c 2021-04-06 21:34:57.340978869 +0200 ++++ libmagic/readcdf.c 2021-09-21 13:27:27.999369100 +0200 @@ -31,7 +31,11 @@ #include @@ -3067,9 +3067,9 @@ diff -ur libmagic.orig/readcdf.c libmagic/readcdf.c out0: /* If we handled it already, return */ if (i != -1) -diff -ur libmagic.orig/softmagic.c libmagic/softmagic.c +diff -u libmagic.orig/softmagic.c libmagic/softmagic.c --- libmagic.orig/softmagic.c 2021-02-23 01:49:06.000000000 +0100 -+++ libmagic/softmagic.c 2021-04-06 21:34:57.340978869 +0200 ++++ libmagic/softmagic.c 2022-06-30 16:58:15.521661800 +0200 @@ -43,6 +43,10 @@ #include #include "der.h" @@ -3247,7 +3247,29 @@ diff -ur libmagic.orig/softmagic.c libmagic/softmagic.c return rv; } -@@ -1845,15 +1847,15 @@ +@@ -1531,11 +1533,7 @@ + size_t len; + *c = ms->c; + len = c->len * sizeof(*c->li); +- ms->c.li = CAST(struct level_info *, malloc(len)); +- if (ms->c.li == NULL) { +- ms->c = *c; +- return -1; +- } ++ ms->c.li = CAST(struct level_info *, emalloc(len)); + memcpy(ms->c.li, c->li, len); + return 0; + } +@@ -1543,7 +1541,7 @@ + private void + restore_cont(struct magic_set *ms, struct cont *c) + { +- free(ms->c.li); ++ efree(ms->c.li); + ms->c = *c; + } + +@@ -1845,15 +1843,15 @@ if ((ms->flags & MAGIC_NODESC) == 0 && file_printf(ms, F(ms, m->desc, "%u"), offset) == -1) { @@ -3266,7 +3288,7 @@ diff -ur libmagic.orig/softmagic.c libmagic/softmagic.c return rv; case FILE_USE: -@@ -1958,10 +1960,13 @@ +@@ -1958,10 +1956,13 @@ } else if ((flags & STRING_COMPACT_WHITESPACE) && isspace(*a)) { @@ -3281,7 +3303,7 @@ diff -ur libmagic.orig/softmagic.c libmagic/softmagic.c b++; } else { -@@ -1997,6 +2002,60 @@ +@@ -1997,6 +1998,60 @@ return file_strncmp(a, b, len, maxlen, flags); } @@ -3342,7 +3364,7 @@ diff -ur libmagic.orig/softmagic.c libmagic/softmagic.c private int magiccheck(struct magic_set *ms, struct magic *m) { -@@ -2176,65 +2235,77 @@ +@@ -2176,65 +2231,77 @@ break; } case FILE_REGEX: { @@ -3471,9 +3493,9 @@ diff -ur libmagic.orig/softmagic.c libmagic/softmagic.c break; } case FILE_USE: -diff -ur libmagic.orig/strcasestr.c libmagic/strcasestr.c +diff -u libmagic.orig/strcasestr.c libmagic/strcasestr.c --- libmagic.orig/strcasestr.c 2021-02-23 01:49:12.000000000 +0100 -+++ libmagic/strcasestr.c 2021-04-06 21:34:57.340978869 +0200 ++++ libmagic/strcasestr.c 2021-09-21 13:27:28.002306200 +0200 @@ -39,6 +39,8 @@ #include "file.h" @@ -3483,7 +3505,3 @@ diff -ur libmagic.orig/strcasestr.c libmagic/strcasestr.c #include #include #include ---- libmagic/config.h 2021-04-06 22:19:57.552120067 +0200 -+++ /dev/null 2021-03-31 20:37:24.776503884 +0200 -@@ -1 +0,0 @@ --#include "php.h" diff --git a/ext/fileinfo/libmagic/softmagic.c b/ext/fileinfo/libmagic/softmagic.c index c86524e31e623..5132b4ddea7ed 100644 --- a/ext/fileinfo/libmagic/softmagic.c +++ b/ext/fileinfo/libmagic/softmagic.c @@ -1533,11 +1533,7 @@ save_cont(struct magic_set *ms, struct cont *c) size_t len; *c = ms->c; len = c->len * sizeof(*c->li); - ms->c.li = CAST(struct level_info *, malloc(len)); - if (ms->c.li == NULL) { - ms->c = *c; - return -1; - } + ms->c.li = CAST(struct level_info *, emalloc(len)); memcpy(ms->c.li, c->li, len); return 0; } @@ -1545,7 +1541,7 @@ save_cont(struct magic_set *ms, struct cont *c) private void restore_cont(struct magic_set *ms, struct cont *c) { - free(ms->c.li); + efree(ms->c.li); ms->c = *c; } diff --git a/ext/fileinfo/tests/bug81723.phpt b/ext/fileinfo/tests/bug81723.phpt new file mode 100644 index 0000000000000..16bfb81f10de8 --- /dev/null +++ b/ext/fileinfo/tests/bug81723.phpt @@ -0,0 +1,12 @@ +--TEST-- +Bug #81723 (Memory corruption in finfo_buffer()) +--EXTENSIONS-- +fileinfo +--FILE-- + +--EXPECT-- diff --git a/ext/gd/gd.c b/ext/gd/gd.c index 0dbcf2de4bfe8..7a093b17741b4 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -3086,22 +3086,22 @@ PHP_FUNCTION(imagecopyresized) dstW = DW; if (dstW <= 0) { - zend_argument_value_error(3, "must be greater than 0"); + zend_argument_value_error(7, "must be greater than 0"); RETURN_THROWS(); } if (dstH <= 0) { - zend_argument_value_error(4, "must be greater than 0"); + zend_argument_value_error(8, "must be greater than 0"); RETURN_THROWS(); } if (srcW <= 0) { - zend_argument_value_error(5, "must be greater than 0"); + zend_argument_value_error(9, "must be greater than 0"); RETURN_THROWS(); } if (srcH <= 0) { - zend_argument_value_error(6, "must be greater than 0"); + zend_argument_value_error(10, "must be greater than 0"); RETURN_THROWS(); } diff --git a/ext/gd/tests/gh8848.phpt b/ext/gd/tests/gh8848.phpt new file mode 100644 index 0000000000000..0e18b64babb3d --- /dev/null +++ b/ext/gd/tests/gh8848.phpt @@ -0,0 +1,29 @@ +--TEST-- +GH-8848 (imagecopyresized() error refers to the wrong argument) +--EXTENSIONS-- +gd +--FILE-- +getMessage(), PHP_EOL; + } +} +?> +--EXPECT-- +imagecopyresized(): Argument #7 ($dst_width) must be greater than 0 +imagecopyresized(): Argument #8 ($dst_height) must be greater than 0 +imagecopyresized(): Argument #9 ($src_width) must be greater than 0 +imagecopyresized(): Argument #10 ($src_height) must be greater than 0 diff --git a/ext/intl/converter/converter.c b/ext/intl/converter/converter.c index c3d54e8a84a4d..5358c8a0e38f8 100644 --- a/ext/intl/converter/converter.c +++ b/ext/intl/converter/converter.c @@ -933,10 +933,18 @@ static zend_object *php_converter_clone_object(zend_object *object) { intl_errors_reset(&oldobj->error); +#if U_ICU_VERSION_MAJOR_NUM > 70 + objval->src = ucnv_clone(oldobj->src, &error); +#else objval->src = ucnv_safeClone(oldobj->src, NULL, NULL, &error); +#endif if (U_SUCCESS(error)) { error = U_ZERO_ERROR; +#if U_ICU_VERSION_MAJOR_NUM > 70 + objval->dest = ucnv_clone(oldobj->dest, &error); +#else objval->dest = ucnv_safeClone(oldobj->dest, NULL, NULL, &error); +#endif } if (U_FAILURE(error)) { zend_string *err_msg; diff --git a/ext/intl/grapheme/grapheme_util.c b/ext/intl/grapheme/grapheme_util.c index 25a0b5dfb6309..5722d410a80a1 100644 --- a/ext/intl/grapheme/grapheme_util.c +++ b/ext/intl/grapheme/grapheme_util.c @@ -372,8 +372,6 @@ zend_long grapheme_strrpos_ascii(char *haystack, size_t haystack_len, char *need /* {{{ grapheme_get_break_iterator: get a clone of the global character break iterator */ UBreakIterator* grapheme_get_break_iterator(void *stack_buffer, UErrorCode *status ) { - int32_t buffer_size; - UBreakIterator *global_break_iterator = INTL_G( grapheme_iterator ); if ( NULL == global_break_iterator ) { @@ -387,8 +385,12 @@ UBreakIterator* grapheme_get_break_iterator(void *stack_buffer, UErrorCode *stat INTL_G(grapheme_iterator) = global_break_iterator; } - buffer_size = U_BRK_SAFECLONE_BUFFERSIZE; +#if U_ICU_VERSION_MAJOR_NUM >= 69 + return ubrk_clone(global_break_iterator, status); +#else + int32_t buffer_size = U_BRK_SAFECLONE_BUFFERSIZE; return ubrk_safeClone(global_break_iterator, stack_buffer, &buffer_size, status); +#endif } /* }}} */ diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index d9eaaf5794431..6d5d55790bcf8 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -1672,22 +1672,18 @@ static void zend_jit_add_hint(zend_lifetime_interval **intervals, int dst, int s src = dst; dst = tmp; } - while (1) { - if (intervals[dst]->hint) { - if (intervals[dst]->hint->range.start < intervals[src]->range.start) { - int tmp = src; - src = intervals[dst]->hint->ssa_var; - dst = tmp; - } else { - dst = intervals[dst]->hint->ssa_var; - } + while (dst != src && intervals[dst]->hint) { + if (intervals[dst]->hint->range.start < intervals[src]->range.start) { + int tmp = src; + src = intervals[dst]->hint->ssa_var; + dst = tmp; } else { - if (dst != src) { - intervals[dst]->hint = intervals[src]; - } - return; + dst = intervals[dst]->hint->ssa_var; } } + if (dst != src) { + intervals[dst]->hint = intervals[src]; + } } /* See "Linear Scan Register Allocation on SSA Form", Christian Wimmer and diff --git a/ext/opcache/jit/zend_jit_arm64.dasc b/ext/opcache/jit/zend_jit_arm64.dasc index fdebed8f066e3..7f9f08bdd7788 100644 --- a/ext/opcache/jit/zend_jit_arm64.dasc +++ b/ext/opcache/jit/zend_jit_arm64.dasc @@ -13992,6 +13992,9 @@ static int zend_jit_hash_jmp(dasm_State **Dst, const zend_op *opline, const zend } else { exit_point = zend_jit_trace_get_exit_point(target, 0); exit_addr = zend_jit_trace_get_exit_addr(exit_point); + if (!exit_addr) { + return 0; + } | .addr &exit_addr } } @@ -14154,6 +14157,9 @@ static int zend_jit_switch(dasm_State **Dst, const zend_op *opline, const zend_o } else { exit_point = zend_jit_trace_get_exit_point(target, 0); exit_addr = zend_jit_trace_get_exit_addr(exit_point); + if (!exit_addr) { + return 0; + } | .addr &exit_addr } } diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index f953d704ca090..2b9f33a67be74 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -2563,6 +2563,11 @@ static void ZEND_FASTCALL zend_jit_assign_op_to_typed_prop(zval *zptr, zend_prop zend_execute_data *execute_data = EG(current_execute_data); zval z_copy; + if (UNEXPECTED(prop_info->flags & ZEND_ACC_READONLY)) { + zend_readonly_property_modification_error(prop_info); + return; + } + ZVAL_DEREF(zptr); /* Make sure that in-place concatenation is used if the LHS is a string. */ if (binary_op == concat_function && Z_TYPE_P(zptr) == IS_STRING) { diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 3335f3cefe33e..d90f4372eabba 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -14877,6 +14877,9 @@ static int zend_jit_hash_jmp(dasm_State **Dst, const zend_op *opline, const zend } else { exit_point = zend_jit_trace_get_exit_point(target, 0); exit_addr = zend_jit_trace_get_exit_addr(exit_point); + if (!exit_addr) { + return 0; + } | .aword &exit_addr } } @@ -15043,6 +15046,9 @@ static int zend_jit_switch(dasm_State **Dst, const zend_op *opline, const zend_o } else { exit_point = zend_jit_trace_get_exit_point(target, 0); exit_addr = zend_jit_trace_get_exit_addr(exit_point); + if (!exit_addr) { + return 0; + } | .aword &exit_addr } } diff --git a/ext/opcache/tests/jit/fetch_obj_006.phpt b/ext/opcache/tests/jit/fetch_obj_006.phpt index 120c2f4dbeddd..afb0668cd2507 100644 --- a/ext/opcache/tests/jit/fetch_obj_006.phpt +++ b/ext/opcache/tests/jit/fetch_obj_006.phpt @@ -21,11 +21,10 @@ $appendProp2 = (function() { $this->prop[] = 1; })->bindTo($test, Test::class); $appendProp2(); -$appendProp2(); ?> --EXPECTF-- -Fatal error: Uncaught Error: Cannot modify readonly property Test::$prop in %sfetch_obj_006.php:13 +Fatal error: Uncaught Error: Cannot indirectly modify readonly property Test::$prop in %s:%d Stack trace: -#0 %sfetch_obj_006.php(16): Test->{closure}() +#0 %sfetch_obj_006.php(15): Test->{closure}() #1 {main} - thrown in %sfetch_obj_006.php on line 13 \ No newline at end of file + thrown in %sfetch_obj_006.php on line 13 diff --git a/ext/opcache/tests/jit/gh8030-001.phpt b/ext/opcache/tests/jit/gh8030-001.phpt new file mode 100644 index 0000000000000..ddce1fab93ce6 --- /dev/null +++ b/ext/opcache/tests/jit/gh8030-001.phpt @@ -0,0 +1,543 @@ +--TEST-- +GH-8030: Segfault with JIT and large match/switch statements 001 +--EXTENSIONS-- +opcache +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.jit_buffer_size=1M +opcache.jit=1255 +opcache.file_update_protection=0 +opcache.revalidate_freq=0 +opcache.protect_memory=1 +--FILE-- + 1, + 2 => 2, + 3 => 3, + 4 => 4, + 5 => 5, + 6 => 6, + 7 => 7, + 8 => 8, + 9 => 9, + 10 => 10, + 11 => 11, + 12 => 12, + 13 => 13, + 14 => 14, + 15 => 15, + 16 => 16, + 17 => 17, + 18 => 18, + 19 => 19, + 20 => 20, + 21 => 21, + 22 => 22, + 23 => 23, + 24 => 24, + 25 => 25, + 26 => 26, + 27 => 27, + 28 => 28, + 29 => 29, + 30 => 30, + 31 => 31, + 32 => 32, + 33 => 33, + 34 => 34, + 35 => 35, + 36 => 36, + 37 => 37, + 38 => 38, + 39 => 39, + 40 => 40, + 41 => 41, + 42 => 42, + 43 => 43, + 44 => 44, + 45 => 45, + 46 => 46, + 47 => 47, + 48 => 48, + 49 => 49, + 50 => 50, + 51 => 51, + 52 => 52, + 53 => 53, + 54 => 54, + 55 => 55, + 56 => 56, + 57 => 57, + 58 => 58, + 59 => 59, + 60 => 60, + 61 => 61, + 62 => 62, + 63 => 63, + 64 => 64, + 65 => 65, + 66 => 66, + 67 => 67, + 68 => 68, + 69 => 69, + 70 => 70, + 71 => 71, + 72 => 72, + 73 => 73, + 74 => 74, + 75 => 75, + 76 => 76, + 77 => 77, + 78 => 78, + 79 => 79, + 80 => 80, + 81 => 81, + 82 => 82, + 83 => 83, + 84 => 84, + 85 => 85, + 86 => 86, + 87 => 87, + 88 => 88, + 89 => 89, + 90 => 90, + 91 => 91, + 92 => 92, + 93 => 93, + 94 => 94, + 95 => 95, + 96 => 96, + 97 => 97, + 98 => 98, + 99 => 99, + 100 => 100, + 101 => 101, + 102 => 102, + 103 => 103, + 104 => 104, + 105 => 105, + 106 => 106, + 107 => 107, + 108 => 108, + 109 => 109, + 110 => 110, + 111 => 111, + 112 => 112, + 113 => 113, + 114 => 114, + 115 => 115, + 116 => 116, + 117 => 117, + 118 => 118, + 119 => 119, + 120 => 120, + 121 => 121, + 122 => 122, + 123 => 123, + 124 => 124, + 125 => 125, + 126 => 126, + 127 => 127, + 128 => 128, + 129 => 129, + 130 => 130, + 131 => 131, + 132 => 132, + 133 => 133, + 134 => 134, + 135 => 135, + 136 => 136, + 137 => 137, + 138 => 138, + 139 => 139, + 140 => 140, + 141 => 141, + 142 => 142, + 143 => 143, + 144 => 144, + 145 => 145, + 146 => 146, + 147 => 147, + 148 => 148, + 149 => 149, + 150 => 150, + 151 => 151, + 152 => 152, + 153 => 153, + 154 => 154, + 155 => 155, + 156 => 156, + 157 => 157, + 158 => 158, + 159 => 159, + 160 => 160, + 161 => 161, + 162 => 162, + 163 => 163, + 164 => 164, + 165 => 165, + 166 => 166, + 167 => 167, + 168 => 168, + 169 => 169, + 170 => 170, + 171 => 171, + 172 => 172, + 173 => 173, + 174 => 174, + 175 => 175, + 176 => 176, + 177 => 177, + 178 => 178, + 179 => 179, + 180 => 180, + 181 => 181, + 182 => 182, + 183 => 183, + 184 => 184, + 185 => 185, + 186 => 186, + 187 => 187, + 188 => 188, + 189 => 189, + 190 => 190, + 191 => 191, + 192 => 192, + 193 => 193, + 194 => 194, + 195 => 195, + 196 => 196, + 197 => 197, + 198 => 198, + 199 => 199, + 200 => 200, + 201 => 201, + 202 => 202, + 203 => 203, + 204 => 204, + 205 => 205, + 206 => 206, + 207 => 207, + 208 => 208, + 209 => 209, + 210 => 210, + 211 => 211, + 212 => 212, + 213 => 213, + 214 => 214, + 215 => 215, + 216 => 216, + 217 => 217, + 218 => 218, + 219 => 219, + 220 => 220, + 221 => 221, + 222 => 222, + 223 => 223, + 224 => 224, + 225 => 225, + 226 => 226, + 227 => 227, + 228 => 228, + 229 => 229, + 230 => 230, + 231 => 231, + 232 => 232, + 233 => 233, + 234 => 234, + 235 => 235, + 236 => 236, + 237 => 237, + 238 => 238, + 239 => 239, + 240 => 240, + 241 => 241, + 242 => 242, + 243 => 243, + 244 => 244, + 245 => 245, + 246 => 246, + 247 => 247, + 248 => 248, + 249 => 249, + 250 => 250, + 251 => 251, + 252 => 252, + 253 => 253, + 254 => 254, + 255 => 255, + 256 => 256, + 257 => 257, + 258 => 258, + 259 => 259, + 260 => 260, + 261 => 261, + 262 => 262, + 263 => 263, + 264 => 264, + 265 => 265, + 266 => 266, + 267 => 267, + 268 => 268, + 269 => 269, + 270 => 270, + 271 => 271, + 272 => 272, + 273 => 273, + 274 => 274, + 275 => 275, + 276 => 276, + 277 => 277, + 278 => 278, + 279 => 279, + 280 => 280, + 281 => 281, + 282 => 282, + 283 => 283, + 284 => 284, + 285 => 285, + 286 => 286, + 287 => 287, + 288 => 288, + 289 => 289, + 290 => 290, + 291 => 291, + 292 => 292, + 293 => 293, + 294 => 294, + 295 => 295, + 296 => 296, + 297 => 297, + 298 => 298, + 299 => 299, + 300 => 300, + 301 => 301, + 302 => 302, + 303 => 303, + 304 => 304, + 305 => 305, + 306 => 306, + 307 => 307, + 308 => 308, + 309 => 309, + 310 => 310, + 311 => 311, + 312 => 312, + 313 => 313, + 314 => 314, + 315 => 315, + 316 => 316, + 317 => 317, + 318 => 318, + 319 => 319, + 320 => 320, + 321 => 321, + 322 => 322, + 323 => 323, + 324 => 324, + 325 => 325, + 326 => 326, + 327 => 327, + 328 => 328, + 329 => 329, + 330 => 330, + 331 => 331, + 332 => 332, + 333 => 333, + 334 => 334, + 335 => 335, + 336 => 336, + 337 => 337, + 338 => 338, + 339 => 339, + 340 => 340, + 341 => 341, + 342 => 342, + 343 => 343, + 344 => 344, + 345 => 345, + 346 => 346, + 347 => 347, + 348 => 348, + 349 => 349, + 350 => 350, + 351 => 351, + 352 => 352, + 353 => 353, + 354 => 354, + 355 => 355, + 356 => 356, + 357 => 357, + 358 => 358, + 359 => 359, + 360 => 360, + 361 => 361, + 362 => 362, + 363 => 363, + 364 => 364, + 365 => 365, + 366 => 366, + 367 => 367, + 368 => 368, + 369 => 369, + 370 => 370, + 371 => 371, + 372 => 372, + 373 => 373, + 374 => 374, + 375 => 375, + 376 => 376, + 377 => 377, + 378 => 378, + 379 => 379, + 380 => 380, + 381 => 381, + 382 => 382, + 383 => 383, + 384 => 384, + 385 => 385, + 386 => 386, + 387 => 387, + 388 => 388, + 389 => 389, + 390 => 390, + 391 => 391, + 392 => 392, + 393 => 393, + 394 => 394, + 395 => 395, + 396 => 396, + 397 => 397, + 398 => 398, + 399 => 399, + 400 => 400, + 401 => 401, + 402 => 402, + 403 => 403, + 404 => 404, + 405 => 405, + 406 => 406, + 407 => 407, + 408 => 408, + 409 => 409, + 410 => 410, + 411 => 411, + 412 => 412, + 413 => 413, + 414 => 414, + 415 => 415, + 416 => 416, + 417 => 417, + 418 => 418, + 419 => 419, + 420 => 420, + 421 => 421, + 422 => 422, + 423 => 423, + 424 => 424, + 425 => 425, + 426 => 426, + 427 => 427, + 428 => 428, + 429 => 429, + 430 => 430, + 431 => 431, + 432 => 432, + 433 => 433, + 434 => 434, + 435 => 435, + 436 => 436, + 437 => 437, + 438 => 438, + 439 => 439, + 440 => 440, + 441 => 441, + 442 => 442, + 443 => 443, + 444 => 444, + 445 => 445, + 446 => 446, + 447 => 447, + 448 => 448, + 449 => 449, + 450 => 450, + 451 => 451, + 452 => 452, + 453 => 453, + 454 => 454, + 455 => 455, + 456 => 456, + 457 => 457, + 458 => 458, + 459 => 459, + 460 => 460, + 461 => 461, + 462 => 462, + 463 => 463, + 464 => 464, + 465 => 465, + 466 => 466, + 467 => 467, + 468 => 468, + 469 => 469, + 470 => 470, + 471 => 471, + 472 => 472, + 473 => 473, + 474 => 474, + 475 => 475, + 476 => 476, + 477 => 477, + 478 => 478, + 479 => 479, + 480 => 480, + 481 => 481, + 482 => 482, + 483 => 483, + 484 => 484, + 485 => 485, + 486 => 486, + 487 => 487, + 488 => 488, + 489 => 489, + 490 => 490, + 491 => 491, + 492 => 492, + 493 => 493, + 494 => 494, + 495 => 495, + 496 => 496, + 497 => 497, + 498 => 498, + 499 => 499, + 500 => 500, + 501 => 501, + 502 => 502, + 503 => 503, + 504 => 504, + 505 => 505, + 506 => 506, + 507 => 507, + 508 => 508, + 509 => 509, + 510 => 510, + 511 => 511, + 512 => 512, + 513 => 513, + }; +} +for ($i=0; $i<2; $i++){ + var_dump(lookup(510)); + var_dump(lookup(513)); +} +?> +==DONE== +--EXPECT-- +int(510) +int(513) +int(510) +int(513) +==DONE== diff --git a/ext/opcache/tests/jit/gh8030-002.phpt b/ext/opcache/tests/jit/gh8030-002.phpt new file mode 100644 index 0000000000000..ed0081a2eabed --- /dev/null +++ b/ext/opcache/tests/jit/gh8030-002.phpt @@ -0,0 +1,547 @@ +--TEST-- +GH-8030: Segfault with JIT and large match/switch statements 002 +--EXTENSIONS-- +opcache +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.jit_buffer_size=1M +opcache.jit=1255 +opcache.file_update_protection=0 +opcache.revalidate_freq=0 +opcache.protect_memory=1 +--FILE-- + +==DONE== +--EXPECT-- +int(510) +int(513) +int(-1) +int(510) +int(513) +int(-1) +==DONE== diff --git a/ext/opcache/tests/jit/gh8847.phpt b/ext/opcache/tests/jit/gh8847.phpt new file mode 100644 index 0000000000000..588d15ab88dc0 --- /dev/null +++ b/ext/opcache/tests/jit/gh8847.phpt @@ -0,0 +1,25 @@ +--TEST-- +Bug GH-8847: PHP hanging infinitly at 100% cpu when check php syntaxe of a valid file +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +--FILE-- += 0 && !$function1) + $int--; + if($bool) + while($int >= 0 && $function1) + $int--; + return $int; + } +} +?> +DONE +--EXPECTF-- +DONE diff --git a/ext/opcache/tests/jit/gh8863.phpt b/ext/opcache/tests/jit/gh8863.phpt new file mode 100644 index 0000000000000..5f43e34a8ce7e --- /dev/null +++ b/ext/opcache/tests/jit/gh8863.phpt @@ -0,0 +1,33 @@ +--TEST-- +Bug GH-8863: RW operation on readonly property doesn't throw with JIT +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +--FILE-- +prop = 1; + } + + public function rw() { + $this->prop += 1; + echo "Done\n"; + } +} + +$test = new Test(); +try { + $test->rw(); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} +?> +DONE +--EXPECT-- +Cannot modify readonly property Test::$prop +DONE diff --git a/ext/opcache/tests/opt/inference_012.phpt b/ext/opcache/tests/opt/inference_012.phpt new file mode 100644 index 0000000000000..2c123b32fac08 --- /dev/null +++ b/ext/opcache/tests/opt/inference_012.phpt @@ -0,0 +1,26 @@ +--TEST-- +Type inference 012: FETCH_DIM_UNSET +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--FILE-- + $closure(), 'b' => [$closure() => []]]; + $x = $arr; + unset($x['b'][$closure()]['d']); + $x = $arr; +} + +test(); +?> +DONE +--EXPECTF-- +Warning: Undefined variable $x in %sinference_012.php on line 4 + +Warning: Undefined variable $arr in %sinference_012.php on line 5 +DONE diff --git a/ext/opcache/tests/opt/inference_013.phpt b/ext/opcache/tests/opt/inference_013.phpt new file mode 100644 index 0000000000000..c318eecae8c7f --- /dev/null +++ b/ext/opcache/tests/opt/inference_013.phpt @@ -0,0 +1,19 @@ +--TEST-- +Type inference 013: ASSIGN_DIM +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--FILE-- + +DONE +--EXPECT-- +DONE diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index bf408136cc5f9..7ce4878139d19 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -1550,6 +1550,10 @@ ZEND_METHOD(Reflection, getModifierNames) if (modifiers & ZEND_ACC_STATIC) { add_next_index_stringl(return_value, "static", sizeof("static")-1); } + + if (modifiers & ZEND_ACC_READONLY) { + add_next_index_stringl(return_value, "readonly", sizeof("readonly")-1); + } } /* }}} */ diff --git a/ext/reflection/tests/Reflection_getModifierNames_001.phpt b/ext/reflection/tests/Reflection_getModifierNames_001.phpt new file mode 100644 index 0000000000000..6506bce63b552 --- /dev/null +++ b/ext/reflection/tests/Reflection_getModifierNames_001.phpt @@ -0,0 +1,23 @@ +--TEST-- +Reflection::getModifierNames() basic +--FILE-- + +--EXPECT-- +private +protected,static +public,readonly +abstract +abstract,final +public,static,readonly diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index b461d0bc27e40..4edc6361605fb 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -1891,21 +1891,22 @@ static zend_result spl_filesystem_file_read_ex(spl_filesystem_object *intern, bo } if (!buf) { - return FAILURE; - } - - if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_DROP_NEW_LINE)) { - if (line_len > 0 && buf[line_len - 1] == '\n') { - line_len--; - if (line_len > 0 && buf[line_len - 1] == '\r') { + intern->u.file.current_line = estrdup(""); + intern->u.file.current_line_len = 0; + } else { + if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_DROP_NEW_LINE)) { + if (line_len > 0 && buf[line_len - 1] == '\n') { line_len--; + if (line_len > 0 && buf[line_len - 1] == '\r') { + line_len--; + } + buf[line_len] = '\0'; } - buf[line_len] = '\0'; } - } - intern->u.file.current_line = buf; - intern->u.file.current_line_len = line_len; + intern->u.file.current_line = buf; + intern->u.file.current_line_len = line_len; + } intern->u.file.current_line_num += line_add; return SUCCESS; diff --git a/ext/spl/tests/SplFileObject/fgetcsv_file_empty_lines.phpt b/ext/spl/tests/SplFileObject/fgetcsv_file_empty_lines.phpt deleted file mode 100644 index bcd68eeadba94..0000000000000 --- a/ext/spl/tests/SplFileObject/fgetcsv_file_empty_lines.phpt +++ /dev/null @@ -1,38 +0,0 @@ ---TEST-- -SplFileObject::fgetcsv with empty lines ---FILE-- -fwrite("foo,bar\n"); -$file->fwrite("\n"); -$file->fwrite("baz,qux"); - -$file->rewind(); - - -var_dump($file->fgetcsv()); -var_dump($file->fgetcsv()); -var_dump($file->fgetcsv()); -var_dump($file->fgetcsv()); - -?> ---EXPECT-- -array(2) { - [0]=> - string(3) "foo" - [1]=> - string(3) "bar" -} -array(1) { - [0]=> - NULL -} -array(2) { - [0]=> - string(3) "baz" - [1]=> - string(3) "qux" -} -bool(false) diff --git a/ext/spl/tests/SplFileObject/foreach_file_empty_lines.phpt b/ext/spl/tests/SplFileObject/foreach_file_empty_lines.phpt deleted file mode 100644 index 5fefdf0fddd5a..0000000000000 --- a/ext/spl/tests/SplFileObject/foreach_file_empty_lines.phpt +++ /dev/null @@ -1,37 +0,0 @@ ---TEST-- -Iterate over SplFileObject with empty lines with CSV flags ---FILE-- -fwrite("foo,bar\n"); -$file->fwrite("\n"); -$file->fwrite("baz,qux"); - -$file->rewind(); - -$file->setFlags(SplFileObject::READ_CSV | SplFileObject::READ_AHEAD | SplFileObject::SKIP_EMPTY /* | SplFileObject::DROP_NEW_LINE */); - - -foreach ($file as $line) { - var_dump($line); -} -?> ---EXPECT-- -array(2) { - [0]=> - string(3) "foo" - [1]=> - string(3) "bar" -} -array(1) { - [0]=> - NULL -} -array(2) { - [0]=> - string(3) "baz" - [1]=> - string(3) "qux" -} diff --git a/ext/spl/tests/SplFileObject/gh8563.phpt b/ext/spl/tests/SplFileObject/gh8563.phpt deleted file mode 100644 index 11309ae8101fa..0000000000000 --- a/ext/spl/tests/SplFileObject/gh8563.phpt +++ /dev/null @@ -1,48 +0,0 @@ ---TEST-- -Bug GH-8563: Different results for seek() on SplFileObject and SplTempFileObject ---FILE-- -fwrite("line {$i}" . PHP_EOL); - $file_02->fwrite("line {$i}" . PHP_EOL); - $file_03->fwrite("line {$i}" . PHP_EOL); - $file_04->fwrite("line {$i}" . PHP_EOL); -} - -// reset -$file_01->rewind(); -$file_02->rewind(); -$file_03->rewind(); -$file_04->rewind(); - -// seek -$file_01->seek(INDEX); -$file_02->seek(INDEX); -$file_03->seek(INDEX); -$file_04->seek(INDEX); - -// show results -echo 'file_01: ' . $file_01->key(), PHP_EOL; -echo 'file_02: ' . $file_02->key(), PHP_EOL; -echo 'file_03: ' . $file_03->key(), PHP_EOL; -echo 'file_04: ' . $file_04->key(), PHP_EOL; -?> ---CLEAN-- - ---EXPECT-- -file_01: 4 -file_02: 4 -file_03: 4 -file_04: 4 diff --git a/ext/spl/tests/SplFileObject/SplFileObject_fgetcsv_basic.phpt b/ext/spl/tests/SplFileObject_fgetcsv_basic.phpt similarity index 92% rename from ext/spl/tests/SplFileObject/SplFileObject_fgetcsv_basic.phpt rename to ext/spl/tests/SplFileObject_fgetcsv_basic.phpt index ca584251af9f4..2580021426fd3 100644 --- a/ext/spl/tests/SplFileObject/SplFileObject_fgetcsv_basic.phpt +++ b/ext/spl/tests/SplFileObject_fgetcsv_basic.phpt @@ -13,7 +13,6 @@ fclose($fp); $fo = new SplFileObject('SplFileObject__fgetcsv1.csv'); var_dump($fo->fgetcsv()); -var_dump($fo->fgetcsv()); ?> --CLEAN-- string(1) "5" } -bool(false) diff --git a/ext/spl/tests/SplFileObject/SplFileObject_key_error001.phpt b/ext/spl/tests/SplFileObject_key_error001.phpt similarity index 97% rename from ext/spl/tests/SplFileObject/SplFileObject_key_error001.phpt rename to ext/spl/tests/SplFileObject_key_error001.phpt index 7d0e3ae8d9698..0c21d0b905e95 100644 --- a/ext/spl/tests/SplFileObject/SplFileObject_key_error001.phpt +++ b/ext/spl/tests/SplFileObject_key_error001.phpt @@ -18,5 +18,5 @@ var_dump($s->key()); var_dump($s->valid()); ?> --EXPECT-- -int(12) +int(14) bool(false) diff --git a/ext/spl/tests/SplFileObject/SplFileObject_key_error002.phpt b/ext/spl/tests/SplFileObject_key_error002.phpt similarity index 97% rename from ext/spl/tests/SplFileObject/SplFileObject_key_error002.phpt rename to ext/spl/tests/SplFileObject_key_error002.phpt index 0834dbc0524fc..8fc9b7fef0a58 100644 --- a/ext/spl/tests/SplFileObject/SplFileObject_key_error002.phpt +++ b/ext/spl/tests/SplFileObject_key_error002.phpt @@ -18,5 +18,5 @@ var_dump($s->key()); var_dump($s->valid()); ?> --EXPECT-- -int(12) +int(13) bool(false) diff --git a/ext/spl/tests/bug81477.phpt b/ext/spl/tests/bug81477.phpt index 421c74dc4d68e..f7730a791aa03 100644 --- a/ext/spl/tests/bug81477.phpt +++ b/ext/spl/tests/bug81477.phpt @@ -21,6 +21,7 @@ string(8) "baz,bat " string(10) "more,data " +string(0) "" --CLEAN-- # endif #endif +#if HAVE_COMMONCRYPTO_COMMONRANDOM_H +# include +# include +#endif #if __has_feature(memory_sanitizer) # include @@ -94,6 +98,19 @@ PHPAPI int php_random_bytes(void *bytes, size_t size, bool should_throw) } return FAILURE; } +#elif HAVE_COMMONCRYPTO_COMMONRANDOM_H + /* + * Purposely prioritized upon arc4random_buf for modern macOs releases + * arc4random api on this platform uses `ccrng_generate` which returns + * a status but silented to respect the "no fail" arc4random api interface + * the vast majority of the time, it works fine ; but better make sure we catch failures + */ + if (CCRandomGenerateBytes(bytes, size) != kCCSuccess) { + if (should_throw) { + zend_throw_exception(zend_ce_exception, "Error generating bytes", 0); + } + return FAILURE; + } #elif HAVE_DECL_ARC4RANDOM_BUF && ((defined(__OpenBSD__) && OpenBSD >= 201405) || (defined(__NetBSD__) && __NetBSD_Version__ >= 700000001) || defined(__APPLE__)) arc4random_buf(bytes, size); #else diff --git a/ext/standard/streamsfuncs.c b/ext/standard/streamsfuncs.c index f4460c68f7527..5335a47291b5a 100644 --- a/ext/standard/streamsfuncs.c +++ b/ext/standard/streamsfuncs.c @@ -67,10 +67,22 @@ PHP_FUNCTION(stream_socket_pair) RETURN_FALSE; } - array_init(return_value); - - s1 = php_stream_sock_open_from_socket(pair[0], 0); - s2 = php_stream_sock_open_from_socket(pair[1], 0); + s1 = php_stream_sock_open_from_socket(pair[0], 0); + if (s1 == NULL) { + close(pair[0]); + close(pair[1]); + php_error_docref(NULL, E_WARNING, "Failed to open stream from socketpair"); + RETURN_FALSE; + } + s2 = php_stream_sock_open_from_socket(pair[1], 0); + if (s2 == NULL) { + php_stream_free(s1, PHP_STREAM_FREE_CLOSE); + close(pair[1]); + php_error_docref(NULL, E_WARNING, "Failed to open stream from socketpair"); + RETURN_FALSE; + } + + array_init(return_value); /* set the __exposed flag. * php_stream_to_zval() does, add_next_index_resource() does not */ diff --git a/ext/zlib/zlib_filter.c b/ext/zlib/zlib_filter.c index 286fd0ca8c54a..24d418ae04cfa 100644 --- a/ext/zlib/zlib_filter.c +++ b/ext/zlib/zlib_filter.c @@ -327,7 +327,7 @@ static php_stream_filter *php_zlib_filter_create(const char *filtername, zval *f /* log-2 base of history window (9 - 15) */ zend_long tmp = zval_get_long(tmpzval); if (tmp < -MAX_WBITS || tmp > MAX_WBITS + 32) { - php_error_docref(NULL, E_WARNING, "Invalid parameter give for window size. (" ZEND_LONG_FMT ")", tmp); + php_error_docref(NULL, E_WARNING, "Invalid parameter given for window size (" ZEND_LONG_FMT ")", tmp); } else { windowBits = tmp; } @@ -359,7 +359,7 @@ static php_stream_filter *php_zlib_filter_create(const char *filtername, zval *f /* Memory Level (1 - 9) */ tmp = zval_get_long(tmpzval); if (tmp < 1 || tmp > MAX_MEM_LEVEL) { - php_error_docref(NULL, E_WARNING, "Invalid parameter give for memory level. (" ZEND_LONG_FMT ")", tmp); + php_error_docref(NULL, E_WARNING, "Invalid parameter given for memory level (" ZEND_LONG_FMT ")", tmp); } else { memLevel = tmp; } @@ -369,7 +369,7 @@ static php_stream_filter *php_zlib_filter_create(const char *filtername, zval *f /* log-2 base of history window (9 - 15) */ tmp = zval_get_long(tmpzval); if (tmp < -MAX_WBITS || tmp > MAX_WBITS + 16) { - php_error_docref(NULL, E_WARNING, "Invalid parameter give for window size. (" ZEND_LONG_FMT ")", tmp); + php_error_docref(NULL, E_WARNING, "Invalid parameter given for window size (" ZEND_LONG_FMT ")", tmp); } else { windowBits = tmp; } diff --git a/main/main.c b/main/main.c index 2f6ef27e49de6..252e50a9ff3c2 100644 --- a/main/main.c +++ b/main/main.c @@ -832,9 +832,10 @@ PHPAPI ZEND_COLD void php_log_err_with_severity(const char *log_message, int sys #endif len = spprintf(&tmp, 0, "[%s] %s%s", ZSTR_VAL(error_time_str), log_message, PHP_EOL); #ifdef PHP_WIN32 - php_flock(fd, 2); + php_flock(fd, LOCK_EX); /* XXX should eventually write in a loop if len > UINT_MAX */ php_ignore_value(write(fd, tmp, (unsigned)len)); + php_flock(fd, LOCK_UN); #else php_ignore_value(write(fd, tmp, len)); #endif diff --git a/main/php_version.h b/main/php_version.h index 43d5eb5b19321..a8dd4ece266d6 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 8 -#define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.1.8-dev" -#define PHP_VERSION_ID 80108 +#define PHP_RELEASE_VERSION 9 +#define PHP_EXTRA_VERSION "" +#define PHP_VERSION "8.1.9" +#define PHP_VERSION_ID 80109 diff --git a/sapi/cli/php_cli.c b/sapi/cli/php_cli.c index 47241f8af4e04..0ad53e813c944 100644 --- a/sapi/cli/php_cli.c +++ b/sapi/cli/php_cli.c @@ -538,14 +538,6 @@ static void cli_register_file_handles(bool no_close) /* {{{ */ s_out = php_stream_open_wrapper_ex("php://stdout", "wb", 0, NULL, sc_out); s_err = php_stream_open_wrapper_ex("php://stderr", "wb", 0, NULL, sc_err); - /* Release stream resources, but don't free the underlying handles. Othewrise, - * extensions which write to stderr or company during mshutdown/gshutdown - * won't have the expected functionality. - */ - if (s_in) s_in->flags |= PHP_STREAM_FLAG_NO_CLOSE; - if (s_out) s_out->flags |= PHP_STREAM_FLAG_NO_CLOSE; - if (s_err) s_err->flags |= PHP_STREAM_FLAG_NO_CLOSE; - if (s_in==NULL || s_out==NULL || s_err==NULL) { if (s_in) php_stream_close(s_in); if (s_out) php_stream_close(s_out); @@ -553,6 +545,12 @@ static void cli_register_file_handles(bool no_close) /* {{{ */ return; } + if (no_close) { + s_in->flags |= PHP_STREAM_FLAG_NO_CLOSE; + s_out->flags |= PHP_STREAM_FLAG_NO_CLOSE; + s_err->flags |= PHP_STREAM_FLAG_NO_CLOSE; + } + s_in_process = s_in; php_stream_to_zval(s_in, &ic.value); diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c index 5798a72d6c160..04f6497deb968 100644 --- a/sapi/cli/php_cli_server.c +++ b/sapi/cli/php_cli_server.c @@ -2296,7 +2296,7 @@ static void php_cli_server_dtor(php_cli_server *server) /* {{{ */ !WIFSIGNALED(php_cli_server_worker_status)); } - free(php_cli_server_workers); + pefree(php_cli_server_workers, 1); } #endif } /* }}} */ @@ -2382,12 +2382,8 @@ static void php_cli_server_startup_workers(void) { if (php_cli_server_workers_max > 1) { zend_long php_cli_server_worker; - php_cli_server_workers = calloc( - php_cli_server_workers_max, sizeof(pid_t)); - if (!php_cli_server_workers) { - php_cli_server_workers_max = 1; - return; - } + php_cli_server_workers = pecalloc( + php_cli_server_workers_max, sizeof(pid_t), 1); php_cli_server_master = getpid(); diff --git a/sapi/cli/tests/gh8827-001.phpt b/sapi/cli/tests/gh8827-001.phpt new file mode 100644 index 0000000000000..fab7b02d9e975 --- /dev/null +++ b/sapi/cli/tests/gh8827-001.phpt @@ -0,0 +1,38 @@ +--TEST-- +std handles can be deliberately closed 001 +--SKIPIF-- + +--FILE-- + +--EXPECT-- +STDIN: +bool(false) +STDERR: +bool(false) +STDOUT: diff --git a/sapi/cli/tests/gh8827-002.phpt b/sapi/cli/tests/gh8827-002.phpt new file mode 100644 index 0000000000000..d039896cb1cd9 --- /dev/null +++ b/sapi/cli/tests/gh8827-002.phpt @@ -0,0 +1,47 @@ +--TEST-- +std handles can be deliberately closed 002 +--SKIPIF-- + +--FILE-- + +--EXPECT-- +STDIN: +bool(false) +STDERR: +bool(false) +STDOUT: +bool(false) diff --git a/sapi/cli/tests/gh8827-003.phpt b/sapi/cli/tests/gh8827-003.phpt new file mode 100644 index 0000000000000..8c1fc49141f48 --- /dev/null +++ b/sapi/cli/tests/gh8827-003.phpt @@ -0,0 +1,57 @@ +--TEST-- +std handles can be deliberately closed 003 +--SKIPIF-- + +--FILE-- + +--EXPECT-- +stdoutFile: +Goes to stdoutFile +Also goes to stdoutFile +stderrFile: +Goes to stderrFile diff --git a/sapi/fpm/fpm/fpm_conf.c b/sapi/fpm/fpm/fpm_conf.c index e507c00d76693..b4178625611ea 100644 --- a/sapi/fpm/fpm/fpm_conf.c +++ b/sapi/fpm/fpm/fpm_conf.c @@ -1630,7 +1630,10 @@ int fpm_conf_load_ini_file(char *filename) /* {{{ */ tmp = zend_parse_ini_string(buf, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t)fpm_conf_ini_parser, &error); ini_filename = filename; if (error || tmp == FAILURE) { - if (ini_include) free(ini_include); + if (ini_include) { + free(ini_include); + ini_include = NULL; + } ini_recursion--; close(fd); free(buf); diff --git a/sapi/fpm/fpm/zlog.c b/sapi/fpm/fpm/zlog.c index 22f62b3cabe73..95f98e6afd54b 100644 --- a/sapi/fpm/fpm/zlog.c +++ b/sapi/fpm/fpm/zlog.c @@ -651,7 +651,7 @@ zlog_bool zlog_stream_set_msg_suffix( stream->msg_final_suffix_len = strlen(final_suffix); len = stream->msg_final_suffix_len + 1; if (stream->msg_final_suffix != NULL) { - free(stream->msg_suffix); + free(stream->msg_final_suffix); } stream->msg_final_suffix = malloc(len); if (stream->msg_final_suffix == NULL) { diff --git a/sapi/phpdbg/phpdbg.c b/sapi/phpdbg/phpdbg.c index 193a89bfa687a..221803f88e7e9 100644 --- a/sapi/phpdbg/phpdbg.c +++ b/sapi/phpdbg/phpdbg.c @@ -858,7 +858,7 @@ static ssize_t phpdbg_stdiop_write(php_stream *stream, const char *buf, size_t c while (data->fd >= 0) { struct stat stat[3]; memset(stat, 0, sizeof(stat)); - if (((fstat(fileno(stderr), &stat[2]) < 0) & (fstat(fileno(stdout), &stat[0]) < 0)) | (fstat(data->fd, &stat[1]) < 0)) { + if (((fstat(fileno(stderr), &stat[2]) < 0) && (fstat(fileno(stdout), &stat[0]) < 0)) || (fstat(data->fd, &stat[1]) < 0)) { break; }