Fix RS_isRegis() to agree exactly with RS_compile()'s idea of what's a valid
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 21 Jan 2008 02:46:11 +0000 (02:46 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 21 Jan 2008 02:46:11 +0000 (02:46 +0000)
regis.  Correct the latter's oversight that a bracket-expression needs to be
terminated.  Reduce the ereports to elogs, since they are now not expected to
ever be hit (thus addressing Alvaro's original complaint).
In passing, const-ify the string argument to RS_compile.

src/backend/tsearch/regis.c
src/backend/tsearch/spell.c
src/include/tsearch/dicts/regis.h

index 0656f357d21f07ce050a05b02e9b1a7127e28593..3f4a7754c4a6da5e60e1fce0400cb59e87ab0e7e 100644 (file)
 #include "tsearch/dicts/regis.h"
 #include "tsearch/ts_locale.h"
 
+#define RS_IN_ONEOF 1
+#define RS_IN_ONEOF_IN 2
+#define RS_IN_NONEOF   3
+#define RS_IN_WAIT     4
+
+
+/*
+ * Test whether a regex is of the subset supported here.
+ * Keep this in sync with RS_compile!
+ */
 bool
 RS_isRegis(const char *str)
 {
-       while (str && *str)
+       int                     state = RS_IN_WAIT;
+       const char *c = str;
+
+       while (*c)
        {
-               if (t_isalpha(str) ||
-                       t_iseq(str, '[') ||
-                       t_iseq(str, ']') ||
-                       t_iseq(str, '^'))
-                       str += pg_mblen(str);
+               if (state == RS_IN_WAIT)
+               {
+                       if (t_isalpha(c))
+                               /* okay */ ;
+                       else if (t_iseq(c, '['))
+                               state = RS_IN_ONEOF;
+                       else
+                               return false;
+               }
+               else if (state == RS_IN_ONEOF)
+               {
+                       if (t_iseq(c, '^'))
+                               state = RS_IN_NONEOF;
+                       else if (t_isalpha(c))
+                               state = RS_IN_ONEOF_IN;
+                       else
+                               return false;
+               }
+               else if (state == RS_IN_ONEOF_IN || state == RS_IN_NONEOF)
+               {
+                       if (t_isalpha(c))
+                               /* okay */ ;
+                       else if (t_iseq(c, ']'))
+                               state = RS_IN_WAIT;
+                       else
+                               return false;
+               }
                else
-                       return false;
+                       elog(ERROR, "internal error in RS_isRegis: state %d", state);
+               c += pg_mblen(c);
        }
-       return true;
-}
 
-#define RS_IN_ONEOF 1
-#define RS_IN_ONEOF_IN 2
-#define RS_IN_NONEOF   3
-#define RS_IN_WAIT     4
+       return (state == RS_IN_WAIT);
+}
 
 static RegisNode *
 newRegisNode(RegisNode *prev, int len)
@@ -50,11 +82,11 @@ newRegisNode(RegisNode *prev, int len)
 }
 
 void
-RS_compile(Regis *r, bool issuffix, char *str)
+RS_compile(Regis *r, bool issuffix, const char *str)
 {
        int                     len = strlen(str);
        int                     state = RS_IN_WAIT;
-       char       *c = (char *) str;
+       const char *c = str;
        RegisNode  *ptr = NULL;
 
        memset(r, 0, sizeof(Regis));
@@ -83,11 +115,8 @@ RS_compile(Regis *r, bool issuffix, char *str)
                                ptr->type = RSF_ONEOF;
                                state = RS_IN_ONEOF;
                        }
-                       else
-                               ereport(ERROR,
-                                               (errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
-                                                errmsg("invalid regis pattern: \"%s\"",
-                                                               str)));
+                       else                            /* shouldn't get here */
+                               elog(ERROR, "invalid regis pattern: \"%s\"", str);
                }
                else if (state == RS_IN_ONEOF)
                {
@@ -102,11 +131,8 @@ RS_compile(Regis *r, bool issuffix, char *str)
                                ptr->len = pg_mblen(c);
                                state = RS_IN_ONEOF_IN;
                        }
-                       else
-                               ereport(ERROR,
-                                               (errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
-                                                errmsg("invalid regis pattern: \"%s\"",
-                                                               str)));
+                       else                            /* shouldn't get here */
+                               elog(ERROR, "invalid regis pattern: \"%s\"", str);
                }
                else if (state == RS_IN_ONEOF_IN || state == RS_IN_NONEOF)
                {
@@ -117,17 +143,17 @@ RS_compile(Regis *r, bool issuffix, char *str)
                        }
                        else if (t_iseq(c, ']'))
                                state = RS_IN_WAIT;
-                       else
-                               ereport(ERROR,
-                                               (errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
-                                                errmsg("invalid regis pattern: \"%s\"",
-                                                               str)));
+                       else                            /* shouldn't get here */
+                               elog(ERROR, "invalid regis pattern: \"%s\"", str);
                }
                else
                        elog(ERROR, "internal error in RS_compile: state %d", state);
                c += pg_mblen(c);
        }
 
+       if (state != RS_IN_WAIT)                /* shouldn't get here */
+               elog(ERROR, "invalid regis pattern: \"%s\"", str);
+
        ptr = r->node;
        while (ptr)
        {
index 5a9645ffbddc31b350b11f7df756d685b56cf0b8..f10d23c1421bd84c3c455f405adef41e3793698f 100644 (file)
@@ -333,7 +333,7 @@ NIAddAffix(IspellDict *Conf, int flag, char flagflags, const char *mask, const c
                Affix->issimple = 0;
                Affix->isregis = 1;
                RS_compile(&(Affix->reg.regis), (type == FF_SUFFIX) ? true : false,
-                                  (char *) ((mask && *mask) ? mask : VoidString));
+                                  (mask && *mask) ? mask : VoidString);
        }
        else
        {
index 88c7a021cd2d906831b6cc3a0b2c033a8cd4131f..5b905c53a29c7f3b37132ea2f10a4f193137dec1 100644 (file)
@@ -40,7 +40,7 @@ typedef struct Regis
 
 bool           RS_isRegis(const char *str);
 
-void           RS_compile(Regis *r, bool issuffix, char *str);
+void           RS_compile(Regis *r, bool issuffix, const char *str);
 void           RS_free(Regis *r);
 
 /*returns true if matches */