Attempting to delete the __pclass key from the HashTable returned by Persistable::bsonSerialize() triggers an assert failure in PHP 7.2:
php: /tmp/build_php-7.2.0RC1.ocF/php-7.2.0RC1/Zend/zend_hash.c:1162: zend_hash_str_del: Assertion `((ht)->gc.refcount == 1) || ((ht)->u.flags & (1<<6))' failed. Aborted (core dumped) Termsig=6
This is traced back to the zend_hash_str_del() call in php_phongo_zval_to_bson(). Assert failures show up for the following tests:
MongoDB\BSON\fromPHP(): Null type map values imply default behavior [tests/bson/bson-toPHP-002.phpt] PHPC-334: Injected __pclass should override a __pclass key in bsonSerialize() return value [tests/bson/bug0334-001.phpt] PHPC-334: Encoded BSON should never have multiple __pclass keys [tests/bson/bug0334-002.phpt] PHPC-924: Cursor::setTypeMap() may unnecessarily convert first BSON document (__pclass) [tests/cursor/bug0924-002.phpt] PHPC-545: Update does not serialize embedded Persistable's __pclass field [tests/standalone/bug0545.phpt]
In all of these tests, the reference count on the HashTable returned by Persistable::bsonSerialize() is 2 instead of 1. The returned array may be generated in various ways:
- bson-toPHP-002.phpt returns an array class property, which is initialized in the constructor.
- bug0334-001.phpt and bug0334-002.phpt return an array literal.
- bug0924-002.phpt returns the result of casting an array class property to an object.
- bug0545.phpt assigns the return value of get_object_vars() to a local variable, which is then returned.
Some recent upstream commits in PHP relevant to this assertion are:
- Enable HT RC assertions with escape-hatch (fd40250)
- Merged zend_array and HashTable into the single data structure (e10e151)
The assertion logic dates back to PHP 7.0.0. My local PHP build environments all have ZEND_DEBUG defined, so I can confirm that this assertion only started failing in PHP 7.2.
After further investigation, this uncovered a long-outstanding bug where the memory of the Persistable::bsonSerialize() return value might be modified if we actually unset an existing __pclass field.
- is related to
-
PHPC-1005 Ensure array symtable converts to object proptable in PHP 7.2
- Closed