Lookups: fix $local_part_data for a match on a filename list element. Bug 2691
[exim.git] / src / src / match.c
index 65d44198e6a25b82f81e31a5ee09b9b3c130eaa2..73cdab01278ddad00b06cb2048cf6ec395598f14 100644 (file)
@@ -104,8 +104,6 @@ uschar *filename = NULL;
 uschar *keyquery, *result, *semicolon;
 void *handle;
 
-error = error;  /* Keep clever compilers from complaining */
-
 if (valueptr) *valueptr = NULL;
 
 /* For regular expressions, use cb->origsubject rather than cb->subject so that
@@ -286,22 +284,7 @@ if (!cb->use_partial) partial = -1;
 
 /* Set the parameters for the three different kinds of lookup. */
 
-keyquery = semicolon + 1;
-Uskip_whitespace(&keyquery);
-
-if (mac_islookup(search_type, lookup_absfilequery))
-  {
-  filename = keyquery;
-  while (*keyquery && !isspace(*keyquery)) keyquery++;
-  filename = string_copyn(filename, keyquery - filename);
-  Uskip_whitespace(&keyquery);
-  }
-
-else if (!mac_islookup(search_type, lookup_querystyle))
-  {
-  filename = keyquery;
-  keyquery = s;
-  }
+keyquery = search_args(search_type, s, semicolon+1, &filename, opts);
 
 /* Now do the actual lookup; throw away the data returned unless it was asked
 for; partial matching is all handled inside search_find(). Note that there is
@@ -803,7 +786,7 @@ while ((sss = string_nextinlist(&list, &sep, NULL, 0)))
       if (listname[0] == 0)
         listname = string_sprintf("\"%s\"", *listptr);
       log_write(0, LOG_MAIN|LOG_PANIC_DIE, "%s",
-        string_open_failed(errno, "%s when checking %s", sss, listname));
+        string_open_failed("%s when checking %s", sss, listname));
       }
 
     /* Trailing comments are introduced by #, but in an address list or local
@@ -826,19 +809,19 @@ while ((sss = string_nextinlist(&list, &sep, NULL, 0)))
         sss = ss + 1;
         }
 
-      ss = filebuffer + Ustrlen(filebuffer);             /* trailing space */
+      ss = filebuffer + Ustrlen(filebuffer);           /* trailing space */
       while (ss > filebuffer && isspace(ss[-1])) ss--;
       *ss = 0;
 
       ss = filebuffer;
-      while (isspace(*ss)) ss++;                         /* leading space */
+      while (isspace(*ss)) ss++;                       /* leading space */
 
-      if (*ss == 0) continue;                            /* ignore empty */
+      if (!*ss) continue;                              /* ignore empty */
 
-      file_yield = yield;                                /* positive yield */
-      sss = ss;                                          /* for debugging */
+      file_yield = yield;                              /* positive yield */
+      sss = ss;                                                /* for debugging */
 
-      if (*ss == '!')                                    /* negation */
+      if (*ss == '!')                                  /* negation */
         {
         file_yield = (file_yield == OK)? FAIL : OK;
         while (isspace((*(++ss))));
@@ -850,6 +833,11 @@ while ((sss = string_nextinlist(&list, &sep, NULL, 0)))
          (void)fclose(f);
          HDEBUG(D_lists) debug_printf("%s %s (matched \"%s\" in %s)\n", ot,
            yield == OK ? "yes" : "no", sss, filename);
+
+         /* The "pattern" being matched came from the file; we use a stack-local.
+         Copy it to allocated memory now we know it matched. */
+
+         if (valueptr) *valueptr = string_copy(ss);
          return file_yield;
 
         case DEFER:
@@ -1019,8 +1007,6 @@ uschar *subject = cb->address;
 const uschar *s;
 uschar *pdomain, *sdomain;
 
-error = error;  /* Keep clever compilers from complaining */
-
 DEBUG(D_lists) debug_printf("address match test: subject=%s pattern=%s\n",
   subject, pattern);
 
@@ -1080,7 +1066,6 @@ if (pattern[0] == '@' && pattern[1] == '@')
   {
   int watchdog = 50;
   uschar *list, *ss;
-  uschar buffer[1024];
 
   if (sdomain == subject + 1 && *subject == '*') return FAIL;
 
@@ -1111,7 +1096,7 @@ if (pattern[0] == '@' && pattern[1] == '@')
     /* Look up the local parts provided by the list; negation is permitted.
     If a local part has to begin with !, a regex can be used. */
 
-    while ((ss = string_nextinlist(CUSS &list, &sep, buffer, sizeof(buffer))))
+    while ((ss = string_nextinlist(CUSS &list, &sep, NULL, 0)))
       {
       int local_yield;
 
@@ -1288,9 +1273,11 @@ compared. Therefore, Exim now forces the entire address into lower case here,
 provided that "caseless" is set. (It is FALSE for calls for matching rewriting
 patterns.) Otherwise just the domain is lower cases. A magic item "+caseful" in
 the list can be used to restore a caseful copy of the local part from the
-original address. */
+original address.
+Limit the subject address size to avoid mem-exhastion attacks.  The size chosen
+is historical (we used to use big_buffer her). */
 
-if ((len = Ustrlen(address)) > 255) len = 255;
+if ((len = Ustrlen(address)) > BIG_BUFFER_SIZE) len = BIG_BUFFER_SIZE;
 ab.address = string_copyn(address, len);
 
 for (uschar * p = ab.address + len - 1; p >= ab.address; p--)