Tweak the ACL variable name code to require either a digit or an
authorPhilip Hazel <ph10@hermes.cam.ac.uk>
Tue, 19 Sep 2006 14:31:06 +0000 (14:31 +0000)
committerPhilip Hazel <ph10@hermes.cam.ac.uk>
Tue, 19 Sep 2006 14:31:06 +0000 (14:31 +0000)
underscore after acl_c or acl_m.

doc/doc-txt/ChangeLog
doc/doc-txt/NewStuff
src/src/acl.c
src/src/expand.c
test/aux-var-src/0372.F
test/confs/0372
test/stderr/0372

index 7dc6095..1dcf3b2 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.393 2006/09/19 11:28:44 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.394 2006/09/19 14:31:06 ph10 Exp $
 
 Change log file for Exim from version 4.21
 -------------------------------------------
@@ -43,7 +43,7 @@ PH/07 There was no check for overflow in expansions such as ${if >{1}{4096M}}.
 PH/08 An error is now given if message_size_limit is specified negative.
 
 PH/09 Applied and tidied up Jakob Hirsch's patch for allowing ACL variables
-      to be given arbitrary names.
+      to be given (somewhat) arbitrary names.
 
 
 Exim version 4.63
index 5be3e69..6ee8f6b 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/NewStuff,v 1.109 2006/09/19 11:28:44 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/NewStuff,v 1.110 2006/09/19 14:31:06 ph10 Exp $
 
 New Features in Exim
 --------------------
@@ -13,22 +13,23 @@ Version 4.64
 ------------
 
 1. ACL variables can now be given arbitrary names, as long as they start with
-   "acl_c" or "acl_m" (for connection variables and message variables) and are
-   at least 6 characters long. However, only alphanumeric characters and
-   underscores are allowed. This is a compatible change because the old set of
+   "acl_c" or "acl_m" (for connection variables and message variables), are
+   at least six characters long, with the sixth character being either a digit
+   or an underscore. The rest of the name can contain alphanumeric characters
+   and underscores. This is a compatible change because the old set of
    variables such as acl_m12 are a subset of the allowed names. There may now
    be any number of ACL variables. For example:
 
-     set acl_c_foo = something
-     set acl_ccc   = thingsome
-     set acl_m13   = value for original ACL variable
-     set acl_m13b  = whatever
+     set acl_c13   = value for original ACL variable
+     set acl_c13b  = whatever
+     set acl_m_foo = something
 
-   What happens if an undefined ACL variable is referenced depends on the
-   setting of the strict_acl_vars option. If it is false (the default), an
-   empty string is substituted; if it is true, an error is generated. This
-   affects all ACL variables, including the "old" ones such as acl_c4.
-   (Previously there wasn't the concept of an undefined ACL variable.)
+   What happens if a syntactically valid but undefined ACL variable is
+   referenced depends on the setting of the strict_acl_vars option. If it is
+   false (the default), an empty string is substituted; if it is true, an error
+   is generated. This affects all ACL variables, including the "old" ones such
+   as acl_c4. (Previously there wasn't the concept of an undefined ACL
+   variable.)
 
    The implementation has been done in such a way that spool files containing
    ACL variable settings written by previous releases of Exim are compatible
index 8c2ab69..5709a11 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/acl.c,v 1.64 2006/09/19 11:28:45 ph10 Exp $ */
+/* $Cambridge: exim/src/src/acl.c,v 1.65 2006/09/19 14:31:06 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -808,8 +808,10 @@ while ((s = (*func)()) != NULL)
   gives us a variable name to insert into the data block. The original ACL
   variable names were acl_c0 ... acl_c9 and acl_m0 ... acl_m9. This was
   extended to 20 of each type, but after that people successfully argued for
-  arbitrary names. For compatibility, however, the names must still start with
-  acl_c or acl_m. After that, we allow alphanumerics and underscores. */
+  arbitrary names. In the new scheme, the names must start with acl_c or acl_m.
+  After that, we allow alphanumerics and underscores, but the first character
+  after c or m must be a digit or an underscore. This retains backwards
+  compatibility. */
 
   if (c == ACLC_SET)
     {
@@ -824,6 +826,14 @@ while ((s = (*func)()) != NULL)
       }
 
     endptr = s + 5;
+    if (!isdigit(*endptr) && *endptr != '_')
+      {
+      *error = string_sprintf("invalid variable name after \"set\" in ACL "
+        "modifier \"set %s\" (digit or underscore must follow acl_c or acl_m)",
+        s);
+      return NULL;
+      }
+
     while (*endptr != 0 && *endptr != '=' && !isspace(*endptr))
       {
       if (!isalnum(*endptr) && *endptr != '_')
@@ -835,13 +845,6 @@ while ((s = (*func)()) != NULL)
       endptr++;
       }
 
-    if (endptr - s < 6)
-      {
-      *error = string_sprintf("invalid variable name after \"set\" in ACL "
-        "modifier \"set %s\" (must be at least 6 characters)", s);
-      return NULL;
-      }
-
     cond->u.varname = string_copyn(s + 4, endptr - s - 4);
     s = endptr;
     while (isspace(*s)) s++;
index 2e39f26..b47a1bc 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/expand.c,v 1.61 2006/09/19 11:28:45 ph10 Exp $ */
+/* $Cambridge: exim/src/src/expand.c,v 1.62 2006/09/19 14:31:07 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -1236,15 +1236,16 @@ int last = var_table_size;
 /* Handle ACL variables, whose names are of the form acl_cxxx or acl_mxxx.
 Originally, xxx had to be a number in the range 0-9 (later 0-19), but from
 release 4.64 onwards arbitrary names are permitted, as long as the first 5
-characters are acl_c or acl_m (this gave backwards compatibility at the
-changeover). There may be built-in variables whose names start acl_ but they
-should never start acl_c or acl_m. This slightly messy specification is a
-consequence of the history, needless to say.
+characters are acl_c or acl_m and the sixth is either a digit or an underscore
+(this gave backwards compatibility at the changeover). There may be built-in
+variables whose names start acl_ but they should never start in this way. This
+slightly messy specification is a consequence of the history, needless to say.
 
 If an ACL variable does not exist, treat it as empty, unless strict_acl_vars is
 set, in which case give an error. */
 
-if (Ustrncmp(name, "acl_c", 5) == 0 || Ustrncmp(name, "acl_m", 5) == 0)
+if ((Ustrncmp(name, "acl_c", 5) == 0 || Ustrncmp(name, "acl_m", 5) == 0) &&
+     !isalpha(name[5]))
   {
   tree_node *node =
     tree_search((name[4] == 'c')? acl_var_c : acl_var_m, name + 4);
@@ -1566,6 +1567,33 @@ return 0;
 
 
 /*************************************************
+*     Elaborate message for bad variable         *
+*************************************************/
+
+/* For the "unknown variable" message, take a look at the variable's name, and
+give additional information about possible ACL variables. The extra information
+is added on to expand_string_message.
+
+Argument:   the name of the variable
+Returns:    nothing
+*/
+
+static void
+check_variable_error_message(uschar *name)
+{
+if (Ustrncmp(name, "acl_", 4) == 0)
+  expand_string_message = string_sprintf("%s (%s)", expand_string_message,
+    (name[4] == 'c' || name[4] == 'm')?
+      (isalpha(name[5])?
+        US"6th character of a user-defined ACL variable must be a digit or underscore" :
+        US"strict_acl_vars is set"    /* Syntax is OK, it has to be this */
+      ) :
+      US"user-defined ACL variables must start acl_c or acl_m");
+}
+
+
+
+/*************************************************
 *        Read and evaluate a condition           *
 *************************************************/
 
@@ -1671,13 +1699,7 @@ switch(cond_type)
       expand_string_message = (name[0] == 0)?
         string_sprintf("variable name omitted after \"def:\"") :
         string_sprintf("unknown variable \"%s\" after \"def:\"", name);
-
-      if (strict_acl_vars &&
-          Ustrncmp(name, "acl_", 4) == 0 &&
-          (name[4] == 'c' || name[4] == 'm'))
-        expand_string_message = string_sprintf("%s (strict_acl_vars is set)",
-          expand_string_message);
-
+      check_variable_error_message(name);
       return NULL;
       }
     if (yield != NULL) *yield = (value[0] != 0) == testfor;
@@ -2956,13 +2978,7 @@ while (*s != 0)
         {
         expand_string_message =
           string_sprintf("unknown variable name \"%s\"", name);
-
-        if (strict_acl_vars &&
-            Ustrncmp(name, "acl_", 4) == 0 &&
-            (name[4] == 'c' || name[4] == 'm'))
-          expand_string_message = string_sprintf("%s (strict_acl_vars is set)",
-            expand_string_message);
-
+          check_variable_error_message(name);
         goto EXPAND_FAILED;
         }
       }
@@ -5122,13 +5138,7 @@ while (*s != 0)
       {
       expand_string_message =
         string_sprintf("unknown variable in \"${%s}\"", name);
-
-      if (strict_acl_vars &&
-          Ustrncmp(name, "acl_", 4) == 0 &&
-          (name[4] == 'c' || name[4] == 'm'))
-        expand_string_message = string_sprintf("%s (strict_acl_vars is set)",
-          expand_string_message);
-
+      check_variable_error_message(name);
       goto EXPAND_FAILED;
       }
     len = Ustrlen(value);
index c241837..df13039 100644 (file)
@@ -10,7 +10,7 @@ logwrite "  acl_c0=\"$acl_c0\"\n  acl_c1=\"$acl_c1\"\n  acl_c2=\"$acl_c2\"\n  \
             acl_m2=\"$acl_m2\"\n  acl_m3=\"$acl_m3\"\n  acl_m4=\"$acl_m4\"\n  \
             acl_m5=\"$acl_m5\"\n  acl_m6=\"$acl_m6\"\n  acl_m7=\"$acl_m7\"\n  \
             acl_m8=\"$acl_m8\"\n  acl_m9=\"$acl_m9\"\n  \
-            acl_mfoo=\"$acl_mfoo\"\n  acl_mbar=\"$acl_mbar\"\n  \
+            acl_m_foo=\"$acl_m_foo\"\n  acl_m_bar=\"$acl_m_bar\"\n  \
             acl_c_foo=\"$acl_c_foo\"\n  acl_c_bar=\"$acl_c_bar\"\n"  
 logwrite "-------------------------"
 
index 682eb91..af03b3a 100644 (file)
@@ -30,8 +30,8 @@ a1:
          set acl_m0  = value for m0 is local_part: $local_part
          set acl_m5  = value for m5 contains newline\nthere!
          set acl_m9  = value for m9 is domain: $domain
-         set acl_mfoo = value for mfoo is local_part: $local_part
-         set acl_mbar = value for mbar is domain: $domain
+         set acl_m_foo = value for mfoo is local_part: $local_part
+         set acl_m_bar = value for mbar is domain: $domain
 
   accept local_parts = a
          set acl_m0  = value for m0 is local_part: $local_part
@@ -58,7 +58,7 @@ r1:
                 acl_m2="$acl_m2"\nacl_m3="$acl_m3"\nacl_m4="$acl_m4"\n\
                 acl_m5="$acl_m5"\nacl_m6="$acl_m6"\nacl_m7="$acl_m7"\n\
                 acl_m8="$acl_m8"\nacl_m9="$acl_m9"\n\
-                acl_mfoo="$acl_mfoo"\nacl_mbar="$acl_mbar"\n\
+                acl_m_foo="$acl_m_foo"\nacl_m_bar="$acl_m_bar"\n\
                 acl_c_foo="$acl_c_foo"\nacl_c_bar="$acl_c_bar"
   transport = t1
 
index b0c01f4..771c7a4 100644 (file)
@@ -26,8 +26,8 @@ there!"
   acl_m7=""
   acl_m8=""
   acl_m9="value for m9 is domain: y"
-  acl_mfoo="value for mfoo is local_part: x"
-  acl_mbar="value for mbar is domain: y"
+  acl_m_foo="value for mfoo is local_part: x"
+  acl_m_bar="value for mbar is domain: y"
   acl_c_foo="value for c_foo is ip: 1.2.3.4"
   acl_c_bar="value for c_bar is name: host.name"
 -------------------------
@@ -53,8 +53,8 @@ acl_m6=""
 acl_m7=""
 acl_m8=""
 acl_m9="value for m9 is domain: y"
-acl_mfoo="value for mfoo is local_part: x"
-acl_mbar="value for mbar is domain: y"
+acl_m_foo="value for mfoo is local_part: x"
+acl_m_bar="value for mbar is domain: y"
 acl_c_foo="value for c_foo is ip: 1.2.3.4"
 acl_c_bar="value for c_bar is name: host.name"
 LOG: MAIN
@@ -86,8 +86,8 @@ there!"
   acl_m7=""
   acl_m8=""
   acl_m9="value for m9 is domain: b"
-  acl_mfoo=""
-  acl_mbar=""
+  acl_m_foo=""
+  acl_m_bar=""
   acl_c_foo="value for c_foo is ip: 1.2.3.4"
   acl_c_bar="value for c_bar is name: host.name"
 -------------------------
@@ -112,8 +112,8 @@ acl_m6=""
 acl_m7=""
 acl_m8=""
 acl_m9="value for m9 is domain: b"
-acl_mfoo=""
-acl_mbar=""
+acl_m_foo=""
+acl_m_bar=""
 acl_c_foo="value for c_foo is ip: 1.2.3.4"
 acl_c_bar="value for c_bar is name: host.name"
 LOG: MAIN
@@ -123,4 +123,4 @@ LOG: MAIN
 LOG: smtp_connection MAIN
   SMTP connection from CALLER closed by QUIT
 ----- System filter -----
-1999-03-02 09:44:33 10HmaZ-0005vi-00 Error in system filter: failed to expand "  acl_c0="$acl_c0"\n  acl_c1="$acl_c1"\n  acl_c2="$acl_c2"\n  acl_c3="$acl_c3"\n  acl_c4="$acl_c4"\n  acl_c5="$acl_c5"\n  acl_c6="$acl_c6"\n  acl_c7="$acl_c7"\n  acl_c8="$acl_c8"\n  acl_c9="$acl_c9"\n  acl_m0="$acl_m0"\n  acl_m1="$acl_m1"\n  acl_m2="$acl_m2"\n  acl_m3="$acl_m3"\n  acl_m4="$acl_m4"\n  acl_m5="$acl_m5"\n  acl_m6="$acl_m6"\n  acl_m7="$acl_m7"\n  acl_m8="$acl_m8"\n  acl_m9="$acl_m9"\n  acl_mfoo="$acl_mfoo"\n  acl_mbar="$acl_mbar"\n  acl_c_foo="$acl_c_foo"\n  acl_c_bar="$acl_c_bar"\n" in logwrite command: unknown variable name "acl_c1" (strict_acl_vars is set)
+1999-03-02 09:44:33 10HmaZ-0005vi-00 Error in system filter: failed to expand "  acl_c0="$acl_c0"\n  acl_c1="$acl_c1"\n  acl_c2="$acl_c2"\n  acl_c3="$acl_c3"\n  acl_c4="$acl_c4"\n  acl_c5="$acl_c5"\n  acl_c6="$acl_c6"\n  acl_c7="$acl_c7"\n  acl_c8="$acl_c8"\n  acl_c9="$acl_c9"\n  acl_m0="$acl_m0"\n  acl_m1="$acl_m1"\n  acl_m2="$acl_m2"\n  acl_m3="$acl_m3"\n  acl_m4="$acl_m4"\n  acl_m5="$acl_m5"\n  acl_m6="$acl_m6"\n  acl_m7="$acl_m7"\n  acl_m8="$acl_m8"\n  acl_m9="$acl_m9"\n  acl_m_foo="$acl_m_foo"\n  acl_m_bar="$acl_m_bar"\n  acl_c_foo="$acl_c_foo"\n  acl_c_bar="$acl_c_bar"\n" in logwrite command: unknown variable name "acl_c1" (strict_acl_vars is set)