I'm writing this answer, because I stumbeled across the same problem. As Alan Moore pointed out the adjusting the backtrack and recursion limits won't help to solve the problem.
The described error occurs when a needle exceeds the largest possible needle size, which is limited by the underlying pcre library. The described error is NOT caused by php, but by the underlying pcre library. It's the error message #20 which is defined here:
https://github.com/php/.../pcre_compile.c#L477
php just prints the errortext it received from the pcre library on failure.
However, this error appears in my environment, when I try using previously captured fragments as a needle and they're bigger than 32k bytes.
It can easily be tested by using this simple script from php's cli
<?php
// This script demonstrates the above error and dumps an info
// when the needle is too long or with 64k iterations.
$expand=$needle="_^b_";
while( ! preg_match( $needle, "Stack Exchange Demo Text" ) )
{
// Die after 64 kbytes of accumulated chunk needle
// Adjust to 32k for a better illustration
if ( strlen($expand) > 1024*64 ) die();
if ( $expand == "_^b_" ) $expand = "";
$expand .= "a";
$needle = '_^'.$needle.'_ism';
echo strlen($needle)."\n";
}
?>
To fix the error, either the resulting needle must be reduced or - if everything is needed to be captured - multiple preg_match with the additional offset parameter must be used.
<?php
if (
preg_match(
'/'.preg_quote(
substr( $big_chunk, 0, 20*1024 ) // 1st 20k chars
)
.'.*?'.
preg_quote(
substr( $big_chunk, -5 ) // last 5
)
.'/',
$subject
)
) {
// do stuff
}
// The match all needles in text attempt
if ( preg_match(
$needle_of_1st_32kbytes_chunk,
$subj, $matches, $flags = 0,
$offset = 32*1024*0 // Offset -> 0
)
&& preg_match(
$needle_of_2nd_32kbytes_chunk,
$subj, $matches, $flags = 0,
$offset = 32*1024*1 // Offset -> 32k
)
// && ... as many preg matches as needed
) {
// do stuff
}
// it would be nicer to put the texts in a foreach-loop iterating
// over the existings chunks
?>
You get the idea.
Allthough this answer is kinda laaaaate, I hope it still helps people who run into this problem without a good explanation why the error occurs.