Commit 16e217ee550 for php.net

commit 16e217ee5509c35712bcfa1d2468f5d6b6470d43
Merge: 80d580b2922 c0fa54f796f
Author: Saki Takamachi <saki@php.net>
Date:   Sun Jun 7 12:18:40 2026 +0900

    Merge branch 'PHP-8.4' into PHP-8.5

    * PHP-8.4:
      ext/bcmath: bounds-check $precision in bcround() and Number::round() (#22182)

diff --cc NEWS
index 9a98aadadf8,ff552103ebc..7bc92d48ec3
--- a/NEWS
+++ b/NEWS
@@@ -1,7 -1,11 +1,11 @@@
  PHP                                                                        NEWS
  |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 -?? ??? ????, PHP 8.4.23
 +?? ??? ????, PHP 8.5.8

+ - BCMath:
+   . Fixed issues with oversized allocations and signed overflow in bcround()
+     and BcMath\Number::round(). (edorian)
+
  - GD:
    . Fixed bug GH-22121 (Double free in gdImageSetStyle() after
      overflow-triggered early return). (iliaal)
diff --cc UPGRADING
index 8b6e0c57cb1,821fa4a723f..39400b5ea6d
--- a/UPGRADING
+++ b/UPGRADING
@@@ -597,134 -625,149 +597,138 @@@ PHP 8.5 UPGRADE NOTE
  5. Changed Functions
  ========================================

+ - BCMath:
+   . bcround() and BcMath\Number::round() now throw a ValueError when the precision
+     argument is out of range.
+
 -- Core:
 -  . trigger_error() and user_error() now have a return type of true instead of
 -    bool.
 -
 -- DOM:
 -  . DOMDocument::registerNodeClass() now has a tentative return type of true.
 -    Previously, the return type was bool but only true could be returned in practice.
 -
 -- GD:
 -  . imagescale now throws a ValueError when both width and height arguments are negative.
 -
 -- Hash:
 -  . Changed the return type of hash_update() to true. It was already the case that only
 -    true could be returned, but the stub was not updated yet.
 -
  - Intl:
 -  . NumberFormatter::ROUND_TOWARD_ZERO and NumberFormatter::ROUND_AWAY_FROM_ZERO
 -    have been added as aliases for NumberFormatter::ROUND_DOWN and
 -    NumberFormatter::ROUND_UP to be consistent with the new PHP_ROUND_* modes.
 -    RFC: https://wiki.php.net/rfc/new_rounding_modes_to_round_function
 -  . ResourceBundle::get() now has a tentative return type of:
 -    ResourceBundle|array|string|int|null
 -  . The idn_to_ascii() and idn_to_utf8() now always throw ValueErrors if the
 -    $domain name is empty or too long, and if $variant is not
 -    INTL_IDNA_VARIANT_UTS46.
 -
 -- LibXML:
 -  . libxml_set_streams_context() now immediately throws a TypeError when a
 -    non-stream-context resource is passed to the function, instead of throwing
 -    later when the stream context is used.
 +  . IntlDateFormatter::setTimeZone()/datefmt_set_timezone()
 +    throws an IntlException on uninitialised classes/clone failures.
 +  . grapheme_extract() properly assigns $next value when skipping over
 +    invalid starting bytes. Previously there were cases where it would
 +    point to the start of the grapheme boundary instead of the end.
 +  . Locale:: methods throw a ValueError when locale inputs contain null
 +    bytes.
 +  . transliterator_get_error_code(), transliterator_get_error_message()
 +    TransLiterator::getErrorCode(), and TransLiterator::getErrorMessage()
 +    have dropped the false from the return type union. Returning false
 +    was actually never possible.
 +  . grapheme_strpos(), grapheme_stripos(), grapheme_strrpos(),
 +    grapheme_strripos(), grapheme_substr(), grapheme_strstr()
 +    and grapheme_stristr() functions add $locale parameter.
 +    RFC: https://wiki.php.net/rfc/grapheme_add_locale_for_case_insensitive

 -- MBString:
 -  . The behavior of mb_strcut is more consistent now on invalid UTF-8 and UTF-16
 -    strings. (For valid UTF-8 and UTF-16 strings, there is no change.)
 +- LDAP:
 +  . ldap_get_option() now accepts a NULL connection, like ldap_set_option(),
 +    to allow retrieval of global options.

 -- ODBC:
 -  . Parameter $row of odbc_fetch_object(), odbc_fetch_array(), and
 -    odbc_fetch_into() now has a default value of null, consistent with
 -    odbc_fetch_row(). Previously, the default values were -1, -1, and 0,
 -    respectively.
 +- libxml:
 +  . libxml_set_external_entity_loader() now has a formal return type of true.

  - OpenSSL:
 -  . The extra_attributes parameter in openssl_csr_new sets CSR attributes
 -    instead of subject DN which was incorrectly done previously.
 -  . The dn parameter in openssl_csr_new allows setting array of values for
 -    a single entry.
 -  . New serial_hex parameter added to openssl_csr_sign to allow setting serial
 -    number in the hexadecimal format.
 -  . Parsing ASN.1 UTCTime by openssl_x509_parse fails if seconds are omitted
 -    for OpenSSL version below 3.2 (-1 is returned for such fields). The
 -    OpenSSL version 3.3+ does not load such certificates already.
 -
 -- Output:
 -  . Output handler status flags passed to the flags parameter of ob_start
 -    are now cleared.
 +  . openssl_public_encrypt() and openssl_private_decrypt() have a new parameter
 +    $digest_algo that allows specifying the hash digest algorithm for OAEP padding.
 +  . openssl_sign() and openssl_verify() have a new parameter $padding to allow
 +    using more secure RSA PSS padding.
 +  . openssl_cms_encrypt() $cipher_algo parameter can be a string with the
 +    cipher name. That allows to use more algorithms including AES GCM cipher
 +    algorithms for auth enveloped data.

 -- PDO:
 -  . getAttribute, enabled to get the value of ATTR_STRINGIFY_FETCHES.
 -
 -- PDO_FIREBIRD:
 -  . getAttribute, enabled to get values of FB_ATTR_DATE_FORMAT, FB_ATTR_TIME_FORMAT,
 -    FB_ATTR_TIMESTAMP_FORMAT.
 -  . Added new attributes to specify transaction isolation level and access mode.
 -    Along with these, five constants (Pdo\Firebird::TRANSACTION_ISOLATION_LEVEL,
 -    Pdo\Firebird::READ_COMMITTED, Pdo\Firebird::REPEATABLE_READ,
 -    Pdo\Firebird::SERIALIZABLE, Pdo\Firebird::WRITABLE_TRANSACTION) have been added.
 -  . When using persistent connections, there is now a liveness check in the
 -    constructor.
 -  . The content that is built changes depending on the value of FB_API_VER in
 -    ibase.h, so added static method Pdo\Firebird::getApiVersion() to obtain that
 -    value. This value can also be referenced from phpinfo.
 -  . Five new data types are now available: INT128, DEC16, DEC34, TIMESTAMP_TZ, TIME_TZ.
 -    These are available starting with Firebird 4.0.
 -
 -- PDO_MYSQL:
 -  . getAttribute, enabled to get the value of ATTR_FETCH_TABLE_NAMES.
 +- PCNTL:
 +  . pcntl_exec() now has a formal return type of false.
 +  . pcntl_waitid() takes an additional resource_usage argument to
 +    gather various platform specific metrics about the child process.

  - PDO_PGSQL:
 -  . getAttribute() can now retrieve the memory usage of query results.
 -    PDO::PGSQL_ATTR_RESULT_MEMORY_SIZE was added for this feature.
 -  . If the column is of FLOAT4OID/FLOAT8OID type, query returns it as a
 -    float instead of a string.
 +  . PDO::pgsqlCopyFromArray now supports Iterable inputs.
 +  . Pdo\Pgsql::setAttribute and Pdo\Pgsql::prepare support setting
 +    PDO::ATTR_PREFETCH to 0 which enters lazy fetch mode.
 +    In this mode, statements cannot be run in parallel.

 -- PGSQL:
 -  . pg_select, the conditions arguments accepts an empty array and is optional.
 +- PDO_SQLITE:
 +  . SQLite PDO::quote() will now throw an exception or emit a warning,
 +    depending on the error mode, if the string contains a null byte.
 +  . PDO::sqliteCreateCollation will now throw an exception
 +    if the callback has the wrong return type, making it more
 +    in line with Pdo_Sqlite::createCollation behavior.

 -- Phar:
 -  . Phar::setAlias() and Phar::setDefaultStub() methods now have a tentative
 -    return type of true instead of bool.
 +- PGSQL:
 +  . pg_copy_from now supports Iterable inputs.
 +  . pg_connect checks if the connection_string argument contains
 +    any null byte.
 +  . pg_close_stmt checks if the statement_name argument contains
 +    any null byte.

  - POSIX:
 -  . posix_isatty now sets the error number when the file descriptor/stream argument
 -    is invalid.
 +  . posix_ttyname sets last_error to EBADF when encountering
 +    an invalid file descriptor.
 +  . posix_isatty raises an E_WARNING message when encountering
 +    an invalid file descriptor.
 +  . posix_fpathconf checks invalid file descriptors and sets
 +    last_error to EBADF and raises an E_WARNING message.
 +  . posix_kill throws a ValueError when the process_id argument is lower
 +    or greater than what the platform supports (signed integer or long
 +    range), posix_setpgid throws a ValueError when the process_id or
 +    the process_group_id is lower than zero or greater than
 +    what the platform supports.
 +  . posix_setrlimit throws a ValueError when the hard_limit or soft_limit
 +    arguments are lower than -1 or if soft_limit is greater than hard_limit.

  - Reflection:
 -  . ReflectionGenerator::getFunction() may now be called after the generator
 -    finished executing.
 +  . The output of ReflectionClass::__toString() for enums has changed to
 +    better indicate that the class is an enum, and that the enum cases
 +    are enum cases rather than normal class constants.
 +  . The output of ReflectionProperty::__toString() for properties with
 +    hooks has changed to indicate what hooks the property has, whether those
 +    hooks are final, and whether the property is virtual. This also affects
 +    the output of ReflectionClass::__toString() when a class contains hooked
 +    properties.
 +  . ReflectionAttribute::newInstance() can now throw errors for internal
 +    attributes if the attribute was applied on an invalid target and the
 +    error was delayed from compile time to runtime via the
 +    #[\DelayedTargetValidation] attribute.
 +    RFC: https://wiki.php.net/rfc/delayedtargetvalidation_attribute
 +
 +- Session:
 +  . session_start is stricter in regard to the options argument.
 +    It throws a ValueError if the array is not a hashmap, or
 +    a TypeError if the read_and_close value is not a valid type
 +    compatible with int.
 +
 +- SNMP:
 +  . snmpget, snmpset, snmp_get2, snmp_set2, snmp_get3, snmp_set3
 +    and SNMP::__construct() throw a ValueError when the hostname
 +    is too large, contains any null byte or if the port is given
 +    when negative or greater than 65535, timeout and retries values
 +    are lower than -1 or too large.

  - Sockets:
 -  . Parameter $backlog of socket_create_listen() now has a default value of SOMAXCONN.
 -    Previously, it was 128.
 +  . socket_create_listen, socket_bind and socket_sendto throw a
 +    ValueError if the port is lower than 0 or greater than 65535,
 +    and also if any of the hints array entries are indexed numerically.
 +  . socket_addrinfo_lookup throws a TypeError if any of the hints
 +    values cannot be cast to int and can throw a ValueError if
 +    any of these values overflow.
 +  . socket_set_option with MCAST_LEAVE_GROUP/MCAST_LEAVE_SOURCE_GROUP
 +    options will throw an exception if the value isn't a valid object
 +    or array.
 +  . socket_create/socket_bind can create AF_PACKET family sockets.
 +  . socket_getsockname gets the interface index and its string
 +    representation with AF_PACKET socket.
 +  . socket_set_option with multicast context throws a ValueError
 +    when the created socket is not of AF_INET/AF_INET6 family.

 -- SPL:
 -  . SplPriorityQueue::insert() and SplPriorityQueue::recoverFromCorruption()
 -    now has a tentative return type of true
 -  . SplHeap::insert() and SplHeap::recoverFromCorruption()
 -    now has a tentative return type of true instead of bool
 +- Tidy:
 +  . tidy::__construct/parseFile/parseString now throws a ValueError if the
 +    configuration contains an invalid value or attempts to set a read-only
 +    internal entry, and a TypeError if a configuration key is not a string.

 -- Standard:
 -  . The internal implementation for rounding to integers has been rewritten
 -    to be easier to verify for correctness and to be easier to maintain.
 -    Some rounding bugs have been fixed as a result of the rewrite. For
 -    example previously rounding 0.49999999999999994 to the nearest integer
 -    would have resulted in 1.0 instead of the correct result 0.0. Additional
 -    inputs might also be affected and result in different outputs compared to
 -    earlier PHP versions.
 -  . The $mode parameter of the round() function has been widened to RoundingMode|int,
 -    accepting instances of a new RoundingMode enum.
 -    RFC: https://wiki.php.net/rfc/correctly_name_the_rounding_mode_and_make_it_an_enum
 -  . Four new modes have been added to the round() function: RoundingMode::PositiveInfinity,
 -    RoundingMode::NegativeInfinity, RoundingMode::TowardsZero, RoundingMode::AwayFromZero.
 -    RFC: https://wiki.php.net/rfc/new_rounding_modes_to_round_function
 -  . Fixed a bug caused by "pre-rounding" of the round() function. Previously, using
 -    "pre-rounding" to treat a value like 0.285 (actually 0.28499999999999998) as a
 -    decimal number and round it to 0.29. However, "pre-rounding" incorrectly rounds
 -    certain numbers, so this fix removes "pre-rounding" and changes the way numbers
 -    are compared, so that the values are correctly rounded as decimal numbers.
 -  . The maximum precision that can be handled by round() has been extended by one
 -    digit. For example, `round(4503599627370495.5)` returned in `4503599627370495.5`,
 -    but now returns `4503599627370496`.
 -  . The default value of the 'cost' option for PASSWORD_BCRYPT for password_hash()
 -    has been increased from '10' to '12'.
 -    RFC: https://wiki.php.net/rfc/bcrypt_cost_2023
 -  . debug_zval_dump() now indicates whether an array is packed.
 -  . long2ip() now returns string instead of string|false.
 -  . output_add_rewrite_var() now uses url_rewriter.hosts instead of
 -    session.trans_sid_hosts for selecting hosts that will be rewritten.
 -  . highlight_string() now has a return type of string|true instead of string|bool.
 -  . print_r() now has a return type of string|true instead of string|bool.
 +- Zlib:
 +  . The "use_include_path" argument for the
 +    gzfile, gzopen and readgzfile functions has been changed
 +    from int to boolean.
 +  . gzfile, gzopen and readgzfile functions now respect the default
 +    stream context.

  ========================================
  6. New Functions
diff --cc ext/bcmath/libbcmath/src/round.c
index 44df6036cbe,a495221ff00..046493b9265
--- a/ext/bcmath/libbcmath/src/round.c
+++ b/ext/bcmath/libbcmath/src/round.c
@@@ -68,18 -67,16 +68,16 @@@ size_t bc_round(bc_num num, zend_long p

  		if (bc_is_zero(num)) {
  			*result = bc_copy_num(BCG(_zero_));
 -			return;
 +			return 0;
  		}

- 		/* If precision is -3, it becomes 1000. */
- 		if (UNEXPECTED(precision == ZEND_LONG_MIN)) {
- 			*result = bc_new_num((size_t) ZEND_LONG_MAX + 2, 0);
- 		} else {
- 			*result = bc_new_num(-precision + 1, 0);
- 		}
+ 		/* If precision is -3, it becomes 1000. Negate in unsigned space so
+ 		 * precision == ZEND_LONG_MIN doesn't overflow signed long. */
+ 		zend_ulong magnitude = -(zend_ulong) precision;
+ 		*result = bc_new_num((size_t) magnitude + 1, 0);
  		(*result)->n_value[0] = 1;
  		(*result)->n_sign = num->n_sign;
 -		return;
 +		return 0;
  	}

  	/* Just like bcadd('1', '1', 4) becomes '2.0000', it pads with zeros at the end if necessary. */