summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Harris <jgh146exb@wizmail.org>2016-03-09 17:40:48 +0000
committerJeremy Harris <jgh146exb@wizmail.org>2016-03-09 18:45:31 +0000
commit93cc2d6e053031a7008f73ca1ea072038bfa3fc8 (patch)
tree76d079a8d6bd231559ddd84131e663e975946d5b
parentfae3a611be53dbf58cbb7c2c4846081ecb87606e (diff)
String expansions: fix ${extract }, for the numeric/3-string case. Bug 1807
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.
-rw-r--r--doc/doc-txt/ChangeLog5
-rw-r--r--src/src/expand.c55
-rw-r--r--test/scripts/0000-Basic/00023
-rw-r--r--test/stdout/00023
4 files changed, 45 insertions, 21 deletions
diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index d36b731cd..320b29a53 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -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.
+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
diff --git a/src/src/expand.c b/src/src/expand.c
index 99d2ffc00..47f1453be 100644
--- a/src/src/expand.c
+++ b/src/src/expand.c
@@ -5307,9 +5307,25 @@ while (*s != 0)
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 == '{') /*}*/
@@ -5336,27 +5352,24 @@ while (*s != 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;
}
}
}
diff --git a/test/scripts/0000-Basic/0002 b/test/scripts/0000-Basic/0002
index 105134da3..bc61998ca 100644
--- a/test/scripts/0000-Basic/0002
+++ b/test/scripts/0000-Basic/0002
@@ -615,6 +615,9 @@ ${extract{}{X=3}}
${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}}
diff --git a/test/stdout/0002 b/test/stdout/0002
index ee351a278..ee1ef9d93 100644
--- a/test/stdout/0002
+++ b/test/stdout/0002
@@ -577,6 +577,9 @@
> 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