1

Why does this call return NULL? Is the regex wrong? With the test input it doesn't return NULL. The docs say NULL indicates an error but what error could it be?

$s = hex2bin('5b5d202073205b0d0a0d0a0d0a0d0a20202020202020203a');
// $s = 'test';
$s = preg_replace('/\[\](\s|.)*\]/s', '', $s);
var_dump($s);

// PHP 7.2.10-1+0~20181001133118.7+stretch~1.gbpb6e829 (cli) (built: Oct  1 2018 13:31:18) ( NTS )
XTF
  • 1,091
  • 1
  • 13
  • 31
  • What do you need to do here? Your `$s` has no second `]` hence there is no match. Also, `(\s|.)*` is not necessary, it is bad, just use `.*` (`preg_replace("/\[].*]/s", "", $s)`) – Wiktor Stribiżew Oct 26 '18 at 20:51
  • 1
    It's also a good idea to use single quotes around a regexp rather than double quotes. Otherwise you run the risk that a regexp escape sequence will be processed as a string escape sequence. – Barmar Oct 26 '18 at 20:54
  • 1
    @WiktorStribiżew I'm primarily wondering why this returns NULL. If there's no match the input should just be returned shouldn't it? – XTF Oct 26 '18 at 20:54
  • It return `NULL` if the regexp is invalid. – Barmar Oct 26 '18 at 20:55
  • 1
    What's the point of `(\s|.)`. `.` matches `\s` already.. – Devon Bessemer Oct 26 '18 at 20:58
  • Your initial string is not `'test'`. – Barmar Oct 26 '18 at 21:01

1 Answers1

5

Your regex is causing catastrophic backtracking and causing PHP regex engine to fail. You can use preg_last_error() function to check this.

$r = preg_replace("/\[\](\s|.)*\]/s", "", $s);
if (preg_last_error() == PREG_BACKTRACK_LIMIT_ERROR) {
    print 'Backtrack limit was exhausted!';
}

Output:

Backtrack limit was exhausted!

You are getting NULL return value from preg_replace due to this error. As per PHP doc of preg_replace:

If matches are found, the new subject will be returned, otherwise subject will be returned unchanged or NULL if an error occurred.


Fix: You don't need (\s|.) when using s modifier (DOTALL). since dot matches any character including newline when using s modifier.

You should just use this regex:

$r = preg_replace('/\[\].*?\]/s', "", $s);
echo preg_last_error();
//=> 0
anubhava
  • 761,203
  • 64
  • 569
  • 643