From 0c324b983f6ca92a6b96074072bcf51a655839ad Mon Sep 17 00:00:00 2001 From: John Blackbourn Date: Wed, 5 Jul 2023 17:41:22 +0000 Subject: [PATCH] General: Increase the minimum supported version of PHP to 7.0.0. This also removes the random compat library which is no longer necessary, and adjusts unit tests and CI workflows that no longer need to take PHP 5.6 into account. Thank you for your service, PHP 5. Onwards! Props SergeyBiryukov, mukesh27, dingo_d, audrasjb, jrf, costdev, azaozz, JavierCasares, hellofromTonya, samiamnot, spacedmonkey, masteradhoc, knutsp, garyjones, chanthaboune Fixes #57345 Built from https://develop.svn.wordpress.org/trunk@56141 git-svn-id: http://core.svn.wordpress.org/trunk@55653 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- readme.html | 2 +- wp-includes/compat.php | 4 - .../random_compat/byte_safe_strings.php | 195 --------------- wp-includes/random_compat/cast_to_int.php | 77 ------ wp-includes/random_compat/error_polyfill.php | 49 ---- wp-includes/random_compat/random.php | 226 ------------------ .../random_compat/random_bytes_com_dotnet.php | 91 ------- .../random_bytes_dev_urandom.php | 190 --------------- .../random_compat/random_bytes_libsodium.php | 91 ------- .../random_bytes_libsodium_legacy.php | 93 ------- .../random_compat/random_bytes_mcrypt.php | 79 ------ wp-includes/random_compat/random_int.php | 204 ---------------- wp-includes/version.php | 4 +- 13 files changed, 3 insertions(+), 1302 deletions(-) delete mode 100644 wp-includes/random_compat/byte_safe_strings.php delete mode 100644 wp-includes/random_compat/cast_to_int.php delete mode 100644 wp-includes/random_compat/error_polyfill.php delete mode 100644 wp-includes/random_compat/random.php delete mode 100644 wp-includes/random_compat/random_bytes_com_dotnet.php delete mode 100644 wp-includes/random_compat/random_bytes_dev_urandom.php delete mode 100644 wp-includes/random_compat/random_bytes_libsodium.php delete mode 100644 wp-includes/random_compat/random_bytes_libsodium_legacy.php delete mode 100644 wp-includes/random_compat/random_bytes_mcrypt.php delete mode 100644 wp-includes/random_compat/random_int.php diff --git a/readme.html b/readme.html index 86edbaa53c..a40c5e98a9 100644 --- a/readme.html +++ b/readme.html @@ -51,7 +51,7 @@

System Requirements

diff --git a/wp-includes/compat.php b/wp-includes/compat.php index 696642f8d2..2b8de57bd7 100644 --- a/wp-includes/compat.php +++ b/wp-includes/compat.php @@ -333,10 +333,6 @@ if ( ! function_exists( 'hash_equals' ) ) : } endif; -// random_int() was introduced in PHP 7.0. -if ( ! function_exists( 'random_int' ) ) { - require ABSPATH . WPINC . '/random_compat/random.php'; -} // sodium_crypto_box() was introduced in PHP 7.2. if ( ! function_exists( 'sodium_crypto_box' ) ) { require ABSPATH . WPINC . '/sodium_compat/autoload.php'; diff --git a/wp-includes/random_compat/byte_safe_strings.php b/wp-includes/random_compat/byte_safe_strings.php deleted file mode 100644 index ef24488f9e..0000000000 --- a/wp-includes/random_compat/byte_safe_strings.php +++ /dev/null @@ -1,195 +0,0 @@ - RandomCompat_strlen($binary_string)) { - return ''; - } - - return (string) mb_substr( - (string) $binary_string, - (int) $start, - (int) $length, - '8bit' - ); - } - - } else { - - /** - * substr() implementation that isn't brittle to mbstring.func_overload - * - * This version just uses the default substr() - * - * @param string $binary_string - * @param int $start - * @param int|null $length (optional) - * - * @throws TypeError - * - * @return string - */ - function RandomCompat_substr($binary_string, $start, $length = null) - { - if (!is_string($binary_string)) { - throw new TypeError( - 'RandomCompat_substr(): First argument should be a string' - ); - } - - if (!is_int($start)) { - throw new TypeError( - 'RandomCompat_substr(): Second argument should be an integer' - ); - } - - if ($length !== null) { - if (!is_int($length)) { - throw new TypeError( - 'RandomCompat_substr(): Third argument should be an integer, or omitted' - ); - } - - return (string) substr( - (string )$binary_string, - (int) $start, - (int) $length - ); - } - - return (string) substr( - (string) $binary_string, - (int) $start - ); - } - } -} diff --git a/wp-includes/random_compat/cast_to_int.php b/wp-includes/random_compat/cast_to_int.php deleted file mode 100644 index 1b1bbfe8de..0000000000 --- a/wp-includes/random_compat/cast_to_int.php +++ /dev/null @@ -1,77 +0,0 @@ - operators might accidentally let a float - * through. - * - * @param int|float $number The number we want to convert to an int - * @param bool $fail_open Set to true to not throw an exception - * - * @return float|int - * @psalm-suppress InvalidReturnType - * - * @throws TypeError - */ - function RandomCompat_intval($number, $fail_open = false) - { - if (is_int($number) || is_float($number)) { - $number += 0; - } elseif (is_numeric($number)) { - /** @psalm-suppress InvalidOperand */ - $number += 0; - } - /** @var int|float $number */ - - if ( - is_float($number) - && - $number > ~PHP_INT_MAX - && - $number < PHP_INT_MAX - ) { - $number = (int) $number; - } - - if (is_int($number)) { - return (int) $number; - } elseif (!$fail_open) { - throw new TypeError( - 'Expected an integer.' - ); - } - return $number; - } -} diff --git a/wp-includes/random_compat/error_polyfill.php b/wp-includes/random_compat/error_polyfill.php deleted file mode 100644 index c02c5c8b4c..0000000000 --- a/wp-includes/random_compat/error_polyfill.php +++ /dev/null @@ -1,49 +0,0 @@ -= 70000) { - return; -} - -if (!defined('RANDOM_COMPAT_READ_BUFFER')) { - define('RANDOM_COMPAT_READ_BUFFER', 8); -} - -$RandomCompatDIR = dirname(__FILE__); - -require_once $RandomCompatDIR.DIRECTORY_SEPARATOR.'byte_safe_strings.php'; -require_once $RandomCompatDIR.DIRECTORY_SEPARATOR.'cast_to_int.php'; -require_once $RandomCompatDIR.DIRECTORY_SEPARATOR.'error_polyfill.php'; - -if (!is_callable('random_bytes')) { - /** - * PHP 5.2.0 - 5.6.x way to implement random_bytes() - * - * We use conditional statements here to define the function in accordance - * to the operating environment. It's a micro-optimization. - * - * In order of preference: - * 1. Use libsodium if available. - * 2. fread() /dev/urandom if available (never on Windows) - * 3. mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM) - * 4. COM('CAPICOM.Utilities.1')->GetRandom() - * - * See RATIONALE.md for our reasoning behind this particular order - */ - if (extension_loaded('libsodium')) { - // See random_bytes_libsodium.php - if (PHP_VERSION_ID >= 50300 && is_callable('\\Sodium\\randombytes_buf')) { - require_once $RandomCompatDIR.DIRECTORY_SEPARATOR.'random_bytes_libsodium.php'; - } elseif (method_exists('Sodium', 'randombytes_buf')) { - require_once $RandomCompatDIR.DIRECTORY_SEPARATOR.'random_bytes_libsodium_legacy.php'; - } - } - - /** - * Reading directly from /dev/urandom: - */ - if (DIRECTORY_SEPARATOR === '/') { - // DIRECTORY_SEPARATOR === '/' on Unix-like OSes -- this is a fast - // way to exclude Windows. - $RandomCompatUrandom = true; - $RandomCompat_basedir = ini_get('open_basedir'); - - if (!empty($RandomCompat_basedir)) { - $RandomCompat_open_basedir = explode( - PATH_SEPARATOR, - strtolower($RandomCompat_basedir) - ); - $RandomCompatUrandom = (array() !== array_intersect( - array('/dev', '/dev/', '/dev/urandom'), - $RandomCompat_open_basedir - )); - $RandomCompat_open_basedir = null; - } - - if ( - !is_callable('random_bytes') - && - $RandomCompatUrandom - && - @is_readable('/dev/urandom') - ) { - // Error suppression on is_readable() in case of an open_basedir - // or safe_mode failure. All we care about is whether or not we - // can read it at this point. If the PHP environment is going to - // panic over trying to see if the file can be read in the first - // place, that is not helpful to us here. - - // See random_bytes_dev_urandom.php - require_once $RandomCompatDIR.DIRECTORY_SEPARATOR.'random_bytes_dev_urandom.php'; - } - // Unset variables after use - $RandomCompat_basedir = null; - } else { - $RandomCompatUrandom = false; - } - - /** - * mcrypt_create_iv() - * - * We only want to use mcypt_create_iv() if: - * - * - random_bytes() hasn't already been defined - * - the mcrypt extensions is loaded - * - One of these two conditions is true: - * - We're on Windows (DIRECTORY_SEPARATOR !== '/') - * - We're not on Windows and /dev/urandom is readabale - * (i.e. we're not in a chroot jail) - * - Special case: - * - If we're not on Windows, but the PHP version is between - * 5.6.10 and 5.6.12, we don't want to use mcrypt. It will - * hang indefinitely. This is bad. - * - If we're on Windows, we want to use PHP >= 5.3.7 or else - * we get insufficient entropy errors. - */ - if ( - !is_callable('random_bytes') - && - // Windows on PHP < 5.3.7 is broken, but non-Windows is not known to be. - (DIRECTORY_SEPARATOR === '/' || PHP_VERSION_ID >= 50307) - && - // Prevent this code from hanging indefinitely on non-Windows; - // see https://bugs.php.net/bug.php?id=69833 - ( - DIRECTORY_SEPARATOR !== '/' || - (PHP_VERSION_ID <= 50609 || PHP_VERSION_ID >= 50613) - ) - && - extension_loaded('mcrypt') - ) { - // See random_bytes_mcrypt.php - require_once $RandomCompatDIR.DIRECTORY_SEPARATOR.'random_bytes_mcrypt.php'; - } - $RandomCompatUrandom = null; - - /** - * This is a Windows-specific fallback, for when the mcrypt extension - * isn't loaded. - */ - if ( - !is_callable('random_bytes') - && - extension_loaded('com_dotnet') - && - class_exists('COM') - ) { - $RandomCompat_disabled_classes = preg_split( - '#\s*,\s*#', - strtolower(ini_get('disable_classes')) - ); - - if (!in_array('com', $RandomCompat_disabled_classes)) { - try { - $RandomCompatCOMtest = new COM('CAPICOM.Utilities.1'); - /** @psalm-suppress TypeDoesNotContainType */ - if (is_callable(array($RandomCompatCOMtest, 'GetRandom'))) { - // See random_bytes_com_dotnet.php - require_once $RandomCompatDIR.DIRECTORY_SEPARATOR.'random_bytes_com_dotnet.php'; - } - } catch (com_exception $e) { - // Don't try to use it. - } - } - $RandomCompat_disabled_classes = null; - $RandomCompatCOMtest = null; - } - - /** - * throw new Exception - */ - if (!is_callable('random_bytes')) { - /** - * We don't have any more options, so let's throw an exception right now - * and hope the developer won't let it fail silently. - * - * @param mixed $length - * @psalm-suppress InvalidReturnType - * @throws Exception - * @return string - */ - function random_bytes($length) - { - unset($length); // Suppress "variable not used" warnings. - throw new Exception( - 'There is no suitable CSPRNG installed on your system' - ); - return ''; - } - } -} - -if (!is_callable('random_int')) { - require_once $RandomCompatDIR.DIRECTORY_SEPARATOR.'random_int.php'; -} - -$RandomCompatDIR = null; diff --git a/wp-includes/random_compat/random_bytes_com_dotnet.php b/wp-includes/random_compat/random_bytes_com_dotnet.php deleted file mode 100644 index 537d02b27a..0000000000 --- a/wp-includes/random_compat/random_bytes_com_dotnet.php +++ /dev/null @@ -1,91 +0,0 @@ -GetRandom($bytes, 0)); - if (RandomCompat_strlen($buf) >= $bytes) { - /** - * Return our random entropy buffer here: - */ - return (string) RandomCompat_substr($buf, 0, $bytes); - } - ++$execCount; - } while ($execCount < $bytes); - - /** - * If we reach here, PHP has failed us. - */ - throw new Exception( - 'Could not gather sufficient random data' - ); - } -} diff --git a/wp-includes/random_compat/random_bytes_dev_urandom.php b/wp-includes/random_compat/random_bytes_dev_urandom.php deleted file mode 100644 index c4e31ccbbb..0000000000 --- a/wp-includes/random_compat/random_bytes_dev_urandom.php +++ /dev/null @@ -1,190 +0,0 @@ - $st */ - $st = fstat($fp); - if (($st['mode'] & 0170000) !== 020000) { - fclose($fp); - $fp = false; - } - } - } - - if (is_resource($fp)) { - /** - * stream_set_read_buffer() does not exist in HHVM - * - * If we don't set the stream's read buffer to 0, PHP will - * internally buffer 8192 bytes, which can waste entropy - * - * stream_set_read_buffer returns 0 on success - */ - if (is_callable('stream_set_read_buffer')) { - stream_set_read_buffer($fp, RANDOM_COMPAT_READ_BUFFER); - } - if (is_callable('stream_set_chunk_size')) { - stream_set_chunk_size($fp, RANDOM_COMPAT_READ_BUFFER); - } - } - } - - try { - /** @var int $bytes */ - $bytes = RandomCompat_intval($bytes); - } catch (TypeError $ex) { - throw new TypeError( - 'random_bytes(): $bytes must be an integer' - ); - } - - if ($bytes < 1) { - throw new Error( - 'Length must be greater than 0' - ); - } - - /** - * This if() block only runs if we managed to open a file handle - * - * It does not belong in an else {} block, because the above - * if (empty($fp)) line is logic that should only be run once per - * page load. - */ - if (is_resource($fp)) { - /** - * @var int - */ - $remaining = $bytes; - - /** - * @var string|bool - */ - $buf = ''; - - /** - * We use fread() in a loop to protect against partial reads - */ - do { - /** - * @var string|bool - */ - $read = fread($fp, $remaining); - if (!is_string($read)) { - /** - * We cannot safely read from the file. Exit the - * do-while loop and trigger the exception condition - * - * @var string|bool - */ - $buf = false; - break; - } - /** - * Decrease the number of bytes returned from remaining - */ - $remaining -= RandomCompat_strlen($read); - /** - * @var string $buf - */ - $buf .= $read; - } while ($remaining > 0); - - /** - * Is our result valid? - * @var string|bool $buf - */ - if (is_string($buf)) { - if (RandomCompat_strlen($buf) === $bytes) { - /** - * Return our random entropy buffer here: - */ - return $buf; - } - } - } - - /** - * If we reach here, PHP has failed us. - */ - throw new Exception( - 'Error reading from source device' - ); - } -} diff --git a/wp-includes/random_compat/random_bytes_libsodium.php b/wp-includes/random_compat/random_bytes_libsodium.php deleted file mode 100644 index 2e56290182..0000000000 --- a/wp-includes/random_compat/random_bytes_libsodium.php +++ /dev/null @@ -1,91 +0,0 @@ - 2147483647) { - $buf = ''; - for ($i = 0; $i < $bytes; $i += 1073741824) { - $n = ($bytes - $i) > 1073741824 - ? 1073741824 - : $bytes - $i; - $buf .= \Sodium\randombytes_buf($n); - } - } else { - /** @var string|bool $buf */ - $buf = \Sodium\randombytes_buf($bytes); - } - - if (is_string($buf)) { - if (RandomCompat_strlen($buf) === $bytes) { - return $buf; - } - } - - /** - * If we reach here, PHP has failed us. - */ - throw new Exception( - 'Could not gather sufficient random data' - ); - } -} diff --git a/wp-includes/random_compat/random_bytes_libsodium_legacy.php b/wp-includes/random_compat/random_bytes_libsodium_legacy.php deleted file mode 100644 index f78b2199a2..0000000000 --- a/wp-includes/random_compat/random_bytes_libsodium_legacy.php +++ /dev/null @@ -1,93 +0,0 @@ - 2147483647) { - for ($i = 0; $i < $bytes; $i += 1073741824) { - $n = ($bytes - $i) > 1073741824 - ? 1073741824 - : $bytes - $i; - $buf .= Sodium::randombytes_buf((int) $n); - } - } else { - $buf .= Sodium::randombytes_buf((int) $bytes); - } - - if (is_string($buf)) { - if (RandomCompat_strlen($buf) === $bytes) { - return $buf; - } - } - - /** - * If we reach here, PHP has failed us. - */ - throw new Exception( - 'Could not gather sufficient random data' - ); - } -} diff --git a/wp-includes/random_compat/random_bytes_mcrypt.php b/wp-includes/random_compat/random_bytes_mcrypt.php deleted file mode 100644 index 0b13fa73c5..0000000000 --- a/wp-includes/random_compat/random_bytes_mcrypt.php +++ /dev/null @@ -1,79 +0,0 @@ - operators might accidentally let a float - * through. - */ - - try { - /** @var int $min */ - $min = RandomCompat_intval($min); - } catch (TypeError $ex) { - throw new TypeError( - 'random_int(): $min must be an integer' - ); - } - - try { - /** @var int $max */ - $max = RandomCompat_intval($max); - } catch (TypeError $ex) { - throw new TypeError( - 'random_int(): $max must be an integer' - ); - } - - /** - * Now that we've verified our weak typing system has given us an integer, - * let's validate the logic then we can move forward with generating random - * integers along a given range. - */ - if ($min > $max) { - throw new Error( - 'Minimum value must be less than or equal to the maximum value' - ); - } - - if ($max === $min) { - return (int) $min; - } - - /** - * Initialize variables to 0 - * - * We want to store: - * $bytes => the number of random bytes we need - * $mask => an integer bitmask (for use with the &) operator - * so we can minimize the number of discards - */ - $attempts = $bits = $bytes = $mask = $valueShift = 0; - /** @var int $attempts */ - /** @var int $bits */ - /** @var int $bytes */ - /** @var int $mask */ - /** @var int $valueShift */ - - /** - * At this point, $range is a positive number greater than 0. It might - * overflow, however, if $max - $min > PHP_INT_MAX. PHP will cast it to - * a float and we will lose some precision. - * - * @var int|float $range - */ - $range = $max - $min; - - /** - * Test for integer overflow: - */ - if (!is_int($range)) { - - /** - * Still safely calculate wider ranges. - * Provided by @CodesInChaos, @oittaa - * - * @ref https://gist.github.com/CodesInChaos/03f9ea0b58e8b2b8d435 - * - * We use ~0 as a mask in this case because it generates all 1s - * - * @ref https://eval.in/400356 (32-bit) - * @ref http://3v4l.org/XX9r5 (64-bit) - */ - $bytes = PHP_INT_SIZE; - /** @var int $mask */ - $mask = ~0; - - } else { - - /** - * $bits is effectively ceil(log($range, 2)) without dealing with - * type juggling - */ - while ($range > 0) { - if ($bits % 8 === 0) { - ++$bytes; - } - ++$bits; - $range >>= 1; - /** @var int $mask */ - $mask = $mask << 1 | 1; - } - $valueShift = $min; - } - - /** @var int $val */ - $val = 0; - /** - * Now that we have our parameters set up, let's begin generating - * random integers until one falls between $min and $max - */ - /** @psalm-suppress RedundantCondition */ - do { - /** - * The rejection probability is at most 0.5, so this corresponds - * to a failure probability of 2^-128 for a working RNG - */ - if ($attempts > 128) { - throw new Exception( - 'random_int: RNG is broken - too many rejections' - ); - } - - /** - * Let's grab the necessary number of random bytes - */ - $randomByteString = random_bytes($bytes); - - /** - * Let's turn $randomByteString into an integer - * - * This uses bitwise operators (<< and |) to build an integer - * out of the values extracted from ord() - * - * Example: [9F] | [6D] | [32] | [0C] => - * 159 + 27904 + 3276800 + 201326592 => - * 204631455 - */ - $val &= 0; - for ($i = 0; $i < $bytes; ++$i) { - $val |= ord($randomByteString[$i]) << ($i * 8); - } - /** @var int $val */ - - /** - * Apply mask - */ - $val &= $mask; - $val += $valueShift; - - ++$attempts; - /** - * If $val overflows to a floating point number, - * ... or is larger than $max, - * ... or smaller than $min, - * then try again. - */ - } while (!is_int($val) || $val > $max || $val < $min); - - return (int) $val; - } -} diff --git a/wp-includes/version.php b/wp-includes/version.php index 56aa7763fb..2560c7180a 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -16,7 +16,7 @@ * * @global string $wp_version */ -$wp_version = '6.3-beta3-56140'; +$wp_version = '6.3-beta3-56141'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema. @@ -37,7 +37,7 @@ $tinymce_version = '49110-20201110'; * * @global string $required_php_version */ -$required_php_version = '5.6.20'; +$required_php_version = '7.0.0'; /** * Holds the required MySQL version.