Set $value for match_<list-type> and inlist
authorJeremy Harris <jgh146exb@wizmail.org>
Fri, 11 Mar 2022 15:54:26 +0000 (15:54 +0000)
committerJeremy Harris <jgh146exb@wizmail.org>
Fri, 11 Mar 2022 16:05:52 +0000 (16:05 +0000)
doc/doc-docbook/spec.xfpt
doc/doc-txt/NewStuff
src/src/expand.c

index 1f0f473d804cf0de17200613447e959fec6f7f92..105e2fc5d514ea88b3e5005ecf5fadf7fd210d79 100644 (file)
@@ -11902,6 +11902,19 @@ ${if inlisti{Needle}{fOo:NeeDLE:bAr}}
   ${if forany{fOo:NeeDLE:bAr}{eqi{$item}{Needle}}}
 .endd
 
   ${if forany{fOo:NeeDLE:bAr}{eqi{$item}{Needle}}}
 .endd
 
+.new
+The variable &$value$& will be set for a successful match and can be
+used in the success clause of an &%if%& expansion item using the condition.
+.cindex "tainted data" "de-tainting"
+It will have the same taint status as the list; expansions such as
+.code
+${if inlist {$h_mycode:} {0 : 1 : 42} {$value}}
+.endd
+can be used for de-tainting.
+Any previous &$value$& is restored after the if.
+.wen
+
+
 .vitem &*isip&~{*&<&'string'&>&*}*&  &&&
        &*isip4&~{*&<&'string'&>&*}*& &&&
        &*isip6&~{*&<&'string'&>&*}*&
 .vitem &*isip&~{*&<&'string'&>&*}*&  &&&
        &*isip4&~{*&<&'string'&>&*}*& &&&
        &*isip6&~{*&<&'string'&>&*}*&
@@ -12098,6 +12111,18 @@ item can be used, as in all address lists, to cause subsequent items to
 have their local parts matched casefully. Domains are always matched
 caselessly.
 
 have their local parts matched casefully. Domains are always matched
 caselessly.
 
+.new
+The variable &$value$& will be set for a successful match and can be
+used in the success clause of an &%if%& expansion item using the condition.
+.cindex "tainted data" "de-tainting"
+It will have the same taint status as the list; expansions such as
+.code
+${if match_local_part {$local_part} {alice : bill : charlotte : dave} {$value}}
+.endd
+can be used for de-tainting.
+Any previous &$value$& is restored after the if.
+.wen
+
 Note that <&'string2'&> is not itself subject to string expansion, unless
 Exim was built with the EXPAND_LISTMATCH_RHS option.
 
 Note that <&'string2'&> is not itself subject to string expansion, unless
 Exim was built with the EXPAND_LISTMATCH_RHS option.
 
index 730508adc944d618d08c338920a96b14d3023cf9..11004e33a59376c6d024e8c32420b69c6a66a81d 100644 (file)
@@ -23,6 +23,10 @@ Version 4.96
     built using untrusted data ("tainted").  For now lack of quoting is merely
     logged; a future release will upgrade this to an error.
 
     built using untrusted data ("tainted").  For now lack of quoting is merely
     logged; a future release will upgrade this to an error.
 
+ 7. The expansion conditions match_<list-type> and inlist now set $value for
+    the expansion of the "true" result of the ${if}.  With a static list, this
+    can be used for de-tainting.
+
 Version 4.95
 ------------
 
 Version 4.95
 ------------
 
index b7719f642a6027044ffe04a657aedc4c6783036a..85619acfef4c5994ac6cc5655ba664b41690e000 100644 (file)
@@ -2964,12 +2964,12 @@ switch(cond_type = identify_operator(&s, &opname))
 
     case ECOND_MATCH_ADDRESS:  /* Match in an address list */
       rc = match_address_list(sub[0], TRUE, FALSE, &(sub[1]), NULL, -1, 0,
 
     case ECOND_MATCH_ADDRESS:  /* Match in an address list */
       rc = match_address_list(sub[0], TRUE, FALSE, &(sub[1]), NULL, -1, 0,
-                             NULL);
+                             CUSS &lookup_value);
       goto MATCHED_SOMETHING;
 
     case ECOND_MATCH_DOMAIN:   /* Match in a domain list */
       rc = match_isinlist(sub[0], &(sub[1]), 0, &domainlist_anchor, NULL,
       goto MATCHED_SOMETHING;
 
     case ECOND_MATCH_DOMAIN:   /* Match in a domain list */
       rc = match_isinlist(sub[0], &(sub[1]), 0, &domainlist_anchor, NULL,
-       MCL_DOMAIN + MCL_NOEXPAND, TRUE, NULL);
+       MCL_DOMAIN + MCL_NOEXPAND, TRUE, CUSS &lookup_value);
       goto MATCHED_SOMETHING;
 
     case ECOND_MATCH_IP:       /* Match IP address in a host list */
       goto MATCHED_SOMETHING;
 
     case ECOND_MATCH_IP:       /* Match IP address in a host list */
@@ -3003,13 +3003,13 @@ switch(cond_type = identify_operator(&s, &opname))
               &cb,                       /* argument for function */
               MCL_HOST,                  /* type of check */
               sub[0],                    /* text for debugging */
               &cb,                       /* argument for function */
               MCL_HOST,                  /* type of check */
               sub[0],                    /* text for debugging */
-              NULL);                     /* where to pass back data */
+              CUSS &lookup_value);       /* where to pass back data */
        }
       goto MATCHED_SOMETHING;
 
     case ECOND_MATCH_LOCAL_PART:
       rc = match_isinlist(sub[0], &(sub[1]), 0, &localpartlist_anchor, NULL,
        }
       goto MATCHED_SOMETHING;
 
     case ECOND_MATCH_LOCAL_PART:
       rc = match_isinlist(sub[0], &(sub[1]), 0, &localpartlist_anchor, NULL,
-       MCL_LOCALPART + MCL_NOEXPAND, TRUE, NULL);
+       MCL_LOCALPART + MCL_NOEXPAND, TRUE, CUSS &lookup_value);
       /* Fall through */
       /* VVVVVVVVVVVV */
       MATCHED_SOMETHING:
       /* Fall through */
       /* VVVVVVVVVVVV */
       MATCHED_SOMETHING:
@@ -3187,6 +3187,7 @@ switch(cond_type = identify_operator(&s, &opname))
         if (compare(sub[0], iterate_item) == 0)
           {
           tempcond = TRUE;
         if (compare(sub[0], iterate_item) == 0)
           {
           tempcond = TRUE;
+         lookup_value = iterate_item;
           break;
           }
        }
           break;
           }
        }
@@ -4801,6 +4802,7 @@ while (*s)
       const uschar *next_s;
       int save_expand_nmax =
         save_expand_strings(save_expand_nstring, save_expand_nlength);
       const uschar *next_s;
       int save_expand_nmax =
         save_expand_strings(save_expand_nstring, save_expand_nlength);
+      uschar * save_lookup_value = lookup_value;
 
       Uskip_whitespace(&s);
       if (!(next_s = eval_condition(s, &resetok, skipping ? NULL : &cond)))
 
       Uskip_whitespace(&s);
       if (!(next_s = eval_condition(s, &resetok, skipping ? NULL : &cond)))
@@ -4834,6 +4836,7 @@ while (*s)
       /* Restore external setting of expansion variables for continuation
       at this level. */
 
       /* Restore external setting of expansion variables for continuation
       at this level. */
 
+      lookup_value = save_lookup_value;
       restore_expand_strings(save_expand_nmax, save_expand_nstring,
         save_expand_nlength);
       break;
       restore_expand_strings(save_expand_nmax, save_expand_nstring,
         save_expand_nlength);
       break;
@@ -6544,6 +6547,9 @@ while (*s)
         item of the output list, add in a space if the new item begins with the
         separator character, or is an empty string. */
 
         item of the output list, add in a space if the new item begins with the
         separator character, or is an empty string. */
 
+/*XXX is there not a standard support function for this, appending to a list? */
+/* yes, string_append_listele(), but it depends on lack of text before the list */
+
         if (  yield && yield->ptr != save_ptr
           && (temp[0] == *outsep || temp[0] == 0))
           yield = string_catn(yield, US" ", 1);
         if (  yield && yield->ptr != save_ptr
           && (temp[0] == *outsep || temp[0] == 0))
           yield = string_catn(yield, US" ", 1);