@@ -212,10 +212,16 @@ static zend_object *spl_filesystem_object_new(zend_class_entry *class_type)
212212}
213213/* }}} */
214214
215+ static inline bool spl_intern_is_glob (const spl_filesystem_object * intern )
216+ {
217+ /* NULL check on `dirp` is necessary as destructors may interfere. */
218+ return intern -> u .dir .dirp && php_stream_is (intern -> u .dir .dirp , & php_glob_stream_ops );
219+ }
220+
215221PHPAPI zend_string * spl_filesystem_object_get_path (spl_filesystem_object * intern ) /* {{{ */
216222{
217223#ifdef HAVE_GLOB
218- if (intern -> type == SPL_FS_DIR && php_stream_is (intern -> u . dir . dirp , & php_glob_stream_ops )) {
224+ if (intern -> type == SPL_FS_DIR && spl_intern_is_glob (intern )) {
219225 size_t len = 0 ;
220226 char * tmp = php_glob_stream_get_path (intern -> u .dir .dirp , & len );
221227 if (len == 0 ) {
@@ -658,7 +664,7 @@ static inline HashTable *spl_filesystem_object_get_debug_info(zend_object *objec
658664 if (intern -> type == SPL_FS_DIR ) {
659665#ifdef HAVE_GLOB
660666 pnstr = spl_gen_private_prop_name (spl_ce_DirectoryIterator , "glob" , sizeof ("glob" )- 1 );
661- if (intern -> u . dir . dirp && php_stream_is (intern -> u . dir . dirp , & php_glob_stream_ops )) {
667+ if (spl_intern_is_glob (intern )) {
662668 ZVAL_STR_COPY (& tmp , intern -> path );
663669 } else {
664670 ZVAL_FALSE (& tmp );
@@ -1614,11 +1620,11 @@ PHP_METHOD(GlobIterator, count)
16141620 RETURN_THROWS ();
16151621 }
16161622
1617- if (intern -> u . dir . dirp && php_stream_is (intern -> u . dir . dirp , & php_glob_stream_ops )) {
1623+ if (spl_intern_is_glob (intern )) {
16181624 RETURN_LONG (php_glob_stream_get_count (intern -> u .dir .dirp , NULL ));
16191625 } else {
1620- /* should not happen */
1621- // TODO ZEND_ASSERT ?
1626+ /* This can happen by abusing destructors. */
1627+ /* TODO: relax this from E_ERROR to an exception */
16221628 php_error_docref (NULL , E_ERROR , "GlobIterator lost glob state" );
16231629 }
16241630}
0 commit comments