@@ -1561,6 +1561,7 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *su
1561
1561
size_t match_len ; /* Length of the current match */
1562
1562
int backref ; /* Backreference number */
1563
1563
PCRE2_SIZE start_offset ; /* Where the new search starts */
1564
+ size_t last_end_offset ; /* Where the last search ended */
1564
1565
char * walkbuf , /* Location of current replacement in the result */
1565
1566
* walk , /* Used to walk the replacement string */
1566
1567
* match , /* The current match */
@@ -1579,6 +1580,7 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *su
1579
1580
/* Initialize */
1580
1581
match = NULL ;
1581
1582
start_offset = 0 ;
1583
+ last_end_offset = 0 ;
1582
1584
result_len = 0 ;
1583
1585
PCRE_G (error_code ) = PHP_PCRE_NO_ERROR ;
1584
1586
@@ -1605,7 +1607,7 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *su
1605
1607
options , match_data , mctx );
1606
1608
1607
1609
while (1 ) {
1608
- piece = subject + start_offset ;
1610
+ piece = subject + last_end_offset ;
1609
1611
1610
1612
if (count >= 0 && limit > 0 ) {
1611
1613
zend_bool simple_string ;
@@ -1635,7 +1637,7 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *su
1635
1637
/* Set the match location in subject */
1636
1638
match = subject + offsets [0 ];
1637
1639
1638
- new_len = result_len + offsets [0 ] - start_offset ; /* part before the match */
1640
+ new_len = result_len + offsets [0 ] - last_end_offset ; /* part before the match */
1639
1641
1640
1642
walk = ZSTR_VAL (replace_str );
1641
1643
replace_end = walk + ZSTR_LEN (replace_str );
@@ -1712,7 +1714,7 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *su
1712
1714
limit -- ;
1713
1715
1714
1716
/* Advance to the next piece. */
1715
- start_offset = offsets [1 ];
1717
+ start_offset = last_end_offset = offsets [1 ];
1716
1718
1717
1719
/* If we have matched an empty string, mimic what Perl's /g options does.
1718
1720
This turns out to be rather cunning. First we set PCRE2_NOTEMPTY_ATSTART and try
@@ -1732,10 +1734,7 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *su
1732
1734
to achieve this, unless we're already at the end of the string. */
1733
1735
if (start_offset < subject_len ) {
1734
1736
size_t unit_len = calculate_unit_length (pce , piece );
1735
-
1736
1737
start_offset += unit_len ;
1737
- memcpy (ZSTR_VAL (result ) + result_len , piece , unit_len );
1738
- result_len += unit_len ;
1739
1738
} else {
1740
1739
goto not_matched ;
1741
1740
}
@@ -1750,7 +1749,7 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *su
1750
1749
result = zend_string_copy (subject_str );
1751
1750
break ;
1752
1751
}
1753
- new_len = result_len + subject_len - start_offset ;
1752
+ new_len = result_len + subject_len - last_end_offset ;
1754
1753
if (new_len >= alloc_len ) {
1755
1754
alloc_len = new_len ; /* now we know exactly how long it is */
1756
1755
if (NULL != result ) {
@@ -1760,8 +1759,8 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *su
1760
1759
}
1761
1760
}
1762
1761
/* stick that last bit of string on our output */
1763
- memcpy (ZSTR_VAL (result ) + result_len , piece , subject_len - start_offset );
1764
- result_len += subject_len - start_offset ;
1762
+ memcpy (ZSTR_VAL (result ) + result_len , piece , subject_len - last_end_offset );
1763
+ result_len += subject_len - last_end_offset ;
1765
1764
ZSTR_VAL (result )[result_len ] = '\0' ;
1766
1765
ZSTR_LEN (result ) = result_len ;
1767
1766
break ;
@@ -1803,6 +1802,7 @@ static zend_string *php_pcre_replace_func_impl(pcre_cache_entry *pce, zend_strin
1803
1802
size_t new_len ; /* Length of needed storage */
1804
1803
size_t alloc_len ; /* Actual allocated length */
1805
1804
PCRE2_SIZE start_offset ; /* Where the new search starts */
1805
+ size_t last_end_offset ; /* Where the last search ended */
1806
1806
char * match , /* The current match */
1807
1807
* piece ; /* The current piece of subject */
1808
1808
size_t result_len ; /* Length of result */
@@ -1832,6 +1832,7 @@ static zend_string *php_pcre_replace_func_impl(pcre_cache_entry *pce, zend_strin
1832
1832
/* Initialize */
1833
1833
match = NULL ;
1834
1834
start_offset = 0 ;
1835
+ last_end_offset = 0 ;
1835
1836
result_len = 0 ;
1836
1837
PCRE_G (error_code ) = PHP_PCRE_NO_ERROR ;
1837
1838
@@ -1864,7 +1865,7 @@ static zend_string *php_pcre_replace_func_impl(pcre_cache_entry *pce, zend_strin
1864
1865
options , match_data , mctx );
1865
1866
1866
1867
while (1 ) {
1867
- piece = subject + start_offset ;
1868
+ piece = subject + last_end_offset ;
1868
1869
1869
1870
if (count >= 0 && limit ) {
1870
1871
/* Check for too many substrings condition. */
@@ -1892,7 +1893,7 @@ static zend_string *php_pcre_replace_func_impl(pcre_cache_entry *pce, zend_strin
1892
1893
/* Set the match location in subject */
1893
1894
match = subject + offsets [0 ];
1894
1895
1895
- new_len = result_len + offsets [0 ] - start_offset ; /* part before the match */
1896
+ new_len = result_len + offsets [0 ] - last_end_offset ; /* part before the match */
1896
1897
1897
1898
/* Use custom function to get replacement string and its length. */
1898
1899
eval_result = preg_do_repl_func (
@@ -1924,7 +1925,7 @@ static zend_string *php_pcre_replace_func_impl(pcre_cache_entry *pce, zend_strin
1924
1925
limit -- ;
1925
1926
1926
1927
/* Advance to the next piece. */
1927
- start_offset = offsets [1 ];
1928
+ start_offset = last_end_offset = offsets [1 ];
1928
1929
1929
1930
/* If we have matched an empty string, mimic what Perl's /g options does.
1930
1931
This turns out to be rather cunning. First we set PCRE2_NOTEMPTY_ATSTART and try
@@ -1944,10 +1945,7 @@ static zend_string *php_pcre_replace_func_impl(pcre_cache_entry *pce, zend_strin
1944
1945
to achieve this, unless we're already at the end of the string. */
1945
1946
if (start_offset < subject_len ) {
1946
1947
size_t unit_len = calculate_unit_length (pce , piece );
1947
-
1948
1948
start_offset += unit_len ;
1949
- memcpy (ZSTR_VAL (result ) + result_len , piece , unit_len );
1950
- result_len += unit_len ;
1951
1949
} else {
1952
1950
goto not_matched ;
1953
1951
}
@@ -1962,7 +1960,7 @@ static zend_string *php_pcre_replace_func_impl(pcre_cache_entry *pce, zend_strin
1962
1960
result = zend_string_copy (subject_str );
1963
1961
break ;
1964
1962
}
1965
- new_len = result_len + subject_len - start_offset ;
1963
+ new_len = result_len + subject_len - last_end_offset ;
1966
1964
if (new_len >= alloc_len ) {
1967
1965
alloc_len = new_len ; /* now we know exactly how long it is */
1968
1966
if (NULL != result ) {
@@ -1972,8 +1970,8 @@ static zend_string *php_pcre_replace_func_impl(pcre_cache_entry *pce, zend_strin
1972
1970
}
1973
1971
}
1974
1972
/* stick that last bit of string on our output */
1975
- memcpy (ZSTR_VAL (result ) + result_len , piece , subject_len - start_offset );
1976
- result_len += subject_len - start_offset ;
1973
+ memcpy (ZSTR_VAL (result ) + result_len , piece , subject_len - last_end_offset );
1974
+ result_len += subject_len - last_end_offset ;
1977
1975
ZSTR_VAL (result )[result_len ] = '\0' ;
1978
1976
ZSTR_LEN (result ) = result_len ;
1979
1977
break ;
0 commit comments