29

Is there a good way of test if a string is a regex or normal string in PHP?

Ideally I want to write a function to run a string through, that returns true or false.

I had a look at preg_last_error():

<?php
preg_match('/[a-z]/', 'test');
var_dump(preg_last_error());
preg_match('invalid regex', 'test');
var_dump(preg_last_error());
?>

Where obviously first one is not an error, and second one is. But preg_last_error() returns int 0 both times.

Any ideas?

Hosh Sadiq
  • 1,484
  • 2
  • 21
  • 41

4 Answers4

16

The simplest way to test if a string is a regex is:

if( preg_match("/^\/.+\/[a-z]*$/i",$regex))

This will tell you if a string has a good chance of being intended to be as a regex. However there are many string that would pass that check but fail being a regex. Unescaped slashes in the middle, unknown modifiers at the end, mismatched parentheses etc. could all cause problems.

The reason preg_last_error returned 0 is because the "invalid regex" is not:

  • PREG_INTERNAL_ERROR (an internal error)
  • PREG_BACKTRACK_LIMIT_ERROR (excessively forcing backtracking)
  • PREG_RECURSION_LIMIT_ERROR (excessively recursing)
  • PREG_BAD_UTF8_ERROR (badly formatted UTF-8)
  • PREG_BAD_UTF8_OFFSET_ERROR (offset to the middle of a UTF-8 character)
kingjeffrey
  • 14,316
  • 6
  • 41
  • 47
Niet the Dark Absol
  • 311,322
  • 76
  • 447
  • 566
15

Here is a good answer how to:

https://stackoverflow.com/a/12941133/2519073

if(@preg_match($yourPattern, null) === false){
    //pattern is broken
}else{
    //pattern is real
}
Community
  • 1
  • 1
ya_dimon
  • 2,835
  • 2
  • 26
  • 39
10

The only easy way to test if a regex is valid in PHP is to use it and check if a warning is thrown.

ini_set('track_errors', 'on');
$php_errormsg = '';
@preg_match('/[blah/', '');
if($php_errormsg) echo 'regex is invalid';

However, using arbitrary user input as a regex is a bad idea. There were security holes (buffer overflow => remote code execution) in the PCRE engine before and it might be possible to create specially crafted long regexes which require lots of cpu/memory to compile/execute.

ThiefMaster
  • 298,938
  • 77
  • 579
  • 623
9

Why not just use...another regex? Three lines, no @ kludges or anything:

// Test this string
$str = "/^[A-Za-z ]+$/";

// Compare it to a regex pattern that simulates any regex
$regex = "/^\/[\s\S]+\/$/";

// Will it blend?
echo (preg_match($regex, $str) ? "TRUE" : "FALSE");

Or, in function form, even more pretty:

public static function isRegex($str0) {
    $regex = "/^\/[\s\S]+\/$/";
    return preg_match($regex, $str0);
}

This doesn't test validity; but it looks like the question is Is there a good way of test if a string is a regex or normal string in PHP? and it does do that.

Ben
  • 51,262
  • 47
  • 169
  • 217