Skip to content
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion ext/standard/array.c
Original file line number Diff line number Diff line change
Expand Up @@ -3234,6 +3234,10 @@ static void php_splice(HashTable *in_hash, zend_long offset, zend_long length, H
/* Create and initialize output hash */
zend_hash_init(&out_hash, (length > 0 ? num_in - length : 0) + (replace ? zend_hash_num_elements(replace) : 0), NULL, ZVAL_PTR_DTOR, 0);

if (length > ZEND_LONG_MAX - offset || length < ZEND_LONG_MIN + offset) {
goto end;
}

if (HT_IS_PACKED(in_hash)) {
/* Start at the beginning of the input hash and copy entries to output hash until offset is reached */
entry = in_hash->arPacked;
Expand All @@ -3260,7 +3264,7 @@ static void php_splice(HashTable *in_hash, zend_long offset, zend_long length, H
zend_hash_packed_del_val(in_hash, entry);
}
} else { /* otherwise just skip those entries */
int pos2 = pos;
zend_long pos2 = pos;

for ( ; pos2 < offset + length && idx < in_hash->nNumUsed; idx++, entry++) {
if (Z_TYPE_P(entry) == IS_UNDEF) continue;
Expand Down Expand Up @@ -3368,6 +3372,7 @@ static void php_splice(HashTable *in_hash, zend_long offset, zend_long length, H
}
}

end:
/* replace HashTable data */
HT_SET_ITERATORS_COUNT(&out_hash, HT_ITERATORS_COUNT(in_hash));
HT_SET_ITERATORS_COUNT(in_hash, 0);
Expand Down
15 changes: 15 additions & 0 deletions ext/standard/tests/array/gh18480.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
--TEST--
GH-18480 (array_splice overflow with large offset / length values)
--FILE--
<?php
$a = [PHP_INT_MAX];
$offset = PHP_INT_MAX;
var_dump(array_splice($a,$offset, PHP_INT_MAX));
$offset = PHP_INT_MIN;
var_dump(array_splice($a,$offset, PHP_INT_MIN));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests should always end with ?>

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also you didn't test every combination of PHP_INT_MIN/PHP_INT_MAX with offset/length, you should have 4 tests in total. You should also reassign the $a array before every test so they don't influence each other.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think more if we try to test non packed arrays too.

--EXPECT--
array(0) {
}
array(0) {
}

Loading