CVE-2021-3689 (published 2021-08-10T11:15Z)

yii2 is vulnerable to Use of Predictable Algorithm in Random Number Generator

Severity: MEDIUM
CVSS v2 base score: 5.0 (AV:N/AC:L/Au:N/C:N/I:P/A:N)
CVSS v3 base score: 7.5, HIGH (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N)

Weakness information:
cwe_id: CWE-330
cwe_name: Use of Insufficiently Random Values
description: The product uses insufficiently random numbers or values in a security context that depends on unpredictable numbers.
extended_description: When product generates predictable values in a context requiring unpredictability, it may be possible for an attacker to guess the next value that will be generated, and use this guess to impersonate another user or access sensitive information.
         

Fix information:
repo_url: https://github.com/yiisoft/yii2
commit_details: repo_url: https://github.com/yiisoft/yii2
author: Alexander Makarov
author_date: 2021-08-09 10:25:36+03:00
msg: Fix #18817: Use `paragonie/random_compat` for random bytes and int generation
repository: repo_url: https://github.com/yiisoft/yii2
repo_name: yiisoft/yii2
description: Yii 2: The Fast, Secure and Professional PHP Framework
repo_language: PHP
owner: yiisoft
file_changes: filename: composer.json
change_type: ModificationType.MODIFY
diff: @@ -78,7 +78,8 @@
         "bower-asset/jquery": "3.6.*@stable | 3.5.*@stable | 3.4.*@stable | 3.3.*@stable | 3.2.*@stable | 3.1.*@stable | 2.2.*@stable | 2.1.*@stable | 1.11.*@stable | 1.12.*@stable",
         "bower-asset/inputmask": "~3.2.2 | ~3.3.5",
         "bower-asset/punycode": "1.3.*",
-        "bower-asset/yii2-pjax": "~2.0.1"
+        "bower-asset/yii2-pjax": "~2.0.1",
+        "paragonie/random_compat": ">=1"
     },
     "require-dev": {
         "cweagans/composer-patches": "^1.7",

programming_language: Jupyter Notebook
filename: composer.lock
change_type: ModificationType.MODIFY
diff: @@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "7e41c6fc0175fd049e0e52c4e8b25e5c",
+    "content-hash": "8f9a4d7e645592f806605d32d676f54e",
     "packages": [
         {
             "name": "bower-asset/inputmask",
@@ -199,6 +199,60 @@
             },
             "time": "2020-06-29T00:56:53+00:00"
         },
+        {
+            "name": "paragonie/random_compat",
+            "version": "v2.0.20",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/paragonie/random_compat.git",
+                "reference": "0f1f60250fccffeaf5dda91eea1c018aed1adc2a"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/paragonie/random_compat/zipball/0f1f60250fccffeaf5dda91eea1c018aed1adc2a",
+                "reference": "0f1f60250fccffeaf5dda91eea1c018aed1adc2a",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.2.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "4.*|5.*"
+            },
+            "suggest": {
+                "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "lib/random.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Paragon Initiative Enterprises",
+                    "email": "security@paragonie.com",
+                    "homepage": "https://paragonie.com"
+                }
+            ],
+            "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
+            "keywords": [
+                "csprng",
+                "polyfill",
+                "pseudorandom",
+                "random"
+            ],
+            "support": {
+                "email": "info@paragonie.com",
+                "issues": "https://github.com/paragonie/random_compat/issues",
+                "source": "https://github.com/paragonie/random_compat"
+            },
+            "time": "2021-04-17T09:33:01+00:00"
+        },
         {
             "name": "yiisoft/yii2-composer",
             "version": "2.0.10",
@@ -891,60 +945,6 @@
             },
             "time": "2015-09-13T19:01:00+00:00"
         },
-        {
-            "name": "paragonie/random_compat",
-            "version": "v2.0.20",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/paragonie/random_compat.git",
-                "reference": "0f1f60250fccffeaf5dda91eea1c018aed1adc2a"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/paragonie/random_compat/zipball/0f1f60250fccffeaf5dda91eea1c018aed1adc2a",
-                "reference": "0f1f60250fccffeaf5dda91eea1c018aed1adc2a",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.2.0"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "4.*|5.*"
-            },
-            "suggest": {
-                "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
-            },
-            "type": "library",
-            "autoload": {
-                "files": [
-                    "lib/random.php"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Paragon Initiative Enterprises",
-                    "email": "security@paragonie.com",
-                    "homepage": "https://paragonie.com"
-                }
-            ],
-            "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
-            "keywords": [
-                "csprng",
-                "polyfill",
-                "pseudorandom",
-                "random"
-            ],
-            "support": {
-                "email": "info@paragonie.com",
-                "issues": "https://github.com/paragonie/random_compat/issues",
-                "source": "https://github.com/paragonie/random_compat"
-            },
-            "time": "2021-04-17T09:33:01+00:00"
-        },
         {
             "name": "phpdocumentor/reflection-docblock",
             "version": "2.0.5",
@@ -2919,5 +2919,5 @@
     "platform-overrides": {
         "php": "5.4"
     },
-    "plugin-api-version": "2.0.0"
+    "plugin-api-version": "2.1.0"
 }

programming_language: Jupyter Notebook
filename: CHANGELOG.md
change_type: ModificationType.MODIFY
diff: @@ -4,6 +4,7 @@ Yii Framework 2 Change Log
 2.0.43 under development
 ------------------------
 
+- Enh #18817: Use `paragonie/random_compat` for random bytes and int generation (samdark)
 - Bug #14663: Do not convert int to string if database type of a column is numeric (egorrishe)
 - Bug #18650: Refactor `framework/assets/yii.activeForm.js` arrow function into traditional function for IE11 compatibility (marcovtwout)
 - Bug #18749: Fix `yii\web\ErrorHandler::encodeHtml()` to support strings with invalid UTF symbols (vjik)

programming_language: Markdown
filename: Security.php
change_type: ModificationType.MODIFY
diff: @@ -116,14 +116,6 @@ class Security extends Component
         return $this->_useLibreSSL;
     }
 
-    /**
-     * @return bool if operating system is Windows
-     */
-    private function isWindows()
-    {
-        return DIRECTORY_SEPARATOR !== '/';
-    }
-
     /**
      * Encrypts data using a password.
      * Derives keys for encryption and authentication from the password using PBKDF2 and a random salt,
@@ -471,8 +463,6 @@ class Security extends Component
         return false;
     }
 
-    private $_randomFile;
-
     /**
      * Generates specified number of random bytes.
      * Note that output may not be ASCII.
@@ -493,84 +483,7 @@ class Security extends Component
             throw new InvalidArgumentException('First parameter ($length) must be greater than 0');
         }
 
-        // always use random_bytes() if it is available
-        if (function_exists('random_bytes')) {
-            return random_bytes($length);
-        }
-
-        // The recent LibreSSL RNGs are faster and likely better than /dev/urandom.
-        // Since 5.4.0, openssl_random_pseudo_bytes() reads from CryptGenRandom on Windows instead
-        // of using OpenSSL library. LibreSSL is OK everywhere but don't use OpenSSL on non-Windows.
-        if (function_exists('openssl_random_pseudo_bytes')
-            && ($this->shouldUseLibreSSL() || $this->isWindows())
-        ) {
-            $key = openssl_random_pseudo_bytes($length, $cryptoStrong);
-            if ($cryptoStrong === false) {
-                throw new Exception(
-                    'openssl_random_pseudo_bytes() set $crypto_strong false. Your PHP setup is insecure.'
-                );
-            }
-            if ($key !== false && StringHelper::byteLength($key) === $length) {
-                return $key;
-            }
-        }
-
-        // mcrypt_create_iv() does not use libmcrypt. Since PHP 5.3.7 it directly reads
-        // CryptGenRandom on Windows. Elsewhere it directly reads /dev/urandom.
-        if (function_exists('mcrypt_create_iv')) {
-            $key = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
-            if (StringHelper::byteLength($key) === $length) {
-                return $key;
-            }
-        }
-
-        // If not on Windows, try to open a random device.
-        if ($this->_randomFile === null && !$this->isWindows()) {
-            // urandom is a symlink to random on FreeBSD.
-            $device = PHP_OS === 'FreeBSD' ? '/dev/random' : '/dev/urandom';
-            // Check random device for special character device protection mode. Use lstat()
-            // instead of stat() in case an attacker arranges a symlink to a fake device.
-            $lstat = @lstat($device);
-            if ($lstat !== false && ($lstat['mode'] & 0170000) === 020000) {
-                $this->_randomFile = fopen($device, 'rb') ?: null;
-
-                if (is_resource($this->_randomFile)) {
-                    // Reduce PHP stream buffer from default 8192 bytes to optimize data
-                    // transfer from the random device for smaller values of $length.
-                    // This also helps to keep future randoms out of user memory space.
-                    $bufferSize = 8;
-
-                    if (function_exists('stream_set_read_buffer')) {
-                        stream_set_read_buffer($this->_randomFile, $bufferSize);
-                    }
-                    // stream_set_read_buffer() isn't implemented on HHVM
-                    if (function_exists('stream_set_chunk_size')) {
-                        stream_set_chunk_size($this->_randomFile, $bufferSize);
-                    }
-                }
-            }
-        }
-
-        if (is_resource($this->_randomFile)) {
-            $buffer = '';
-            $stillNeed = $length;
-            while ($stillNeed > 0) {
-                $someBytes = fread($this->_randomFile, $stillNeed);
-                if ($someBytes === false) {
-                    break;
-                }
-                $buffer .= $someBytes;
-                $stillNeed -= StringHelper::byteLength($someBytes);
-                if ($stillNeed === 0) {
-                    // Leaving file pointer open in order to make next generation faster by reusing it.
-                    return $buffer;
-                }
-            }
-            fclose($this->_randomFile);
-            $this->_randomFile = null;
-        }
-
-        throw new Exception('Unable to generate a random key');
+        return random_bytes($length);
     }
 
     /**

programming_language: PHP
filename: DbCache.php
change_type: ModificationType.MODIFY
diff: @@ -276,7 +276,8 @@ class DbCache extends Cache
      */
     public function gc($force = false)
     {
-        if ($force || mt_rand(0, 1000000) < $this->gcProbability) {
+
+        if ($force || random_int(0, 1000000) < $this->gcProbability) {
             $this->db->createCommand()
                 ->delete($this->cacheTable, '[[expire]] > 0 AND [[expire]] < ' . time())
                 ->execute();

programming_language: PHP
filename: FileCache.php
change_type: ModificationType.MODIFY
diff: @@ -245,7 +245,7 @@ class FileCache extends Cache
      */
     public function gc($force = false, $expiredOnly = true)
     {
-        if ($force || mt_rand(0, 1000000) < $this->gcProbability) {
+        if ($force || random_int(0, 1000000) < $this->gcProbability) {
             $this->gcRecursive($this->cachePath, $expiredOnly);
         }
     }

programming_language: PHP
filename: CaptchaAction.php
change_type: ModificationType.MODIFY
diff: @@ -214,16 +214,17 @@ class CaptchaAction extends Action
         if ($this->maxLength > 20) {
             $this->maxLength = 20;
         }
-        $length = mt_rand($this->minLength, $this->maxLength);
+
+        $length = random_int($this->minLength, $this->maxLength);
 
         $letters = 'bcdfghjklmnpqrstvwxyz';
         $vowels = 'aeiou';
         $code = '';
         for ($i = 0; $i < $length; ++$i) {
-            if ($i % 2 && mt_rand(0, 10) > 2 || !($i % 2) && mt_rand(0, 10) > 9) {
-                $code .= $vowels[mt_rand(0, 4)];
+            if ($i % 2 && random_int(0, 10) > 2 || !($i % 2) && random_int(0, 10) > 9) {
+                $code .= $vowels[random_int(0, 4)];
             } else {
-                $code .= $letters[mt_rand(0, 20)];
+                $code .= $letters[random_int(0, 20)];
             }
         }
 
@@ -298,8 +299,8 @@ class CaptchaAction extends Action
         $x = 10;
         $y = round($this->height * 27 / 40);
         for ($i = 0; $i < $length; ++$i) {
-            $fontSize = (int) (mt_rand(26, 32) * $scale * 0.8);
-            $angle = mt_rand(-10, 10);
+            $fontSize = (int) (random_int(26, 32) * $scale * 0.8);
+            $angle = random_int(-10, 10);
             $letter = $code[$i];
             $box = imagettftext($image, $fontSize, $angle, $x, $y, $foreColor, $this->fontFile, $letter);
             $x = $box[2] + $this->offset;
@@ -341,9 +342,9 @@ class CaptchaAction extends Action
         for ($i = 0; $i < $length; ++$i) {
             $draw = new \ImagickDraw();
             $draw->setFont($this->fontFile);
-            $draw->setFontSize((int) (mt_rand(26, 32) * $scale * 0.8));
+            $draw->setFontSize((int) (random_int(26, 32) * $scale * 0.8));
             $draw->setFillColor($foreColor);
-            $image->annotateImage($draw, $x, $y, mt_rand(-10, 10), $code[$i]);
+            $image->annotateImage($draw, $x, $y, random_int(-10, 10), $code[$i]);
             $fontMetrics = $image->queryFontMetrics($draw, $code[$i]);
             $x += (int) $fontMetrics['textWidth'] + $this->offset;
         }

programming_language: PHP
filename: composer.json
change_type: ModificationType.MODIFY
diff: @@ -73,7 +73,8 @@
         "bower-asset/jquery": "3.6.*@stable | 3.5.*@stable | 3.4.*@stable | 3.3.*@stable | 3.2.*@stable | 3.1.*@stable | 2.2.*@stable | 2.1.*@stable | 1.11.*@stable | 1.12.*@stable",
         "bower-asset/inputmask": "~3.2.2 | ~3.3.5",
         "bower-asset/punycode": "1.3.*",
-        "bower-asset/yii2-pjax": "~2.0.1"
+        "bower-asset/yii2-pjax": "~2.0.1",
+        "paragonie/random_compat": ">=1"
     },
     "autoload": {
         "psr-4": {"yii\\": ""}

programming_language: TypeScript
filename: BaseMailer.php
change_type: ModificationType.MODIFY
diff: @@ -343,7 +343,7 @@ abstract class BaseMailer extends Component implements MailerInterface, ViewCont
     {
         $time = microtime(true);
 
-        return date('Ymd-His-', $time) . sprintf('%04d', (int) (($time - (int) $time) * 10000)) . '-' . sprintf('%04d', mt_rand(0, 10000)) . '.eml';
+        return date('Ymd-His-', $time) . sprintf('%04d', (int) (($time - (int) $time) * 10000)) . '-' . sprintf('%04d', random_int(0, 10000)) . '.eml';
     }
 
     /**

programming_language: PHP
filename: SecurityTest.php
change_type: ModificationType.MODIFY
diff: @@ -5,53 +5,7 @@
  * @license http://www.yiiframework.com/license/
  */
 
-namespace yii\base {
-
-    /**
-     * emulate availability of functions, to test different branches of Security class
-     * where different execution paths are chosen based on calling function_exists.
-     *
-     * This function overrides function_exists from the root namespace in yii\base.
-     * @param string $name
-     */
-    function function_exists($name)
-    {
-        if (isset(\yiiunit\framework\base\SecurityTest::$functions[$name])) {
-            return \yiiunit\framework\base\SecurityTest::$functions[$name];
-        }
-
-        return \function_exists($name);
-    }
-    /**
-     * Emulate chunked reading of fread(), to test different branches of Security class
-     * where different execution paths are chosen based on the return value of fopen/fread.
-     *
-     * This function overrides fopen and fread from the root namespace in yii\base.
-     * @param string $filename
-     * @param mixed $mode
-     */
-    function fopen($filename, $mode)
-    {
-        if (\yiiunit\framework\base\SecurityTest::$fopen !== null) {
-            return \yiiunit\framework\base\SecurityTest::$fopen;
-        }
-
-        return \fopen($filename, $mode);
-    }
-    function fread($handle, $length)
-    {
-        if (\yiiunit\framework\base\SecurityTest::$fread !== null) {
-            return \yiiunit\framework\base\SecurityTest::$fread;
-        }
-        if (\yiiunit\framework\base\SecurityTest::$fopen !== null) {
-            return $length < 8 ? \str_repeat('s', $length) : 'test1234';
-        }
-
-        return \fread($handle, $length);
-    }
-} // closing namespace yii\base;
-
-namespace yiiunit\framework\base {
+namespace yiiunit\framework\base;
 
 use yii\base\Security;
 use yiiunit\TestCase;
@@ -63,16 +17,6 @@ class SecurityTest extends TestCase
 {
     const CRYPT_VECTORS = 'old';
 
-    /**
-     * @var array set of functions for which a fake return value for `function_exists()` is provided.
-     */
-    public static $functions = [];
-    /**
-     * @var resource|false|null fake return value for fopen() in \yii\base namespace. Normal behavior if this is null.
-     */
-    public static $fopen;
-    public static $fread;
-
     /**
      * @var ExposedSecurity
      */
@@ -80,27 +24,11 @@ class SecurityTest extends TestCase
 
     protected function setUp()
     {
-        static::$functions = [];
-        static::$fopen = null;
-        static::$fread = null;
         parent::setUp();
         $this->security = new ExposedSecurity();
         $this->security->derivationIterations = 1000; // speed up test running
     }
 
-    protected function tearDown()
-    {
-        static::$functions = [];
-        static::$fopen = null;
-        static::$fread = null;
-        parent::tearDown();
-    }
-
-    private function isWindows()
-    {
-        return DIRECTORY_SEPARATOR !== '/';
-    }
-
     // Tests :
 
     public function testHashData()
@@ -893,76 +821,8 @@ TEXT;
         $key1 = $this->security->generateRandomKey($input);
     }
 
-    /**
-     * Test the case where opening /dev/urandom fails.
-     */
-    public function testRandomKeyNoOptions()
-    {
-        static::$functions = ['random_bytes' => false, 'openssl_random_pseudo_bytes' => false, 'mcrypt_create_iv' => false];
-        static::$fopen = false;
-        $this->expectException('yii\base\Exception');
-        $this->expectExceptionMessage('Unable to generate a random key');
-
-        $this->security->generateRandomKey(42);
-    }
-
-    /**
-     * Test the case where reading from /dev/urandom fails.
-     */
-    public function testRandomKeyFreadFailure()
-    {
-        static::$functions = ['random_bytes' => false, 'openssl_random_pseudo_bytes' => false, 'mcrypt_create_iv' => false];
-        static::$fread = false;
-        $this->expectException('yii\base\Exception');
-        $this->expectExceptionMessage('Unable to generate a random key');
-
-        $this->security->generateRandomKey(42);
-    }
-
-    /**
-     * returns a set of different combinations of functions available.
-     */
-    public function randomKeyVariants()
+    public function testGenerateRandomKey()
     {
-        return [
-            [['random_bytes' => true,  'openssl_random_pseudo_bytes' => true,  'mcrypt_create_iv' => true]],
-            [['random_bytes' => true,  'openssl_random_pseudo_bytes' => true,  'mcrypt_create_iv' => false]],
-            [['random_bytes' => true,  'openssl_random_pseudo_bytes' => false, 'mcrypt_create_iv' => true]],
-            [['random_bytes' => true,  'openssl_random_pseudo_bytes' => false, 'mcrypt_create_iv' => false]],
-            [['random_bytes' => false, 'openssl_random_pseudo_bytes' => true,  'mcrypt_create_iv' => true]],
-            [['random_bytes' => false, 'openssl_random_pseudo_bytes' => true,  'mcrypt_create_iv' => false]],
-            [['random_bytes' => false, 'openssl_random_pseudo_bytes' => false, 'mcrypt_create_iv' => true]],
-            [['random_bytes' => false, 'openssl_random_pseudo_bytes' => false, 'mcrypt_create_iv' => false]],
-        ];
-    }
-
-    /**
-     * @dataProvider randomKeyVariants
-     * @param array $functions
-     */
-    public function testGenerateRandomKey($functions)
-    {
-        foreach ($functions as $fun => $available) {
-            if ($available && !\function_exists($fun)) {
-                $this->markTestSkipped("Can not test generateRandomKey() branch that includes $fun, because it is not available on your system.");
-            }
-        }
-        // there is no /dev/urandom on windows so we expect this to fail
-        if ($this->isWindows() && $functions['random_bytes'] === false && $functions['openssl_random_pseudo_bytes'] === false && $functions['mcrypt_create_iv'] === false) {
-            $this->expectException('yii\base\Exception');
-            $this->expectExceptionMessage('Unable to generate a random key');
-        }
-        // Function mcrypt_create_iv() is deprecated since PHP 7.1
-        if (version_compare(PHP_VERSION, '7.1.0alpha', '>=') && $functions['random_bytes'] === false && $functions['mcrypt_create_iv'] === true) {
-            if ($functions['openssl_random_pseudo_bytes'] === false) {
-                $this->markTestSkipped('Function mcrypt_create_iv() is deprecated as of PHP 7.1');
-            } elseif (!$this->security->shouldUseLibreSSL() && !$this->isWindows()) {
-                $this->markTestSkipped('Function openssl_random_pseudo_bytes need LibreSSL version >=2.1.5 or Windows system on server');
-            }
-        }
-
-        static::$functions = $functions;
-
         // test various string lengths
         for ($length = 1; $length < 64; $length++) {
             $key1 = $this->security->generateRandomKey($length);
@@ -985,16 +845,6 @@ TEXT;
         $this->assertInternalType('string', $key2);
         $this->assertEquals($length, strlen($key2));
         $this->assertNotEquals($key1, $key2);
-
-        // force /dev/urandom reading loop to deal with chunked data
-        // the above test may have read everything in one run.
-        // not sure if this can happen in real life but if it does
-        // we should be prepared
-        static::$fopen = fopen('php://memory', 'rwb');
-        $length = 1024 * 1024;
-        $key1 = $this->security->generateRandomKey($length);
-        $this->assertInternalType('string', $key1);
-        $this->assertEquals($length, strlen($key1));
     }
 
     protected function randTime(Security $security, $count, $length, $message)
@@ -1010,42 +860,6 @@ TEXT;
         fwrite(STDERR, "$message: $count x $length B = $nbytes B in $milisec ms => $rate MB/s\n");
     }
 
-    public function testGenerateRandomKeySpeed()
-    {
-        self::markTestSkipped('Comment markTestSkipped in testGenerateRandomKeySpeed() in order to get RNG benchmark.');
-        $tests = [
-            "function_exists('random_bytes')",
-            "defined('OPENSSL_VERSION_TEXT') ? OPENSSL_VERSION_TEXT : null",
-            'PHP_VERSION_ID',
-            'PHP_OS',
-            "function_exists('mcrypt_create_iv') ? bin2hex(mcrypt_create_iv(4, MCRYPT_DEV_URANDOM)) : null",
-            'DIRECTORY_SEPARATOR',
-            "ini_get('open_basedir')",
-        ];
-        if ($this->isWindows()) {
-            $tests[] = "sprintf('%o', lstat(PHP_OS === 'FreeBSD' ? '/dev/random' : '/dev/urandom')['mode'] & 0170000)";
-            $tests[] = "bin2hex(file_get_contents(PHP_OS === 'FreeBSD' ? '/dev/random' : '/dev/urandom', false, null, 0, 8))";
-        }
-        foreach ($tests as $i => $test) {
-            $result = eval('return ' . $test . ';');
-            fwrite(STDERR, sprintf("%2d %s ==> %s\n", $i + 1, $test, var_export($result, true)));
-        }
-
-        foreach ([16, 2000, 262144] as $block) {
-            $security = new Security();
-            foreach (range(1, 10) as $nth) {
-                $this->randTime($security, 1, $block, "Call $nth");
-            }
-            unset($security);
-        }
-
-        $security = new Security();
-        $this->randTime($security, 10000, 16, 'Rate test');
-
-        $security = new Security();
-        $this->randTime($security, 10000, 5000, 'Rate test');
-    }
-
     public function testGenerateRandomString()
     {
         $length = 21;
@@ -1305,4 +1119,3 @@ TEXT;
         ];
     }
 }
-} // closing namespace yiiunit\framework\base;

programming_language: PHP
filename: FileValidatorTest.php
change_type: ModificationType.MODIFY
diff: @@ -324,7 +324,7 @@ class FileValidatorTest extends TestCase
             $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
             $randomString = '';
             for ($i = 0; $i < $len; $i++) {
-                $randomString .= $characters[rand(0, strlen($characters) - 1)];
+                $randomString .= $characters[random_int(0, strlen($characters) - 1)];
             }
 
             return $randomString;
@@ -340,7 +340,7 @@ class FileValidatorTest extends TestCase
             if (is_readable($tempName)) {
                 $size = filesize($tempName);
             } else {
-                $size = isset($param['size']) ? $param['size'] : rand(
+                $size = isset($param['size']) ? $param['size'] : random_int(
                     1,
                     $this->sizeToBytes(ini_get('upload_max_filesize'))
                 );

programming_language: PHP
filename: UploadedFileTest.php
change_type: ModificationType.MODIFY
diff: @@ -7,6 +7,7 @@
 
 namespace yiiunit\framework\web;
 
+use Yii;
 use yii\web\UploadedFile;
 use yiiunit\framework\web\mocks\UploadedFileMock;
 use yiiunit\framework\web\stubs\ModelStub;
@@ -28,10 +29,10 @@ class UploadedFileTest extends TestCase
     private function generateFakeFileData()
     {
         return [
-            'name' => md5(mt_rand()),
-            'tmp_name' => md5(mt_rand()),
+            'name' => md5(random_int(0, PHP_INT_MAX)),
+            'tmp_name' => md5(random_int(0, PHP_INT_MAX)),
             'type' => 'image/jpeg',
-            'size' => mt_rand(1000, 10000),
+            'size' => random_int(1000, 10000),
             'error' => '0',
         ];
     }
@@ -39,10 +40,10 @@ class UploadedFileTest extends TestCase
     private function generateTempFileData()
     {
         return [
-            'name' => md5(mt_rand()),
+            'name' => md5(random_int(0, PHP_INT_MAX)),
             'tmp_name' => tempnam(sys_get_temp_dir(), ''),
             'type' => 'image/jpeg',
-            'size' => mt_rand(1000, 10000),
+            'size' => random_int(1000, 10000),
             'error' => '0',
         ];
     }

programming_language: PHP