WordPress.org

Make WordPress Core


Ignore:
Timestamp:
11/08/2017 11:47:04 AM (4 years ago)
Author:
dd32
Message:

External Libraries: Update Random_Compat from 1.2.1 to 2.0.11.

Notably this fixes PHP7 parse errors of the files and removes the OpenSSL functionality.
Full Changes: https://github.com/paragonie/random_compat/compare/v1.2.1...v2.0.11

Props jrdelarosa.
See #42439.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/random_compat/random_int.php

    r36886 r42130  
    11<?php
    2 /**
    3  * Random_* Compatibility Library
    4  * for using the new PHP 7 random_* API in PHP 5 projects
    5  *
    6  * The MIT License (MIT)
    7  *
    8  * Copyright (c) 2015 Paragon Initiative Enterprises
    9  *
    10  * Permission is hereby granted, free of charge, to any person obtaining a copy
    11  * of this software and associated documentation files (the "Software"), to deal
    12  * in the Software without restriction, including without limitation the rights
    13  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    14  * copies of the Software, and to permit persons to whom the Software is
    15  * furnished to do so, subject to the following conditions:
    16  *
    17  * The above copyright notice and this permission notice shall be included in
    18  * all copies or substantial portions of the Software.
    19  *
    20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    21  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    23  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    24  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    25  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    26  * SOFTWARE.
    27  */
    282
    29 /**
    30  * Fetch a random integer between $min and $max inclusive
    31  *
    32  * @param int $min
    33  * @param int $max
    34  *
    35  * @throws Exception
    36  *
    37  * @return int
    38  */
    39 function random_int($min, $max)
    40 {
     3if (!is_callable('random_int')) {
    414    /**
    42      * Type and input logic checks
    43      *
    44      * If you pass it a float in the range (~PHP_INT_MAX, PHP_INT_MAX)
    45      * (non-inclusive), it will sanely cast it to an int. If you it's equal to
    46      * ~PHP_INT_MAX or PHP_INT_MAX, we let it fail as not an integer. Floats
    47      * lose precision, so the <= and => operators might accidentally let a float
    48      * through.
     5     * Random_* Compatibility Library
     6     * for using the new PHP 7 random_* API in PHP 5 projects
     7     *
     8     * The MIT License (MIT)
     9     *
     10     * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises
     11     *
     12     * Permission is hereby granted, free of charge, to any person obtaining a copy
     13     * of this software and associated documentation files (the "Software"), to deal
     14     * in the Software without restriction, including without limitation the rights
     15     * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     16     * copies of the Software, and to permit persons to whom the Software is
     17     * furnished to do so, subject to the following conditions:
     18     *
     19     * The above copyright notice and this permission notice shall be included in
     20     * all copies or substantial portions of the Software.
     21     *
     22     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     23     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     24     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     25     * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     26     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     27     * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     28     * SOFTWARE.
    4929     */
    50    
    51     try {
    52         $min = RandomCompat_intval($min);
    53     } catch (TypeError $ex) {
    54         throw new TypeError(
    55             'random_int(): $min must be an integer'
    56         );
    57     }
    58 
    59     try {
    60         $max = RandomCompat_intval($max);
    61     } catch (TypeError $ex) {
    62         throw new TypeError(
    63             'random_int(): $max must be an integer'
    64         );
    65     }
    66    
    67     /**
    68      * Now that we've verified our weak typing system has given us an integer,
    69      * let's validate the logic then we can move forward with generating random
    70      * integers along a given range.
    71      */
    72     if ($min > $max) {
    73         throw new Error(
    74             'Minimum value must be less than or equal to the maximum value'
    75         );
    76     }
    77 
    78     if ($max === $min) {
    79         return $min;
    80     }
    8130
    8231    /**
    83      * Initialize variables to 0
    84      *
    85      * We want to store:
    86      * $bytes => the number of random bytes we need
    87      * $mask => an integer bitmask (for use with the &) operator
    88      *          so we can minimize the number of discards
     32     * Fetch a random integer between $min and $max inclusive
     33     *
     34     * @param int $min
     35     * @param int $max
     36     *
     37     * @throws Exception
     38     *
     39     * @return int
    8940     */
    90     $attempts = $bits = $bytes = $mask = $valueShift = 0;
     41    function random_int($min, $max)
     42    {
     43        /**
     44         * Type and input logic checks
     45         *
     46         * If you pass it a float in the range (~PHP_INT_MAX, PHP_INT_MAX)
     47         * (non-inclusive), it will sanely cast it to an int. If you it's equal to
     48         * ~PHP_INT_MAX or PHP_INT_MAX, we let it fail as not an integer. Floats
     49         * lose precision, so the <= and => operators might accidentally let a float
     50         * through.
     51         */
    9152
    92     /**
    93      * At this point, $range is a positive number greater than 0. It might
    94      * overflow, however, if $max - $min > PHP_INT_MAX. PHP will cast it to
    95      * a float and we will lose some precision.
    96      */
    97     $range = $max - $min;
     53        try {
     54            $min = RandomCompat_intval($min);
     55        } catch (TypeError $ex) {
     56            throw new TypeError(
     57                'random_int(): $min must be an integer'
     58            );
     59        }
    9860
    99     /**
    100      * Test for integer overflow:
    101      */
    102     if (!is_int($range)) {
    103 
    104         /**
    105          * Still safely calculate wider ranges.
    106          * Provided by @CodesInChaos, @oittaa
    107          *
    108          * @ref https://gist.github.com/CodesInChaos/03f9ea0b58e8b2b8d435
    109          *
    110          * We use ~0 as a mask in this case because it generates all 1s
    111          *
    112          * @ref https://eval.in/400356 (32-bit)
    113          * @ref http://3v4l.org/XX9r5  (64-bit)
    114          */
    115         $bytes = PHP_INT_SIZE;
    116         $mask = ~0;
    117 
    118     } else {
    119 
    120         /**
    121          * $bits is effectively ceil(log($range, 2)) without dealing with
    122          * type juggling
    123          */
    124         while ($range > 0) {
    125             if ($bits % 8 === 0) {
    126                ++$bytes;
    127             }
    128             ++$bits;
    129             $range >>= 1;
    130             $mask = $mask << 1 | 1;
    131         }
    132         $valueShift = $min;
    133     }
    134 
    135     /**
    136      * Now that we have our parameters set up, let's begin generating
    137      * random integers until one falls between $min and $max
    138      */
    139     do {
    140         /**
    141          * The rejection probability is at most 0.5, so this corresponds
    142          * to a failure probability of 2^-128 for a working RNG
    143          */
    144         if ($attempts > 128) {
    145             throw new Exception(
    146                 'random_int: RNG is broken - too many rejections'
     61        try {
     62            $max = RandomCompat_intval($max);
     63        } catch (TypeError $ex) {
     64            throw new TypeError(
     65                'random_int(): $max must be an integer'
    14766            );
    14867        }
    14968
    15069        /**
    151          * Let's grab the necessary number of random bytes
     70         * Now that we've verified our weak typing system has given us an integer,
     71         * let's validate the logic then we can move forward with generating random
     72         * integers along a given range.
    15273         */
    153         $randomByteString = random_bytes($bytes);
    154         if ($randomByteString === false) {
    155             throw new Exception(
    156                 'Random number generator failure'
     74        if ($min > $max) {
     75            throw new Error(
     76                'Minimum value must be less than or equal to the maximum value'
    15777            );
    15878        }
    15979
    160         /**
    161          * Let's turn $randomByteString into an integer
    162          *
    163          * This uses bitwise operators (<< and |) to build an integer
    164          * out of the values extracted from ord()
    165          *
    166          * Example: [9F] | [6D] | [32] | [0C] =>
    167          *   159 + 27904 + 3276800 + 201326592 =>
    168          *   204631455
    169          */
    170         $val = 0;
    171         for ($i = 0; $i < $bytes; ++$i) {
    172             $val |= ord($randomByteString[$i]) << ($i * 8);
     80        if ($max === $min) {
     81            return (int) $min;
    17382        }
    17483
    17584        /**
    176          * Apply mask
     85         * Initialize variables to 0
     86         *
     87         * We want to store:
     88         * $bytes => the number of random bytes we need
     89         * $mask => an integer bitmask (for use with the &) operator
     90         *          so we can minimize the number of discards
    17791         */
    178         $val &= $mask;
    179         $val += $valueShift;
     92        $attempts = $bits = $bytes = $mask = $valueShift = 0;
    18093
    181         ++$attempts;
    18294        /**
    183          * If $val overflows to a floating point number,
    184          * ... or is larger than $max,
    185          * ... or smaller than $min,
    186          * then try again.
     95         * At this point, $range is a positive number greater than 0. It might
     96         * overflow, however, if $max - $min > PHP_INT_MAX. PHP will cast it to
     97         * a float and we will lose some precision.
    18798         */
    188     } while (!is_int($val) || $val > $max || $val < $min);
     99        $range = $max - $min;
    189100
    190     return (int) $val;
     101        /**
     102         * Test for integer overflow:
     103         */
     104        if (!is_int($range)) {
     105
     106            /**
     107             * Still safely calculate wider ranges.
     108             * Provided by @CodesInChaos, @oittaa
     109             *
     110             * @ref https://gist.github.com/CodesInChaos/03f9ea0b58e8b2b8d435
     111             *
     112             * We use ~0 as a mask in this case because it generates all 1s
     113             *
     114             * @ref https://eval.in/400356 (32-bit)
     115             * @ref http://3v4l.org/XX9r5  (64-bit)
     116             */
     117            $bytes = PHP_INT_SIZE;
     118            $mask = ~0;
     119
     120        } else {
     121
     122            /**
     123             * $bits is effectively ceil(log($range, 2)) without dealing with
     124             * type juggling
     125             */
     126            while ($range > 0) {
     127                if ($bits % 8 === 0) {
     128                    ++$bytes;
     129                }
     130                ++$bits;
     131                $range >>= 1;
     132                $mask = $mask << 1 | 1;
     133            }
     134            $valueShift = $min;
     135        }
     136
     137        $val = 0;
     138        /**
     139         * Now that we have our parameters set up, let's begin generating
     140         * random integers until one falls between $min and $max
     141         */
     142        do {
     143            /**
     144             * The rejection probability is at most 0.5, so this corresponds
     145             * to a failure probability of 2^-128 for a working RNG
     146             */
     147            if ($attempts > 128) {
     148                throw new Exception(
     149                    'random_int: RNG is broken - too many rejections'
     150                );
     151            }
     152
     153            /**
     154             * Let's grab the necessary number of random bytes
     155             */
     156            $randomByteString = random_bytes($bytes);
     157
     158            /**
     159             * Let's turn $randomByteString into an integer
     160             *
     161             * This uses bitwise operators (<< and |) to build an integer
     162             * out of the values extracted from ord()
     163             *
     164             * Example: [9F] | [6D] | [32] | [0C] =>
     165             *   159 + 27904 + 3276800 + 201326592 =>
     166             *   204631455
     167             */
     168            $val &= 0;
     169            for ($i = 0; $i < $bytes; ++$i) {
     170                $val |= ord($randomByteString[$i]) << ($i * 8);
     171            }
     172
     173            /**
     174             * Apply mask
     175             */
     176            $val &= $mask;
     177            $val += $valueShift;
     178
     179            ++$attempts;
     180            /**
     181             * If $val overflows to a floating point number,
     182             * ... or is larger than $max,
     183             * ... or smaller than $min,
     184             * then try again.
     185             */
     186        } while (!is_int($val) || $val > $max || $val < $min);
     187
     188        return (int) $val;
     189    }
    191190}
Note: See TracChangeset for help on using the changeset viewer.