@@ -1574,6 +1574,7 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *su
1574
1574
size_t match_len ; /* Length of the current match */
1575
1575
int backref ; /* Backreference number */
1576
1576
PCRE2_SIZE start_offset ; /* Where the new search starts */
1577
+ size_t last_end_offset ; /* Where the last search ended */
1577
1578
char * walkbuf , /* Location of current replacement in the result */
1578
1579
* walk , /* Used to walk the replacement string */
1579
1580
* match , /* The current match */
@@ -1592,6 +1593,7 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *su
1592
1593
/* Initialize */
1593
1594
match = NULL ;
1594
1595
start_offset = 0 ;
1596
+ last_end_offset = 0 ;
1595
1597
result_len = 0 ;
1596
1598
PCRE_G (error_code ) = PHP_PCRE_NO_ERROR ;
1597
1599
@@ -1618,7 +1620,7 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *su
1618
1620
options , match_data , mctx );
1619
1621
1620
1622
while (1 ) {
1621
- piece = subject + start_offset ;
1623
+ piece = subject + last_end_offset ;
1622
1624
1623
1625
if (count >= 0 && limit > 0 ) {
1624
1626
zend_bool simple_string ;
@@ -1648,7 +1650,7 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *su
1648
1650
/* Set the match location in subject */
1649
1651
match = subject + offsets [0 ];
1650
1652
1651
- new_len = result_len + offsets [0 ] - start_offset ; /* part before the match */
1653
+ new_len = result_len + offsets [0 ] - last_end_offset ; /* part before the match */
1652
1654
1653
1655
walk = ZSTR_VAL (replace_str );
1654
1656
replace_end = walk + ZSTR_LEN (replace_str );
@@ -1725,7 +1727,7 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *su
1725
1727
limit -- ;
1726
1728
1727
1729
/* Advance to the next piece. */
1728
- start_offset = offsets [1 ];
1730
+ start_offset = last_end_offset = offsets [1 ];
1729
1731
1730
1732
/* If we have matched an empty string, mimic what Perl's /g options does.
1731
1733
This turns out to be rather cunning. First we set PCRE2_NOTEMPTY_ATSTART and try
@@ -1745,10 +1747,7 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *su
1745
1747
to achieve this, unless we're already at the end of the string. */
1746
1748
if (start_offset < subject_len ) {
1747
1749
size_t unit_len = calculate_unit_length (pce , piece );
1748
-
1749
1750
start_offset += unit_len ;
1750
- memcpy (ZSTR_VAL (result ) + result_len , piece , unit_len );
1751
- result_len += unit_len ;
1752
1751
} else {
1753
1752
goto not_matched ;
1754
1753
}
@@ -1763,7 +1762,7 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *su
1763
1762
result = zend_string_copy (subject_str );
1764
1763
break ;
1765
1764
}
1766
- new_len = result_len + subject_len - start_offset ;
1765
+ new_len = result_len + subject_len - last_end_offset ;
1767
1766
if (new_len >= alloc_len ) {
1768
1767
alloc_len = new_len ; /* now we know exactly how long it is */
1769
1768
if (NULL != result ) {
@@ -1773,8 +1772,8 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *su
1773
1772
}
1774
1773
}
1775
1774
/* stick that last bit of string on our output */
1776
- memcpy (ZSTR_VAL (result ) + result_len , piece , subject_len - start_offset );
1777
- result_len += subject_len - start_offset ;
1775
+ memcpy (ZSTR_VAL (result ) + result_len , piece , subject_len - last_end_offset );
1776
+ result_len += subject_len - last_end_offset ;
1778
1777
ZSTR_VAL (result )[result_len ] = '\0' ;
1779
1778
ZSTR_LEN (result ) = result_len ;
1780
1779
break ;
@@ -1816,6 +1815,7 @@ static zend_string *php_pcre_replace_func_impl(pcre_cache_entry *pce, zend_strin
1816
1815
size_t new_len ; /* Length of needed storage */
1817
1816
size_t alloc_len ; /* Actual allocated length */
1818
1817
PCRE2_SIZE start_offset ; /* Where the new search starts */
1818
+ size_t last_end_offset ; /* Where the last search ended */
1819
1819
char * match , /* The current match */
1820
1820
* piece ; /* The current piece of subject */
1821
1821
size_t result_len ; /* Length of result */
@@ -1845,6 +1845,7 @@ static zend_string *php_pcre_replace_func_impl(pcre_cache_entry *pce, zend_strin
1845
1845
/* Initialize */
1846
1846
match = NULL ;
1847
1847
start_offset = 0 ;
1848
+ last_end_offset = 0 ;
1848
1849
result_len = 0 ;
1849
1850
PCRE_G (error_code ) = PHP_PCRE_NO_ERROR ;
1850
1851
@@ -1877,7 +1878,7 @@ static zend_string *php_pcre_replace_func_impl(pcre_cache_entry *pce, zend_strin
1877
1878
options , match_data , mctx );
1878
1879
1879
1880
while (1 ) {
1880
- piece = subject + start_offset ;
1881
+ piece = subject + last_end_offset ;
1881
1882
1882
1883
if (count >= 0 && limit ) {
1883
1884
/* Check for too many substrings condition. */
@@ -1905,7 +1906,7 @@ static zend_string *php_pcre_replace_func_impl(pcre_cache_entry *pce, zend_strin
1905
1906
/* Set the match location in subject */
1906
1907
match = subject + offsets [0 ];
1907
1908
1908
- new_len = result_len + offsets [0 ] - start_offset ; /* part before the match */
1909
+ new_len = result_len + offsets [0 ] - last_end_offset ; /* part before the match */
1909
1910
1910
1911
/* Use custom function to get replacement string and its length. */
1911
1912
eval_result = preg_do_repl_func (fci , fcc , subject , offsets , subpat_names , count ,
@@ -1936,7 +1937,7 @@ static zend_string *php_pcre_replace_func_impl(pcre_cache_entry *pce, zend_strin
1936
1937
limit -- ;
1937
1938
1938
1939
/* Advance to the next piece. */
1939
- start_offset = offsets [1 ];
1940
+ start_offset = last_end_offset = offsets [1 ];
1940
1941
1941
1942
/* If we have matched an empty string, mimic what Perl's /g options does.
1942
1943
This turns out to be rather cunning. First we set PCRE2_NOTEMPTY_ATSTART and try
@@ -1956,10 +1957,7 @@ static zend_string *php_pcre_replace_func_impl(pcre_cache_entry *pce, zend_strin
1956
1957
to achieve this, unless we're already at the end of the string. */
1957
1958
if (start_offset < subject_len ) {
1958
1959
size_t unit_len = calculate_unit_length (pce , piece );
1959
-
1960
1960
start_offset += unit_len ;
1961
- memcpy (ZSTR_VAL (result ) + result_len , piece , unit_len );
1962
- result_len += unit_len ;
1963
1961
} else {
1964
1962
goto not_matched ;
1965
1963
}
@@ -1974,7 +1972,7 @@ static zend_string *php_pcre_replace_func_impl(pcre_cache_entry *pce, zend_strin
1974
1972
result = zend_string_copy (subject_str );
1975
1973
break ;
1976
1974
}
1977
- new_len = result_len + subject_len - start_offset ;
1975
+ new_len = result_len + subject_len - last_end_offset ;
1978
1976
if (new_len >= alloc_len ) {
1979
1977
alloc_len = new_len ; /* now we know exactly how long it is */
1980
1978
if (NULL != result ) {
@@ -1984,8 +1982,8 @@ static zend_string *php_pcre_replace_func_impl(pcre_cache_entry *pce, zend_strin
1984
1982
}
1985
1983
}
1986
1984
/* stick that last bit of string on our output */
1987
- memcpy (ZSTR_VAL (result ) + result_len , piece , subject_len - start_offset );
1988
- result_len += subject_len - start_offset ;
1985
+ memcpy (ZSTR_VAL (result ) + result_len , piece , subject_len - last_end_offset );
1986
+ result_len += subject_len - last_end_offset ;
1989
1987
ZSTR_VAL (result )[result_len ] = '\0' ;
1990
1988
ZSTR_LEN (result ) = result_len ;
1991
1989
break ;
0 commit comments