String expansions: fix ${extract }, for the numeric/3-string case. Bug 1807
authorJeremy Harris <jgh146exb@wizmail.org>
Wed, 9 Mar 2016 17:40:48 +0000 (17:40 +0000)
committerJeremy Harris <jgh146exb@wizmail.org>
Wed, 9 Mar 2016 18:45:31 +0000 (18:45 +0000)
Broken-by: 82dbd37
In "skipping" mode when parsing an expansion we want to avoid expanding
the arguments, as the data for expansion is not necessarily valid.  This
bit us previously for an extract within an "if inlist". But the number of
args for ${extract } depends on the expanded value of the first arg.

Retreat from strict parsing and just line up the outer braces,
accepting any number of args while skipping.  The separate
non-skipping execution will do the proper checking.

doc/doc-txt/ChangeLog
src/src/expand.c
test/scripts/0000-Basic/0002
test/stdout/0002

index d36b731cd11cd4b1f18bb1d3d4fbf9aed3a31b07..320b29a5394320ac9d46738b11ec355f592aaab6 100644 (file)
@@ -194,6 +194,11 @@ JH/47 Fix build on HP-UX and older Solaris, which need (un)setenv now also
       for the new environment-manipulation done at startup.  Move the routines
       from being local to tls.c to being global via the os.c file.
 
       for the new environment-manipulation done at startup.  Move the routines
       from being local to tls.c to being global via the os.c file.
 
+JH/48 Bug 1807: Fix ${extract } for the numeric/3-string case. While preparsing
+      an extract embedded as result-arg for a map, the first arg for extract
+      is unavailable so we cannot tell if this is a numbered or keyed
+      extraction.  Accept either.
+
 
 
 Exim version 4.86
 
 
 Exim version 4.86
index 99d2ffc00052bf20f908f1ee271f78fd869ec52f..47f1453bebc2cf89cf906e8d1d75c698f1cfeffd 100644 (file)
@@ -5307,9 +5307,25 @@ while (*s != 0)
       int save_expand_nmax =
         save_expand_strings(save_expand_nstring, save_expand_nlength);
 
       int save_expand_nmax =
         save_expand_strings(save_expand_nstring, save_expand_nlength);
 
-      /* Read the arguments */
+      /* While skipping we cannot rely on the data for expansions being
+      available (eg. $item) hence cannot decide on numeric vs. keyed.
+      Just read as many arguments as there are. */
 
 
-      for (i = 0; i < j; i++)
+      if (skipping)
+       {
+        while (isspace(*s)) s++;
+        while (*s == '{')
+         {
+          if (!expand_string_internal(s+1, TRUE, &s, skipping, TRUE, &resetok))
+           goto EXPAND_FAILED;                                 /*{*/
+          if (*s++ != '}') goto EXPAND_FAILED_CURLY;
+         while (isspace(*s)) s++;
+         }
+       if (*s != '}')
+         goto EXPAND_FAILED_CURLY;
+       }
+
+      else for (i = 0; i < j; i++) /* Read the proper number of arguments */
         {
         while (isspace(*s)) s++;
         if (*s == '{')                                                 /*}*/
         {
         while (isspace(*s)) s++;
         if (*s == '{')                                                 /*}*/
@@ -5336,27 +5352,24 @@ while (*s != 0)
             while (len > 0 && isspace(p[len-1])) len--;
             p[len] = 0;
 
             while (len > 0 && isspace(p[len-1])) len--;
             p[len] = 0;
 
-            if (!skipping)
+           if (*p == 0)
              {
              {
-             if (*p == 0)
-               {
-               expand_string_message = US"first argument of \"extract\" must "
-                 "not be empty";
-               goto EXPAND_FAILED;
-               }
+             expand_string_message = US"first argument of \"extract\" must "
+               "not be empty";
+             goto EXPAND_FAILED;
+             }
 
 
-             if (*p == '-')
-               {
-               field_number = -1;
-               p++;
-               }
-             while (*p != 0 && isdigit(*p)) x = x * 10 + *p++ - '0';
-             if (*p == 0)
-               {
-               field_number *= x;
-               j = 3;               /* Need 3 args */
-               field_number_set = TRUE;
-               }
+           if (*p == '-')
+             {
+             field_number = -1;
+             p++;
+             }
+           while (*p != 0 && isdigit(*p)) x = x * 10 + *p++ - '0';
+           if (*p == 0)
+             {
+             field_number *= x;
+             j = 3;               /* Need 3 args */
+             field_number_set = TRUE;
              }
             }
           }
              }
             }
           }
index 105134da33c9fd2f659c2bfa4d6166f84b9fd9fc..bc61998ca6775440172a0302ee9c50d67e05e9c0 100644 (file)
@@ -615,6 +615,9 @@ ${extract{}{X=3}}
 ${extract{ }{X=3}}
 ${extract{ 2 }{ }{a b c}}
 
 ${extract{ }{X=3}}
 ${extract{ 2 }{ }{a b c}}
 
+${map{a,1:b,2:c,3}{${extract{1}{,}{$item}{$value}{}}}}
+${map{a,1:b,2:c,3}{${extract{1}{,}{$item}{$value}{failcase}{bogus_argument}}}}
+
 # Translation
 
 abcdea aaa xyz ${tr{abcdea}{aaa}{xyz}}
 # Translation
 
 abcdea aaa xyz ${tr{abcdea}{aaa}{xyz}}
index ee351a2784b92597350deed1ea48bbfcadaf3bf6..ee1ef9d93a90f7dda645cd639f0982ebc5ef9b11 100644 (file)
 > Failed: first argument of "extract" must not be empty
 > b
 > 
 > Failed: first argument of "extract" must not be empty
 > b
 > 
+> a:b:c
+> Failed: missing or misplaced { or } inside "map" item
+> 
 > # Translation
 > 
 > abcdea aaa xyz zbcdez
 > # Translation
 > 
 > abcdea aaa xyz zbcdez