From 2f3c95e53da0eb7a03be3ef7df252ff5740fe625 Mon Sep 17 00:00:00 2001 From: Stephan Bosch <stephan@rename-it.nl> Date: Tue, 12 Aug 2008 19:51:56 +0200 Subject: [PATCH] Limited number of accepted match values --- TODO | 4 +- src/lib-sieve/mcht-matches.c | 86 ++++++++++++++--------- src/lib-sieve/plugins/include/Makefile.am | 1 + src/lib-sieve/plugins/regex/mcht-regex.c | 13 ++-- src/lib-sieve/sieve-limits.h | 6 ++ src/lib-sieve/sieve-match-types.c | 6 +- 6 files changed, 77 insertions(+), 39 deletions(-) diff --git a/TODO b/TODO index 4c81eb74f..173e90f02 100644 --- a/TODO +++ b/TODO @@ -9,8 +9,8 @@ Next (in order of descending priority/precedence): - Imapflags: when keep/fileinto is used multiple times in a script and duplicate message elimination is performed, the last flag list value MUST win. - - If an address is not syntactically valid, then it will not be matched - by tests specifying ":localpart" or ":domain". + - 'If an address is not syntactically valid, then it will not be matched + by tests specifying ":localpart" or ":domain"'. * Code cleanup * Full security review. Enforce limits on number of created objects, script size, execution time, etc... diff --git a/src/lib-sieve/mcht-matches.c b/src/lib-sieve/mcht-matches.c index aa070174e..fd565ada7 100644 --- a/src/lib-sieve/mcht-matches.c +++ b/src/lib-sieve/mcht-matches.c @@ -86,7 +86,8 @@ static int mcht_matches_match { const struct sieve_comparator *cmp = mctx->comparator; struct sieve_match_values *mvalues; - string_t *mvalue, *mchars, *section, *subsection; + string_t *mvalue = NULL, *mchars = NULL; + string_t *section, *subsection; const char *vend, *kend, *vp, *kp, *wp, *pvp; bool backtrack = FALSE; /* TRUE: match of '?'-connected sections failed */ char wcard = '\0'; /* Current wildcard */ @@ -98,8 +99,6 @@ static int mcht_matches_match val_size = 0; } - mvalue = t_str_new(32); /* Match value (*) */ - mchars = t_str_new(32); /* Match characters (.?..?.??) */ section = t_str_new(32); /* Section (after beginning or *) */ subsection = t_str_new(32); /* Sub-section (after ?) */ @@ -109,11 +108,15 @@ static int mcht_matches_match kp = key; /* Key pointer */ wp = key; /* Wildcard (key) pointer */ pvp = val; /* Previous value Pointer */ - - /* Reset match values list */ - mvalues = sieve_match_values_start(mctx->interp); - sieve_match_values_add(mvalues, NULL); + /* Start new match values list */ + if ( (mvalues = sieve_match_values_start(mctx->interp)) != NULL ) { + sieve_match_values_add(mvalues, NULL); + + mvalue = t_str_new(32); /* Match value (*) */ + mchars = t_str_new(32); /* Match characters (.?..?.??) */ + } + /* Match the pattern: * <pattern> = <section>*<section>*<section>.... * <section> = [text]?[text]?[text].... @@ -153,8 +156,9 @@ static int mcht_matches_match debug_printf("found wildcard '%c' at pos [%d]\n", next_wcard, (int) (wp-key)); - - str_truncate(mvalue, 0); + + if ( mvalues != NULL ) + str_truncate(mvalue, 0); } else { debug_printf("backtracked"); backtrack = FALSE; @@ -183,16 +187,20 @@ static int mcht_matches_match vp = PTR_OFFSET(vend, -str_len(section)); qend = vp; qp = vp - key_offset; - str_append_n(mvalue, pvp, qp-pvp); + + if ( mvalues != NULL ) + str_append_n(mvalue, pvp, qp-pvp); if ( !cmp->char_match(cmp, &vp, vend, &needle, nend) ) { debug_printf(" match at end failed\n"); break; } - sieve_match_values_add(mvalues, mvalue); - for ( ; qp < qend; qp++ ) - sieve_match_values_add_char(mvalues, *qp); + if ( mvalues != NULL ) { + sieve_match_values_add(mvalues, mvalue); + for ( ; qp < qend; qp++ ) + sieve_match_values_add_char(mvalues, *qp); + } kp = kend; vp = vend; @@ -203,8 +211,9 @@ static int mcht_matches_match const char *prk = NULL; const char *prw = NULL; const char *chars; - - str_truncate(mchars, 0); + + if ( mvalues != NULL ) + str_truncate(mchars, 0); if ( wcard == '\0' ) { /* Match needs to happen right at the beginning */ @@ -234,9 +243,12 @@ static int mcht_matches_match qend = vp - str_len(section); qp = qend - key_offset; - str_append_n(mvalue, pvp, qp-pvp); - for ( ; qp < qend; qp++ ) - str_append_c(mchars, *qp); + + if ( mvalues != NULL ) { + str_append_n(mvalue, pvp, qp-pvp); + for ( ; qp < qend; qp++ ) + str_append_c(mchars, *qp); + } } if ( wp < kend ) wp++; @@ -246,7 +258,8 @@ static int mcht_matches_match debug_printf("next_wcard = '?'; need to match arbitrary character\n"); /* Add match value */ - str_append_c(mchars, *vp); + if ( mvalues != NULL ) + str_append_c(mchars, *vp); vp++; next_wcard = _scan_key_section(subsection, &wp, kend); @@ -268,7 +281,8 @@ static int mcht_matches_match kp = prk; wp = prw; - str_append_c(mvalue, *vp); + if ( mvalues != NULL ) + str_append_c(mvalue, *vp); vp++; wcard = '*'; @@ -292,11 +306,13 @@ static int mcht_matches_match break; } - if ( prv != NULL ) - sieve_match_values_add(mvalues, mvalue); - chars = (const char *) str_data(mchars); - for ( i = 0; i < str_len(mchars); i++ ) { - sieve_match_values_add_char(mvalues, chars[i]); + if ( mvalues != NULL ) { + if ( prv != NULL ) + sieve_match_values_add(mvalues, mvalue); + chars = (const char *) str_data(mchars); + for ( i = 0; i < str_len(mchars); i++ ) { + sieve_match_values_add_char(mvalues, chars[i]); + } } if ( next_wcard != '*' ) { @@ -310,11 +326,15 @@ static int mcht_matches_match * (avoid scanning the rest of the string) */ if ( kp == kend && next_wcard == '*' ) { - str_truncate(mvalue, 0); - str_append_n(mvalue, vp, vend-vp); - sieve_match_values_add(mvalues, mvalue); + if ( mvalues != NULL ) { + str_truncate(mvalue, 0); + str_append_n(mvalue, vp, vend-vp); + sieve_match_values_add(mvalues, mvalue); + } + kp = kend; vp = vend; + debug_printf("key ends with '*'\n"); break; } @@ -325,7 +345,7 @@ static int mcht_matches_match debug_printf("=== Finish ===\n"); debug_printf(" result: %s\n", (kp == kend && vp == vend) ? "true" : "false"); - /* Eat away a trailing series of *rs */ + /* Eat away a trailing series of *s */ if ( vp == vend ) { while ( kp < kend && *kp == '*' ) kp++; } @@ -334,9 +354,11 @@ static int mcht_matches_match * are exhausted. */ if (kp == kend && vp == vend) { - string_t *matched = str_new_const(pool_datastack_create(), val, val_size); - sieve_match_values_set(mvalues, 0, matched); - sieve_match_values_commit(mctx->interp, &mvalues); + if ( mvalues != NULL ) { + string_t *matched = str_new_const(pool_datastack_create(), val, val_size); + sieve_match_values_set(mvalues, 0, matched); + sieve_match_values_commit(mctx->interp, &mvalues); + } return TRUE; } diff --git a/src/lib-sieve/plugins/include/Makefile.am b/src/lib-sieve/plugins/include/Makefile.am index 44236db11..7d8805f50 100644 --- a/src/lib-sieve/plugins/include/Makefile.am +++ b/src/lib-sieve/plugins/include/Makefile.am @@ -22,5 +22,6 @@ libsieve_ext_include_la_SOURCES = \ noinst_HEADERS = \ ext-include-common.h \ + ext-include-limits.h \ ext-include-binary.h \ ext-include-variables.h diff --git a/src/lib-sieve/plugins/regex/mcht-regex.c b/src/lib-sieve/plugins/regex/mcht-regex.c index bfd98e4df..fa0501836 100644 --- a/src/lib-sieve/plugins/regex/mcht-regex.c +++ b/src/lib-sieve/plugins/regex/mcht-regex.c @@ -8,6 +8,7 @@ #include "str.h" #include "sieve-common.h" +#include "sieve-limits.h" #include "sieve-ast.h" #include "sieve-commands.h" #include "sieve-validator.h" @@ -25,7 +26,7 @@ * Configuration */ -#define MCHT_REGEX_MAX_SUBSTITUTIONS 64 +#define MCHT_REGEX_MAX_SUBSTITUTIONS SIEVE_MAX_MATCH_VALUES /* * Forward declarations */ @@ -240,14 +241,17 @@ static int mcht_regex_match if ( key_index == 0 ) ctx->value_index++; - regexp = mcht_regex_get(ctx, mctx->comparator, key, key_index); - + if ( (regexp=mcht_regex_get(ctx, mctx->comparator, key, key_index)) == NULL ) + return FALSE; + if ( regexec(regexp, val, ctx->nmatch, ctx->pmatch, 0) == 0 ) { size_t i; int skipped = 0; string_t *subst = t_str_new(32); struct sieve_match_values *mvalues = sieve_match_values_start(mctx->interp); - + + i_assert( mvalues != NULL ); + for ( i = 0; i < ctx->nmatch; i++ ) { str_truncate(subst, 0); @@ -261,6 +265,7 @@ static int mcht_regex_match } else skipped++; } + sieve_match_values_commit(mctx->interp, &mvalues); return TRUE; } diff --git a/src/lib-sieve/sieve-limits.h b/src/lib-sieve/sieve-limits.h index d3426ca4f..18b2437b1 100644 --- a/src/lib-sieve/sieve-limits.h +++ b/src/lib-sieve/sieve-limits.h @@ -16,6 +16,12 @@ #define SIEVE_MAX_BLOCK_NESTING 32 #define SIEVE_MAX_TEST_NESTING 32 +/* + * Runtime + */ + +#define SIEVE_MAX_MATCH_VALUES 32 + /* * Actions */ diff --git a/src/lib-sieve/sieve-match-types.c b/src/lib-sieve/sieve-match-types.c index 731ac411d..287fc6158 100644 --- a/src/lib-sieve/sieve-match-types.c +++ b/src/lib-sieve/sieve-match-types.c @@ -6,6 +6,8 @@ #include "hash.h" #include "array.h" +#include "sieve-common.h" +#include "sieve-limits.h" #include "sieve-extensions.h" #include "sieve-commands.h" #include "sieve-code.h" @@ -207,6 +209,8 @@ static string_t *sieve_match_values_add_entry string_t *entry; if ( mvalues == NULL ) return NULL; + + if ( mvalues->count >= SIEVE_MAX_MATCH_VALUES ) return NULL; if ( mvalues->count >= array_count(&mvalues->values) ) { entry = str_new(mvalues->pool, 64); @@ -225,7 +229,7 @@ static string_t *sieve_match_values_add_entry void sieve_match_values_set (struct sieve_match_values *mvalues, unsigned int index, string_t *value) { - if ( mvalues != NULL ) { + if ( mvalues != NULL && index < array_count(&mvalues->values) ) { string_t * const *ep = array_idx(&mvalues->values, index); string_t *entry = *ep; -- GitLab