[augeas-devel] augeas: master - Properly check regexp literals for syntax errors

David Lutterkort lutter at fedoraproject.org
Thu Nov 26 01:15:44 UTC 2009


Gitweb:        http://git.fedorahosted.org/git/augeas.git?p=augeas.git;a=commitdiff;h=51cfb5af2805ff602c8b1f398b13cf4930c688b4
Commit:        51cfb5af2805ff602c8b1f398b13cf4930c688b4
Parent:        4effdd8e3d94bbd49cd50f1ff21b41b03cd10e1b
Author:        David Lutterkort <lutter at redhat.com>
AuthorDate:    Wed Nov 25 17:10:27 2009 -0800
Committer:     David Lutterkort <lutter at redhat.com>
CommitterDate: Wed Nov 25 17:10:27 2009 -0800

Properly check regexp literals for syntax errors

  * src/regexp.h (regexp_check): new function
  * src/regexp.c (regexp_compile_internal): new function to base both
    regexp_compile and regexp_check off
  * src/syntax.c (check_value): produce a syntax error if regexp does not
    pass regexp_check; (check_exp): make sure we do check values

Fixes ticket #93
---
 src/regexp.c |   20 ++++++++++++++++----
 src/regexp.h |    6 ++++++
 src/syntax.c |    8 ++++++--
 3 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/src/regexp.c b/src/regexp.c
index caecce4..85dea58 100644
--- a/src/regexp.c
+++ b/src/regexp.c
@@ -26,6 +26,7 @@
 #include "internal.h"
 #include "syntax.h"
 #include "memory.h"
+#include "errcode.h"
 
 static const struct string empty_pattern_string = {
     .ref = REF_MAX, .str = (char *) "()"
@@ -331,7 +332,7 @@ struct regexp *regexp_make_empty(struct info *info) {
     return regexp;
 }
 
-int regexp_compile(struct regexp *r) {
+static int regexp_compile_internal(struct regexp *r, const char **c) {
     /* See the GNU regex manual or regex.h in gnulib for
      * an explanation of these flags. They are set so that the regex
      * matcher interprets regular expressions the same way that libfa
@@ -343,21 +344,32 @@ int regexp_compile(struct regexp *r) {
         |RE_NO_BK_VBAR|RE_NO_EMPTY_RANGES
         |RE_NO_POSIX_BACKTRACKING|RE_CONTEXT_INVALID_DUP|RE_NO_GNU_OPS;
     reg_syntax_t old_syntax = re_syntax_options;
-    const char *c = NULL;
+
+    *c = NULL;
 
     if (r->re == NULL)
         CALLOC(r->re, 1);
 
     re_syntax_options = syntax;
-    c = re_compile_pattern(r->pattern->str, strlen(r->pattern->str), r->re);
+    *c = re_compile_pattern(r->pattern->str, strlen(r->pattern->str), r->re);
     re_syntax_options = old_syntax;
 
     r->re->regs_allocated = REGS_REALLOCATE;
-    if (c != NULL)
+    if (*c != NULL)
         return -1;
     return 0;
 }
 
+int regexp_compile(struct regexp *r) {
+    const char *c;
+
+    return regexp_compile_internal(r, &c);
+}
+
+int regexp_check(struct regexp *r, const char **msg) {
+    return regexp_compile_internal(r, msg);
+}
+
 int regexp_match(struct regexp *r,
                  const char *string, const int size,
                  const int start, struct re_registers *regs) {
diff --git a/src/regexp.h b/src/regexp.h
index ef601d8..783b123 100644
--- a/src/regexp.h
+++ b/src/regexp.h
@@ -57,6 +57,12 @@ void free_regexp(struct regexp *regexp);
  */
 int regexp_compile(struct regexp *r);
 
+/* Check the syntax of R->PATTERN; return -1 if the pattern has a syntax
+ * error, and a string indicating the error in *C. Return 0 if the pattern
+ * is a valid regular expression.
+ */
+int regexp_check(struct regexp *r, const char **msg);
+
 /* Call RE_MATCH on R->RE and return its result; if R hasn't been compiled
  * yet, compile it. Return -3 if compilation fails
  */
diff --git a/src/syntax.c b/src/syntax.c
index 686d0c8..6918376 100644
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -1147,9 +1147,13 @@ static int check_binop(const char *opname, struct term *term,
 }
 
 static int check_value(struct value *v) {
+    const char *msg;
+
     if (v->tag == V_REGEXP) {
-        if (regexp_compile(v->regexp) == -1)
+        if (regexp_check(v->regexp, &msg) == -1) {
+            syntax_error(v->info, "Invalid regular expression: %s", msg);
             return 0;
+        }
     }
     return 1;
 }
@@ -1158,7 +1162,7 @@ static int check_value(struct value *v) {
 static int check_exp(struct term *term, struct ctx *ctx) {
     int result = 1;
     assert(term->type == NULL || term->tag == A_VALUE || term->ref > 1);
-    if (term->type != NULL)
+    if (term->type != NULL && term->tag != A_VALUE)
         return 1;
 
     switch (term->tag) {




More information about the augeas-devel mailing list