Browse Source

Merge branch 'PHP-7.1'

pull/2442/head
Nikita Popov 9 years ago
parent
commit
51b06aa86e
  1. 27
      ext/standard/array.c
  2. 11
      ext/standard/tests/array/bug74361.phpt
  3. 24
      ext/standard/tests/array/bug74361_2.phpt

27
ext/standard/array.c

@ -5699,19 +5699,26 @@ PHP_FUNCTION(array_rand)
if (num_req == 1) { if (num_req == 1) {
HashTable *ht = Z_ARRVAL_P(input); HashTable *ht = Z_ARRVAL_P(input);
/* Compact the hashtable if less than 3/4 of elements are used */
if (num_avail < ht->nNumUsed - (ht->nNumUsed>>2)) {
if (ht->u.flags & HASH_FLAG_PACKED) {
zend_hash_packed_to_hash(ht);
} else {
zend_hash_rehash(ht);
}
if (num_avail < ht->nNumUsed - (ht->nNumUsed>>1)) {
/* If less than 1/2 of elements are used, don't sample. Instead search for a
* specific offset using linear scan. */
zend_long i = 0, randval = php_mt_rand_range(0, num_avail - 1);
ZEND_HASH_FOREACH_KEY(Z_ARRVAL_P(input), num_key, string_key) {
if (i == randval) {
if (string_key) {
RETURN_STR_COPY(string_key);
} else {
RETURN_LONG(num_key);
}
}
i++;
} ZEND_HASH_FOREACH_END();
} }
/* Sample random buckets until we hit one that is not empty. /* Sample random buckets until we hit one that is not empty.
* The worst case probability of hitting an empty element is 1-3/4. The worst case
* probability of hitting N empty elements in a row is (1-3/4)**N.
* For N=5 this becomes smaller than 0.1%. */
* The worst case probability of hitting an empty element is 1-1/2. The worst case
* probability of hitting N empty elements in a row is (1-1/2)**N.
* For N=10 this becomes smaller than 0.1%. */
do { do {
zend_long randval = php_mt_rand_range(0, ht->nNumUsed - 1); zend_long randval = php_mt_rand_range(0, ht->nNumUsed - 1);
Bucket *bucket = &ht->arData[randval]; Bucket *bucket = &ht->arData[randval];

11
ext/standard/tests/array/bug74361.phpt

@ -0,0 +1,11 @@
--TEST--
Bug #74361: Compaction in array_rand() violates COW
--FILE--
<?php
$array = [4 => 4];
var_dump(array_rand($array));
?>
--EXPECT--
int(4)

24
ext/standard/tests/array/bug74361_2.phpt

@ -0,0 +1,24 @@
--TEST--
Bug #74361: Compaction in array_rand() violates COW (variation)
--FILE--
<?php
$array = range(0, 15);
for ($i = 0; $i <= 8; $i++) {
unset($array[$i]);
}
foreach ($array as $x) {
var_dump($x);
array_rand($array, 1);
}
?>
--EXPECT--
int(9)
int(10)
int(11)
int(12)
int(13)
int(14)
int(15)
Loading…
Cancel
Save