diff --git a/ext/dom/tests/gh17201.phpt b/ext/dom/tests/gh17201.phpt new file mode 100644 index 0000000000000..a7d8ecd827db5 --- /dev/null +++ b/ext/dom/tests/gh17201.phpt @@ -0,0 +1,20 @@ +--TEST-- +GH-17201 (Dom\TokenList issues with interned string replace) +--EXTENSIONS-- +dom +--INI-- +opcache.protect_memory=1 +--FILE-- +'); +$element = $dom->documentElement; +$list = $element->classList; +$list->replace('AA', 'AB'); // Use interned string +foreach ($list as $entry) { + var_dump($entry); +} +?> +--EXPECT-- +string(2) "AB" +string(1) "B" +string(1) "C" diff --git a/ext/dom/token_list.c b/ext/dom/token_list.c index 15eaeb402017d..fe768e17b2e9c 100644 --- a/ext/dom/token_list.c +++ b/ext/dom/token_list.c @@ -583,7 +583,8 @@ PHP_METHOD(Dom_TokenList, replace) /* It already exists, remove token instead. */ zend_hash_del_bucket(token_set, bucket); } else { - Z_STR(bucket->val) = new_token; + /* Need to use ZVAL_STR instead of Z_STR to reset the type flags. */ + ZVAL_STR(&bucket->val, new_token); } /* 5. Run the update steps. */