X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/1cce3af8c29cfa691a3e28c79227f358e5a7b3b9..38a0a95ff69327042421b9ee6982e386175f141b:/src/src/expand.c diff --git a/src/src/expand.c b/src/src/expand.c index 4cd98f7d4..2e39f2638 100644 --- a/src/src/expand.c +++ b/src/src/expand.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/expand.c,v 1.58 2006/04/18 11:13:19 ph10 Exp $ */ +/* $Cambridge: exim/src/src/expand.c,v 1.61 2006/09/19 11:28:45 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -300,6 +300,8 @@ enum { /* This table must be kept in alphabetical order. */ static var_entry var_table[] = { + /* WARNING: Do not invent variables whose names start acl_c or acl_m because + they will be confused with user-creatable ACL variables. */ { "acl_verify_message", vtype_stringptr, &acl_verify_message }, { "address_data", vtype_stringptr, &deliver_address_data }, { "address_file", vtype_stringptr, &address_file }, @@ -1231,37 +1233,25 @@ find_variable(uschar *name, BOOL exists_only, BOOL skipping, int *newsize) int first = 0; int last = var_table_size; -/* Handle ACL variables, which are not in the table because their number may -vary depending on a build-time setting. If the variable's name is not of the -form acl_mddd or acl_cddd, where the d's are digits, fall through to look for -other names that start with acl_. */ +/* 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. -if (Ustrncmp(name, "acl_", 4) == 0) - { - uschar *endptr; - int offset = -1; - int max = 0; - - if (name[4] == 'm') - { - offset = ACL_CVARS; - max = ACL_MVARS; - } - else if (name[4] == 'c') - { - offset = 0; - max = ACL_CVARS; - } +If an ACL variable does not exist, treat it as empty, unless strict_acl_vars is +set, in which case give an error. */ - if (offset >= 0) - { - int n = Ustrtoul(name + 5, &endptr, 10); - if (*endptr == 0 && n < max) - return (acl_var[offset + n] == NULL)? US"" : acl_var[offset + n]; - } +if (Ustrncmp(name, "acl_c", 5) == 0 || Ustrncmp(name, "acl_m", 5) == 0) + { + tree_node *node = + tree_search((name[4] == 'c')? acl_var_c : acl_var_m, name + 4); + return (node == NULL)? (strict_acl_vars? NULL : US"") : node->data.ptr; } -/* Similarly for $auth variables. */ +/* Handle $auth variables. */ if (Ustrncmp(name, "auth", 4) == 0) { @@ -1681,6 +1671,13 @@ 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); + return NULL; } if (yield != NULL) *yield = (value[0] != 0) == testfor; @@ -1893,25 +1890,8 @@ switch(cond_type) if (!isalpha(name[0])) { - uschar *endptr; - num[i] = (int)Ustrtol((const uschar *)sub[i], &endptr, 10); - if (tolower(*endptr) == 'k') - { - num[i] *= 1024; - endptr++; - } - else if (tolower(*endptr) == 'm') - { - num[i] *= 1024*1024; - endptr++; - } - while (isspace(*endptr)) endptr++; - if (*endptr != 0) - { - expand_string_message = string_sprintf("\"%s\" is not a number", - sub[i]); - return NULL; - } + num[i] = expand_string_integer(sub[i], FALSE); + if (expand_string_message != NULL) return NULL; } } @@ -2976,6 +2956,13 @@ 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); + goto EXPAND_FAILED; } } @@ -3662,7 +3649,7 @@ while (*s != 0) { /* Handle an IP (internet) domain */ - if (strncmp(sub_arg[0], "inet:", 5) == 0) + if (Ustrncmp(sub_arg[0], "inet:", 5) == 0) { BOOL connected = FALSE; int namelen, port; @@ -5135,6 +5122,13 @@ 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); + goto EXPAND_FAILED; } len = Ustrlen(value); @@ -5260,22 +5254,26 @@ return yield; /* Expand a string, and convert the result into an integer. -Argument: the string to be expanded +Arguments: + string the string to be expanded + isplus TRUE if a non-negative number is expected Returns: the integer value, or -1 for an expansion error ) in both cases, message in -2 for an integer interpretation error ) expand_string_message - + expand_string_message is set NULL for an OK integer */ int -expand_string_integer(uschar *string) +expand_string_integer(uschar *string, BOOL isplus) { long int value; uschar *s = expand_string(string); uschar *msg = US"invalid integer \"%s\""; uschar *endptr; +/* If expansion failed, expand_string_message will be set. */ + if (s == NULL) return -1; /* On an overflow, strtol() returns LONG_MAX or LONG_MIN, and sets errno @@ -5283,12 +5281,17 @@ to ERANGE. When there isn't an overflow, errno is not changed, at least on some systems, so we set it zero ourselves. */ errno = 0; +expand_string_message = NULL; /* Indicates no error */ value = strtol(CS s, CSS &endptr, 0); if (endptr == s) { msg = US"integer expected but \"%s\" found"; } +else if (value < 0 && isplus) + { + msg = US"non-negative integer expected but \"%s\" found"; + } else { /* Ensure we can cast this down to an int */