diff --git a/.gdbinit b/.gdbinit index c4705b2f59a95..4477828265e0e 100644 --- a/.gdbinit +++ b/.gdbinit @@ -42,7 +42,7 @@ define print_cvs printf "Compiled variables count: %d\n\n", $cv_count while $cv_idx < $cv_count - printf "[%d] '%s'\n", $cv_idx, $cv[$cv_idx].val + printf "[%d] '$%s'\n", $cv_idx, $cv[$cv_idx].val@$cv[$cv_idx].len set $zvalue = ((zval *) $cv_ex_ptr) + $callFrameSize + $cv_idx printzv $zvalue set $cv_idx = $cv_idx + 1 diff --git a/.github/nightly_matrix.php b/.github/nightly_matrix.php index 311176ef5e53e..846c60e8fd56d 100644 --- a/.github/nightly_matrix.php +++ b/.github/nightly_matrix.php @@ -1,7 +1,8 @@ 'master', 'version' => [8, 5]], + ['ref' => 'master', 'version' => [8, 6]], + ['ref' => 'PHP-8.5', 'version' => [8, 5]], ['ref' => 'PHP-8.4', 'version' => [8, 4]], ['ref' => 'PHP-8.3', 'version' => [8, 3]], ['ref' => 'PHP-8.2', 'version' => [8, 2]], diff --git a/.github/scripts/windows/find-target-branch.bat b/.github/scripts/windows/find-target-branch.bat index a0b47f2488946..44b0bde1ec8ca 100644 --- a/.github/scripts/windows/find-target-branch.bat +++ b/.github/scripts/windows/find-target-branch.bat @@ -3,6 +3,6 @@ for /f "usebackq tokens=3" %%i in (`findstr PHP_MAJOR_VERSION main\php_version.h`) do set BRANCH=%%i for /f "usebackq tokens=3" %%i in (`findstr PHP_MINOR_VERSION main\php_version.h`) do set BRANCH=%BRANCH%.%%i -if /i "%BRANCH%" equ "8.5" ( +if /i "%BRANCH%" equ "8.6" ( set BRANCH=master ) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 62ea796502127..e0322e3b1be2e 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -44,6 +44,9 @@ on: skip_wordpress: required: true type: boolean + variation_enable_zend_max_execution_timers: + required: true + type: boolean permissions: contents: read jobs: @@ -90,9 +93,9 @@ jobs: ALPINE: if: inputs.run_alpine name: ALPINE_X64_ASAN_UBSAN_DEBUG_ZTS - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 container: - image: 'alpine:3.20.1' + image: 'alpine:3.22' steps: - name: git checkout uses: actions/checkout@v5 @@ -100,11 +103,6 @@ jobs: ref: ${{ inputs.branch }} - name: apk uses: ./.github/actions/apk - - name: LLVM 17 (ASAN-only) - # libclang_rt.asan-x86_64.a is provided by compiler-rt, and only for clang17: - # https://pkgs.alpinelinux.org/contents?file=libclang_rt.asan-x86_64.a&path=&name=&branch=v3.20 - run: | - apk add clang17 compiler-rt - name: System info run: | echo "::group::Show host CPU info" @@ -119,8 +117,8 @@ jobs: configurationParameters: >- CFLAGS="-fsanitize=undefined,address -fno-sanitize=function -DZEND_TRACK_ARENA_ALLOC" LDFLAGS="-fsanitize=undefined,address -fno-sanitize=function" - CC=clang-17 - CXX=clang++-17 + CC=clang-20 + CXX=clang++-20 --enable-debug --enable-zts skipSlow: true # FIXME: This should likely include slow extensions @@ -199,6 +197,7 @@ jobs: zts: true configuration_parameters: >- CFLAGS="-DZEND_RC_DEBUG=1 -DPROFITABILITY_CHECKS=0 -DZEND_VERIFY_FUNC_INFO=1 -DZEND_VERIFY_TYPE_INFERENCE" + ${{ inputs.variation_enable_zend_max_execution_timers && '--enable-zend-max-execution-timers' || '' }} run_tests_parameters: -d zend_test.observer.enabled=1 -d zend_test.observer.show_output=0 timeout_minutes: 360 test_function_jit: true diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index f086c24a5366b..6b7f6afc446ae 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -162,6 +162,7 @@ jobs: with: key: "${{github.job}}-${{hashFiles('main/php_version.h')}}" append-timestamp: false + save: ${{ github.event_name != 'pull_request' }} - name: ./configure uses: ./.github/actions/configure-x32 with: diff --git a/.github/workflows/root.yml b/.github/workflows/root.yml index 16418b1aa1d3a..b70b026eced07 100644 --- a/.github/workflows/root.yml +++ b/.github/workflows/root.yml @@ -64,4 +64,5 @@ jobs: skip_laravel: ${{ matrix.branch.version[0] == 8 && matrix.branch.version[1] == 1 }} skip_symfony: ${{ matrix.branch.version[0] == 8 && matrix.branch.version[1] == 1 }} skip_wordpress: ${{ matrix.branch.version[0] == 8 && matrix.branch.version[1] == 1 }} + variation_enable_zend_max_execution_timers: ${{ (matrix.branch.version[0] == 8 && matrix.branch.version[1] >= 3) || matrix.branch.version[0] >= 9 }} secrets: inherit diff --git a/NEWS b/NEWS index b006f93e0c32c..b20a4fe61695d 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,92 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.3.26 +09 Oct 2025, PHP 8.3.27RC1 + +- Core: + . Fixed bug GH-19765 (object_properties_load() bypasses readonly property + checks). (timwolla) + . Fixed hard_timeout with --enable-zend-max-execution-timers. (Appla) + . Fixed bug GH-19792 (SCCP causes UAF for return value if both warning and + exception are triggered). (nielsdos) + . Fixed bug GH-19653 (Closure named argument unpacking between temporary + closures can cause a crash). (nielsdos, Arnaud, Bob) + . Fixed bug GH-19839 (Incorrect HASH_FLAG_HAS_EMPTY_IND flag on userland + array). (ilutov) + . Fixed bug GH-19480 (error_log php.ini cannot be unset when open_basedir is + configured). (nielsdos) + . Fixed bug GH-20002 (Broken build on *BSD with MSAN). (outtersg) + +- CLI: + . Fix useless "Failed to poll event" error logs due to EAGAIN in CLI server + with PHP_CLI_SERVER_WORKERS. (leotaku) + +- Curl: + . Fix cloning of CURLOPT_POSTFIELDS when using the clone operator instead + of the curl_copy_handle() function to clone a CurlHandle. (timwolla) + . Fix curl build and test failures with version 8.16. + (nielsdos, ilutov, Jakub Zelenka) + +- Date: + . Fixed GH-17159: "P" format for ::createFromFormat swallows string literals. + (nielsdos) + +- DBA: + . Fixed GH-19885 (dba_fetch() overflow on skip argument). (David Carlier) + +- GD: + . Fixed GH-19955 (imagefttext() memory leak). (David Carlier) + +- MySQLnd: + . Fixed bug #67563 (mysqli compiled with mysqlnd does not take ipv6 adress + as parameter). (nielsdos) + +- Phar: + . Fix memory leak and invalid continuation after tar header writing fails. + (nielsdos) + . Fix memory leaks when creating temp file fails when applying zip signature. + (nielsdos) + +- SimpleXML: + . Fixed bug GH-19988 (zend_string_init with NULL pointer in simplexml (UB)). + (nielsdos) + +- Soap: + . Fixed bug GH-19784 (SoapServer memory leak). (nielsdos) + . Fixed bug GH-20011 (Array of SoapVar of unknown type causes crash). + (nielsdos) + +- Standard: + . Fixed bug GH-12265 (Cloning an object breaks serialization recursion). + (nielsdos) + . Fixed bug GH-19701 (Serialize/deserialize loses some data). (nielsdos) + . Fixed bug GH-19801 (leaks in var_dump() and debug_zval_dump()). + (alexandre-daubois) + . Fixed bug GH-20043 (array_unique assertion failure with RC1 array + causing an exception on sort). (nielsdos) + . Fixed bug GH-19926 (reset internal pointer earlier while splicing array + while COW violation flag is still set). (alexandre-daubois) + . Fixed bug GH-19570 (unable to fseek in /dev/zero and /dev/null). + (nielsdos, divinity76) + +- Streams: + . Fixed bug GH-19248 (Use strerror_r instead of strerror in main). + (Jakub Zelenka) + . Fixed bug GH-17345 (Bug #35916 was not completely fixed). (nielsdos) + . Fixed bug GH-19705 (segmentation when attempting to flush on non seekable + stream. (bukka/David Carlier) + +- XMLReader: + . Fixed bug GH-20009 (XMLReader leak on RelaxNG schema failure). (nielsdos) + +- Zip: + . Fixed bug GH-19688 (Remove pattern overflow in zip addGlob()). (nielsdos) + . Fixed bug GH-19932 (Memory leak in zip setEncryptionName()/setEncryptionIndex()). + (David Carlier) + +- Zlib: + . Fixed bug GH-19922 (Double free on gzopen). (David Carlier) + +25 Sep 2025, PHP 8.3.26 - Core: . Fixed bug GH-18850 (Repeated inclusion of file with __halt_compiler() diff --git a/Zend/Optimizer/sccp.c b/Zend/Optimizer/sccp.c index d5486803e19a6..4b7a77abb0911 100644 --- a/Zend/Optimizer/sccp.c +++ b/Zend/Optimizer/sccp.c @@ -842,9 +842,7 @@ static inline zend_result ct_eval_func_call( zval_ptr_dtor(result); zend_clear_exception(); retval = FAILURE; - } - - if (EG(capture_warnings_during_sccp) > 1) { + } else if (EG(capture_warnings_during_sccp) > 1) { zval_ptr_dtor(result); retval = FAILURE; } diff --git a/Zend/tests/closures/gh19653_1.phpt b/Zend/tests/closures/gh19653_1.phpt new file mode 100644 index 0000000000000..93b119eb57826 --- /dev/null +++ b/Zend/tests/closures/gh19653_1.phpt @@ -0,0 +1,27 @@ +--TEST-- +GH-19653 (Closure named argument unpacking between temporary closures can cause a crash) +--CREDITS-- +ivan-u7n +--FILE-- + +--EXPECT-- +usage1() func1() a1=a1 a2=a2 a3=m3+ +usage1() [function] func1() a1=a1 a2=m2+ a3=m3+ diff --git a/Zend/tests/closures/gh19653_2.phpt b/Zend/tests/closures/gh19653_2.phpt new file mode 100644 index 0000000000000..7eb837dd22c4d --- /dev/null +++ b/Zend/tests/closures/gh19653_2.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-19653 (Closure named argument unpacking between temporary closures can cause a crash) - eval variation +--CREDITS-- +arnaud-lb +--FILE-- + +--EXPECTF-- +int(1) + +Fatal error: Uncaught Error: Unknown named parameter $a in %s:%d +Stack trace: +#0 %s(%d): usage1(Object(Closure)) +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/gh19839.phpt b/Zend/tests/gh19839.phpt new file mode 100644 index 0000000000000..cc589ce0605f1 --- /dev/null +++ b/Zend/tests/gh19839.phpt @@ -0,0 +1,18 @@ +--TEST-- +GH-19839: Incorrect HASH_FLAG_HAS_EMPTY_IND flag on userland array +--FILE-- + +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/zend.h b/Zend/zend.h index 23df63cde2d4a..26902cbddfa6a 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -20,7 +20,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "4.3.26-dev" +#define ZEND_VERSION "4.3.27RC1" #define ZEND_ENGINE_3 diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 79800a61a0476..ed6b24bc55216 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -1701,6 +1701,14 @@ ZEND_API void object_properties_load(zend_object *object, HashTable *properties) property_info && (property_info->flags & ZEND_ACC_STATIC) == 0) { zval *slot = OBJ_PROP(object, property_info->offset); + if (UNEXPECTED((property_info->flags & ZEND_ACC_READONLY) && !Z_ISUNDEF_P(slot))) { + if (Z_PROP_FLAG_P(slot) & IS_PROP_REINITABLE) { + Z_PROP_FLAG_P(slot) &= ~IS_PROP_REINITABLE; + } else { + zend_readonly_property_modification_error(property_info); + return; + } + } zval_ptr_dtor(slot); ZVAL_COPY_VALUE(slot, prop); zval_add_ref(slot); diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 99da3a4a051f3..d44af38c64c63 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -5058,7 +5058,12 @@ static zend_never_inline zend_result ZEND_FASTCALL zend_quick_check_constant( static zend_always_inline uint32_t zend_get_arg_offset_by_name( zend_function *fbc, zend_string *arg_name, void **cache_slot) { - if (EXPECTED(*cache_slot == fbc)) { + /* Due to closures, the `fbc` address isn't unique if the memory address is reused. + * The argument info will be however and uniquely positions the arguments. + * We do support NULL arg_info, so we have to distinguish that from an uninitialized cache slot. */ + void *unique_id = (void *) ((uintptr_t) fbc->common.arg_info | 1); + + if (EXPECTED(*cache_slot == unique_id)) { return *(uintptr_t *)(cache_slot + 1); } @@ -5067,10 +5072,12 @@ static zend_always_inline uint32_t zend_get_arg_offset_by_name( if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) || EXPECTED(fbc->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) { for (uint32_t i = 0; i < num_args; i++) { - zend_arg_info *arg_info = &fbc->op_array.arg_info[i]; + zend_arg_info *arg_info = &fbc->common.arg_info[i]; if (zend_string_equals(arg_name, arg_info->name)) { - *cache_slot = fbc; - *(uintptr_t *)(cache_slot + 1) = i; + if (fbc->type == ZEND_USER_FUNCTION && (!fbc->op_array.refcount || !(fbc->op_array.fn_flags & ZEND_ACC_CLOSURE))) { + *cache_slot = unique_id; + *(uintptr_t *)(cache_slot + 1) = i; + } return i; } } @@ -5079,7 +5086,7 @@ static zend_always_inline uint32_t zend_get_arg_offset_by_name( zend_internal_arg_info *arg_info = &fbc->internal_function.arg_info[i]; size_t len = strlen(arg_info->name); if (zend_string_equals_cstr(arg_name, arg_info->name, len)) { - *cache_slot = fbc; + *cache_slot = unique_id; *(uintptr_t *)(cache_slot + 1) = i; return i; } @@ -5087,8 +5094,13 @@ static zend_always_inline uint32_t zend_get_arg_offset_by_name( } if (fbc->common.fn_flags & ZEND_ACC_VARIADIC) { - *cache_slot = fbc; - *(uintptr_t *)(cache_slot + 1) = fbc->common.num_args; + if ((fbc->type == ZEND_USER_FUNCTION + && (!fbc->op_array.refcount || !(fbc->op_array.fn_flags & ZEND_ACC_CLOSURE))) + || (fbc->type == ZEND_INTERNAL_FUNCTION + && !(fbc->common.fn_flags & ZEND_ACC_USER_ARG_INFO))) { + *cache_slot = unique_id; + *(uintptr_t *)(cache_slot + 1) = fbc->common.num_args; + } return fbc->common.num_args; } diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index fe37b024934df..d4a373616fe92 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -1531,7 +1531,9 @@ static void zend_set_timeout_ex(zend_long seconds, bool reset_signals) /* {{{ */ return; } #elif defined(ZEND_MAX_EXECUTION_TIMERS) - zend_max_execution_timer_settime(seconds); + if (seconds > 0) { + zend_max_execution_timer_settime(seconds); + } if (reset_signals) { sigset_t sigset; @@ -1618,7 +1620,9 @@ void zend_unset_timeout(void) /* {{{ */ tq_timer = NULL; } #elif ZEND_MAX_EXECUTION_TIMERS - zend_max_execution_timer_settime(0); + if (EG(timeout_seconds)) { + zend_max_execution_timer_settime(0); + } #elif defined(HAVE_SETITIMER) if (EG(timeout_seconds)) { struct itimerval no_timeout; diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index 07d5bed6d7655..fdc05ff8cbfae 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -2466,6 +2466,7 @@ ZEND_API HashTable* ZEND_FASTCALL zend_array_dup(HashTable *source) target->nTableSize = HT_MIN_SIZE; HT_SET_DATA_ADDR(target, &uninitialized_bucket); } else if (GC_FLAGS(source) & IS_ARRAY_IMMUTABLE) { + ZEND_ASSERT(!(HT_FLAGS(source) & HASH_FLAG_HAS_EMPTY_IND)); HT_FLAGS(target) = HT_FLAGS(source) & HASH_FLAG_MASK; target->nTableMask = source->nTableMask; target->nNumUsed = source->nNumUsed; @@ -2482,6 +2483,7 @@ ZEND_API HashTable* ZEND_FASTCALL zend_array_dup(HashTable *source) memcpy(HT_GET_DATA_ADDR(target), HT_GET_DATA_ADDR(source), HT_USED_SIZE(source)); } } else if (HT_IS_PACKED(source)) { + ZEND_ASSERT(!(HT_FLAGS(source) & HASH_FLAG_HAS_EMPTY_IND)); HT_FLAGS(target) = HT_FLAGS(source) & HASH_FLAG_MASK; target->nTableMask = HT_MIN_MASK; target->nNumUsed = source->nNumUsed; @@ -2501,7 +2503,8 @@ ZEND_API HashTable* ZEND_FASTCALL zend_array_dup(HashTable *source) zend_array_dup_packed_elements(source, target, 1); } } else { - HT_FLAGS(target) = HT_FLAGS(source) & HASH_FLAG_MASK; + /* Indirects are removed during duplication, remove HASH_FLAG_HAS_EMPTY_IND accordingly. */ + HT_FLAGS(target) = HT_FLAGS(source) & (HASH_FLAG_MASK & ~HASH_FLAG_HAS_EMPTY_IND); target->nTableMask = source->nTableMask; target->nNextFreeElement = source->nNextFreeElement; target->nInternalPointer = diff --git a/Zend/zend_string.c b/Zend/zend_string.c index dfe059359aa53..e9ebee08f4393 100644 --- a/Zend/zend_string.c +++ b/Zend/zend_string.c @@ -505,8 +505,10 @@ ZEND_API zend_string *zend_string_concat3( return res; } -/* strlcpy and strlcat are not intercepted by msan, so we need to do it ourselves. */ -#if __has_feature(memory_sanitizer) +/* strlcpy and strlcat are not always intercepted by msan, so we need to do it + * ourselves. Apply a simple heuristic to determine the platforms that need it. + * See https://github.com/php/php-src/issues/20002. */ +#if __has_feature(memory_sanitizer) && !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__APPLE__) static size_t (*libc_strlcpy)(char *__restrict, const char *__restrict, size_t); size_t strlcpy(char *__restrict dest, const char *__restrict src, size_t n) { diff --git a/configure.ac b/configure.ac index 0c9bf96e64b9a..48f19717e8ece 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.3.26-dev],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) +AC_INIT([PHP],[8.3.27RC1],[https://github.com/php/php-src/issues],[php],[https://www.php.net]) AC_CONFIG_SRCDIR([main/php_version.h]) AC_CONFIG_AUX_DIR([build]) AC_PRESERVE_HELP_ORDER diff --git a/ext/curl/interface.c b/ext/curl/interface.c index b3139422cffa5..bf8703278b5d0 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -468,7 +468,7 @@ static zend_object *curl_clone_obj(zend_object *object) { clone_ch->cp = cp; _php_setup_easy_copy_handlers(clone_ch, ch); - postfields = &clone_ch->postfields; + postfields = &ch->postfields; if (Z_TYPE_P(postfields) != IS_UNDEF) { if (build_mime_structure_from_hash(clone_ch, postfields) == FAILURE) { zend_throw_exception(NULL, "Failed to clone CurlHandle", 0); @@ -677,11 +677,11 @@ static int curl_fnmatch(void *ctx, const char *pattern, const char *string) /* }}} */ /* {{{ curl_progress */ -static size_t curl_progress(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow) +static int curl_progress(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow) { php_curl *ch = (php_curl *)clientp; php_curl_callback *t = ch->handlers.progress; - size_t rval = 0; + int rval = 0; #if PHP_CURL_DEBUG fprintf(stderr, "curl_progress() called\n"); @@ -726,11 +726,11 @@ static size_t curl_progress(void *clientp, double dltotal, double dlnow, double #if LIBCURL_VERSION_NUM >= 0x072000 /* {{{ curl_xferinfo */ -static size_t curl_xferinfo(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) +static int curl_xferinfo(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) { php_curl *ch = (php_curl *)clientp; php_curl_callback *t = ch->handlers.xferinfo; - size_t rval = 0; + int rval = 0; #if PHP_CURL_DEBUG fprintf(stderr, "curl_xferinfo() called\n"); @@ -1154,8 +1154,8 @@ static void _php_curl_set_default_options(php_curl *ch) { char *cainfo; - curl_easy_setopt(ch->cp, CURLOPT_NOPROGRESS, 1); - curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 0); + curl_easy_setopt(ch->cp, CURLOPT_NOPROGRESS, 1L); + curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 0L); curl_easy_setopt(ch->cp, CURLOPT_ERRORBUFFER, ch->err.str); curl_easy_setopt(ch->cp, CURLOPT_WRITEFUNCTION, curl_write); curl_easy_setopt(ch->cp, CURLOPT_FILE, (void *) ch); @@ -1164,10 +1164,10 @@ static void _php_curl_set_default_options(php_curl *ch) curl_easy_setopt(ch->cp, CURLOPT_HEADERFUNCTION, curl_write_header); curl_easy_setopt(ch->cp, CURLOPT_WRITEHEADER, (void *) ch); #ifndef ZTS - curl_easy_setopt(ch->cp, CURLOPT_DNS_USE_GLOBAL_CACHE, 1); + curl_easy_setopt(ch->cp, CURLOPT_DNS_USE_GLOBAL_CACHE, 1L); #endif - curl_easy_setopt(ch->cp, CURLOPT_DNS_CACHE_TIMEOUT, 120); - curl_easy_setopt(ch->cp, CURLOPT_MAXREDIRS, 20); /* prevent infinite redirects */ + curl_easy_setopt(ch->cp, CURLOPT_DNS_CACHE_TIMEOUT, 120L); + curl_easy_setopt(ch->cp, CURLOPT_MAXREDIRS, 20L); /* prevent infinite redirects */ cainfo = INI_STR("openssl.cafile"); if (!(cainfo && cainfo[0] != '\0')) { @@ -1178,7 +1178,7 @@ static void _php_curl_set_default_options(php_curl *ch) } #ifdef ZTS - curl_easy_setopt(ch->cp, CURLOPT_NOSIGNAL, 1); + curl_easy_setopt(ch->cp, CURLOPT_NOSIGNAL, 1L); #endif } /* }}} */ @@ -1689,7 +1689,7 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue lval = zval_get_long(zvalue); if (lval == 1) { php_error_docref(NULL, E_NOTICE, "CURLOPT_SSL_VERIFYHOST no longer accepts the value 1, value 2 will be used instead"); - error = curl_easy_setopt(ch->cp, option, 2); + error = curl_easy_setopt(ch->cp, option, 2L); break; } ZEND_FALLTHROUGH; @@ -2260,7 +2260,7 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue case CURLOPT_FOLLOWLOCATION: lval = zend_is_true(zvalue); - error = curl_easy_setopt(ch->cp, option, lval); + error = curl_easy_setopt(ch->cp, option, (long) lval); break; case CURLOPT_HEADERFUNCTION: @@ -2278,7 +2278,7 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue /* no need to build the mime structure for empty hashtables; also works around https://github.com/curl/curl/issues/6455 */ curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDS, ""); - error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDSIZE, 0); + error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDSIZE, 0L); } else { return build_mime_structure_from_hash(ch, zvalue); } @@ -2371,7 +2371,7 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue case CURLOPT_POSTREDIR: lval = zval_get_long(zvalue); - error = curl_easy_setopt(ch->cp, CURLOPT_POSTREDIR, lval & CURL_REDIR_POST_ALL); + error = curl_easy_setopt(ch->cp, CURLOPT_POSTREDIR, (long) (lval & CURL_REDIR_POST_ALL)); break; /* the following options deal with files, therefore the open_basedir check @@ -2406,11 +2406,11 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue if (zend_is_true(zvalue)) { curl_easy_setopt(ch->cp, CURLOPT_DEBUGFUNCTION, curl_debug); curl_easy_setopt(ch->cp, CURLOPT_DEBUGDATA, (void *)ch); - curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 1); + curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 1L); } else { curl_easy_setopt(ch->cp, CURLOPT_DEBUGFUNCTION, NULL); curl_easy_setopt(ch->cp, CURLOPT_DEBUGDATA, NULL); - curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 0); + curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 0L); } break; diff --git a/ext/curl/tests/curl_copy_handle_variation3_clone.phpt b/ext/curl/tests/curl_copy_handle_variation3_clone.phpt new file mode 100644 index 0000000000000..7951cb0258111 --- /dev/null +++ b/ext/curl/tests/curl_copy_handle_variation3_clone.phpt @@ -0,0 +1,34 @@ +--TEST-- +clone() allows to post CURLFile multiple times +--EXTENSIONS-- +curl +--FILE-- + $file); +var_dump(curl_setopt($ch1, CURLOPT_POSTFIELDS, $params)); + +$ch2 = clone($ch1); + +var_dump(curl_exec($ch1)); + +var_dump(curl_exec($ch2)); +?> +--EXPECTF-- +bool(true) +string(%d) "curl_copy_handle_variation3_clone.txt|application/octet-stream|5" +string(%d) "curl_copy_handle_variation3_clone.txt|application/octet-stream|5" +--CLEAN-- + diff --git a/ext/curl/tests/curl_setopt_ssl.phpt b/ext/curl/tests/curl_setopt_ssl.phpt index 11d8fff702a88..ff08528321a0f 100644 --- a/ext/curl/tests/curl_setopt_ssl.phpt +++ b/ext/curl/tests/curl_setopt_ssl.phpt @@ -18,9 +18,13 @@ if ($curl_version['version_number'] < 0x074700) { --FILE-- 0 && **ptr == ')') { ++*ptr; + paren_count--; } return retval; } @@ -1018,11 +1021,11 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) std: s->tok = cursor; s->len = 0; -#line 1151 "ext/date/lib/parse_date.re" +#line 1154 "ext/date/lib/parse_date.re" -#line 1026 "" +#line 1029 "ext/date/lib/parse_date.c" { YYCTYPE yych; unsigned int yyaccept = 0; @@ -1203,23 +1206,23 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(2, *YYCURSOR); ++YYCURSOR; YYDEBUG(3, *YYCURSOR); -#line 1984 "ext/date/lib/parse_date.re" +#line 1987 "ext/date/lib/parse_date.re" { s->pos = cursor; s->line++; goto std; } -#line 1212 "" +#line 1215 "ext/date/lib/parse_date.c" yy4: YYDEBUG(4, *YYCURSOR); ++YYCURSOR; yy5: YYDEBUG(5, *YYCURSOR); -#line 1990 "ext/date/lib/parse_date.re" +#line 1993 "ext/date/lib/parse_date.re" { add_error(s, TIMELIB_ERR_UNEXPECTED_CHARACTER, "Unexpected character"); goto std; } -#line 1223 "" +#line 1226 "ext/date/lib/parse_date.c" yy6: YYDEBUG(6, *YYCURSOR); yyaccept = 0; @@ -1234,11 +1237,11 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych <= '9') goto yy58; yy8: YYDEBUG(8, *YYCURSOR); -#line 1979 "ext/date/lib/parse_date.re" +#line 1982 "ext/date/lib/parse_date.re" { goto std; } -#line 1242 "" +#line 1245 "ext/date/lib/parse_date.c" yy9: YYDEBUG(9, *YYCURSOR); yych = *++YYCURSOR; @@ -1272,11 +1275,11 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(11, *YYCURSOR); ++YYCURSOR; YYDEBUG(12, *YYCURSOR); -#line 1974 "ext/date/lib/parse_date.re" +#line 1977 "ext/date/lib/parse_date.re" { goto std; } -#line 1280 "" +#line 1283 "ext/date/lib/parse_date.c" yy13: YYDEBUG(13, *YYCURSOR); yyaccept = 1; @@ -1777,7 +1780,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy20: YYDEBUG(20, *YYCURSOR); -#line 1889 "ext/date/lib/parse_date.re" +#line 1892 "ext/date/lib/parse_date.re" { int tz_not_found; DEBUG_OUTPUT("tzcorrection | tz"); @@ -1791,7 +1794,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_TIMEZONE; } -#line 1795 "" +#line 1798 "ext/date/lib/parse_date.c" yy21: YYDEBUG(21, *YYCURSOR); yych = *++YYCURSOR; @@ -3596,7 +3599,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy81: YYDEBUG(81, *YYCURSOR); -#line 1636 "ext/date/lib/parse_date.re" +#line 1639 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("datenoyearrev"); TIMELIB_INIT; @@ -3607,7 +3610,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_TEXT; } -#line 3611 "" +#line 3614 "ext/date/lib/parse_date.c" yy82: YYDEBUG(82, *YYCURSOR); yych = *++YYCURSOR; @@ -4122,7 +4125,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } if (yych == '.') goto yy289; YYDEBUG(114, *YYCURSOR); -#line 1211 "ext/date/lib/parse_date.re" +#line 1214 "ext/date/lib/parse_date.re" { timelib_ull i; @@ -4147,7 +4150,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 4151 "" +#line 4154 "ext/date/lib/parse_date.c" yy115: YYDEBUG(115, *YYCURSOR); ++YYCURSOR; @@ -5873,7 +5876,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy177: YYDEBUG(177, *YYCURSOR); -#line 1377 "ext/date/lib/parse_date.re" +#line 1380 "ext/date/lib/parse_date.re" { int tz_not_found; DEBUG_OUTPUT("timetiny24 | timeshort24 | timelong24 | iso8601long"); @@ -5900,7 +5903,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_TIME24_WITH_ZONE; } -#line 5904 "" +#line 5907 "ext/date/lib/parse_date.c" yy178: YYDEBUG(178, *YYCURSOR); yyaccept = 4; @@ -6929,7 +6932,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy224: YYDEBUG(224, *YYCURSOR); -#line 1471 "ext/date/lib/parse_date.re" +#line 1474 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("americanshort | american"); @@ -6944,7 +6947,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_AMERICAN; } -#line 6948 "" +#line 6951 "ext/date/lib/parse_date.c" yy225: YYDEBUG(225, *YYCURSOR); yyaccept = 5; @@ -7187,7 +7190,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych <= '9') goto yy431; yy251: YYDEBUG(251, *YYCURSOR); -#line 1553 "ext/date/lib/parse_date.re" +#line 1556 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("datefull"); @@ -7201,7 +7204,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_FULL; } -#line 7205 "" +#line 7208 "ext/date/lib/parse_date.c" yy252: YYDEBUG(252, *YYCURSOR); yyaccept = 3; @@ -7315,7 +7318,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych == 'e') goto yy440; yy260: YYDEBUG(260, *YYCURSOR); -#line 1958 "ext/date/lib/parse_date.re" +#line 1961 "ext/date/lib/parse_date.re" { timelib_ull i; DEBUG_OUTPUT("relative"); @@ -7330,7 +7333,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 7334 "" +#line 7337 "ext/date/lib/parse_date.c" yy261: YYDEBUG(261, *YYCURSOR); yych = *++YYCURSOR; @@ -7776,7 +7779,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych <= '9') goto yy471; yy290: YYDEBUG(290, *YYCURSOR); -#line 1237 "ext/date/lib/parse_date.re" +#line 1240 "ext/date/lib/parse_date.re" { timelib_sll i; timelib_ull us; @@ -7815,7 +7818,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 7819 "" +#line 7822 "ext/date/lib/parse_date.c" yy291: YYDEBUG(291, *YYCURSOR); yych = *++YYCURSOR; @@ -7840,7 +7843,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy293: YYDEBUG(293, *YYCURSOR); -#line 1799 "ext/date/lib/parse_date.re" +#line 1802 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("ago"); TIMELIB_INIT; @@ -7860,7 +7863,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_AGO; } -#line 7864 "" +#line 7867 "ext/date/lib/parse_date.c" yy294: YYDEBUG(294, *YYCURSOR); yyaccept = 7; @@ -7899,7 +7902,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy295: YYDEBUG(295, *YYCURSOR); -#line 1879 "ext/date/lib/parse_date.re" +#line 1882 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("monthtext"); TIMELIB_INIT; @@ -7908,7 +7911,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_TEXT; } -#line 7912 "" +#line 7915 "ext/date/lib/parse_date.c" yy296: YYDEBUG(296, *YYCURSOR); yyaccept = 7; @@ -8483,7 +8486,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy315: YYDEBUG(315, *YYCURSOR); -#line 1820 "ext/date/lib/parse_date.re" +#line 1823 "ext/date/lib/parse_date.re" { const timelib_relunit* relunit; DEBUG_OUTPUT("daytext"); @@ -8500,7 +8503,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_WEEKDAY; } -#line 8504 "" +#line 8507 "ext/date/lib/parse_date.c" yy316: YYDEBUG(316, *YYCURSOR); yych = *++YYCURSOR; @@ -8768,7 +8771,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy325: YYDEBUG(325, *YYCURSOR); -#line 1622 "ext/date/lib/parse_date.re" +#line 1625 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("datetextual | datenoyear"); @@ -8781,7 +8784,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_TEXT; } -#line 8785 "" +#line 8788 "ext/date/lib/parse_date.c" yy326: YYDEBUG(326, *YYCURSOR); yyaccept = 10; @@ -9475,7 +9478,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy351: YYDEBUG(351, *YYCURSOR); -#line 1168 "ext/date/lib/parse_date.re" +#line 1171 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("now"); TIMELIB_INIT; @@ -9483,7 +9486,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 9487 "" +#line 9490 "ext/date/lib/parse_date.c" yy352: YYDEBUG(352, *YYCURSOR); yyaccept = 2; @@ -10986,7 +10989,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy420: YYDEBUG(420, *YYCURSOR); -#line 1405 "ext/date/lib/parse_date.re" +#line 1408 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("gnunocolon"); TIMELIB_INIT; @@ -11008,7 +11011,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_GNU_NOCOLON; } -#line 11012 "" +#line 11015 "ext/date/lib/parse_date.c" yy421: YYDEBUG(421, *YYCURSOR); yyaccept = 13; @@ -11089,7 +11092,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy422: YYDEBUG(422, *YYCURSOR); -#line 1790 "ext/date/lib/parse_date.re" +#line 1793 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("year4"); TIMELIB_INIT; @@ -11097,7 +11100,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_CLF; } -#line 11101 "" +#line 11104 "ext/date/lib/parse_date.c" yy423: YYDEBUG(423, *YYCURSOR); yyaccept = 3; @@ -11704,7 +11707,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(456, *YYCURSOR); ++YYCURSOR; YYDEBUG(457, *YYCURSOR); -#line 1339 "ext/date/lib/parse_date.re" +#line 1342 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("timetiny12 | timeshort12 | timelong12"); TIMELIB_INIT; @@ -11721,7 +11724,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_TIME12; } -#line 11725 "" +#line 11728 "ext/date/lib/parse_date.c" yy458: YYDEBUG(458, *YYCURSOR); yych = *++YYCURSOR; @@ -13048,7 +13051,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy526: YYDEBUG(526, *YYCURSOR); -#line 1177 "ext/date/lib/parse_date.re" +#line 1180 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("noon"); TIMELIB_INIT; @@ -13059,7 +13062,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 13063 "" +#line 13066 "ext/date/lib/parse_date.c" yy527: YYDEBUG(527, *YYCURSOR); yyaccept = 2; @@ -14105,7 +14108,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy567: YYDEBUG(567, *YYCURSOR); -#line 1539 "ext/date/lib/parse_date.re" +#line 1542 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("gnudateshort"); @@ -14118,7 +14121,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 14122 "" +#line 14125 "ext/date/lib/parse_date.c" yy568: YYDEBUG(568, *YYCURSOR); yyaccept = 15; @@ -14569,7 +14572,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy600: YYDEBUG(600, *YYCURSOR); -#line 1608 "ext/date/lib/parse_date.re" +#line 1611 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("datenodayrev"); @@ -14582,7 +14585,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_NO_DAY; } -#line 14586 "" +#line 14589 "ext/date/lib/parse_date.c" yy601: YYDEBUG(601, *YYCURSOR); yych = *++YYCURSOR; @@ -15957,7 +15960,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(696, *YYCURSOR); ++YYCURSOR; YYDEBUG(697, *YYCURSOR); -#line 1594 "ext/date/lib/parse_date.re" +#line 1597 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("datenoday"); @@ -15970,7 +15973,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_NO_DAY; } -#line 15974 "" +#line 15977 "ext/date/lib/parse_date.c" yy698: YYDEBUG(698, *YYCURSOR); yych = *++YYCURSOR; @@ -16531,7 +16534,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy722: YYDEBUG(722, *YYCURSOR); -#line 1189 "ext/date/lib/parse_date.re" +#line 1192 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("midnight | today"); TIMELIB_INIT; @@ -16540,7 +16543,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 16544 "" +#line 16547 "ext/date/lib/parse_date.c" yy723: YYDEBUG(723, *YYCURSOR); yych = *++YYCURSOR; @@ -16850,7 +16853,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych <= '9') goto yy897; yy739: YYDEBUG(739, *YYCURSOR); -#line 1580 "ext/date/lib/parse_date.re" +#line 1583 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("pointed date YY"); @@ -16863,7 +16866,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_FULL_POINTED; } -#line 16867 "" +#line 16870 "ext/date/lib/parse_date.c" yy740: YYDEBUG(740, *YYCURSOR); yyaccept = 15; @@ -16975,7 +16978,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy752: YYDEBUG(752, *YYCURSOR); -#line 1525 "ext/date/lib/parse_date.re" +#line 1528 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("gnudateshorter"); @@ -16988,7 +16991,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 16992 "" +#line 16995 "ext/date/lib/parse_date.c" yy753: YYDEBUG(753, *YYCURSOR); yyaccept = 18; @@ -17237,7 +17240,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy777: YYDEBUG(777, *YYCURSOR); -#line 1451 "ext/date/lib/parse_date.re" +#line 1454 "ext/date/lib/parse_date.re" { int tz_not_found; DEBUG_OUTPUT("iso8601nocolon"); @@ -17256,7 +17259,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_ISO_NOCOLON; } -#line 17260 "" +#line 17263 "ext/date/lib/parse_date.c" yy778: YYDEBUG(778, *YYCURSOR); yyaccept = 19; @@ -18484,7 +18487,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy849: YYDEBUG(849, *YYCURSOR); -#line 1928 "ext/date/lib/parse_date.re" +#line 1931 "ext/date/lib/parse_date.re" { int tz_not_found; DEBUG_OUTPUT("dateshortwithtimeshort | dateshortwithtimelong | dateshortwithtimelongtz"); @@ -18513,7 +18516,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_SHORTDATE_WITH_TIME; } -#line 18517 "" +#line 18520 "ext/date/lib/parse_date.c" yy850: YYDEBUG(850, *YYCURSOR); yyaccept = 20; @@ -19557,7 +19560,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy926: YYDEBUG(926, *YYCURSOR); -#line 1686 "ext/date/lib/parse_date.re" +#line 1689 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("pgydotd"); @@ -19570,7 +19573,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_PG_YEARDAY; } -#line 19574 "" +#line 19577 "ext/date/lib/parse_date.c" yy927: YYDEBUG(927, *YYCURSOR); yyaccept = 21; @@ -19824,7 +19827,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych <= '7') goto yy1059; yy942: YYDEBUG(942, *YYCURSOR); -#line 1719 "ext/date/lib/parse_date.re" +#line 1722 "ext/date/lib/parse_date.re" { timelib_sll w, d; DEBUG_OUTPUT("isoweek"); @@ -19842,7 +19845,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_ISO_WEEK; } -#line 19846 "" +#line 19849 "ext/date/lib/parse_date.c" yy943: YYDEBUG(943, *YYCURSOR); yych = *++YYCURSOR; @@ -20318,7 +20321,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych == 'e') goto yy1094; yy982: YYDEBUG(982, *YYCURSOR); -#line 1862 "ext/date/lib/parse_date.re" +#line 1865 "ext/date/lib/parse_date.re" { timelib_sll i; int behavior = 0; @@ -20334,7 +20337,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 20338 "" +#line 20341 "ext/date/lib/parse_date.c" yy983: YYDEBUG(983, *YYCURSOR); yych = *++YYCURSOR; @@ -20681,7 +20684,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(1020, *YYCURSOR); ++YYCURSOR; YYDEBUG(1021, *YYCURSOR); -#line 1568 "ext/date/lib/parse_date.re" +#line 1571 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("pointed date YYYY"); TIMELIB_INIT; @@ -20692,7 +20695,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_FULL_POINTED; } -#line 20696 "" +#line 20699 "ext/date/lib/parse_date.c" yy1022: YYDEBUG(1022, *YYCURSOR); ++YYCURSOR; @@ -20721,7 +20724,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy1025: YYDEBUG(1025, *YYCURSOR); -#line 1499 "ext/date/lib/parse_date.re" +#line 1502 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("iso8601date2"); @@ -20734,7 +20737,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 20738 "" +#line 20741 "ext/date/lib/parse_date.c" yy1026: YYDEBUG(1026, *YYCURSOR); yyaccept = 15; @@ -20954,7 +20957,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy1043: YYDEBUG(1043, *YYCURSOR); -#line 1487 "ext/date/lib/parse_date.re" +#line 1490 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("iso8601date4 | iso8601date2 | iso8601dateslash | dateslash"); TIMELIB_INIT; @@ -20965,7 +20968,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 20969 "" +#line 20972 "ext/date/lib/parse_date.c" yy1044: YYDEBUG(1044, *YYCURSOR); yyaccept = 26; @@ -21080,7 +21083,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy1048: YYDEBUG(1048, *YYCURSOR); -#line 1648 "ext/date/lib/parse_date.re" +#line 1651 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("datenocolon"); TIMELIB_INIT; @@ -21091,7 +21094,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_DATE_NOCOLON; } -#line 21095 "" +#line 21098 "ext/date/lib/parse_date.c" yy1049: YYDEBUG(1049, *YYCURSOR); yych = *++YYCURSOR; @@ -21161,7 +21164,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(1059, *YYCURSOR); ++YYCURSOR; YYDEBUG(1060, *YYCURSOR); -#line 1700 "ext/date/lib/parse_date.re" +#line 1703 "ext/date/lib/parse_date.re" { timelib_sll w, d; DEBUG_OUTPUT("isoweekday"); @@ -21179,7 +21182,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_ISO_WEEK; } -#line 21183 "" +#line 21186 "ext/date/lib/parse_date.c" yy1061: YYDEBUG(1061, *YYCURSOR); yych = *++YYCURSOR; @@ -21242,7 +21245,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych <= '9') goto yy1143; yy1070: YYDEBUG(1070, *YYCURSOR); -#line 1738 "ext/date/lib/parse_date.re" +#line 1741 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("pgtextshort"); @@ -21255,7 +21258,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_PG_TEXT; } -#line 21259 "" +#line 21262 "ext/date/lib/parse_date.c" yy1071: YYDEBUG(1071, *YYCURSOR); yych = *++YYCURSOR; @@ -21728,7 +21731,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) ++YYCURSOR; yy1107: YYDEBUG(1107, *YYCURSOR); -#line 1199 "ext/date/lib/parse_date.re" +#line 1202 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("tomorrow"); TIMELIB_INIT; @@ -21739,7 +21742,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 21743 "" +#line 21746 "ext/date/lib/parse_date.c" yy1108: YYDEBUG(1108, *YYCURSOR); yyaccept = 28; @@ -22076,7 +22079,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(1140, *YYCURSOR); ++YYCURSOR; YYDEBUG(1141, *YYCURSOR); -#line 1752 "ext/date/lib/parse_date.re" +#line 1755 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("pgtextreverse"); @@ -22089,7 +22092,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_PG_TEXT; } -#line 22093 "" +#line 22096 "ext/date/lib/parse_date.c" yy1142: YYDEBUG(1142, *YYCURSOR); ++YYCURSOR; @@ -22133,7 +22136,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy1145: YYDEBUG(1145, *YYCURSOR); -#line 1294 "ext/date/lib/parse_date.re" +#line 1297 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("backof | frontof"); TIMELIB_INIT; @@ -22155,7 +22158,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_LF_DAY_OF_MONTH; } -#line 22159 "" +#line 22162 "ext/date/lib/parse_date.c" yy1146: YYDEBUG(1146, *YYCURSOR); yyaccept = 29; @@ -22479,7 +22482,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) } yy1172: YYDEBUG(1172, *YYCURSOR); -#line 1838 "ext/date/lib/parse_date.re" +#line 1841 "ext/date/lib/parse_date.re" { timelib_sll i; int behavior = 0; @@ -22502,7 +22505,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 22506 "" +#line 22509 "ext/date/lib/parse_date.c" yy1173: YYDEBUG(1173, *YYCURSOR); yych = *++YYCURSOR; @@ -22514,7 +22517,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) ++YYCURSOR; yy1175: YYDEBUG(1175, *YYCURSOR); -#line 1156 "ext/date/lib/parse_date.re" +#line 1159 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("yesterday"); TIMELIB_INIT; @@ -22525,7 +22528,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 22529 "" +#line 22532 "ext/date/lib/parse_date.c" yy1176: YYDEBUG(1176, *YYCURSOR); yyaccept = 31; @@ -23018,7 +23021,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(1222, *YYCURSOR); ++YYCURSOR; YYDEBUG(1223, *YYCURSOR); -#line 1904 "ext/date/lib/parse_date.re" +#line 1907 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("dateshortwithtimeshort12 | dateshortwithtimelong12"); TIMELIB_INIT; @@ -23041,7 +23044,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_SHORTDATE_WITH_TIME; } -#line 23045 "" +#line 23048 "ext/date/lib/parse_date.c" yy1224: YYDEBUG(1224, *YYCURSOR); yych = *++YYCURSOR; @@ -23543,7 +23546,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(1268, *YYCURSOR); ++YYCURSOR; YYDEBUG(1269, *YYCURSOR); -#line 1317 "ext/date/lib/parse_date.re" +#line 1320 "ext/date/lib/parse_date.re" { timelib_sll i; int behavior = 0; @@ -23564,7 +23567,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_WEEK_DAY_OF_MONTH; } -#line 23568 "" +#line 23571 "ext/date/lib/parse_date.c" yy1270: YYDEBUG(1270, *YYCURSOR); yyaccept = 24; @@ -23611,7 +23614,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(1273, *YYCURSOR); ++YYCURSOR; YYDEBUG(1274, *YYCURSOR); -#line 1277 "ext/date/lib/parse_date.re" +#line 1280 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("firstdayof | lastdayof"); TIMELIB_INIT; @@ -23627,12 +23630,12 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_LF_DAY_OF_MONTH; } -#line 23631 "" +#line 23634 "ext/date/lib/parse_date.c" yy1275: YYDEBUG(1275, *YYCURSOR); ++YYCURSOR; YYDEBUG(1276, *YYCURSOR); -#line 1513 "ext/date/lib/parse_date.re" +#line 1516 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("iso8601datex"); TIMELIB_INIT; @@ -23643,7 +23646,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 23647 "" +#line 23650 "ext/date/lib/parse_date.c" yy1277: YYDEBUG(1277, *YYCURSOR); yych = *++YYCURSOR; @@ -23746,7 +23749,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) YYDEBUG(1290, *YYCURSOR); ++YYCURSOR; YYDEBUG(1291, *YYCURSOR); -#line 1357 "ext/date/lib/parse_date.re" +#line 1360 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("mssqltime"); TIMELIB_INIT; @@ -23765,7 +23768,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_TIME24_WITH_ZONE; } -#line 23769 "" +#line 23772 "ext/date/lib/parse_date.c" yy1292: YYDEBUG(1292, *YYCURSOR); yych = *++YYCURSOR; @@ -24189,7 +24192,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych <= '9') goto yy1331; yy1329: YYDEBUG(1329, *YYCURSOR); -#line 1660 "ext/date/lib/parse_date.re" +#line 1663 "ext/date/lib/parse_date.re" { int tz_not_found; DEBUG_OUTPUT("xmlrpc | xmlrpcnocolon | soap | wddx | exif"); @@ -24214,7 +24217,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_XMLRPC_SOAP; } -#line 24218 "" +#line 24221 "ext/date/lib/parse_date.c" yy1330: YYDEBUG(1330, *YYCURSOR); yych = *++YYCURSOR; @@ -24584,7 +24587,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych <= ':') goto yy1383; yy1375: YYDEBUG(1375, *YYCURSOR); -#line 1766 "ext/date/lib/parse_date.re" +#line 1769 "ext/date/lib/parse_date.re" { int tz_not_found; DEBUG_OUTPUT("clf"); @@ -24607,7 +24610,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) TIMELIB_DEINIT; return TIMELIB_CLF; } -#line 24611 "" +#line 24614 "ext/date/lib/parse_date.c" yy1376: YYDEBUG(1376, *YYCURSOR); yyaccept = 33; @@ -24839,7 +24842,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) if (yych == ':') goto yy1286; goto yy1329; } -#line 1994 "ext/date/lib/parse_date.re" +#line 1997 "ext/date/lib/parse_date.re" } diff --git a/ext/date/lib/parse_date.re b/ext/date/lib/parse_date.re index d32be9bfe7be7..c40a5c07c9aa1 100644 --- a/ext/date/lib/parse_date.re +++ b/ext/date/lib/parse_date.re @@ -939,10 +939,12 @@ timelib_long timelib_parse_zone(const char **ptr, int *dst, timelib_time *t, int { timelib_tzinfo *res; timelib_long retval = 0; + size_t paren_count = 0; *tz_not_found = 0; while (**ptr == ' ' || **ptr == '\t' || **ptr == '(') { + paren_count += **ptr == '('; ++*ptr; } if ((*ptr)[0] == 'G' && (*ptr)[1] == 'M' && (*ptr)[2] == 'T' && ((*ptr)[3] == '+' || (*ptr)[3] == '-')) { @@ -991,8 +993,9 @@ timelib_long timelib_parse_zone(const char **ptr, int *dst, timelib_time *t, int *tz_not_found = (found == 0); retval = offset; } - while (**ptr == ')') { + while (paren_count > 0 && **ptr == ')') { ++*ptr; + paren_count--; } return retval; } diff --git a/ext/date/lib/parse_iso_intervals.c b/ext/date/lib/parse_iso_intervals.c index cdc329431ec45..a9fca1b609413 100644 --- a/ext/date/lib/parse_iso_intervals.c +++ b/ext/date/lib/parse_iso_intervals.c @@ -1,4 +1,4 @@ -/* Generated by re2c 1.0.3 on Wed Sep 11 17:29:40 2024 */ +/* Generated by re2c 1.0.3 on Mon Sep 15 10:38:16 2025 */ #line 1 "ext/date/lib/parse_iso_intervals.re" /* * The MIT License (MIT) @@ -180,7 +180,7 @@ static int scan(Scanner *s) -#line 184 "" +#line 184 "ext/date/lib/parse_iso_intervals.c" { YYCTYPE yych; unsigned int yyaccept = 0; @@ -252,7 +252,7 @@ static int scan(Scanner *s) s->pos = cursor; s->line++; goto std; } -#line 256 "" +#line 256 "ext/date/lib/parse_iso_intervals.c" yy4: YYDEBUG(4, *YYCURSOR); ++YYCURSOR; @@ -263,7 +263,7 @@ static int scan(Scanner *s) add_error(s, "Unexpected character"); goto std; } -#line 267 "" +#line 267 "ext/date/lib/parse_iso_intervals.c" yy6: YYDEBUG(6, *YYCURSOR); ++YYCURSOR; @@ -272,7 +272,7 @@ static int scan(Scanner *s) { goto std; } -#line 276 "" +#line 276 "ext/date/lib/parse_iso_intervals.c" yy8: YYDEBUG(8, *YYCURSOR); yyaccept = 0; @@ -330,7 +330,7 @@ static int scan(Scanner *s) TIMELIB_DEINIT; return TIMELIB_PERIOD; } -#line 334 "" +#line 334 "ext/date/lib/parse_iso_intervals.c" yy11: YYDEBUG(11, *YYCURSOR); yych = *++YYCURSOR; @@ -399,7 +399,7 @@ static int scan(Scanner *s) s->have_recurrences = 1; return TIMELIB_PERIOD; } -#line 403 "" +#line 403 "ext/date/lib/parse_iso_intervals.c" yy19: YYDEBUG(19, *YYCURSOR); yych = *++YYCURSOR; @@ -917,7 +917,7 @@ static int scan(Scanner *s) TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 921 "" +#line 921 "ext/date/lib/parse_iso_intervals.c" yy91: YYDEBUG(91, *YYCURSOR); yych = *++YYCURSOR; @@ -956,7 +956,7 @@ static int scan(Scanner *s) TIMELIB_DEINIT; return TIMELIB_PERIOD; } -#line 960 "" +#line 960 "ext/date/lib/parse_iso_intervals.c" } #line 321 "ext/date/lib/parse_iso_intervals.re" diff --git a/ext/date/lib/timelib.h b/ext/date/lib/timelib.h index a2c976af7ed9c..ef57a7ee783f0 100644 --- a/ext/date/lib/timelib.h +++ b/ext/date/lib/timelib.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2015-2024 Derick Rethans + * Copyright (c) 2015-2025 Derick Rethans * Copyright (c) 2018,2021 MongoDB, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -30,9 +30,9 @@ # include "timelib_config.h" #endif -#define TIMELIB_VERSION 202212 -#define TIMELIB_EXTENDED_VERSION 20221201 -#define TIMELIB_ASCII_VERSION "2022.12" +#define TIMELIB_VERSION 202214 +#define TIMELIB_EXTENDED_VERSION 20221401 +#define TIMELIB_ASCII_VERSION "2022.14" #include #include diff --git a/ext/dba/dba.c b/ext/dba/dba.c index 9affb5aa6fc19..1474573f3e4de 100644 --- a/ext/dba/dba.c +++ b/ext/dba/dba.c @@ -984,6 +984,11 @@ PHP_FUNCTION(dba_fetch) ZEND_PARSE_PARAMETERS_END(); } + if (ZEND_LONG_EXCEEDS_INT(skip)) { + zend_argument_value_error(3, "must be between %d and %d", INT_MIN, INT_MAX); + RETURN_THROWS(); + } + DBA_FETCH_RESOURCE(info, id); if (key_ht) { diff --git a/ext/dba/tests/gh19885.phpt b/ext/dba/tests/gh19885.phpt new file mode 100644 index 0000000000000..987aea4f175a2 --- /dev/null +++ b/ext/dba/tests/gh19885.phpt @@ -0,0 +1,35 @@ +--TEST-- +GH-19885 (dba_fetch() segfault on large skip values) +--EXTENSIONS-- +dba +--SKIPIF-- + +--FILE-- +getMessage(), PHP_EOL; +} + +try { + dba_fetch("https://redirect.github.com/1", $db, PHP_INT_MAX); +} catch (\ValueError $e) { + echo $e->getMessage(), PHP_EOL; +} +// negative skip needs to remain acceptable albeit corrected down the line +var_dump(dba_fetch("https://redirect.github.com/1", $db, -1000000)); +?> +--EXPECTF-- +dba_fetch(): Argument #3 ($skip) must be between -%d and %d +dba_fetch(): Argument #3 ($skip) must be between -%d and %d + +Notice: dba_fetch(): Handler cdb accepts only skip values greater than or equal to zero, using skip=0 in %s on line %d +string(1) "1" diff --git a/ext/gd/libgd/gdkanji.c b/ext/gd/libgd/gdkanji.c index 21bc2280982a8..ef769f89badda 100644 --- a/ext/gd/libgd/gdkanji.c +++ b/ext/gd/libgd/gdkanji.c @@ -368,6 +368,8 @@ do_convert (unsigned char *to, unsigned char *from, const char *code) else error ("something happen"); strcpy ((char *) to, (const char *) from); + if (iconv_close (cd) != 0) + error ("iconv_close() error"); return; } diff --git a/ext/gd/tests/gh19955.phpt b/ext/gd/tests/gh19955.phpt new file mode 100644 index 0000000000000..a4b58e403cf40 --- /dev/null +++ b/ext/gd/tests/gh19955.phpt @@ -0,0 +1,15 @@ +--TEST-- +GH-19955: (imagefttext() memory leak) +--EXTENSIONS-- +gd +--CREDITS-- +YuanchengJiang +--FILE-- + +--EXPECT-- +OK diff --git a/ext/mysqli/tests/bug67563.phpt b/ext/mysqli/tests/bug67563.phpt new file mode 100644 index 0000000000000..72a51ecdccd2c --- /dev/null +++ b/ext/mysqli/tests/bug67563.phpt @@ -0,0 +1,40 @@ +--TEST-- +Fix bug #67563 (mysqli compiled with mysqlnd does not take ipv6 adress as parameter) +--EXTENSIONS-- +mysqli +--SKIPIF-- + +--INI-- +max_execution_time=240 +--FILE-- +close(); + } +} + +print "done!"; +?> +--EXPECT-- +done! diff --git a/ext/mysqlnd/mysqlnd_connection.c b/ext/mysqlnd/mysqlnd_connection.c index d46029889fad0..a97f2820a3190 100644 --- a/ext/mysqlnd/mysqlnd_connection.c +++ b/ext/mysqlnd/mysqlnd_connection.c @@ -513,6 +513,16 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect_handshake)(MYSQLND_CONN_DATA * conn, } /* }}} */ +/* ipv6 addresses have at least two colons, which is how we can differentiate between domain names and addresses */ +static bool mysqlnd_fast_is_ipv6_address(const char *s) +{ + const char *first_colon = strchr(s, ':'); + if (!first_colon) { + return false; + } + return strchr(first_colon + 1, ':') != NULL; +} + /* {{{ mysqlnd_conn_data::get_scheme */ static MYSQLND_STRING MYSQLND_METHOD(mysqlnd_conn_data, get_scheme)(MYSQLND_CONN_DATA * conn, MYSQLND_CSTRING hostname, MYSQLND_CSTRING *socket_or_pipe, unsigned int port, bool * unix_socket, bool * named_pipe) @@ -542,7 +552,13 @@ MYSQLND_METHOD(mysqlnd_conn_data, get_scheme)(MYSQLND_CONN_DATA * conn, MYSQLND_ if (!port) { port = 3306; } - transport.l = mnd_sprintf(&transport.s, 0, "tcp://%s:%u", hostname.s, port); + + /* ipv6 addresses are in the format [address]:port */ + if (hostname.s[0] != '[' && mysqlnd_fast_is_ipv6_address(hostname.s)) { + transport.l = mnd_sprintf(&transport.s, 0, "tcp://[%s]:%u", hostname.s, port); + } else { + transport.l = mnd_sprintf(&transport.s, 0, "tcp://%s:%u", hostname.s, port); + } } DBG_INF_FMT("transport=%s", transport.s? transport.s:"OOM"); DBG_RETURN(transport); diff --git a/ext/opcache/tests/opt/gh19792.phpt b/ext/opcache/tests/opt/gh19792.phpt new file mode 100644 index 0000000000000..edd805ca57a19 --- /dev/null +++ b/ext/opcache/tests/opt/gh19792.phpt @@ -0,0 +1,27 @@ +--TEST-- +GH-19792 (SCCP causes UAF for return value if both warning and exception are triggered) +--EXTENSIONS-- +opcache +zend_test +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--FILE-- +getMessage(), "\n"; +} + +?> +--EXPECTF-- +Warning: a warning in %s on line %d +an exception diff --git a/ext/phar/tar.c b/ext/phar/tar.c index 687ca34c173c9..e675b86943217 100644 --- a/ext/phar/tar.c +++ b/ext/phar/tar.c @@ -1211,7 +1211,16 @@ int phar_tar_flush(phar_archive_data *phar, char *user_stub, zend_long len, int } zend_hash_apply_with_argument(&phar->manifest, phar_tar_writeheaders, (void *) &pass); - /* TODO: memory leak and incorrect continuation if phar_tar_writeheaders fails? */ + + if (error && *error) { + if (closeoldfile) { + php_stream_close(oldfile); + } + + /* on error in the hash iterator above, error is set */ + php_stream_close(newfile); + return EOF; + } /* add signature for executable tars or tars explicitly set with setSignatureAlgorithm */ if (!phar->is_data || phar->sig_flags) { @@ -1294,12 +1303,6 @@ int phar_tar_flush(phar_archive_data *phar, char *user_stub, zend_long len, int php_stream_close(oldfile); } - /* on error in the hash iterator above, error is set */ - if (error && *error) { - php_stream_close(newfile); - return EOF; - } - if (phar->fp && pass.free_fp) { php_stream_close(phar->fp); } diff --git a/ext/phar/tests/tar_flush_too_long_filename.phpt b/ext/phar/tests/tar_flush_too_long_filename.phpt new file mode 100644 index 0000000000000..be18f5e481688 --- /dev/null +++ b/ext/phar/tests/tar_flush_too_long_filename.phpt @@ -0,0 +1,41 @@ +--TEST-- +Tar flush with too long file name +--EXTENSIONS-- +phar +--SKIPIF-- + +--INI-- +phar.require_hash=0 +--FILE-- +addEmptyDir('blah1/'); +$phar->setSignatureAlgorithm(Phar::OPENSSL, "randomcrap"); +try { + $phar->addEmptyDir('blah2/' . str_repeat('X', 1000)); +} catch (PharException $e) { + echo $e->getMessage(); +} + +?> +--CLEAN-- + +--EXPECTF-- +tar-based phar "%s" cannot be created, filename "%s" is too long for tar file format diff --git a/ext/phar/zip.c b/ext/phar/zip.c index 87681c69959a7..dff170dc29b48 100644 --- a/ext/phar/zip.c +++ b/ext/phar/zip.c @@ -1192,7 +1192,9 @@ static int phar_zip_applysignature(phar_archive_data *phar, struct _phar_zip_pas entry.fp_type = PHAR_MOD; entry.is_modified = 1; if (entry.fp == NULL) { + efree(signature); spprintf(pass->error, 0, "phar error: unable to create temporary file for signature"); + php_stream_close(newfile); return FAILURE; } @@ -1456,11 +1458,12 @@ int phar_zip_flush(phar_archive_data *phar, char *user_stub, zend_long len, int phar_metadata_tracker_try_ensure_has_serialized_data(&phar->metadata_tracker, phar->is_persistent); if (temperr) { +temperror: if (error) { spprintf(error, 4096, "phar zip flush of \"%s\" failed: %s", phar->fname, temperr); } efree(temperr); -temperror: +notemperror: php_stream_close(pass.centralfp); nocentralerror: php_stream_close(pass.filefp); @@ -1488,7 +1491,7 @@ int phar_zip_flush(phar_archive_data *phar, char *user_stub, zend_long len, int if (error) { spprintf(error, 4096, "phar zip flush of \"%s\" failed: unable to write central-directory", phar->fname); } - goto temperror; + goto notemperror; } } diff --git a/ext/random/tests/03_randomizer/gh_19765_unserialize.phpt b/ext/random/tests/03_randomizer/gh_19765_unserialize.phpt new file mode 100644 index 0000000000000..24abfca293fc5 --- /dev/null +++ b/ext/random/tests/03_randomizer/gh_19765_unserialize.phpt @@ -0,0 +1,21 @@ +--TEST-- +GH-19765: object_properties_load() bypasses readonly property checks +--FILE-- +__unserialize([['engine' => new PcgOneseq128XslRr64()]]); +} catch (Exception $error) { + echo $error->getMessage() . "\n"; +} +var_dump($r->engine::class); + +?> +--EXPECT-- +Invalid serialization data for Random\Randomizer object +string(21) "Random\Engine\Mt19937" diff --git a/ext/random/tests/03_randomizer/gh_9186_unserialize.phpt b/ext/random/tests/03_randomizer/gh_9186_unserialize.phpt index fe1acb2f74be4..edadb7380bd1f 100644 --- a/ext/random/tests/03_randomizer/gh_9186_unserialize.phpt +++ b/ext/random/tests/03_randomizer/gh_9186_unserialize.phpt @@ -1,5 +1,5 @@ --TEST-- -Fix GH-9186 @strict-properties can be bypassed using unserialization +GH-9186: @strict-properties can be bypassed using unserialization --FILE-- name); - RETURN_STRINGL((char*)node->name, namelen); + RETURN_STRINGL_FAST((const char *) node->name, namelen); } else { RETURN_EMPTY_STRING(); } diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c index 0b4b553d87540..2e03eac0f1b29 100644 --- a/ext/soap/php_encoding.c +++ b/ext/soap/php_encoding.c @@ -3584,6 +3584,11 @@ static encodePtr get_array_type(xmlNodePtr node, zval *array, smart_str *type) soap_error0(E_ERROR, "Encoding: SoapVar has no 'enc_type' property"); } cur_type = Z_LVAL_P(ztype); + if (cur_type == UNKNOWN_TYPE) { + /* Mimic guess_xml_convert() where we use the type of the data. + * UNDEFs are handled transparently as it will error out upon encoding the data. */ + cur_type = Z_TYPE_P(Z_VAR_ENC_VALUE_P(tmp)); + } zval *zstype = Z_VAR_ENC_STYPE_P(tmp); if (Z_TYPE_P(zstype) == IS_STRING) { diff --git a/ext/soap/soap.c b/ext/soap/soap.c index fc51e32658f3a..4a4fa4f4e626b 100644 --- a/ext/soap/soap.c +++ b/ext/soap/soap.c @@ -880,7 +880,13 @@ PHP_METHOD(SoapServer, __construct) service->soap_functions.ft = zend_new_array(0); if (wsdl) { - service->sdl = get_sdl(ZEND_THIS, ZSTR_VAL(wsdl), cache_wsdl); + zend_try { + service->sdl = get_sdl(ZEND_THIS, ZSTR_VAL(wsdl), cache_wsdl); + } zend_catch { + xmlCharEncCloseFunc(service->encoding); + service->encoding = NULL; + zend_bailout(); + } zend_end_try(); if (service->uri == NULL) { if (service->sdl->target_ns) { service->uri = estrdup(service->sdl->target_ns); diff --git a/ext/soap/tests/bugs/gh19784.phpt b/ext/soap/tests/bugs/gh19784.phpt new file mode 100644 index 0000000000000..1f718e74c4598 --- /dev/null +++ b/ext/soap/tests/bugs/gh19784.phpt @@ -0,0 +1,14 @@ +--TEST-- +GH-19784 (SoapServer memory leak) +--EXTENSIONS-- +soap +--FILE-- + $v_5257); +new SoapServer('foobarbaz',$v_5238,); +?> +--EXPECTF-- + +%s%a diff --git a/ext/soap/tests/bugs/gh20011.phpt b/ext/soap/tests/bugs/gh20011.phpt new file mode 100644 index 0000000000000..cf40d813e6178 --- /dev/null +++ b/ext/soap/tests/bugs/gh20011.phpt @@ -0,0 +1,20 @@ +--TEST-- +GH-20011 (Array of SoapVar of unknown type causes crash) +--EXTENSIONS-- +soap +--FILE-- + 'test://', 'uri' => 'http://soapinterop.org/']); +$client->echoStringArray($array); +?> +--EXPECT-- + +test string diff --git a/ext/standard/array.c b/ext/standard/array.c index f0a81b5ba8953..4896ac44a727d 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -3376,6 +3376,12 @@ static void php_splice(HashTable *in_hash, zend_long offset, zend_long length, H HT_SET_ITERATORS_COUNT(in_hash, 0); in_hash->pDestructor = NULL; + /* Set internal pointer to 0 directly instead of calling zend_hash_internal_pointer_reset(). + * This avoids the COW violation assertion and delays advancing to the first valid position + * until after we've switched to the new array structure (out_hash). The iterator will be + * advanced when actually accessed, at which point it will find valid indexes in the new array. */ + in_hash->nInternalPointer = 0; + if (UNEXPECTED(GC_DELREF(in_hash) == 0)) { /* Array was completely deallocated during the operation */ zend_array_destroy(in_hash); @@ -3394,8 +3400,6 @@ static void php_splice(HashTable *in_hash, zend_long offset, zend_long length, H in_hash->nNextFreeElement = out_hash.nNextFreeElement; in_hash->arData = out_hash.arData; in_hash->pDestructor = out_hash.pDestructor; - - zend_hash_internal_pointer_reset(in_hash); } /* }}} */ @@ -4900,6 +4904,11 @@ PHP_FUNCTION(array_unique) ZVAL_UNDEF(&arTmp[i].b.val); zend_sort((void *) arTmp, i, sizeof(struct bucketindex), (compare_func_t) cmp, (swap_func_t) array_bucketindex_swap); + + if (UNEXPECTED(EG(exception))) { + goto out; + } + /* go through the sorted array and delete duplicates from the copy */ lastkept = arTmp; for (cmpdata = arTmp + 1; Z_TYPE(cmpdata->b.val) != IS_UNDEF; cmpdata++) { @@ -4919,6 +4928,8 @@ PHP_FUNCTION(array_unique) } } } + +out: pefree(arTmp, GC_FLAGS(Z_ARRVAL_P(array)) & IS_ARRAY_PERSISTENT); if (in_place) { diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index d2a99fccc95fe..02b63beb59d03 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -2037,10 +2037,8 @@ PHP_FUNCTION(ini_set) #define _CHECK_PATH(var, var_len, ini) php_ini_check_path(var, var_len, ini, sizeof(ini)) /* open basedir check */ if (PG(open_basedir)) { - if (_CHECK_PATH(ZSTR_VAL(varname), ZSTR_LEN(varname), "error_log") || - _CHECK_PATH(ZSTR_VAL(varname), ZSTR_LEN(varname), "java.class.path") || + if (_CHECK_PATH(ZSTR_VAL(varname), ZSTR_LEN(varname), "java.class.path") || _CHECK_PATH(ZSTR_VAL(varname), ZSTR_LEN(varname), "java.home") || - _CHECK_PATH(ZSTR_VAL(varname), ZSTR_LEN(varname), "mail.log") || _CHECK_PATH(ZSTR_VAL(varname), ZSTR_LEN(varname), "java.library.path") || _CHECK_PATH(ZSTR_VAL(varname), ZSTR_LEN(varname), "vpopmail.directory")) { if (php_check_open_basedir(ZSTR_VAL(new_value_str))) { diff --git a/ext/standard/tests/array/gh19926.phpt b/ext/standard/tests/array/gh19926.phpt new file mode 100644 index 0000000000000..b714db9eb2b32 --- /dev/null +++ b/ext/standard/tests/array/gh19926.phpt @@ -0,0 +1,20 @@ +--TEST-- +GH-19926 (Assertion failure zend_hash_internal_pointer_reset_ex) +--FILE-- + +--EXPECT-- +Exception caught, no assertion failure diff --git a/ext/standard/tests/array/gh19926_pointer.phpt b/ext/standard/tests/array/gh19926_pointer.phpt new file mode 100644 index 0000000000000..c134f3b594b3d --- /dev/null +++ b/ext/standard/tests/array/gh19926_pointer.phpt @@ -0,0 +1,19 @@ +--TEST-- +GH-19926 (internal pointer behavior after array_splice) +--FILE-- + +--EXPECT-- +Before array_splice: int(3) +After array_splice: int(999) diff --git a/ext/standard/tests/array/gh20043.phpt b/ext/standard/tests/array/gh20043.phpt new file mode 100644 index 0000000000000..d5c7e06417f18 --- /dev/null +++ b/ext/standard/tests/array/gh20043.phpt @@ -0,0 +1,12 @@ +--TEST-- +GH-20043 (array_unique assertion failure with RC1 array causing an exception on sort) +--FILE-- +getMessage(); +} +?> +--EXPECT-- +Object of class stdClass could not be converted to string diff --git a/ext/standard/tests/file/bug46347.phpt b/ext/standard/tests/file/bug46347.phpt index 903a6e35cc2b2..e337ade9eb8fb 100644 --- a/ext/standard/tests/file/bug46347.phpt +++ b/ext/standard/tests/file/bug46347.phpt @@ -8,14 +8,14 @@ $str = <<< EOF part1.*.part2 = 1 EOF; -$file = __DIR__ . '/parse.ini'; +$file = __DIR__ . '/bug46347.ini'; file_put_contents($file, $str); var_dump(parse_ini_file($file)); ?> --CLEAN-- --EXPECT-- array(1) { diff --git a/ext/standard/tests/filters/convert.phpt b/ext/standard/tests/filters/convert.phpt new file mode 100644 index 0000000000000..a99579b5dd8fe --- /dev/null +++ b/ext/standard/tests/filters/convert.phpt @@ -0,0 +1,130 @@ +--TEST-- +convert stream filter tests +--FILE-- + 20, 'line-break-chars' => "\n"); +test_roundtrip("Long text that will be wrapped", "convert.base64-encode", "convert.base64-decode", $opts); + +$opts2 = array('binary' => true); +test_roundtrip("Text\t\r\n", "convert.quoted-printable-encode", "convert.quoted-printable-decode", $opts2); + +$fp = tmpfile(); +fwrite($fp, "Test"); +rewind($fp); +stream_filter_prepend($fp, 'convert.base64-encode', STREAM_FILTER_READ); +$result = stream_get_contents($fp); +fclose($fp); +var_dump($result === base64_encode("Test")); + +?> +--EXPECTF-- +Filter: convert.base64-encode +Original: Hello World! +Encoded: SGVsbG8gV29ybGQh +Decoded: Hello World! +bool(true) + +Filter: convert.base64-encode +Original (hex): 414243ff +Encoded: QUJD/w== +Decoded (hex): 414243ff +bool(true) + +Filter: convert.base64-encode +Original: +Encoded: +Decoded: +bool(true) + +Filter: convert.base64-encode +Original: A +Encoded: QQ== +Decoded: A +bool(true) + +Filter: convert.quoted-printable-encode +Original: Hello World! +Encoded: Hello World! +Decoded: Hello World! +bool(true) + +Filter: convert.quoted-printable-encode +Original: Line1 +Line2 +Encoded: Line1=0D=0ALine2 +Decoded: Line1 +Line2 +bool(true) + +Filter: convert.base64-encode +Original: Long text that will be wrapped +Encoded: TG9uZyB0ZXh0IHRoYXQg +d2lsbCBiZSB3cmFwcGVk +Decoded: Long text that will be wrapped +bool(true) + +Filter: convert.quoted-printable-encode +Original: Text + +Encoded: Text=09=0D=0A +Decoded: Text + +bool(true) + +bool(true) diff --git a/ext/standard/tests/filters/gh17345.phpt b/ext/standard/tests/filters/gh17345.phpt new file mode 100644 index 0000000000000..f64659390a14f --- /dev/null +++ b/ext/standard/tests/filters/gh17345.phpt @@ -0,0 +1,49 @@ +--TEST-- +GH-17345 (Bug #35916 was not completely fixed) +--FILE-- +data = strtoupper($bucket->data); + $consumed += $bucket->datalen; + stream_bucket_prepend($out, $bucket); + // Interleave new bucket + stream_bucket_prepend($out, clone $bucket); + stream_bucket_prepend($out, $bucket); + } + return PSFS_PASS_ON; + } + + function onCreate(): bool + { + echo "fffffffffff\n"; + return true; + } + + function onClose(): void + { + echo "hello\n"; + } +} + +stream_filter_register("strtoupper", "strtoupper_filter"); +$fp=fopen($file, "w"); +stream_filter_append($fp, "strtoupper"); +fread($fp, 1024); +fwrite($fp, "Thank you\n"); +fclose($fp); +readfile($file); +unlink($file); +?> +--EXPECTF-- +fffffffffff + +Notice: fread(): Read of 8192 bytes failed with errno=9 Bad file descriptor in %s on line %d +hello +THANK YOU diff --git a/ext/standard/tests/general_functions/debug_zval_dump_gh19801_memory_leak.phpt b/ext/standard/tests/general_functions/debug_zval_dump_gh19801_memory_leak.phpt new file mode 100644 index 0000000000000..8d65cd6d18587 --- /dev/null +++ b/ext/standard/tests/general_functions/debug_zval_dump_gh19801_memory_leak.phpt @@ -0,0 +1,32 @@ +--TEST-- +GH-19801 (debug_zval_dump() leak with __debugInfo() that modifies circular references) +--FILE-- +a = null; + gc_collect_cycles(); + return []; + } + }, +]; + +$b = new stdClass; +$b->a = &$a; + +debug_zval_dump($b); +?> +--EXPECTF-- +object(stdClass)#2 (1) refcount(%d){ + ["a"]=> + reference refcount(%d) { + array(1) refcount(%d){ + [0]=> + object(class@anonymous)#1 (0) refcount(%d){ + } + } + } +} diff --git a/ext/standard/tests/general_functions/var_dump_gh19801_memory_leak.phpt b/ext/standard/tests/general_functions/var_dump_gh19801_memory_leak.phpt new file mode 100644 index 0000000000000..f0522916de4e6 --- /dev/null +++ b/ext/standard/tests/general_functions/var_dump_gh19801_memory_leak.phpt @@ -0,0 +1,30 @@ +--TEST-- +GH-19801 (var_dump() memory leak with __debugInfo() that modifies circular references) +--FILE-- +a = null; + gc_collect_cycles(); + return []; + } + }, +]; + +$b = new stdClass; +$b->a = &$a; + +var_dump($b); +?> +--EXPECTF-- +object(stdClass)#2 (1) { + ["a"]=> + &array(1) { + [0]=> + object(class@anonymous)#1 (0) { + } + } +} diff --git a/ext/standard/tests/serialize/gh12265.phpt b/ext/standard/tests/serialize/gh12265.phpt new file mode 100644 index 0000000000000..5f49a62fee29f --- /dev/null +++ b/ext/standard/tests/serialize/gh12265.phpt @@ -0,0 +1,47 @@ +--TEST-- +GH-12265 (Cloning an object breaks serialization recursion) - __serialize variation +--FILE-- + new A($this)]; + } +} + +class C { + public B $b; + + public function __construct() { + $this->b = new B; + } +} + +$b = new B(); +$sb = serialize($b); +$stb = serialize(new B); + +printf("serialized original: %s\n", $sb); +printf("serialized temp : %s\n", $stb); + +$c = new C; +$sc = serialize($c); +$stc = serialize(new C); + +printf("serialized original: %s\n", $sc); +printf("serialized temp : %s\n", $stc); + +?> +--EXPECT-- +serialized original: O:1:"B":1:{s:1:"a";O:1:"A":1:{s:1:"x";r:1;}} +serialized temp : O:1:"B":1:{s:1:"a";O:1:"A":1:{s:1:"x";r:1;}} +serialized original: O:1:"C":1:{s:1:"b";O:1:"B":1:{s:1:"a";O:1:"A":1:{s:1:"x";r:2;}}} +serialized temp : O:1:"C":1:{s:1:"b";O:1:"B":1:{s:1:"a";O:1:"A":1:{s:1:"x";r:2;}}} diff --git a/ext/standard/tests/serialize/gh12265b.phpt b/ext/standard/tests/serialize/gh12265b.phpt new file mode 100644 index 0000000000000..2b9d80a848cee --- /dev/null +++ b/ext/standard/tests/serialize/gh12265b.phpt @@ -0,0 +1,48 @@ +--TEST-- +GH-12265 (Cloning an object breaks serialization recursion) - __sleep variation +--FILE-- +a = new A($this); + return ['a']; + } +} + +class C { + public B $b; + + public function __construct() { + $this->b = new B; + } +} + +$b = new B(); +$sb = serialize($b); +$stb = serialize(new B); + +printf("serialized original: %s\n", $sb); +printf("serialized temp : %s\n", $stb); + +$c = new C; +$sc = serialize($c); +$stc = serialize(new C); + +printf("serialized original: %s\n", $sc); +printf("serialized temp : %s\n", $stc); + +?> +--EXPECT-- +serialized original: O:1:"B":1:{s:1:"a";O:1:"A":1:{s:1:"x";r:1;}} +serialized temp : O:1:"B":1:{s:1:"a";O:1:"A":1:{s:1:"x";r:1;}} +serialized original: O:1:"C":1:{s:1:"b";O:1:"B":1:{s:1:"a";O:1:"A":1:{s:1:"x";r:2;}}} +serialized temp : O:1:"C":1:{s:1:"b";O:1:"B":1:{s:1:"a";O:1:"A":1:{s:1:"x";r:2;}}} diff --git a/ext/standard/tests/serialize/gh19701.phpt b/ext/standard/tests/serialize/gh19701.phpt new file mode 100644 index 0000000000000..a1a3fd5c64bcc --- /dev/null +++ b/ext/standard/tests/serialize/gh19701.phpt @@ -0,0 +1,30 @@ +--TEST-- +GH-19701 (Serialize/deserialize loses some data) +--CREDITS-- +cuchac +DanielEScherzer +--FILE-- +parent = $baseProduct; +$baseProduct->children = [ $child ]; + +$data = [clone $baseProduct, $baseProduct]; + +echo serialize($data), "\n"; + +?> +--EXPECT-- +a:2:{i:0;O:4:"Item":2:{s:8:"children";a:1:{i:0;O:4:"Item":2:{s:8:"children";a:0:{}s:6:"parent";O:4:"Item":2:{s:8:"children";a:1:{i:0;r:4;}s:6:"parent";N;}}}s:6:"parent";N;}i:1;r:6;} diff --git a/ext/standard/tests/streams/gh19570.phpt b/ext/standard/tests/streams/gh19570.phpt new file mode 100644 index 0000000000000..e3d486ea83cf9 --- /dev/null +++ b/ext/standard/tests/streams/gh19570.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-19570 (unable to fseek in /dev/zero and /dev/null) +--SKIPIF-- + +--FILE-- + +--EXPECT-- +int(0) +int(0) +int(0) diff --git a/ext/standard/tests/streams/gh19705.phpt b/ext/standard/tests/streams/gh19705.phpt new file mode 100644 index 0000000000000..d34cfc700596d --- /dev/null +++ b/ext/standard/tests/streams/gh19705.phpt @@ -0,0 +1,11 @@ +--TEST-- +GH-19705 segmentation fault with non writable stream at stream_filter_append call. +--EXTENSIONS-- +zlib +--FILE-- + +--EXPECTF-- +resource(%d) of type (stream filter) diff --git a/ext/standard/user_filters.c b/ext/standard/user_filters.c index acef5146fa25e..962eaaba7d6b0 100644 --- a/ext/standard/user_filters.c +++ b/ext/standard/user_filters.c @@ -404,17 +404,19 @@ static void php_stream_bucket_attach(int append, INTERNAL_FUNCTION_PARAMETERS) memcpy(bucket->buf, Z_STRVAL_P(pzdata), bucket->buflen); } + /* If the bucket is already on a brigade we have to unlink it first to keep the + * linked list consistent. Furthermore, we can transfer the refcount in that case. */ + if (bucket->brigade) { + php_stream_bucket_unlink(bucket); + } else { + bucket->refcount++; + } + if (append) { php_stream_bucket_append(brigade, bucket); } else { php_stream_bucket_prepend(brigade, bucket); } - /* This is a hack necessary to accommodate situations where bucket is appended to the stream - * multiple times. See bug35916.phpt for reference. - */ - if (bucket->refcount == 1) { - bucket->refcount++; - } } /* }}} */ diff --git a/ext/standard/var.c b/ext/standard/var.c index 3d53ebf5137a4..795fb366c6013 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -139,7 +139,7 @@ PHPAPI void php_var_dump(zval *struc, int level) /* {{{ */ } ZEND_HASH_FOREACH_END(); if (!(GC_FLAGS(myht) & GC_IMMUTABLE)) { GC_UNPROTECT_RECURSION(myht); - GC_DELREF(myht); + GC_DTOR_NO_REF(myht); } if (level > 1) { php_printf("%*c", level-1, ' '); @@ -336,7 +336,7 @@ PHPAPI void php_debug_zval_dump(zval *struc, int level) /* {{{ */ } ZEND_HASH_FOREACH_END(); if (!(GC_FLAGS(myht) & GC_IMMUTABLE)) { GC_UNPROTECT_RECURSION(myht); - GC_DELREF(myht); + GC_DTOR_NO_REF(myht); } if (level > 1) { php_printf("%*c", level - 1, ' '); @@ -681,7 +681,10 @@ static inline zend_long php_add_var_hash(php_serialize_data_t data, zval *var, b return 0; } else if (!in_rcn_array && Z_REFCOUNT_P(var) == 1 - && (Z_OBJ_P(var)->properties == NULL || GC_REFCOUNT(Z_OBJ_P(var)->properties) == 1)) { + && (Z_OBJ_P(var)->properties == NULL || GC_REFCOUNT(Z_OBJ_P(var)->properties) == 1) + /* __serialize and __sleep may arbitrarily increase the refcount */ + && Z_OBJCE_P(var)->__serialize == NULL + && zend_hash_find_known_hash(&Z_OBJCE_P(var)->function_table, ZSTR_KNOWN(ZEND_STR_SLEEP)) == NULL) { return 0; } @@ -951,18 +954,11 @@ static void php_var_serialize_nested_data(smart_str *buf, zval *struc, HashTable /* we should still add element even if it's not OK, * since we already wrote the length of the array before */ if (Z_TYPE_P(data) == IS_ARRAY) { - if (UNEXPECTED(Z_IS_RECURSIVE_P(data)) - || UNEXPECTED(Z_TYPE_P(struc) == IS_ARRAY && Z_ARR_P(data) == Z_ARR_P(struc))) { + if (UNEXPECTED(Z_TYPE_P(struc) == IS_ARRAY && Z_ARR_P(data) == Z_ARR_P(struc))) { php_add_var_hash(var_hash, struc, in_rcn_array); smart_str_appendl(buf, "N;", 2); } else { - if (Z_REFCOUNTED_P(data)) { - Z_PROTECT_RECURSION_P(data); - } php_var_serialize_intern(buf, data, var_hash, in_rcn_array, false); - if (Z_REFCOUNTED_P(data)) { - Z_UNPROTECT_RECURSION_P(data); - } } } else { php_var_serialize_intern(buf, data, var_hash, in_rcn_array, false); diff --git a/ext/xmlreader/php_xmlreader.c b/ext/xmlreader/php_xmlreader.c index dca1898f1c044..7a50b660fb59d 100644 --- a/ext/xmlreader/php_xmlreader.c +++ b/ext/xmlreader/php_xmlreader.c @@ -508,6 +508,7 @@ static void php_xmlreader_set_relaxng_schema(INTERNAL_FUNCTION_PARAMETERS, int t RETURN_TRUE; } else { + xmlRelaxNGFree(schema); php_error_docref(NULL, E_WARNING, "Schema contains errors"); RETURN_FALSE; } diff --git a/ext/xsl/tests/gh19988.phpt b/ext/xsl/tests/gh19988.phpt new file mode 100644 index 0000000000000..174af282f9c09 --- /dev/null +++ b/ext/xsl/tests/gh19988.phpt @@ -0,0 +1,19 @@ +--TEST-- +GH-19988 (zend_string_init with NULL pointer in simplexml (UB)) +--EXTENSIONS-- +simplexml +xsl +--CREDITS-- +YuanchengJiang +--FILE-- +load(__DIR__ . '/53965/collection.xsl'); +$processor->importStylesheet($dom); +$result = $processor->transformToDoc($sxe, SimpleXMLElement::class); +var_dump($result->getName()); +?> +--EXPECT-- +string(0) "" diff --git a/ext/zend_test/observer.c b/ext/zend_test/observer.c index 9d0fb27c8a559..bff1d6ff93424 100644 --- a/ext/zend_test/observer.c +++ b/ext/zend_test/observer.c @@ -155,7 +155,7 @@ static void observer_show_init(zend_function *fbc) php_printf("%*s\n", 2 * ZT_G(observer_nesting_depth), "", ZSTR_VAL(fbc->common.function_name)); } } else { - php_printf("%*s\n", 2 * ZT_G(observer_nesting_depth), "", ZSTR_VAL(fbc->op_array.filename)); + php_printf("%*s\n", 2 * ZT_G(observer_nesting_depth), "", fbc->op_array.filename ? ZSTR_VAL(fbc->op_array.filename) : "[no active file]"); } } @@ -178,7 +178,7 @@ static void observer_show_init_backtrace(zend_execute_data *execute_data) php_printf("%*s%s()\n", indent, "", ZSTR_VAL(fbc->common.function_name)); } } else { - php_printf("%*s{main} %s\n", indent, "", ZSTR_VAL(fbc->op_array.filename)); + php_printf("%*s{main} %s\n", indent, "", fbc->op_array.filename ? ZSTR_VAL(fbc->op_array.filename) : "[no active file]"); } } while ((ex = ex->prev_execute_data) != NULL); php_printf("%*s-->\n", 2 * ZT_G(observer_nesting_depth), ""); diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index e7bb97cb44abb..67150d47b0441 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -1528,3 +1528,12 @@ static PHP_FUNCTION(zend_test_gh18756) zend_mm_gc(heap); zend_mm_shutdown(heap, true, false); } + +static PHP_FUNCTION(zend_test_gh19792) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + RETVAL_STRING("this is a non-interned string"); + zend_error(E_WARNING, "a warning"); + zend_throw_error(NULL, "an exception"); +} diff --git a/ext/zend_test/test.stub.php b/ext/zend_test/test.stub.php index f9cb93b5a1ccb..290f55976d169 100644 --- a/ext/zend_test/test.stub.php +++ b/ext/zend_test/test.stub.php @@ -264,6 +264,9 @@ function zend_test_is_zend_ptr(int $addr): bool {} function zend_test_log_err_debug(string $str): void {} function zend_test_gh18756(): void {} + + /** @compile-time-eval */ + function zend_test_gh19792(): void {} } namespace ZendTestNS { diff --git a/ext/zend_test/test_arginfo.h b/ext/zend_test/test_arginfo.h index c7e3df5c58d24..cccd4608d9829 100644 --- a/ext/zend_test/test_arginfo.h +++ b/ext/zend_test/test_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 2f161861ab09b6b5b594dc2db7c2c9df49d76aa7 */ + * Stub hash: fa769dbbf7ba1d10f0141fed6a45fc06a84cd94c */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -164,6 +164,8 @@ ZEND_END_ARG_INFO() #define arginfo_zend_test_gh18756 arginfo_zend_test_void_return +#define arginfo_zend_test_gh19792 arginfo_zend_test_void_return + #define arginfo_ZendTestNS2_namespaced_func arginfo_zend_test_is_pcre_bundled #define arginfo_ZendTestNS2_namespaced_deprecated_func arginfo_zend_test_void_return @@ -295,6 +297,7 @@ static ZEND_FUNCTION(zend_test_cast_fread); static ZEND_FUNCTION(zend_test_is_zend_ptr); static ZEND_FUNCTION(zend_test_log_err_debug); static ZEND_FUNCTION(zend_test_gh18756); +static ZEND_FUNCTION(zend_test_gh19792); static ZEND_FUNCTION(ZendTestNS2_namespaced_func); static ZEND_FUNCTION(ZendTestNS2_namespaced_deprecated_func); static ZEND_FUNCTION(ZendTestNS2_ZendSubNS_namespaced_func); @@ -376,6 +379,7 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(zend_test_is_zend_ptr, arginfo_zend_test_is_zend_ptr) ZEND_FE(zend_test_log_err_debug, arginfo_zend_test_log_err_debug) ZEND_FE(zend_test_gh18756, arginfo_zend_test_gh18756) + ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(zend_test_gh19792, arginfo_zend_test_gh19792) ZEND_NS_FALIAS("ZendTestNS2", namespaced_func, ZendTestNS2_namespaced_func, arginfo_ZendTestNS2_namespaced_func) ZEND_NS_DEP_FALIAS("ZendTestNS2", namespaced_deprecated_func, ZendTestNS2_namespaced_deprecated_func, arginfo_ZendTestNS2_namespaced_deprecated_func) ZEND_NS_FALIAS("ZendTestNS2", namespaced_aliased_func, zend_test_void_return, arginfo_ZendTestNS2_namespaced_aliased_func) diff --git a/ext/zend_test/tests/observer_fiber_backtrace_crash.phpt b/ext/zend_test/tests/observer_fiber_backtrace_crash.phpt new file mode 100644 index 0000000000000..f19005179ac26 --- /dev/null +++ b/ext/zend_test/tests/observer_fiber_backtrace_crash.phpt @@ -0,0 +1,48 @@ +--TEST-- +GH-16319 (Fiber backtrace with null filename should not crash) +--EXTENSIONS-- +zend_test +--INI-- +zend_test.observer.enabled=1 +zend_test.observer.show_init_backtrace=1 +zend_test.observer.show_output=1 +zend_test.observer.observe_all=1 +zend_test.observer.show_opcode=0 +opcache.jit=0 +--FILE-- +start(); +echo "Test completed without crash\n"; +?> +--EXPECTF-- + + + + + + + + + + + + + <{closure}> + + +Test completed without crash + diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index 9f1d296336e09..552d3a7571de5 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -1784,7 +1784,7 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* basename = php_basename(Z_STRVAL_P(zval_file), Z_STRLEN_P(zval_file), NULL, 0); file_stripped = ZSTR_VAL(basename); file_stripped_len = ZSTR_LEN(basename); - } else if (opts.remove_path && !memcmp(Z_STRVAL_P(zval_file), opts.remove_path, opts.remove_path_len)) { + } else if (opts.remove_path && Z_STRLEN_P(zval_file) > opts.remove_path_len && !memcmp(Z_STRVAL_P(zval_file), opts.remove_path, opts.remove_path_len)) { if (IS_SLASH(Z_STRVAL_P(zval_file)[opts.remove_path_len])) { file_stripped = Z_STRVAL_P(zval_file) + opts.remove_path_len + 1; file_stripped_len = Z_STRLEN_P(zval_file) - opts.remove_path_len - 1; @@ -2380,6 +2380,11 @@ PHP_METHOD(ZipArchive, setEncryptionName) RETURN_FALSE; } + if (UNEXPECTED(zip_file_set_encryption(intern, idx, ZIP_EM_NONE, NULL) < 0)) { + php_error_docref(NULL, E_WARNING, "password reset failed"); + RETURN_FALSE; + } + if (zip_file_set_encryption(intern, idx, (zip_uint16_t)method, password)) { RETURN_FALSE; } @@ -2403,6 +2408,11 @@ PHP_METHOD(ZipArchive, setEncryptionIndex) ZIP_FROM_OBJECT(intern, self); + if (UNEXPECTED(zip_file_set_encryption(intern, index, ZIP_EM_NONE, NULL) < 0)) { + php_error_docref(NULL, E_WARNING, "password reset failed"); + RETURN_FALSE; + } + if (zip_file_set_encryption(intern, index, (zip_uint16_t)method, password)) { RETURN_FALSE; } diff --git a/ext/zip/tests/gh19688.phpt b/ext/zip/tests/gh19688.phpt new file mode 100644 index 0000000000000..7e2a2800b2553 --- /dev/null +++ b/ext/zip/tests/gh19688.phpt @@ -0,0 +1,21 @@ +--TEST-- +GH-19688 (Remove pattern overflow in zip addGlob()) +--EXTENSIONS-- +zip +--FILE-- +open($filename, ZipArchive::CREATE | ZipArchive::OVERWRITE); +$options = array('remove_path' => $dir . 'a very long string here that will overrun'); +$zip->addGlob($testfile, 0, $options); +var_dump($zip->getNameIndex(0)); +?> +--CLEAN-- + +--EXPECTF-- +string(%d) "%s001.phpt" diff --git a/ext/zip/tests/gh19932.phpt b/ext/zip/tests/gh19932.phpt new file mode 100644 index 0000000000000..760fa1c9e766d --- /dev/null +++ b/ext/zip/tests/gh19932.phpt @@ -0,0 +1,25 @@ +--TEST-- +GH-19932 (ZipArchive::setEncryptionName()/setEncryptionIndex() memory leak) +--EXTENSIONS-- +zip +--SKIPIF-- + +--FILE-- +open(__DIR__ . "/gh19932.zip", ZipArchive::CREATE); +$zip->addFromString("test.txt", "test"); +$zip->setEncryptionName("test.txt", ZipArchive::EM_AES_256, "password"); +$zip->setEncryptionName("test.txt", ZipArchive::EM_AES_256, "password"); +$zip->setEncryptionIndex("0", ZipArchive::EM_AES_256, "password"); +$zip->setEncryptionIndex("0", ZipArchive::EM_AES_256, "password"); +$zip->close(); +echo "OK"; +?> +--CLEAN-- + +--EXPECT-- +OK + diff --git a/ext/zlib/tests/gh19922.phpt b/ext/zlib/tests/gh19922.phpt new file mode 100644 index 0000000000000..71644512e6656 --- /dev/null +++ b/ext/zlib/tests/gh19922.phpt @@ -0,0 +1,12 @@ +--TEST-- +GH-19922 (gzopen double free on debug build and unseekable stream) +--EXTENSIONS-- +zlib +--FILE-- + +--EXPECTF-- + +Warning: gzopen(php://output): could not make seekable - php://output in %s on line %d +bool(false) diff --git a/main/main.c b/main/main.c index 60e970b76ad76..e7797a4f89e4a 100644 --- a/main/main.c +++ b/main/main.c @@ -625,12 +625,13 @@ static PHP_INI_MH(OnUpdateErrorLog) { /* Only do the safemode/open_basedir check at runtime */ if ((stage == PHP_INI_STAGE_RUNTIME || stage == PHP_INI_STAGE_HTACCESS) && - new_value && zend_string_equals_literal(new_value, "syslog")) { + new_value && !zend_string_equals_literal(new_value, "syslog") && ZSTR_LEN(new_value) > 0) { if (PG(open_basedir) && php_check_open_basedir(ZSTR_VAL(new_value))) { return FAILURE; } } - OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); + char **p = (char **) ZEND_INI_GET_ADDR(); + *p = new_value && ZSTR_LEN(new_value) > 0 ? ZSTR_VAL(new_value) : NULL; return SUCCESS; } /* }}} */ @@ -638,13 +639,14 @@ static PHP_INI_MH(OnUpdateErrorLog) /* {{{ PHP_INI_MH */ static PHP_INI_MH(OnUpdateMailLog) { - /* Only do the safemode/open_basedir check at runtime */ - if ((stage == PHP_INI_STAGE_RUNTIME || stage == PHP_INI_STAGE_HTACCESS) && new_value) { + /* Only do the open_basedir check at runtime */ + if ((stage == PHP_INI_STAGE_RUNTIME || stage == PHP_INI_STAGE_HTACCESS) && new_value && ZSTR_LEN(new_value) > 0) { if (PG(open_basedir) && php_check_open_basedir(ZSTR_VAL(new_value))) { return FAILURE; } } - OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); + char **p = (char **) ZEND_INI_GET_ADDR(); + *p = new_value && ZSTR_LEN(new_value) > 0 ? ZSTR_VAL(new_value) : NULL; return SUCCESS; } /* }}} */ diff --git a/main/network.c b/main/network.c index 8de81a6271a2f..fecec0545e8f0 100644 --- a/main/network.c +++ b/main/network.c @@ -1052,6 +1052,28 @@ PHPAPI int php_sockaddr_size(php_sockaddr_storage *addr) } /* }}} */ +#ifdef PHP_WIN32 +char *php_socket_strerror_s(long err, char *buf, size_t bufsize) +{ + if (buf == NULL) { + char ebuf[1024]; + errno_t res = strerror_s(ebuf, sizeof(ebuf), err); + if (res == 0) { + buf = estrdup(ebuf); + } else { + buf = estrdup("Unknown error"); + } + } else { + errno_t res = strerror_s(buf, bufsize, err); + if (res != 0) { + strncpy(buf, "Unknown error", bufsize); + buf[bufsize?(bufsize-1):0] = 0; + } + } + return buf; +} +#endif + /* Given a socket error code, if buf == NULL: * emallocs storage for the error message and returns * else @@ -1061,16 +1083,40 @@ PHPAPI int php_sockaddr_size(php_sockaddr_storage *addr) PHPAPI char *php_socket_strerror(long err, char *buf, size_t bufsize) { #ifndef PHP_WIN32 - char *errstr; - - errstr = strerror(err); +# ifdef HAVE_STRERROR_R + if (buf == NULL) { + char ebuf[1024]; +# ifdef STRERROR_R_CHAR_P + char *errstr = strerror_r(err, ebuf, sizeof(ebuf)); + buf = estrdup(errstr); +# else + int res = (int) strerror_r(err, ebuf, sizeof(ebuf)); + if (res == 0) { + buf = estrdup(ebuf); + } else { + buf = estrdup("Unknown error"); + } +# endif + } else { +# ifdef STRERROR_R_CHAR_P + buf = strerror_r(err, buf, bufsize); +# else + int res = (int) strerror_r(err, buf, bufsize); + if (res != 0) { + strncpy(buf, "Unknown error", bufsize); + buf[bufsize?(bufsize-1):0] = 0; + } +# endif + } +# else + char *errstr = strerror(err); if (buf == NULL) { buf = estrdup(errstr); } else { strncpy(buf, errstr, bufsize); buf[bufsize?(bufsize-1):0] = 0; } - return buf; +# endif #else char *sysbuf = php_win32_error_to_msg(err); if (!sysbuf[0]) { @@ -1085,9 +1131,8 @@ PHPAPI char *php_socket_strerror(long err, char *buf, size_t bufsize) } php_win32_error_msg_free(sysbuf); - - return buf; #endif + return buf; } /* }}} */ @@ -1095,9 +1140,22 @@ PHPAPI char *php_socket_strerror(long err, char *buf, size_t bufsize) PHPAPI zend_string *php_socket_error_str(long err) { #ifndef PHP_WIN32 - char *errstr; - - errstr = strerror(err); +# ifdef HAVE_STRERROR_R + char ebuf[1024]; +# ifdef STRERROR_R_CHAR_P + char *errstr = strerror_r(err, ebuf, sizeof(ebuf)); +# else + const char *errstr; + int res = (int) strerror_r(err, ebuf, sizeof(ebuf)); + if (res == 0) { + errstr = ebuf; + } else { + errstr = "Unknown error"; + } +# endif +# else + char *errstr = strerror(err); +# endif return zend_string_init(errstr, strlen(errstr), 0); #else zend_string *ret; diff --git a/main/php_network.h b/main/php_network.h index 6fc210b56837b..6b6e486fe48fc 100644 --- a/main/php_network.h +++ b/main/php_network.h @@ -66,6 +66,11 @@ * unless buf is not NULL. * Also works sensibly for win32 */ BEGIN_EXTERN_C() +#ifdef PHP_WIN32 +char *php_socket_strerror_s(long err, char *buf, size_t bufsize); +#else +#define php_socket_strerror_s php_socket_strerror +#endif PHPAPI char *php_socket_strerror(long err, char *buf, size_t bufsize); PHPAPI zend_string *php_socket_error_str(long err); END_EXTERN_C() diff --git a/main/php_version.h b/main/php_version.h index 866ca3a80a072..640e83444d3c3 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 3 -#define PHP_RELEASE_VERSION 26 -#define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "8.3.26-dev" -#define PHP_VERSION_ID 80326 +#define PHP_RELEASE_VERSION 27 +#define PHP_EXTRA_VERSION "RC1" +#define PHP_VERSION "8.3.27RC1" +#define PHP_VERSION_ID 80327 diff --git a/main/rfc1867.c b/main/rfc1867.c index cbdf8aaa07c5d..43c4185677a45 100644 --- a/main/rfc1867.c +++ b/main/rfc1867.c @@ -1038,7 +1038,8 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */ if (wlen == (size_t)-1) { /* write failed */ #if DEBUG_FILE_UPLOAD - sapi_module.sapi_error(E_NOTICE, "write() failed - %s", strerror(errno)); + char errstr[256]; + sapi_module.sapi_error(E_NOTICE, "write() failed - %s", php_socket_strerror_s(errno, errstr, sizeof(errstr))); #endif cancel_upload = PHP_UPLOAD_ERROR_F; } else if (wlen < blen) { diff --git a/main/streams/filter.c b/main/streams/filter.c index a1d63c15f0a52..1ce03d41513cd 100644 --- a/main/streams/filter.c +++ b/main/streams/filter.c @@ -173,6 +173,7 @@ PHPAPI void php_stream_bucket_prepend(php_stream_bucket_brigade *brigade, php_st PHPAPI void php_stream_bucket_append(php_stream_bucket_brigade *brigade, php_stream_bucket *bucket) { + /* TODO: this was added as a bad workaround for bug #35916 and should be removed in the future. */ if (brigade->tail == bucket) { return; } diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c index 1d5b7cfdac40d..09528e926f72c 100644 --- a/main/streams/plain_wrapper.c +++ b/main/streams/plain_wrapper.c @@ -43,6 +43,10 @@ # include #endif +#ifdef __linux__ +# include +#endif + #define php_stream_fopen_from_fd_int(fd, mode, persistent_id) _php_stream_fopen_from_fd_int((fd), (mode), (persistent_id) STREAMS_CC) #define php_stream_fopen_from_fd_int_rel(fd, mode, persistent_id) _php_stream_fopen_from_fd_int((fd), (mode), (persistent_id) STREAMS_REL_CC) #define php_stream_fopen_from_file_int(file, mode) _php_stream_fopen_from_file_int((file), (mode) STREAMS_CC) @@ -255,7 +259,28 @@ PHPAPI php_stream *_php_stream_fopen_tmpfile(int dummy STREAMS_DC) static void detect_is_seekable(php_stdio_stream_data *self) { #if defined(S_ISFIFO) && defined(S_ISCHR) if (self->fd >= 0 && do_fstat(self, 0) == 0) { +#ifdef __linux__ + if (S_ISCHR(self->sb.st_mode)) { + /* Some character devices are exceptions, check their major/minor ID + * https://www.kernel.org/doc/Documentation/admin-guide/devices.txt */ + if (major(self->sb.st_rdev) == 1) { + unsigned m = minor(self->sb.st_rdev); + self->is_seekable = + m == 1 || /* /dev/mem */ + m == 2 || /* /dev/kmem */ + m == 3 || /* /dev/null */ + m == 4 || /* /dev/port (seekable, offset = I/O port) */ + m == 5 || /* /dev/zero */ + m == 7; /* /dev/full */ + } else { + self->is_seekable = false; + } + } else { + self->is_seekable = !S_ISFIFO(self->sb.st_mode); + } +#else self->is_seekable = !(S_ISFIFO(self->sb.st_mode) || S_ISCHR(self->sb.st_mode)); +#endif self->is_pipe = S_ISFIFO(self->sb.st_mode); } #elif defined(PHP_WIN32) @@ -368,7 +393,9 @@ static ssize_t php_stdiop_write(php_stream *stream, const char *buf, size_t coun return bytes_written; } if (!(stream->flags & PHP_STREAM_FLAG_SUPPRESS_ERRORS)) { - php_error_docref(NULL, E_NOTICE, "Write of %zu bytes failed with errno=%d %s", count, errno, strerror(errno)); + char errstr[256]; + php_error_docref(NULL, E_NOTICE, "Write of %zu bytes failed with errno=%d %s", + count, errno, php_socket_strerror_s(errno, errstr, sizeof(errstr))); } } } else { @@ -444,7 +471,9 @@ static ssize_t php_stdiop_read(php_stream *stream, char *buf, size_t count) /* TODO: Should this be treated as a proper error or not? */ } else { if (!(stream->flags & PHP_STREAM_FLAG_SUPPRESS_ERRORS)) { - php_error_docref(NULL, E_NOTICE, "Read of %zu bytes failed with errno=%d %s", count, errno, strerror(errno)); + char errstr[256]; + php_error_docref(NULL, E_NOTICE, "Read of %zu bytes failed with errno=%d %s", + count, errno, php_socket_strerror_s(errno, errstr, sizeof(errstr))); } /* TODO: Remove this special-case? */ @@ -1278,7 +1307,9 @@ static int php_plain_files_unlink(php_stream_wrapper *wrapper, const char *url, ret = VCWD_UNLINK(url); if (ret == -1) { if (options & REPORT_ERRORS) { - php_error_docref1(NULL, url, E_WARNING, "%s", strerror(errno)); + char errstr[256]; + php_error_docref1(NULL, url, E_WARNING, "%s", + php_socket_strerror_s(errno, errstr, sizeof(errstr))); } return 0; } @@ -1324,6 +1355,7 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_f if (ret == -1) { #ifndef PHP_WIN32 + char errstr[256]; # ifdef EXDEV if (errno == EXDEV) { zend_stat_t sb; @@ -1344,7 +1376,8 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_f * access to the file in the meantime. */ if (VCWD_CHOWN(url_to, sb.st_uid, sb.st_gid)) { - php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno)); + php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", + php_socket_strerror_s(errno, errstr, sizeof(errstr))); if (errno != EPERM) { success = 0; } @@ -1352,7 +1385,8 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_f if (success) { if (VCWD_CHMOD(url_to, sb.st_mode)) { - php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno)); + php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", + php_socket_strerror_s(errno, errstr, sizeof(errstr))); if (errno != EPERM) { success = 0; } @@ -1363,10 +1397,12 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_f VCWD_UNLINK(url_from); } } else { - php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno)); + php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", + php_socket_strerror_s(errno, errstr, sizeof(errstr))); } } else { - php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno)); + php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", + php_socket_strerror_s(errno, errstr, sizeof(errstr))); } # if !defined(ZTS) && !defined(TSRM_WIN32) umask(oldmask); @@ -1379,7 +1415,8 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_f #ifdef PHP_WIN32 php_win32_docref2_from_error(GetLastError(), url_from, url_to); #else - php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno)); + php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", + php_socket_strerror_s(errno, errstr, sizeof(errstr))); #endif return 0; } @@ -1449,11 +1486,12 @@ static int php_plain_files_mkdir(php_stream_wrapper *wrapper, const char *dir, i if (!p) { p = buf; } + char errstr[256]; while (true) { int ret = VCWD_MKDIR(buf, (mode_t) mode); if (ret < 0 && errno != EEXIST) { if (options & REPORT_ERRORS) { - php_error_docref(NULL, E_WARNING, "%s", strerror(errno)); + php_error_docref(NULL, E_WARNING, "%s", php_socket_strerror_s(errno, errstr, sizeof(errstr))); } return 0; } @@ -1473,7 +1511,7 @@ static int php_plain_files_mkdir(php_stream_wrapper *wrapper, const char *dir, i /* issue a warning to client when the last directory was created failed */ if (ret < 0) { if (options & REPORT_ERRORS) { - php_error_docref(NULL, E_WARNING, "%s", strerror(errno)); + php_error_docref(NULL, E_WARNING, "%s", php_socket_strerror_s(errno, errstr, sizeof(errstr))); } return 0; } @@ -1492,15 +1530,16 @@ static int php_plain_files_rmdir(php_stream_wrapper *wrapper, const char *url, i return 0; } + char errstr[256]; #ifdef PHP_WIN32 if (!php_win32_check_trailing_space(url, strlen(url))) { - php_error_docref1(NULL, url, E_WARNING, "%s", strerror(ENOENT)); + php_error_docref1(NULL, url, E_WARNING, "%s", php_socket_strerror_s(ENOENT, errstr, sizeof(errstr))); return 0; } #endif if (VCWD_RMDIR(url) < 0) { - php_error_docref1(NULL, url, E_WARNING, "%s", strerror(errno)); + php_error_docref1(NULL, url, E_WARNING, "%s", php_socket_strerror_s(errno, errstr, sizeof(errstr))); return 0; } @@ -1519,10 +1558,11 @@ static int php_plain_files_metadata(php_stream_wrapper *wrapper, const char *url #endif mode_t mode; int ret = 0; + char errstr[256]; #ifdef PHP_WIN32 if (!php_win32_check_trailing_space(url, strlen(url))) { - php_error_docref1(NULL, url, E_WARNING, "%s", strerror(ENOENT)); + php_error_docref1(NULL, url, E_WARNING, "%s", php_socket_strerror_s(ENOENT, errstr, sizeof(errstr))); return 0; } #endif @@ -1541,7 +1581,8 @@ static int php_plain_files_metadata(php_stream_wrapper *wrapper, const char *url if (VCWD_ACCESS(url, F_OK) != 0) { FILE *file = VCWD_FOPEN(url, "w"); if (file == NULL) { - php_error_docref1(NULL, url, E_WARNING, "Unable to create file %s because %s", url, strerror(errno)); + php_error_docref1(NULL, url, E_WARNING, "Unable to create file %s because %s", url, + php_socket_strerror_s(errno, errstr, sizeof(errstr))); return 0; } fclose(file); @@ -1584,7 +1625,8 @@ static int php_plain_files_metadata(php_stream_wrapper *wrapper, const char *url return 0; } if (ret == -1) { - php_error_docref1(NULL, url, E_WARNING, "Operation failed: %s", strerror(errno)); + php_error_docref1(NULL, url, E_WARNING, "Operation failed: %s", + php_socket_strerror_s(errno, errstr, sizeof(errstr))); return 0; } php_clear_stat_cache(0, NULL, 0); diff --git a/main/streams/streams.c b/main/streams/streams.c index 7a1b521108257..372ed6635c3f0 100644 --- a/main/streams/streams.c +++ b/main/streams/streams.c @@ -154,6 +154,7 @@ static void php_stream_display_wrapper_errors(php_stream_wrapper *wrapper, const { char *tmp; char *msg; + char errstr[256]; int free_msg = 0; if (EG(exception)) { @@ -203,7 +204,7 @@ static void php_stream_display_wrapper_errors(php_stream_wrapper *wrapper, const free_msg = 1; } else { if (wrapper == &php_plain_files_wrapper) { - msg = strerror(errno); /* TODO: not ts on linux */ + msg = php_socket_strerror_s(errno, errstr, sizeof(errstr)); } else { msg = "operation failed"; } @@ -1294,7 +1295,7 @@ PHPAPI int _php_stream_flush(php_stream *stream, int closing) { int ret = 0; - if (stream->writefilters.head) { + if (stream->writefilters.head && stream->ops->write) { _php_stream_write_filtered(stream, NULL, 0, closing ? PSFS_FLAG_FLUSH_CLOSE : PSFS_FLAG_FLUSH_INC ); } @@ -2219,7 +2220,6 @@ PHPAPI php_stream *_php_stream_open_wrapper_ex(const char *path, const char *mod int persistent = options & STREAM_OPEN_PERSISTENT; zend_string *path_str = NULL; zend_string *resolved_path = NULL; - char *copy_of_path = NULL; if (opened_path) { if (options & STREAM_OPEN_FOR_ZEND_STREAM) { @@ -2296,8 +2296,7 @@ PHPAPI php_stream *_php_stream_open_wrapper_ex(const char *path, const char *mod if (stream->orig_path) { pefree(stream->orig_path, persistent); } - copy_of_path = pestrdup(path, persistent); - stream->orig_path = copy_of_path; + stream->orig_path = pestrdup(path, persistent); #if ZEND_DEBUG stream->open_filename = __zend_orig_filename ? __zend_orig_filename : __zend_filename; stream->open_lineno = __zend_orig_lineno ? __zend_orig_lineno : __zend_lineno; @@ -2356,11 +2355,6 @@ PHPAPI php_stream *_php_stream_open_wrapper_ex(const char *path, const char *mod } } php_stream_tidy_wrapper_error_log(wrapper); -#if ZEND_DEBUG - if (stream == NULL && copy_of_path != NULL) { - pefree(copy_of_path, persistent); - } -#endif if (resolved_path) { zend_string_release_ex(resolved_path, 0); } diff --git a/main/streams/xp_socket.c b/main/streams/xp_socket.c index b1d89bc44cb2b..ef07f5f486606 100644 --- a/main/streams/xp_socket.c +++ b/main/streams/xp_socket.c @@ -674,9 +674,10 @@ static inline int php_tcp_sockop_bind(php_stream *stream, php_netstream_data_t * if (sock->socket == SOCK_ERR) { if (xparam->want_errortext) { + char errstr[256]; xparam->outputs.error_text = strpprintf(0, "Failed to create unix%s socket %s", stream->ops == &php_stream_unix_socket_ops ? "" : "datagram", - strerror(errno)); + php_socket_strerror_s(errno, errstr, sizeof(errstr))); } return -1; } diff --git a/run-tests.php b/run-tests.php index d51ab99a205a3..8fb638ed3e805 100755 --- a/run-tests.php +++ b/run-tests.php @@ -651,6 +651,12 @@ function main(): void } } + if (!defined('STDIN') || !stream_isatty(STDIN) + || !defined('STDOUT') || !stream_isatty(STDOUT) + || !defined('STDERR') || !stream_isatty(STDERR)) { + $environment['SKIP_IO_CAPTURE_TESTS'] = '1'; + } + if ($selected_tests && count($test_files) === 0) { echo "No tests found.\n"; return; diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c index 9eaeb4779f428..8d67fb2864c6d 100644 --- a/sapi/cli/php_cli_server.c +++ b/sapi/cli/php_cli_server.c @@ -2721,14 +2721,16 @@ static zend_result php_cli_server_do_event_for_each_fd_callback(void *_params, p struct sockaddr *sa = pemalloc(server->socklen, 1); client_sock = accept(server->server_sock, sa, &socklen); if (!ZEND_VALID_SOCKET(client_sock)) { - int err = php_socket_errno(); - if (err != SOCK_EAGAIN && php_cli_server_log_level >= PHP_CLI_SERVER_LOG_ERROR) { + pefree(sa, 1); + if (php_socket_errno() == SOCK_EAGAIN) { + return SUCCESS; + } + if (php_cli_server_log_level >= PHP_CLI_SERVER_LOG_ERROR) { char *errstr = php_socket_strerror(php_socket_errno(), NULL, 0); php_cli_server_logf(PHP_CLI_SERVER_LOG_ERROR, "Failed to accept a client (reason: %s)", errstr); efree(errstr); } - pefree(sa, 1); return FAILURE; } if (SUCCESS != php_set_sock_blocking(client_sock, 0)) { diff --git a/sapi/cli/tests/php_cli_server_pdeathsig.phpt b/sapi/cli/tests/php_cli_server_pdeathsig.phpt index 8b70bbcad4927..66a76a84ccaf6 100644 --- a/sapi/cli/tests/php_cli_server_pdeathsig.phpt +++ b/sapi/cli/tests/php_cli_server_pdeathsig.phpt @@ -9,6 +9,7 @@ if (!(str_contains(PHP_OS, 'Linux') || str_contains(PHP_OS, 'FreeBSD'))) { die('skip PDEATHSIG is only supported on Linux and FreeBSD'); } if (@file_exists('/.dockerenv')) die("skip Broken in Docker"); +if (!shell_exec("which pgrep")) die("skip Missing pgrep command"); ?> --FILE-- +--EXPECT-- +string(0) "" +string(6) "syslog"