Is my preg_match syntax valid?

[亡魂溺海] 提交于 2019-12-12 18:13:30

问题


I'm adding an if statement to my database abstraction layer to pick out any attempted queries to a handful of database tables.

Basically, if my application attempts to create, read or destroy data from a database table called either members or members_profiles I want to invoke my if statement.

if (
    preg_match('/INSERT INTO [members|members_profiles]/', $sql) ||
    preg_match('/UPDATE [members|members_profiles]/', $sql) ||
    preg_match('/DELETE FROM [members|members_profiles]/', $sql))
{
    // do if statement stuff here...
}

I'm no regular expression/preg-match master, but will the above if statement return true if a SQL query matches:

  • INSERT INTO members ... or INSERT INTO members_profiles ...
  • UPDATE members ... or UPDATE members_profiles ...
  • DELETE FROM members ... or DELETE FROM members_profiles ...

Or is my preg-match syntax way off?


回答1:


Just one regex will be enough:

if (preg_match('/(?i)(INSERT\s+INTO|UPDATE|DELETE\s+FROM)(?-i)\s+(members|members_profiles)/', $sql))
{
    // do if statement stuff here...
}

note the () instead of [] and \s+ instead of spaces. because SQL is valid with any number of nay whitespace, and \s+ matches them all. The + behind \s means that it must be at least one whitespace, but it can be more. The (?i) means that all following characters will be checked case insensitive, and the (?-i) turn case sensitivity on again. Since SQL commands are case insensitive.

(abc|def) matches abc or def
[abc|def] matches a, b, c, |, d, e or f

To try out a regular expression you can use http://rubular.com/, it says it's written in ruby for testing regex in ruby, but valid regex should be independent of language, so it can be used to test common regular expressions, that work in other languages, too.




回答2:


The syntax is valid but won't do what you want.

For alternation of patterns, use

preg_match('/INSERT INTO (?:members|members_profiles)/', $sql) ||
//                       ^^^                        ^

In PCRE, […] defines a character class. This will match 1 character, given it appears inside the brackets. In your case [members|members_profiles] will match 1 character if it is one of b, e, f, i, l, m, o, p, r, s, | or _.

Grouping is done using another kind of parenthesis, (?:…).


(BTW, please don't use Regex to detect database changing attempts. Restrict the permissions of the database user instead.)




回答3:


The regex

[ab|cd]

does not match either ab OR cd but matches one of the following single (!) characters: a, b, |, c or d.

What you need is a group instead of a character class:

(ab|cd)

which does match either ab OR cd.

More info on character classes: http://www.regular-expressions.info/charclass.html




回答4:


This is correct

if (
    preg_match('/INSERT\sINTO\s(members|members_profiles)/', $sql) ||
    preg_match('/UPDATE\s(members|members_profiles)/', $sql) ||
    preg_match('/DELETE\sFROM\s(members|members_profiles)/', $sql))
{
    // do if statement stuff here...
}

LE: Changed white space escaping with white space(s) special character




回答5:


Apart the errors already reported by other users, your regular expression is too restrictive, if you need to detect when a query is trying to alter the tables members, and members_profiles.

I would not use such approach, but if you need to really do that then consider that

  • The database engine allows comments. If the database engine is MySQL, I can write INSERT INTO /* little trick */ members …, or INSERT /* into */ INTO /* table */ members ….
  • The database engine allows any number of spaces, or new line characters.


来源:https://stackoverflow.com/questions/3246239/is-my-preg-match-syntax-valid

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!