Issues (6)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/AbstractRand.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Savvot\Random;
4
5
/**
6
 * Abstract base class with basic methods
7
 *
8
 * @package Savvot\Random
9
 * @author  SavvoT <[email protected]>
10
 */
11
abstract class AbstractRand
12
{
13
    /**
14
     * Maximum possible value of randomInt() generator in derived class.
15
     * Must be overridden to correct value if different from default uint32
16
     */
17
    const INT_MAX = 0xFFFFFFFF;
18
19
    /**
20
     * Helper constants with common character lists for randomString() method
21
     */
22
    const CL_ALNUM = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
23
    const CL_NUM = '0123456789';
24
    const CL_ALUC = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
25
    const CL_ALLC = 'abcdefghijklmnopqrstuvwxyz';
26
    const CL_HEXUC = '0123456789ABCDEF';
27
    const CL_HEXLC = '0123456789abcdef';
28
29
    /**
30
     * @var string User specified seed used to initialize a PRNG
31
     */
32
    protected $seed;
33
    /**
34
     * @var string 128bit binary md5 hash from seed.
35
     *             Should be used as data source for PRNG initialization
36
     */
37
    protected $hashedSeed;
38
    /**
39
     * @var float Helper var = 1/INT_MAX
40
     */
41
    protected $intMaxDiv;
42
43
    /**
44
     * @var mixed Internal generator's state.
45
     *            Derived class must use it for storing current state of prng.
46
     *            Can be saved and sets back to "replay" random sequences
47
     */
48
    protected $state;
49
50
    /**
51
     * @var array State stack, used by pushState() and popState() methods
52
     */
53
    protected $stateStack = [];
54
55
    /**
56
     * @var GaussianSampler Normal distributed random numbers generator
57
     */
58
    protected $gaussianSampler;
59
60
    /**
61
     * Initializes random generator
62
     * Must be implemented by derived class
63
     */
64
    abstract protected function init();
65
66
    /**
67
     * Returns random unsigned integer. Int size depends on generator's algorithm.
68
     * Must be implemented by derived class
69
     *
70
     * @return int Random number
71
     */
72
    abstract public function randomInt();
73
74
    /**
75
     * Class constructor. Initializes generator from specified $seed string
76
     *
77
     * @param string $seed Seed to initialize generator's state. Defaults to null (auto)
78
     */
79
    public function __construct($seed = null)
80
    {
81
        $this->intMaxDiv = 1.0 / static::INT_MAX;
82
        $this->setSeed($seed);
83
    }
84
85
    /**
86
     * Sets new seed and initializes generator
87
     *
88
     * @param string|int $seed New seed for PRNG. If null is given, creates random seed from mt_rand
89
     */
90
    public function setSeed($seed = null)
91
    {
92
        $this->seed = $seed !== null ? $seed : mt_rand();
0 ignored issues
show
Documentation Bug introduced by
It seems like $seed !== null ? $seed : mt_rand() can also be of type integer. However, the property $seed is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
93
        $this->hashedSeed = md5($this->seed, true);
94
        $this->init();
95
    }
96
97
    /**
98
     * Returns seed used to initialize PRNG
99
     *
100
     * @return string Seed
101
     */
102
    public function getSeed()
103
    {
104
        return $this->seed;
105
    }
106
107
    /**
108
     * Sets PRNG state, previously saved by getState() function
109
     *
110
     * @param array $state State array with seed and internal generator's state
111
     * @throws RandException
112
     */
113
    public function setState(array $state)
114
    {
115
        if (!isset($state['class'], $state['seed'], $state['state'])) {
116
            throw new RandException('Invalid state');
117
        }
118
        if ($state['class'] !== static::class) {
119
            throw new RandException('This state is from different generator');
120
        }
121
122
        $this->setSeed($state['seed']);
123
        $this->state = $state['state'];
124
    }
125
126
    /**
127
     * Returns array with class name, seed and current internal state
128
     * This state can be used to save generator's state in custom position and "replay" rnd sequences
129
     *
130
     * @return array Information needed to restore generator to known state
131
     */
132
    public function getState()
133
    {
134
        return [
135
            'class' => static::class,
136
            'seed'  => $this->seed,
137
            'state' => $this->state
138
        ];
139
    }
140
141
    /**
142
     * Pushes current internal generator's state onto stack.
143
     */
144
    public function pushState()
145
    {
146
        $this->stateStack[] = $this->getState();
147
    }
148
149
    /**
150
     * Restores last pushed internal generator's state from stack
151
     *
152
     * @throws RandException if stack is empty
153
     */
154
    public function popState()
155
    {
156
        $state = array_pop($this->stateStack);
157
        if ($state === null) {
158
            throw new RandException('State stack is empty');
159
        }
160
        $this->setState($state);
161
    }
162
163
    /**
164
     * Resets generator to initial state
165
     */
166
    public function reset()
167
    {
168
        $this->init();
169
    }
170
171
    /**
172
     * @param float $mean
173
     * @param float $sigma
174
     * @return float Normally distributed random number
175
     */
176
    public function gaussianRandom($mean = 0.0, $sigma = 1.0)
177
    {
178
        // Sampler initialization is heavy so should not be used in __construct
179
        if ($this->gaussianSampler === null) {
180
            $this->gaussianSampler = new GaussianSampler($this);
181
        }
182
183
        return $mean + ($this->gaussianSampler->nextSample() * $sigma);
184
    }
185
186
    /**
187
     * Returns uniformly distributed random number within given range.
188
     * In case of incorrect range RandException will be thrown
189
     *
190
     * @param int $min Range min. Defaults to 0.
191
     * @param int $max Range max. Defaults to INT_MAX
192
     * @return int Random number in specified range inclusive
193
     * @throws RandException
194
     */
195
    public function random($min = 0, $max = null)
196
    {
197
        if ($max === null) {
198
            $max = static::INT_MAX;
199
        } elseif ($max < $min) {
200
            throw new RandException('Max is smaller than min');
201
        } elseif ($max > static::INT_MAX) {
202
            throw new RandException('Max is bigger than maximum generator value');
203
        }
204
        return $min + (int)(($max - $min + 1) * $this->randomInt() * $this->intMaxDiv);
205
    }
206
207
    /**
208
     * Returns unsigned float
209
     *
210
     * @return float Random float value in range 0 <= num <= 1
211
     */
212
    public function randomFloat()
213
    {
214
        return $this->randomInt() * $this->intMaxDiv;
215
    }
216
217
    /**
218
     * Returns true or false
219
     *
220
     * @return bool Random boolean value
221
     */
222
    public function randomBool()
223
    {
224
        return $this->randomInt() > (static::INT_MAX >> 1);
225
    }
226
227
    /**
228
     * Returns random binary data with given length.
229
     * May be optimised by derived class depending on generator algorithm used
230
     *
231
     * @param int $length Length of data to generate
232
     * @return string Random binary data
233
     * @throws RandException
234
     */
235
    public function randomData($length)
236
    {
237
        static $asciiTable;
238
        if ($asciiTable === null) {
239
            $asciiTable = array_map(function ($v){ return chr($v); }, range(0, 255));
240
        }
241
242
        if ($length < 1) {
243
            throw new RandException('Invalid length');
244
        }
245
246
        $data = '';
247
        for ($i = 0; $i < $length; $i++) {
248
            $data .= $asciiTable[$this->random(0, 255)];
249
        }
250
        return $data;
251
    }
252
253
    /**
254
     * Generate random string with given length from specified character list.
255
     * Supports multi-byte characters when $mb flag is set
256
     *
257
     * @param int    $length   Length of string to generate
258
     * @param string $charList List of characters to create string from
259
     * @param bool   $mb       Whether to interpret $charList as multibyte string. Defaults to false
260
     * @return string Random string
261
     */
262
    public function randomString($length, $charList = self::CL_ALNUM, $mb = false)
263
    {
264
        $str = '';
265
        if ($mb) {
266
            $charList = preg_split('//u', $charList, -1, PREG_SPLIT_NO_EMPTY);
267
            $len = count($charList) - 1;
268
        } else {
269
            $len = strlen($charList) - 1;
270
        }
271
272
        for ($i = 0; $i < $length; $i++) {
273
            $str .= $charList[$this->random(0, $len)];
274
        }
275
        return $str;
276
    }
277
278
    /**
279
     * Returns random key from given array
280
     *
281
     * @param array $array Array to get random key from
282
     * @return mixed Random array's key
283
     * @throws RandException
284
     */
285
    public function arrayRand(array $array)
286
    {
287
        if (empty($array)) {
288
            throw new RandException('Empty array specified');
289
        }
290
291
        $keys = array_keys($array);
292
        $i = $this->random(0, count($keys) - 1);
293
        return $keys[$i];
294
    }
295
296
    /**
297
     * Returns random element from given array
298
     *
299
     * @param array $array Array to get random element from
300
     * @return mixed Random array's element
301
     */
302
    public function arrayRandValue(array $array)
303
    {
304
        return $array[$this->arrayRand($array)];
305
    }
306
307
    /**
308
     * Shuffles given array by reference like php shuffle() function
309
     * This function assigns new keys to the elements in array.
310
     *
311
     * @param array $array Array for shuffling
312
     */
313
    public function arrayShuffle(array &$array)
314
    {
315
        $len = count($array) - 1;
316
        if ($len <= 0) {
317
            return;
318
        }
319
320
        $array = array_values($array);
321
        $this->shuffle($array);
322
    }
323
324
    /**
325
     * Shuffles given array by reference like php shuffle() function
326
     * Preserves key => value pairs
327
     *
328
     * @param array $array Reference to array for shuffling
329
     */
330
    public function arrayShuffleAssoc(array &$array)
331
    {
332
        $len = count($array) - 1;
333
        if ($len <= 0) {
334
            return;
335
        }
336
337
        $keys = array_keys($array);
338
        $this->shuffle($keys);
339
340
        foreach ($keys as $key) {
341
            $tmp = $array[$key];
342
            unset($array[$key]);
343
            $array[$key] = $tmp;
344
        }
345
    }
346
347
    /**
348
     * Returns random key from input array by its weight
349
     * Array must be specified in [key => weight, ...] form
350
     *
351
     * @param array $array Input array with with key => weight elements
352
     * @return mixed Random key
353
     * @throws RandException
354
     */
355
    public function arrayWeightRand(array $array)
356
    {
357
        $count = count($array);
358
        if ($count <= 1) {
359
            return key($array);
360
        }
361
        $sum = array_sum($array);
362
        if ($sum < 1) {
363
            throw new RandException('Negative or all-zero weights not allowed');
364
        }
365
        $targetWeight = $this->random(1, $sum);
366
        foreach ($array as $key => $weight) {
367
            if ($weight < 0) {
368
                throw new RandException('Negative weights not allowed');
369
            }
370
            $targetWeight -= $weight;
371
            if ($targetWeight <= 0) {
372
                return $key;
373
            }
374
        }
375
    }
376
377
    /**
378
     * Shuffles input array by element's weights.
379
     * Array must be specified in [key => weight, ...] form
380
     *
381
     * @param array $array Array for shuffling
382
     */
383
    public function arrayWeightShuffle(array &$array)
384
    {
385
        $tmp = [];
386
        $c = count($array);
387
388
        for ($i = 0; $i < $c; $i++) {
389
            $key = $this->arrayWeightRand($array);
390
            $tmp[$key] = $array[$key];
391
            unset($array[$key]);
392
        }
393
        $array = $tmp;
394
    }
395
396
    /**
397
     * Simple array shuffle helper function
398
     *
399
     * @param array $array
400
     */
401
    private function shuffle(array &$array)
402
    {
403
        for ($i = count($array) - 1; $i >= 0; $i--) {
404
            $j = $this->random(0, $i);
405
            $tmp = $array[$i];
406
            $array[$i] = $array[$j];
407
            $array[$j] = $tmp;
408
        }
409
    }
410
}
411