diff --git a/NEWS b/NEWS index 412f6efc1eef4..6472816e407d3 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,11 @@ PHP NEWS . Fixed bug GH-19679 (zend_ssa_range_widening may fail to converge). (Arnaud) . Using null as an array offset or when calling array_key_exists() is now deprecated. (alexandre-daubois) + . Fixed bug GH-19681 (PHP_EXPAND_PATH broken with bash 5.3.0). (Remi) + +- CLI: + . Fixed bug GH-19461 (Improve error message on listening error with IPv6 + address). (alexandre-daubois) - Date: . Fixed date_sunrise() and date_sunset() with partial-hour UTC offset. @@ -35,12 +40,18 @@ PHP NEWS - PDO: . Driver specific methods in the PDO class are now deprecated. (Arnaud) +- Reflection: + . Fix GH-19691 (getModifierNames() not reporting asymmetric visibility). + (DanielEScherzer) + - Session: . Fix RC violation of session SID constant deprecation attribute. (ilutov) - Standard: . Fix GH-19610 (Deprecation warnings in functions taking as argument). (Girgias) + . Fixed bug GH-19577 (Avoid integer overflow when using a small offset + and PHP_INT_MAX with LimitIterator). (alexandre-daubois) - Streams: . Fixed bug GH-14506 (Closing a userspace stream inside a userspace handler diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index edadf024df24b..f3dfe0f9df57a 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -379,24 +379,6 @@ static const uint32_t bin_pages[] = { ZEND_MM_BINS_INFO(_BIN_DATA_PAGES, x, y) }; -#if ZEND_DEBUG -ZEND_COLD void zend_debug_alloc_output(char *format, ...) -{ - char output_buf[256]; - va_list args; - - va_start(args, format); - vsprintf(output_buf, format, args); - va_end(args); - -#ifdef ZEND_WIN32 - OutputDebugString(output_buf); -#else - fprintf(stderr, "%s", output_buf); -#endif -} -#endif - static ZEND_COLD ZEND_NORETURN void zend_mm_panic(const char *message) { fprintf(stderr, "%s\n", message); diff --git a/build/php.m4 b/build/php.m4 index 94556cf648f39..e82e856667e94 100644 --- a/build/php.m4 +++ b/build/php.m4 @@ -54,7 +54,11 @@ AC_DEFUN([PHP_EXPAND_PATH],[ changequote({,}) ep_dir=$(echo $1|$SED 's%/*[^/][^/]*/*$%%') changequote([,]) - ep_realdir=$(cd "$ep_dir" && pwd) + if test -z $ep_dir ; then + ep_realdir=$(pwd) + else + ep_realdir=$(cd "$ep_dir" && pwd) + fi $2="$ep_realdir"/$(basename "$1") fi ]) diff --git a/ext/pdo_firebird/firebird_statement.c b/ext/pdo_firebird/firebird_statement.c index 60a5e60e11bde..96b5cb1da1240 100644 --- a/ext/pdo_firebird/firebird_statement.c +++ b/ext/pdo_firebird/firebird_statement.c @@ -87,7 +87,6 @@ static int get_formatted_time_tz(pdo_stmt_t *stmt, const ISC_TIME_TZ* timeTz, zv struct tm t; ISC_TIME time; char timeBuf[80] = {0}; - char timeTzBuf[124] = {0}; if (fb_decode_time_tz(S->H->isc_status, timeTz, &hours, &minutes, &seconds, &fractions, sizeof(timeZoneBuffer), timeZoneBuffer)) { return 1; } @@ -100,8 +99,8 @@ static int get_formatted_time_tz(pdo_stmt_t *stmt, const ISC_TIME_TZ* timeTz, zv return 1; } - size_t time_tz_len = sprintf(timeTzBuf, "%s %s", timeBuf, timeZoneBuffer); - ZVAL_STRINGL(result, timeTzBuf, time_tz_len); + zend_string *time_tz_str = zend_strpprintf(0, "%s %s", timeBuf, timeZoneBuffer); + ZVAL_NEW_STR(result, time_tz_str); return 0; } @@ -115,7 +114,6 @@ static int get_formatted_timestamp_tz(pdo_stmt_t *stmt, const ISC_TIMESTAMP_TZ* struct tm t; ISC_TIMESTAMP ts; char timestampBuf[80] = {0}; - char timestampTzBuf[124] = {0}; if (fb_decode_timestamp_tz(S->H->isc_status, timestampTz, &year, &month, &day, &hours, &minutes, &seconds, &fractions, sizeof(timeZoneBuffer), timeZoneBuffer)) { return 1; } @@ -130,8 +128,8 @@ static int get_formatted_timestamp_tz(pdo_stmt_t *stmt, const ISC_TIMESTAMP_TZ* return 1; } - size_t timestamp_tz_len = sprintf(timestampTzBuf, "%s %s", timestampBuf, timeZoneBuffer); - ZVAL_STRINGL(result, timestampTzBuf, timestamp_tz_len); + zend_string *timestamp_tz_str = zend_strpprintf(0, "%s %s", timestampBuf, timeZoneBuffer); + ZVAL_NEW_STR(result, timestamp_tz_str); return 0; } diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 3a93e61c6d6ac..3d025c7eefd7c 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -1713,6 +1713,15 @@ ZEND_METHOD(Reflection, getModifierNames) add_next_index_stringl(return_value, "protected", sizeof("protected")-1); break; } + /* These are also mutually exclusive */ + switch (modifiers & ZEND_ACC_PPP_SET_MASK) { + case ZEND_ACC_PROTECTED_SET: + add_next_index_stringl(return_value, "protected(set)", sizeof("protected(set)")-1); + break; + case ZEND_ACC_PRIVATE_SET: + add_next_index_stringl(return_value, "private(set)", sizeof("private(set)")-1); + break; + } if (modifiers & ZEND_ACC_STATIC) { add_next_index_str(return_value, ZSTR_KNOWN(ZEND_STR_STATIC)); diff --git a/ext/reflection/tests/Reflection_getModifierNames_001.phpt b/ext/reflection/tests/Reflection_getModifierNames_001.phpt index 918ef2f28000a..78ba327df6f54 100644 --- a/ext/reflection/tests/Reflection_getModifierNames_001.phpt +++ b/ext/reflection/tests/Reflection_getModifierNames_001.phpt @@ -15,6 +15,8 @@ printModifiers(ReflectionMethod::IS_ABSTRACT | ReflectionMethod::IS_FINAL); printModifiers(ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_STATIC | ReflectionProperty::IS_READONLY); printModifiers(ReflectionClass::IS_READONLY); printModifiers(ReflectionProperty::IS_VIRTUAL); +printModifiers(ReflectionProperty::IS_PROTECTED_SET); +printModifiers(ReflectionProperty::IS_PRIVATE_SET); ?> --EXPECT-- private @@ -25,3 +27,5 @@ abstract,final public,static,readonly readonly virtual +protected(set) +private(set) diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index 677590cc89514..1ae4dae1eaa35 100644 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -2115,14 +2115,27 @@ static zend_object *spl_dual_it_new(zend_class_entry *class_type) } /* }}} */ +/* Returns the relative position for the current iterator position. */ +static zend_long spl_limit_it_relative_pos(spl_dual_it_object *intern) +{ + return intern->current.pos - intern->u.limit.offset; +} + +/* Returns the relative position for an arbitrary position. */ +static zend_long spl_limit_it_relative_pos_for(spl_dual_it_object *intern, zend_long pos) +{ + return pos - intern->u.limit.offset; +} + static inline zend_result spl_limit_it_valid(spl_dual_it_object *intern) { /* FAILURE / SUCCESS */ - if (intern->u.limit.count != -1 && intern->current.pos >= intern->u.limit.offset + intern->u.limit.count) { + if (intern->u.limit.count != -1 && + spl_limit_it_relative_pos(intern) >= intern->u.limit.count) { return FAILURE; - } else { - return spl_dual_it_valid(intern); } + + return spl_dual_it_valid(intern); } static inline void spl_limit_it_seek(spl_dual_it_object *intern, zend_long pos) @@ -2134,7 +2147,7 @@ static inline void spl_limit_it_seek(spl_dual_it_object *intern, zend_long pos) zend_throw_exception_ex(spl_ce_OutOfBoundsException, 0, "Cannot seek to " ZEND_LONG_FMT " which is below the offset " ZEND_LONG_FMT, pos, intern->u.limit.offset); return; } - if (pos - intern->u.limit.offset >= intern->u.limit.count && intern->u.limit.count != -1) { + if (spl_limit_it_relative_pos_for(intern, pos) >= intern->u.limit.count && intern->u.limit.count != -1) { zend_throw_exception_ex(spl_ce_OutOfBoundsException, 0, "Cannot seek to " ZEND_LONG_FMT " which is behind offset " ZEND_LONG_FMT " plus count " ZEND_LONG_FMT, pos, intern->u.limit.offset, intern->u.limit.count); return; } @@ -2191,7 +2204,7 @@ PHP_METHOD(LimitIterator, valid) SPL_FETCH_AND_CHECK_DUAL_IT(intern, ZEND_THIS); /* RETURN_BOOL(spl_limit_it_valid(intern) == SUCCESS);*/ - RETURN_BOOL((intern->u.limit.count == -1 || intern->current.pos < intern->u.limit.offset + intern->u.limit.count) && Z_TYPE(intern->current.data) != IS_UNDEF); + RETURN_BOOL((intern->u.limit.count == -1 || spl_limit_it_relative_pos(intern) < intern->u.limit.count) && Z_TYPE(intern->current.data) != IS_UNDEF); } /* }}} */ /* {{{ Move the iterator forward */ @@ -2204,7 +2217,7 @@ PHP_METHOD(LimitIterator, next) SPL_FETCH_AND_CHECK_DUAL_IT(intern, ZEND_THIS); spl_dual_it_next(intern, 1); - if (intern->u.limit.count == -1 || intern->current.pos < intern->u.limit.offset + intern->u.limit.count) { + if (intern->u.limit.count == -1 || spl_limit_it_relative_pos(intern) < intern->u.limit.count) { spl_dual_it_fetch(intern, 1); } } /* }}} */ diff --git a/ext/spl/tests/gh19577.phpt b/ext/spl/tests/gh19577.phpt new file mode 100644 index 0000000000000..641cfa57e0651 --- /dev/null +++ b/ext/spl/tests/gh19577.phpt @@ -0,0 +1,16 @@ +--TEST-- +GH-19577: Integer overflow in LimitIterator with small offset and PHP_INT_MAX count +--FILE-- + 'A', 1 => 'B', 2 => 'C', 3 => 'D')); +$it = new LimitIterator($it, 2, PHP_INT_MAX); + +foreach($it as $val => $key) { + echo "Key: $val, Value: $key\n"; +} + +?> +--EXPECT-- +Key: 2, Value: C +Key: 3, Value: D diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c index 92c6ecbdfb581..911cfd2bb5910 100644 --- a/sapi/cli/php_cli_server.c +++ b/sapi/cli/php_cli_server.c @@ -2563,7 +2563,11 @@ static zend_result php_cli_server_ctor(php_cli_server *server, const char *addr, server_sock = php_network_listen_socket(host, &port, SOCK_STREAM, &server->address_family, &server->socklen, &errstr); if (server_sock == SOCK_ERR) { - php_cli_server_logf(PHP_CLI_SERVER_LOG_ERROR, "Failed to listen on %s:%d (reason: %s)", host, port, errstr ? ZSTR_VAL(errstr) : "?"); + if (strchr(host, ':')) { + php_cli_server_logf(PHP_CLI_SERVER_LOG_ERROR, "Failed to listen on [%s]:%d (reason: %s)", host, port, errstr ? ZSTR_VAL(errstr) : "?"); + } else { + php_cli_server_logf(PHP_CLI_SERVER_LOG_ERROR, "Failed to listen on %s:%d (reason: %s)", host, port, errstr ? ZSTR_VAL(errstr) : "?"); + } if (errstr) { zend_string_release_ex(errstr, 0); } diff --git a/sapi/cli/tests/php_cli_server_ipv4_error_message.phpt b/sapi/cli/tests/php_cli_server_ipv4_error_message.phpt new file mode 100644 index 0000000000000..71280179cccfc --- /dev/null +++ b/sapi/cli/tests/php_cli_server_ipv4_error_message.phpt @@ -0,0 +1,41 @@ +--TEST-- +IPv4 address error message formatting +--SKIPIF-- + +--FILE-- + array("pipe", "r"), + 1 => array("pipe", "w"), + 2 => array("pipe", "w") +); + +$process = proc_open( + PHP_BINARY . ' -S "192.168.1.999:8080"', + $descriptorspec, + $pipes +); + +if (is_resource($process)) { + usleep(100000); + + $stderr = stream_get_contents($pipes[2]); + + fclose($pipes[0]); + fclose($pipes[1]); + fclose($pipes[2]); + + proc_terminate($process); + proc_close($process); + + var_dump($stderr); +} +?> +--EXPECTF-- +string(%d) "[%s] Failed to listen on 192.168.1.999:8080 %s +" diff --git a/sapi/cli/tests/php_cli_server_ipv6_error_message.phpt b/sapi/cli/tests/php_cli_server_ipv6_error_message.phpt new file mode 100644 index 0000000000000..55432eeec15e7 --- /dev/null +++ b/sapi/cli/tests/php_cli_server_ipv6_error_message.phpt @@ -0,0 +1,40 @@ +--TEST-- +IPv6 address error message formatting +--SKIPIF-- + +--FILE-- + array("pipe", "r"), + 1 => array("pipe", "w"), + 2 => array("pipe", "w") +); + +$process = proc_open( + PHP_BINARY . ' -S "[2001:db8::]:8080"', + $descriptorspec, + $pipes +); + +if (is_resource($process)) { + usleep(100000); + + $stderr = stream_get_contents($pipes[2]); + + fclose($pipes[0]); + fclose($pipes[1]); + fclose($pipes[2]); + + proc_terminate($process); + proc_close($process); + + var_dump($stderr); +} +?> +--EXPECTF-- +string(%d) "[%s] Failed to listen on [2001:db8::]:8080 %s +"