Add optional authenticated_sender info to A= elements of log lines; bug 1314.
[exim.git] / src / src / expand.c
index bd8a1bee2fdd90ed5dab131be56c3b436f634f39..786d4279cbca4c667cc7eef0b03287c89a9a9f05 100644 (file)
@@ -784,8 +784,11 @@ return -1;
 
 /* This function is called to expand a string, and test the result for a "true"
 or "false" value. Failure of the expansion yields FALSE; logged unless it was a
-forced fail or lookup defer. All store used by the function can be released on
-exit.
+forced fail or lookup defer.
+
+We used to release all store used, but this is not not safe due
+to ${dlfunc } and ${acl }.  In any case expand_string_internal()
+is reasonably careful to release what it can.
 
 The actual false-value tests should be replicated for ECOND_BOOL_LAX.
 
@@ -801,7 +804,6 @@ BOOL
 expand_check_condition(uschar *condition, uschar *m1, uschar *m2)
 {
 int rc;
-void *reset_point = store_get(0);
 uschar *ss = expand_string(condition);
 if (ss == NULL)
   {
@@ -812,7 +814,6 @@ if (ss == NULL)
   }
 rc = ss[0] != 0 && Ustrcmp(ss, "0") != 0 && strcmpic(ss, US"no") != 0 &&
   strcmpic(ss, US"false") != 0;
-store_reset(reset_point);
 return rc;
 }
 
@@ -1852,6 +1853,7 @@ if (Ustrncmp(name, "acl_", 4) == 0)
 
 /*
 Load args from sub array to globals, and call acl_check().
+Sub array will be corrupted on return.
 
 Returns:       OK         access is granted by an ACCEPT verb
                DISCARD    access is granted by a DISCARD verb
@@ -1864,13 +1866,24 @@ static int
 eval_acl(uschar ** sub, int nsub, uschar ** user_msgp)
 {
 int i;
-uschar *dummy_log_msg;
+uschar *tmp;
+int sav_narg = acl_narg;
+int ret;
+extern int acl_where;
 
-for (i = 1; i < nsub && sub[i]; i++)
-  acl_arg[i-1] = sub[i];
-acl_narg = i-1;
+if(--nsub > sizeof(acl_arg)/sizeof(*acl_arg)) nsub = sizeof(acl_arg)/sizeof(*acl_arg);
+for (i = 0; i < nsub && sub[i+1]; i++)
+  {
+  tmp = acl_arg[i];
+  acl_arg[i] = sub[i+1];       /* place callers args in the globals */
+  sub[i+1] = tmp;              /* stash the old args using our caller's storage */
+  }
+acl_narg = i;
 while (i < nsub)
-  acl_arg[i++ - 1] = NULL;
+  {
+  sub[i+1] = acl_arg[i];
+  acl_arg[i++] = NULL;
+  }
 
 DEBUG(D_expand)
   debug_printf("expanding: acl: %s  arg: %s%s\n",
@@ -1878,7 +1891,13 @@ DEBUG(D_expand)
     acl_narg>0 ? sub[1]   : US"<none>",
     acl_narg>1 ? " +more" : "");
 
-return acl_check(ACL_WHERE_EXPANSION, NULL, sub[0], user_msgp, &dummy_log_msg);
+ret = acl_eval(acl_where, NULL, sub[0], user_msgp, &tmp);
+
+for (i = 0; i < nsub; i++)
+  acl_arg[i] = sub[i+1];       /* restore old args */
+acl_narg = sav_narg;
+
+return ret;
 }
 
 
@@ -2129,14 +2148,13 @@ switch(cond_type)
   case ECOND_ACL:
     /* ${if acl {{name}{arg1}{arg2}...}  {yes}{no}} */
     {
-    uschar *nameargs;
     uschar *user_msg;
     BOOL cond = FALSE;
     int size = 0;
     int ptr = 0;
 
     while (isspace(*s)) s++;
-    if (*s++ != '{') goto COND_FAILED_CURLY_START;
+    if (*s++ != '{') goto COND_FAILED_CURLY_START;     /*}*/
 
     switch(read_subs(sub, sizeof(sub)/sizeof(*sub), 1,
       &s, yield == NULL, TRUE, US"acl"))
@@ -3548,8 +3566,8 @@ $message_headers which can get very long.
 There's a problem if a ${dlfunc item has side-effects that cause allocation,
 since resetting the store at the end of the expansion will free store that was
 allocated by the plugin code as well as the slop after the expanded string. So
-we skip any resets if ${dlfunc has been used. This is an unfortunate
-consequence of string expansion becoming too powerful.
+we skip any resets if ${dlfunc has been used. The same applies for ${acl. This
+is an unfortunate consequence of string expansion becoming too powerful.
 
 Arguments:
   string         the string to be expanded
@@ -3771,6 +3789,7 @@ while (*s != 0)
     acl_check_internal() directly and get a current level from somewhere.
     See also the acl expansion condition ECOND_ACL and the traditional
     acl modifier ACLC_ACL.
+    Assume that the function has side-effects on the store that must be preserved.
     */
 
     case EITEM_ACL:
@@ -3787,6 +3806,7 @@ while (*s != 0)
         }
       if (skipping) continue;
 
+      resetok = FALSE;
       switch(eval_acl(sub, sizeof(sub)/sizeof(*sub), &user_msg))
        {
        case OK:
@@ -5660,7 +5680,7 @@ while (*s != 0)
        uschar * list;
        int sep = 0;
        uschar * item;
-       uschar * suffix = "";
+       uschar * suffix = US"";
        BOOL needsep = FALSE;
        uschar buffer[256];
 
@@ -5674,10 +5694,10 @@ while (*s != 0)
          }
        else switch(*arg)       /* specific list-type version */
          {
-         case 'a': t = tree_search(addresslist_anchor,   sub); suffix = "_a"; break;
-         case 'd': t = tree_search(domainlist_anchor,    sub); suffix = "_d"; break;
-         case 'h': t = tree_search(hostlist_anchor,      sub); suffix = "_h"; break;
-         case 'l': t = tree_search(localpartlist_anchor, sub); suffix = "_l"; break;
+         case 'a': t = tree_search(addresslist_anchor,   sub); suffix = US"_a"; break;
+         case 'd': t = tree_search(domainlist_anchor,    sub); suffix = US"_d"; break;
+         case 'h': t = tree_search(hostlist_anchor,      sub); suffix = US"_h"; break;
+         case 'l': t = tree_search(localpartlist_anchor, sub); suffix = US"_l"; break;
          default:
             expand_string_message = string_sprintf("bad suffix on \"list\" operator");
            goto EXPAND_FAILED;
@@ -5721,13 +5741,13 @@ while (*s != 0)
              if (*cp++ == ':') /* colon in a non-colon-sep list item, needs doubling */
                {
                 yield = string_cat(yield, &size, &ptr, US"::", 2);
-               item = cp;
+               item = (uschar *)cp;
                }
              else              /* sep in item; should already be doubled; emit once */
                {
                 yield = string_cat(yield, &size, &ptr, (uschar *)tok, 1);
                if (*cp == sep) cp++;
-               item = cp;
+               item = (uschar *)cp;
                }
              }
            }