@@ -995,6 +995,20 @@ static inline void populate_match_value(
995995 }
996996}
997997
998+ static inline void add_named (
999+ zval * subpats , zend_string * name , zval * val , zend_bool unmatched ) {
1000+ /* If the DUPNAMES option is used, multiple subpatterns might have the same name.
1001+ * In this case we want to preserve the one that actually has a value. */
1002+ if (!unmatched ) {
1003+ zend_hash_update (Z_ARRVAL_P (subpats ), name , val );
1004+ } else {
1005+ if (!zend_hash_add (Z_ARRVAL_P (subpats ), name , val )) {
1006+ return ;
1007+ }
1008+ }
1009+ Z_TRY_ADDREF_P (val );
1010+ }
1011+
9981012/* {{{ add_offset_pair */
9991013static inline void add_offset_pair (
10001014 zval * result , const char * subject , PCRE2_SIZE start_offset , PCRE2_SIZE end_offset ,
@@ -1023,8 +1037,7 @@ static inline void add_offset_pair(
10231037 }
10241038
10251039 if (name ) {
1026- Z_ADDREF (match_pair );
1027- zend_hash_update (Z_ARRVAL_P (result ), name , & match_pair );
1040+ add_named (result , name , & match_pair , start_offset == PCRE2_UNSET );
10281041 }
10291042 zend_hash_next_index_insert (Z_ARRVAL_P (result ), & match_pair );
10301043}
@@ -1054,16 +1067,15 @@ static void populate_subpat_array(
10541067 populate_match_value (
10551068 & val , subject , offsets [2 * i ], offsets [2 * i + 1 ], unmatched_as_null );
10561069 if (subpat_names [i ]) {
1057- Z_TRY_ADDREF (val );
1058- zend_hash_update (Z_ARRVAL_P (subpats ), subpat_names [i ], & val );
1070+ add_named (subpats , subpat_names [i ], & val , offsets [2 * i ] == PCRE2_UNSET );
10591071 }
10601072 zend_hash_next_index_insert (Z_ARRVAL_P (subpats ), & val );
10611073 }
10621074 if (unmatched_as_null ) {
10631075 for (i = count ; i < num_subpats ; i ++ ) {
10641076 ZVAL_NULL (& val );
10651077 if (subpat_names [i ]) {
1066- zend_hash_update (Z_ARRVAL_P (subpats ), subpat_names [i ], & val );
1078+ zend_hash_add (Z_ARRVAL_P (subpats ), subpat_names [i ], & val );
10671079 }
10681080 zend_hash_next_index_insert (Z_ARRVAL_P (subpats ), & val );
10691081 }
0 commit comments