File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -78,6 +78,8 @@ PHP NEWS
7878 nested arrays). (Lazizbek Ergashev)
7979 . Fixed bug GH-23115 (Stack overflow in compact() with deeply nested
8080 arrays). (Lazizbek Ergashev)
81+ . Fixed stack overflow in count() with COUNT_RECURSIVE and deeply nested
82+ arrays. (Lazizbek Ergashev)
8183
8284- Streams:
8385 . Fixed bug GH-15836 (Use-after-free when a user stream filter accesses
Original file line number Diff line number Diff line change @@ -611,6 +611,13 @@ PHPAPI zend_long php_count_recursive(HashTable *ht) /* {{{ */
611611 zend_long cnt = 0 ;
612612 zval * element ;
613613
614+ #ifdef ZEND_CHECK_STACK_LIMIT
615+ if (UNEXPECTED (zend_call_stack_overflowed (EG (stack_limit )))) {
616+ zend_call_stack_size_error ();
617+ return 0 ;
618+ }
619+ #endif
620+
614621 if (!(GC_FLAGS (ht ) & GC_IMMUTABLE )) {
615622 if (GC_IS_RECURSIVE (ht )) {
616623 php_error_docref (NULL , E_WARNING , "Recursion detected" );
@@ -624,6 +631,9 @@ PHPAPI zend_long php_count_recursive(HashTable *ht) /* {{{ */
624631 ZVAL_DEREF (element );
625632 if (Z_TYPE_P (element ) == IS_ARRAY ) {
626633 cnt += php_count_recursive (Z_ARRVAL_P (element ));
634+ if (UNEXPECTED (EG (exception ))) {
635+ break ;
636+ }
627637 }
628638 } ZEND_HASH_FOREACH_END ();
629639
@@ -656,6 +666,9 @@ PHP_FUNCTION(count)
656666 cnt = zend_hash_num_elements (Z_ARRVAL_P (array ));
657667 } else {
658668 cnt = php_count_recursive (Z_ARRVAL_P (array ));
669+ if (UNEXPECTED (EG (exception ))) {
670+ RETURN_THROWS ();
671+ }
659672 }
660673 RETURN_LONG (cnt );
661674 break ;
Original file line number Diff line number Diff line change 1+ --TEST--
2+ Stack overflow in count() with COUNT_RECURSIVE and deeply nested arrays
3+ --SKIPIF--
4+ <?php
5+ if (ini_get ('zend.max_allowed_stack_size ' ) === false ) {
6+ die ('skip No stack limit support ' );
7+ }
8+ if (getenv ('SKIP_ASAN ' )) {
9+ die ('skip ASAN needs different stack limit setting due to more stack space usage ' );
10+ }
11+ ?>
12+ --INI--
13+ zend.max_allowed_stack_size=256K
14+ --FILE--
15+ <?php
16+ /* Two elements per nesting level: the sibling must not be visited once the
17+ * stack limit error has been thrown, so only one Error is thrown. */
18+ $ a = [];
19+ for ($ i = 0 ; $ i < 30000 ; $ i ++) {
20+ $ a = [$ a , []];
21+ }
22+
23+ try {
24+ count ($ a , COUNT_RECURSIVE );
25+ } catch (Throwable $ e ) {
26+ echo $ e ::class, ": " , $ e ->getMessage (), "\n" ;
27+ var_dump ($ e ->getPrevious ());
28+ }
29+ ?>
30+ --EXPECTF--
31+ Error: Maximum call stack size of %d bytes (zend.max_allowed_stack_size - zend.reserved_stack_size) reached. Infinite recursion?
32+ NULL
You can’t perform that action at this time.
0 commit comments