Skip to content

Commit 3cf2336

Browse files
committed
changes from feedback
1 parent 17677de commit 3cf2336

File tree

2 files changed

+37
-17
lines changed

2 files changed

+37
-17
lines changed

ext/standard/array.c

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3234,10 +3234,6 @@ static void php_splice(HashTable *in_hash, zend_long offset, zend_long length, H
32343234
/* Create and initialize output hash */
32353235
zend_hash_init(&out_hash, (length > 0 ? num_in - length : 0) + (replace ? zend_hash_num_elements(replace) : 0), NULL, ZVAL_PTR_DTOR, 0);
32363236

3237-
if (length > ZEND_LONG_MAX - offset || length < ZEND_LONG_MIN + offset) {
3238-
goto end;
3239-
}
3240-
32413237
if (HT_IS_PACKED(in_hash)) {
32423238
/* Start at the beginning of the input hash and copy entries to output hash until offset is reached */
32433239
entry = in_hash->arPacked;
@@ -3256,7 +3252,7 @@ static void php_splice(HashTable *in_hash, zend_long offset, zend_long length, H
32563252

32573253
/* If hash for removed entries exists, go until offset+length and copy the entries to it */
32583254
if (removed != NULL) {
3259-
for ( ; pos < offset + length && idx < in_hash->nNumUsed; idx++, entry++) {
3255+
for ( ; pos - offset < length && idx < in_hash->nNumUsed; idx++, entry++) {
32603256
if (Z_TYPE_P(entry) == IS_UNDEF) continue;
32613257
pos++;
32623258
Z_TRY_ADDREF_P(entry);
@@ -3266,7 +3262,7 @@ static void php_splice(HashTable *in_hash, zend_long offset, zend_long length, H
32663262
} else { /* otherwise just skip those entries */
32673263
zend_long pos2 = pos;
32683264

3269-
for ( ; pos2 < offset + length && idx < in_hash->nNumUsed; idx++, entry++) {
3265+
for ( ; pos2 - offset < length && idx < in_hash->nNumUsed; idx++, entry++) {
32703266
if (Z_TYPE_P(entry) == IS_UNDEF) continue;
32713267
pos2++;
32723268
zend_hash_packed_del_val(in_hash, entry);
@@ -3321,7 +3317,7 @@ static void php_splice(HashTable *in_hash, zend_long offset, zend_long length, H
33213317

33223318
/* If hash for removed entries exists, go until offset+length and copy the entries to it */
33233319
if (removed != NULL) {
3324-
for ( ; pos < offset + length && idx < in_hash->nNumUsed; idx++, p++) {
3320+
for ( ; pos - offset < length && idx < in_hash->nNumUsed; idx++, p++) {
33253321
if (Z_TYPE(p->val) == IS_UNDEF) continue;
33263322
pos++;
33273323
entry = &p->val;
@@ -3334,9 +3330,9 @@ static void php_splice(HashTable *in_hash, zend_long offset, zend_long length, H
33343330
zend_hash_del_bucket(in_hash, p);
33353331
}
33363332
} else { /* otherwise just skip those entries */
3337-
int pos2 = pos;
3333+
zend_long pos2 = pos;
33383334

3339-
for ( ; pos2 < offset + length && idx < in_hash->nNumUsed; idx++, p++) {
3335+
for ( ; pos2 - offset < length && idx < in_hash->nNumUsed; idx++, p++) {
33403336
if (Z_TYPE(p->val) == IS_UNDEF) continue;
33413337
pos2++;
33423338
zend_hash_del_bucket(in_hash, p);
@@ -3372,7 +3368,6 @@ static void php_splice(HashTable *in_hash, zend_long offset, zend_long length, H
33723368
}
33733369
}
33743370

3375-
end:
33763371
/* replace HashTable data */
33773372
HT_SET_ITERATORS_COUNT(&out_hash, HT_ITERATORS_COUNT(in_hash));
33783373
HT_SET_ITERATORS_COUNT(in_hash, 0);

ext/standard/tests/array/gh18480.phpt

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,39 @@
22
GH-18480 (array_splice overflow with large offset / length values)
33
--FILE--
44
<?php
5-
$a = [PHP_INT_MAX];
6-
$offset = PHP_INT_MAX;
7-
var_dump(array_splice($a,$offset, PHP_INT_MAX));
8-
$offset = PHP_INT_MIN;
9-
var_dump(array_splice($a,$offset, PHP_INT_MIN));
10-
--EXPECT--
5+
6+
foreach ([PHP_INT_MIN, PHP_INT_MAX] as $length) {
7+
$a = [PHP_INT_MAX];
8+
$offset = PHP_INT_MAX;
9+
var_dump(array_splice($a,$offset, $length));
10+
$a = [PHP_INT_MAX];
11+
$offset = PHP_INT_MIN;
12+
var_dump(array_splice($a,$offset, $length));
13+
$a = ["a" => PHP_INT_MAX];
14+
$offset = PHP_INT_MAX;
15+
var_dump(array_splice($a,$offset, $length));
16+
$a = ["a" => PHP_INT_MAX];
17+
$offset = PHP_INT_MIN;
18+
var_dump(array_splice($a,$offset, $length));
19+
}
20+
--EXPECTF--
1121
array(0) {
1222
}
1323
array(0) {
1424
}
15-
25+
array(0) {
26+
}
27+
array(0) {
28+
}
29+
array(0) {
30+
}
31+
array(1) {
32+
[0]=>
33+
int(%d)
34+
}
35+
array(0) {
36+
}
37+
array(1) {
38+
["a"]=>
39+
int(%d)
40+
}

0 commit comments

Comments
 (0)