diff --git a/NEWS b/NEWS index eb1f4571e86..fdb5a4ec2f0 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.4.8 +- Core: + . Fixed GH-18480 (array_splice with large values for offset/length arguments). + (nielsdos/David Carlier) + - Curl: . Fixed GH-18460 (curl_easy_setopt with CURLOPT_USERPWD/CURLOPT_USERNAME/ CURLOPT_PASSWORD set the Authorization header when set to NULL). diff --git a/ext/standard/array.c b/ext/standard/array.c index 6c753c27e8a..ced173c2e56 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -3364,7 +3364,7 @@ static void php_splice(HashTable *in_hash, zend_long offset, zend_long length, H /* If hash for removed entries exists, go until offset+length and copy the entries to it */ if (removed != NULL) { - for ( ; pos < offset + length && idx < in_hash->nNumUsed; idx++, entry++) { + for ( ; pos - offset < length && idx < in_hash->nNumUsed; idx++, entry++) { if (Z_TYPE_P(entry) == IS_UNDEF) continue; pos++; Z_TRY_ADDREF_P(entry); @@ -3377,9 +3377,9 @@ static void php_splice(HashTable *in_hash, zend_long offset, zend_long length, H } } } else { /* otherwise just skip those entries */ - int pos2 = pos; + zend_long pos2 = pos; - for ( ; pos2 < offset + length && idx < in_hash->nNumUsed; idx++, entry++) { + for ( ; pos2 - offset < length && idx < in_hash->nNumUsed; idx++, entry++) { if (Z_TYPE_P(entry) == IS_UNDEF) continue; pos2++; zend_hash_packed_del_val(in_hash, entry); @@ -3438,7 +3438,7 @@ static void php_splice(HashTable *in_hash, zend_long offset, zend_long length, H /* If hash for removed entries exists, go until offset+length and copy the entries to it */ if (removed != NULL) { - for ( ; pos < offset + length && idx < in_hash->nNumUsed; idx++, p++) { + for ( ; pos - offset < length && idx < in_hash->nNumUsed; idx++, p++) { if (Z_TYPE(p->val) == IS_UNDEF) continue; pos++; entry = &p->val; @@ -3451,9 +3451,9 @@ static void php_splice(HashTable *in_hash, zend_long offset, zend_long length, H zend_hash_del_bucket(in_hash, p); } } else { /* otherwise just skip those entries */ - int pos2 = pos; + zend_long pos2 = pos; - for ( ; pos2 < offset + length && idx < in_hash->nNumUsed; idx++, p++) { + for ( ; pos2 - offset < length && idx < in_hash->nNumUsed; idx++, p++) { if (Z_TYPE(p->val) == IS_UNDEF) continue; pos2++; zend_hash_del_bucket(in_hash, p); diff --git a/ext/standard/tests/array/gh18480.phpt b/ext/standard/tests/array/gh18480.phpt new file mode 100644 index 00000000000..b9466029d4e --- /dev/null +++ b/ext/standard/tests/array/gh18480.phpt @@ -0,0 +1,40 @@ +--TEST-- +GH-18480 (array_splice overflow with large offset / length values) +--FILE-- + PHP_INT_MAX]; + $offset = PHP_INT_MAX; + var_dump(array_splice($a,$offset, $length)); + $a = ["a" => PHP_INT_MAX]; + $offset = PHP_INT_MIN; + var_dump(array_splice($a,$offset, $length)); +} +--EXPECTF-- +array(0) { +} +array(0) { +} +array(0) { +} +array(0) { +} +array(0) { +} +array(1) { + [0]=> + int(%d) +} +array(0) { +} +array(1) { + ["a"]=> + int(%d) +}