From 67475a943f05977d76b32da68761d18f0aa82aa9 Mon Sep 17 00:00:00 2001 From: Dominik Schilling Date: Tue, 8 Mar 2016 17:15:27 +0000 Subject: [PATCH] Update Random_Compat from 1.1.6 to 1.2.1. Changes: https://github.com/paragonie/random_compat/compare/1.1.6...v1.2.1 See #35665. Built from https://develop.svn.wordpress.org/trunk@36886 git-svn-id: http://core.svn.wordpress.org/trunk@36853 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- .../random_compat/byte_safe_strings.php | 15 ++- wp-includes/random_compat/cast_to_int.php | 15 ++- wp-includes/random_compat/random.php | 96 +++++++++++++------ .../random_compat/random_bytes_com_dotnet.php | 4 + .../random_bytes_dev_urandom.php | 6 ++ .../random_compat/random_bytes_libsodium.php | 2 + .../random_bytes_libsodium_legacy.php | 2 + .../random_compat/random_bytes_mcrypt.php | 18 ++-- .../random_compat/random_bytes_openssl.php | 17 +++- wp-includes/random_compat/random_int.php | 6 ++ wp-includes/version.php | 2 +- 11 files changed, 135 insertions(+), 48 deletions(-) diff --git a/wp-includes/random_compat/byte_safe_strings.php b/wp-includes/random_compat/byte_safe_strings.php index a3cc90b146..ae3b7b9e6d 100644 --- a/wp-includes/random_compat/byte_safe_strings.php +++ b/wp-includes/random_compat/byte_safe_strings.php @@ -50,8 +50,10 @@ if (!function_exists('RandomCompat_strlen')) { 'RandomCompat_strlen() expects a string' ); } + return mb_strlen($binary_string, '8bit'); } + } else { /** * strlen() implementation that isn't brittle to mbstring.func_overload @@ -77,8 +79,10 @@ if (!function_exists('RandomCompat_strlen')) { } if (!function_exists('RandomCompat_substr')) { + if ( - defined('MB_OVERLOAD_STRING') && + defined('MB_OVERLOAD_STRING') + && ini_get('mbstring.func_overload') & MB_OVERLOAD_STRING ) { /** @@ -102,11 +106,13 @@ if (!function_exists('RandomCompat_substr')) { '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) { /** * mb_substr($str, 0, NULL, '8bit') returns an empty string on @@ -118,9 +124,12 @@ if (!function_exists('RandomCompat_substr')) { 'RandomCompat_substr(): Third argument should be an integer, or omitted' ); } + return mb_substr($binary_string, $start, $length, '8bit'); } + } else { + /** * substr() implementation that isn't brittle to mbstring.func_overload * @@ -141,19 +150,23 @@ if (!function_exists('RandomCompat_substr')) { '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 substr($binary_string, $start, $length); } + return substr($binary_string, $start); } } diff --git a/wp-includes/random_compat/cast_to_int.php b/wp-includes/random_compat/cast_to_int.php index 474ce64008..f441c5d986 100644 --- a/wp-includes/random_compat/cast_to_int.php +++ b/wp-includes/random_compat/cast_to_int.php @@ -37,26 +37,33 @@ if (!function_exists('RandomCompat_intval')) { * lose precision, so the <= and => operators might accidentally let a float * through. * - * @param numeric $number The number we want to convert to an int - * @param boolean $fail_open Set to true to not throw an exception + * @param int|float $number The number we want to convert to an int + * @param boolean $fail_open Set to true to not throw an exception * * @return int (or float if $fail_open) + * + * @throws TypeError */ function RandomCompat_intval($number, $fail_open = false) { if (is_numeric($number)) { $number += 0; } + if ( - is_float($number) && - $number > ~PHP_INT_MAX && + is_float($number) + && + $number > ~PHP_INT_MAX + && $number < PHP_INT_MAX ) { $number = (int) $number; } + if (is_int($number) || $fail_open) { return $number; } + throw new TypeError( 'Expected an integer.' ); diff --git a/wp-includes/random_compat/random.php b/wp-includes/random_compat/random.php index 81ac0230ec..595115e5d9 100644 --- a/wp-includes/random_compat/random.php +++ b/wp-includes/random_compat/random.php @@ -1,22 +1,25 @@ GetRandom() * 5. openssl_random_pseudo_bytes() (absolute last resort) - * + * * See ERRATA.md for our reasoning behind this particular order */ if (extension_loaded('libsodium')) { @@ -64,6 +77,7 @@ if (PHP_VERSION_ID < 70000) { require_once $RandomCompatDIR.'/random_bytes_libsodium_legacy.php'; } } + /** * Reading directly from /dev/urandom: */ @@ -72,6 +86,7 @@ if (PHP_VERSION_ID < 70000) { // way to exclude Windows. $RandomCompatUrandom = true; $RandomCompat_basedir = ini_get('open_basedir'); + if (!empty($RandomCompat_basedir)) { $RandomCompat_open_basedir = explode( PATH_SEPARATOR, @@ -83,46 +98,61 @@ if (PHP_VERSION_ID < 70000) { ); $RandomCompat_open_basedir = null; } + if ( - !function_exists('random_bytes') && - $RandomCompatUrandom && + !function_exists('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 + // 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.'/random_bytes_dev_urandom.php'; } // Unset variables after use - $RandomCompatUrandom = null; $RandomCompat_basedir = null; + $RandomCompatUrandom = null; } - + /** * mcrypt_create_iv() */ if ( - !function_exists('random_bytes') && - PHP_VERSION_ID >= 50307 && + !function_exists('random_bytes') + && + PHP_VERSION_ID >= 50307 + && extension_loaded('mcrypt') ) { - // See random_bytes_mcrypt.php - require_once $RandomCompatDIR.'/random_bytes_mcrypt.php'; + // Prevent this code from hanging indefinitely on non-Windows; + // see https://bugs.php.net/bug.php?id=69833 + if ( + DIRECTORY_SEPARATOR !== '/' || + (PHP_VERSION_ID <= 50609 || PHP_VERSION_ID >= 50613) + ) { + // See random_bytes_mcrypt.php + require_once $RandomCompatDIR.'/random_bytes_mcrypt.php'; + } } + if ( - !function_exists('random_bytes') && - extension_loaded('com_dotnet') && + !function_exists('random_bytes') + && + extension_loaded('com_dotnet') + && class_exists('COM') ) { $RandomCompat_disabled_classes = preg_split( - '#\s*,\s*#', + '#\s*,\s*#', strtolower(ini_get('disable_classes')) ); - + if (!in_array('com', $RandomCompat_disabled_classes)) { try { $RandomCompatCOMtest = new COM('CAPICOM.Utilities.1'); @@ -137,27 +167,31 @@ if (PHP_VERSION_ID < 70000) { $RandomCompat_disabled_classes = null; $RandomCompatCOMtest = null; } - + /** * openssl_random_pseudo_bytes() */ if ( - !function_exists('random_bytes') && - extension_loaded('openssl') && ( // Unix-like with PHP >= 5.3.0 or ( - DIRECTORY_SEPARATOR === '/' && + DIRECTORY_SEPARATOR === '/' + && PHP_VERSION_ID >= 50300 - ) || + ) + || // Windows with PHP >= 5.4.1 PHP_VERSION_ID >= 50401 ) + && + !function_exists('random_bytes') + && + extension_loaded('openssl') ) { // See random_bytes_openssl.php require_once $RandomCompatDIR.'/random_bytes_openssl.php'; } - + /** * throw new Exception */ @@ -174,8 +208,10 @@ if (PHP_VERSION_ID < 70000) { } } } + if (!function_exists('random_int')) { require_once $RandomCompatDIR.'/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 index 0a781f4efa..3422825492 100644 --- a/wp-includes/random_compat/random_bytes_com_dotnet.php +++ b/wp-includes/random_compat/random_bytes_com_dotnet.php @@ -46,14 +46,17 @@ function random_bytes($bytes) 'random_bytes(): $bytes must be an integer' ); } + if ($bytes < 1) { throw new Error( 'Length must be greater than 0' ); } + $buf = ''; $util = new COM('CAPICOM.Utilities.1'); $execCount = 0; + /** * Let's not let it loop forever. If we run N times and fail to * get N bytes of random data, then CAPICOM has failed us. @@ -68,6 +71,7 @@ function random_bytes($bytes) } ++$execCount; } while ($execCount < $bytes); + /** * If we reach here, PHP has failed us. */ diff --git a/wp-includes/random_compat/random_bytes_dev_urandom.php b/wp-includes/random_compat/random_bytes_dev_urandom.php index 5d07104b3f..db93b07578 100644 --- a/wp-includes/random_compat/random_bytes_dev_urandom.php +++ b/wp-includes/random_compat/random_bytes_dev_urandom.php @@ -62,6 +62,7 @@ function random_bytes($bytes) $fp = false; } } + if (!empty($fp)) { /** * stream_set_read_buffer() does not exist in HHVM @@ -79,6 +80,7 @@ function random_bytes($bytes) } } } + try { $bytes = RandomCompat_intval($bytes); } catch (TypeError $ex) { @@ -86,11 +88,13 @@ function random_bytes($bytes) '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 * @@ -101,6 +105,7 @@ function random_bytes($bytes) if (!empty($fp)) { $remaining = $bytes; $buf = ''; + /** * We use fread() in a loop to protect against partial reads */ @@ -133,6 +138,7 @@ function random_bytes($bytes) } } } + /** * If we reach here, PHP has failed us. */ diff --git a/wp-includes/random_compat/random_bytes_libsodium.php b/wp-includes/random_compat/random_bytes_libsodium.php index 938cac9290..f802d4e124 100644 --- a/wp-includes/random_compat/random_bytes_libsodium.php +++ b/wp-includes/random_compat/random_bytes_libsodium.php @@ -48,11 +48,13 @@ function random_bytes($bytes) 'random_bytes(): $bytes must be an integer' ); } + if ($bytes < 1) { throw new Error( 'Length must be greater than 0' ); } + /** * \Sodium\randombytes_buf() doesn't allow more than 2147483647 bytes to be * generated in one invocation. diff --git a/wp-includes/random_compat/random_bytes_libsodium_legacy.php b/wp-includes/random_compat/random_bytes_libsodium_legacy.php index 4c76ff96d2..44fddbf6fc 100644 --- a/wp-includes/random_compat/random_bytes_libsodium_legacy.php +++ b/wp-includes/random_compat/random_bytes_libsodium_legacy.php @@ -48,11 +48,13 @@ function random_bytes($bytes) 'random_bytes(): $bytes must be an integer' ); } + if ($bytes < 1) { throw new Error( 'Length must be greater than 0' ); } + /** * \Sodium\randombytes_buf() doesn't allow more than 2147483647 bytes to be * generated in one invocation. diff --git a/wp-includes/random_compat/random_bytes_mcrypt.php b/wp-includes/random_compat/random_bytes_mcrypt.php index 5a1b688f60..7ac9d9105f 100644 --- a/wp-includes/random_compat/random_bytes_mcrypt.php +++ b/wp-includes/random_compat/random_bytes_mcrypt.php @@ -48,6 +48,7 @@ function random_bytes($bytes) 'random_bytes(): $bytes must be an integer' ); } + if ($bytes < 1) { throw new Error( 'Length must be greater than 0' @@ -55,14 +56,17 @@ function random_bytes($bytes) } $buf = @mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM); - if ($buf !== false) { - if (RandomCompat_strlen($buf) === $bytes) { - /** - * Return our random entropy buffer here: - */ - return $buf; - } + if ( + $buf !== false + && + RandomCompat_strlen($buf) === $bytes + ) { + /** + * Return our random entropy buffer here: + */ + return $buf; } + /** * If we reach here, PHP has failed us. */ diff --git a/wp-includes/random_compat/random_bytes_openssl.php b/wp-includes/random_compat/random_bytes_openssl.php index 3e12d3da59..62bf770352 100644 --- a/wp-includes/random_compat/random_bytes_openssl.php +++ b/wp-includes/random_compat/random_bytes_openssl.php @@ -48,12 +48,13 @@ function random_bytes($bytes) 'random_bytes(): $bytes must be an integer' ); } + if ($bytes < 1) { throw new Error( 'Length must be greater than 0' ); } - $secure = true; + /** * $secure is passed by reference. If it's set to false, fail. Note * that this will only return false if this function fails to return @@ -61,12 +62,18 @@ function random_bytes($bytes) * * @ref https://github.com/paragonie/random_compat/issues/6#issuecomment-119564973 */ + $secure = true; $buf = openssl_random_pseudo_bytes($bytes, $secure); - if ($buf !== false && $secure) { - if (RandomCompat_strlen($buf) === $bytes) { - return $buf; - } + if ( + $buf !== false + && + $secure + && + RandomCompat_strlen($buf) === $bytes + ) { + return $buf; } + /** * If we reach here, PHP has failed us. */ diff --git a/wp-includes/random_compat/random_int.php b/wp-includes/random_compat/random_int.php index 6c91dbc516..fd3ef87a22 100644 --- a/wp-includes/random_compat/random_int.php +++ b/wp-includes/random_compat/random_int.php @@ -55,6 +55,7 @@ function random_int($min, $max) 'random_int(): $min must be an integer' ); } + try { $max = RandomCompat_intval($max); } catch (TypeError $ex) { @@ -73,6 +74,7 @@ function random_int($min, $max) 'Minimum value must be less than or equal to the maximum value' ); } + if ($max === $min) { return $min; } @@ -98,6 +100,7 @@ function random_int($min, $max) * Test for integer overflow: */ if (!is_int($range)) { + /** * Still safely calculate wider ranges. * Provided by @CodesInChaos, @oittaa @@ -111,7 +114,9 @@ function random_int($min, $max) */ $bytes = PHP_INT_SIZE; $mask = ~0; + } else { + /** * $bits is effectively ceil(log($range, 2)) without dealing with * type juggling @@ -181,5 +186,6 @@ function random_int($min, $max) * 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 3217150ddd..08acf95d6e 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -4,7 +4,7 @@ * * @global string $wp_version */ -$wp_version = '4.5-beta2-36885'; +$wp_version = '4.5-beta2-36886'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.