From 1d94fb86b7dbc3e29c215ad52f5c4ff71152d829 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Mon, 14 Oct 2024 14:02:45 +0200 Subject: [PATCH] Fix handling of invalid iterator in zend_weakmap_iterator_get_current_key() Fixes GH-16371 Closes GH-16436 --- NEWS | 1 + Zend/tests/gh16371.phpt | 47 +++++++++++++++++++++++++++++++++++++++++ Zend/zend_weakrefs.c | 4 ++++ 3 files changed, 52 insertions(+) create mode 100644 Zend/tests/gh16371.phpt diff --git a/NEWS b/NEWS index f54be6afc45..a05fdcf4b34 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,7 @@ PHP NEWS - Core: . Fixed bug GH-16168 (php 8.1 and earlier crash immediately when compiled with Xcode 16 clang on macOS 15). (nielsdos) + . Fixed bug GH-16371 (Assertion failure in Zend/zend_weakrefs.c:646). (Arnaud) - Curl: . Fixed bug GH-16302 (CurlMultiHandle holds a reference to CurlHandle if diff --git a/Zend/tests/gh16371.phpt b/Zend/tests/gh16371.phpt new file mode 100644 index 00000000000..568bb8faf12 --- /dev/null +++ b/Zend/tests/gh16371.phpt @@ -0,0 +1,47 @@ +--TEST-- +GH-16371: Assertion failure in zend_weakmap_iterator_get_current_key() for invalid iterator +--FILE-- +getIterator(); + +print "# Empty WeakMap\n"; + +var_dump($it->key()); +var_dump($it->current()); +var_dump($it->valid()); + +$map = new WeakMap(); +$obj = new stdClass; +$map[$obj] = 0; + +print "# Valid iterator\n"; + +$it = $map->getIterator(); +var_dump($it->key()); +var_dump($it->current()); +var_dump($it->valid()); + +print "# End of iterator\n"; + +$it->next(); +var_dump($it->key()); +var_dump($it->current()); +var_dump($it->valid()); + +?> +--EXPECTF-- +# Empty WeakMap +NULL +NULL +bool(false) +# Valid iterator +object(stdClass)#%d (0) { +} +int(0) +bool(true) +# End of iterator +NULL +NULL +bool(false) diff --git a/Zend/zend_weakrefs.c b/Zend/zend_weakrefs.c index 3f2e517f3fe..bd25b5b8391 100644 --- a/Zend/zend_weakrefs.c +++ b/Zend/zend_weakrefs.c @@ -530,6 +530,10 @@ static void zend_weakmap_iterator_get_current_key(zend_object_iterator *obj_iter zend_string *string_key; zend_ulong num_key; int key_type = zend_hash_get_current_key_ex(&wm->ht, &string_key, &num_key, pos); + if (key_type == HASH_KEY_NON_EXISTENT) { + ZVAL_NULL(key); + return; + } if (key_type != HASH_KEY_IS_LONG) { ZEND_ASSERT(0 && "Must have integer key"); }