@@ -1582,6 +1582,7 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *su
1582
1582
size_t match_len ; /* Length of the current match */
1583
1583
int backref ; /* Backreference number */
1584
1584
PCRE2_SIZE start_offset ; /* Where the new search starts */
1585
+ size_t last_end_offset ; /* Where the last search ended */
1585
1586
char * walkbuf , /* Location of current replacement in the result */
1586
1587
* walk , /* Used to walk the replacement string */
1587
1588
* match , /* The current match */
@@ -1600,6 +1601,7 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *su
1600
1601
/* Initialize */
1601
1602
match = NULL ;
1602
1603
start_offset = 0 ;
1604
+ last_end_offset = 0 ;
1603
1605
result_len = 0 ;
1604
1606
PCRE_G (error_code ) = PHP_PCRE_NO_ERROR ;
1605
1607
@@ -1626,7 +1628,7 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *su
1626
1628
options , match_data , mctx );
1627
1629
1628
1630
while (1 ) {
1629
- piece = subject + start_offset ;
1631
+ piece = subject + last_end_offset ;
1630
1632
1631
1633
if (count >= 0 && limit > 0 ) {
1632
1634
zend_bool simple_string ;
@@ -1656,7 +1658,7 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *su
1656
1658
/* Set the match location in subject */
1657
1659
match = subject + offsets [0 ];
1658
1660
1659
- new_len = result_len + offsets [0 ] - start_offset ; /* part before the match */
1661
+ new_len = result_len + offsets [0 ] - last_end_offset ; /* part before the match */
1660
1662
1661
1663
walk = ZSTR_VAL (replace_str );
1662
1664
replace_end = walk + ZSTR_LEN (replace_str );
@@ -1733,7 +1735,7 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *su
1733
1735
limit -- ;
1734
1736
1735
1737
/* Advance to the next piece. */
1736
- start_offset = offsets [1 ];
1738
+ start_offset = last_end_offset = offsets [1 ];
1737
1739
1738
1740
/* If we have matched an empty string, mimic what Perl's /g options does.
1739
1741
This turns out to be rather cunning. First we set PCRE2_NOTEMPTY_ATSTART and try
@@ -1753,10 +1755,7 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *su
1753
1755
to achieve this, unless we're already at the end of the string. */
1754
1756
if (start_offset < subject_len ) {
1755
1757
size_t unit_len = calculate_unit_length (pce , piece );
1756
-
1757
1758
start_offset += unit_len ;
1758
- memcpy (ZSTR_VAL (result ) + result_len , piece , unit_len );
1759
- result_len += unit_len ;
1760
1759
} else {
1761
1760
goto not_matched ;
1762
1761
}
@@ -1771,7 +1770,7 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *su
1771
1770
result = zend_string_copy (subject_str );
1772
1771
break ;
1773
1772
}
1774
- new_len = result_len + subject_len - start_offset ;
1773
+ new_len = result_len + subject_len - last_end_offset ;
1775
1774
if (new_len >= alloc_len ) {
1776
1775
alloc_len = new_len ; /* now we know exactly how long it is */
1777
1776
if (NULL != result ) {
@@ -1781,8 +1780,8 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *su
1781
1780
}
1782
1781
}
1783
1782
/* stick that last bit of string on our output */
1784
- memcpy (ZSTR_VAL (result ) + result_len , piece , subject_len - start_offset );
1785
- result_len += subject_len - start_offset ;
1783
+ memcpy (ZSTR_VAL (result ) + result_len , piece , subject_len - last_end_offset );
1784
+ result_len += subject_len - last_end_offset ;
1786
1785
ZSTR_VAL (result )[result_len ] = '\0' ;
1787
1786
ZSTR_LEN (result ) = result_len ;
1788
1787
break ;
@@ -1824,6 +1823,7 @@ static zend_string *php_pcre_replace_func_impl(pcre_cache_entry *pce, zend_strin
1824
1823
size_t new_len ; /* Length of needed storage */
1825
1824
size_t alloc_len ; /* Actual allocated length */
1826
1825
PCRE2_SIZE start_offset ; /* Where the new search starts */
1826
+ size_t last_end_offset ; /* Where the last search ended */
1827
1827
char * match , /* The current match */
1828
1828
* piece ; /* The current piece of subject */
1829
1829
size_t result_len ; /* Length of result */
@@ -1853,6 +1853,7 @@ static zend_string *php_pcre_replace_func_impl(pcre_cache_entry *pce, zend_strin
1853
1853
/* Initialize */
1854
1854
match = NULL ;
1855
1855
start_offset = 0 ;
1856
+ last_end_offset = 0 ;
1856
1857
result_len = 0 ;
1857
1858
PCRE_G (error_code ) = PHP_PCRE_NO_ERROR ;
1858
1859
@@ -1885,7 +1886,7 @@ static zend_string *php_pcre_replace_func_impl(pcre_cache_entry *pce, zend_strin
1885
1886
options , match_data , mctx );
1886
1887
1887
1888
while (1 ) {
1888
- piece = subject + start_offset ;
1889
+ piece = subject + last_end_offset ;
1889
1890
1890
1891
if (count >= 0 && limit ) {
1891
1892
/* Check for too many substrings condition. */
@@ -1913,7 +1914,7 @@ static zend_string *php_pcre_replace_func_impl(pcre_cache_entry *pce, zend_strin
1913
1914
/* Set the match location in subject */
1914
1915
match = subject + offsets [0 ];
1915
1916
1916
- new_len = result_len + offsets [0 ] - start_offset ; /* part before the match */
1917
+ new_len = result_len + offsets [0 ] - last_end_offset ; /* part before the match */
1917
1918
1918
1919
/* Use custom function to get replacement string and its length. */
1919
1920
eval_result = preg_do_repl_func (
@@ -1945,7 +1946,7 @@ static zend_string *php_pcre_replace_func_impl(pcre_cache_entry *pce, zend_strin
1945
1946
limit -- ;
1946
1947
1947
1948
/* Advance to the next piece. */
1948
- start_offset = offsets [1 ];
1949
+ start_offset = last_end_offset = offsets [1 ];
1949
1950
1950
1951
/* If we have matched an empty string, mimic what Perl's /g options does.
1951
1952
This turns out to be rather cunning. First we set PCRE2_NOTEMPTY_ATSTART and try
@@ -1965,10 +1966,7 @@ static zend_string *php_pcre_replace_func_impl(pcre_cache_entry *pce, zend_strin
1965
1966
to achieve this, unless we're already at the end of the string. */
1966
1967
if (start_offset < subject_len ) {
1967
1968
size_t unit_len = calculate_unit_length (pce , piece );
1968
-
1969
1969
start_offset += unit_len ;
1970
- memcpy (ZSTR_VAL (result ) + result_len , piece , unit_len );
1971
- result_len += unit_len ;
1972
1970
} else {
1973
1971
goto not_matched ;
1974
1972
}
@@ -1983,7 +1981,7 @@ static zend_string *php_pcre_replace_func_impl(pcre_cache_entry *pce, zend_strin
1983
1981
result = zend_string_copy (subject_str );
1984
1982
break ;
1985
1983
}
1986
- new_len = result_len + subject_len - start_offset ;
1984
+ new_len = result_len + subject_len - last_end_offset ;
1987
1985
if (new_len >= alloc_len ) {
1988
1986
alloc_len = new_len ; /* now we know exactly how long it is */
1989
1987
if (NULL != result ) {
@@ -1993,8 +1991,8 @@ static zend_string *php_pcre_replace_func_impl(pcre_cache_entry *pce, zend_strin
1993
1991
}
1994
1992
}
1995
1993
/* stick that last bit of string on our output */
1996
- memcpy (ZSTR_VAL (result ) + result_len , piece , subject_len - start_offset );
1997
- result_len += subject_len - start_offset ;
1994
+ memcpy (ZSTR_VAL (result ) + result_len , piece , subject_len - last_end_offset );
1995
+ result_len += subject_len - last_end_offset ;
1998
1996
ZSTR_VAL (result )[result_len ] = '\0' ;
1999
1997
ZSTR_LEN (result ) = result_len ;
2000
1998
break ;
0 commit comments