version 1.1.1.3, 2013/07/22 01:17:36
|
version 1.1.1.4, 2013/10/14 07:54:04
|
Line 364 void syserror(const char *message){
|
Line 364 void syserror(const char *message){
|
return; |
return; |
} |
} |
|
|
|
// Check regular expression for non-portable features. |
|
// |
// POSIX extended regular expressions interpret unmatched ')' ordinary: |
// POSIX extended regular expressions interpret unmatched ')' ordinary: |
// "The close-parenthesis shall be considered special in this context |
// "The close-parenthesis shall be considered special in this context |
// only if matched with a preceding open-parenthesis." |
// only if matched with a preceding open-parenthesis." |
// |
// |
// Actual '(...)' nesting errors remain undetected on strict POSIX | // GNU libc and BSD libc support unmatched ')', Cygwin reports an error. |
// implementations (glibc) but an error is reported on others (Cygwin). | // |
// | // POSIX extended regular expressions do not define empty subexpressions: |
// The check below is rather incomplete because it does not handle | // "A vertical-line appearing first or last in an ERE, or immediately following |
// e.g. '\)' '[)]'. | // a vertical-line or a left-parenthesis, or immediately preceding a |
// But it should work for the regex subset used in drive database | // right-parenthesis, produces undefined results." |
// and smartd '-s' directives. | // |
static int check_regex_nesting(const char * pattern) | // GNU libc and Cygwin support empty subexpressions, BSD libc reports an error. |
| // |
| static const char * check_regex(const char * pattern) |
{ |
{ |
int level = 0, i; | int level = 0; |
for (i = 0; pattern[i] && level >= 0; i++) { | char c; |
switch (pattern[i]) { | |
case '(': level++; break; | for (int i = 0; (c = pattern[i]); i++) { |
case ')': level--; break; | // Skip "\x" |
| if (c == '\\') { |
| if (!pattern[++i]) |
| break; |
| continue; |
} |
} |
|
|
|
// Skip "[...]" |
|
if (c == '[') { |
|
if (pattern[++i] == '^') |
|
i++; |
|
if (!pattern[i++]) |
|
break; |
|
while ((c = pattern[i]) && c != ']') |
|
i++; |
|
if (!c) |
|
break; |
|
continue; |
|
} |
|
|
|
// Check "(...)" nesting |
|
if (c == '(') |
|
level++; |
|
else if (c == ')' && --level < 0) |
|
return "Unmatched ')'"; |
|
|
|
// Check for leading/trailing '|' or "||", "|)", "|$", "(|", "^|" |
|
char c1; |
|
if ( (c == '|' && ( i == 0 || !(c1 = pattern[i+1]) |
|
|| c1 == '|' || c1 == ')' || c1 == '$')) |
|
|| ((c == '(' || c == '^') && pattern[i+1] == '|') ) |
|
return "Empty '|' subexpression"; |
} |
} |
return level; | |
| return (const char *)0; |
} |
} |
|
|
// Wrapper class for regex(3) |
// Wrapper class for regex(3) |
Line 465 bool regular_expression::compile()
|
Line 500 bool regular_expression::compile()
|
return false; |
return false; |
} |
} |
|
|
if (check_regex_nesting(m_pattern.c_str()) < 0) { | const char * errmsg = check_regex(m_pattern.c_str()); |
m_errmsg = "Unmatched ')'"; | if (errmsg) { |
| m_errmsg = errmsg; |
free_buf(); |
free_buf(); |
return false; |
return false; |
} |
} |