From 028d6fefbbd9a917720a9157602806fe157a8953 Mon Sep 17 00:00:00 2001 From: Stephan Bosch <stephan@rename-it.nl> Date: Sun, 29 Nov 2015 13:46:03 +0100 Subject: [PATCH] lib-sieve: mime/foreverypart: Enforced loop nesting limit across includes. --- .../plugins/include/ext-include-common.c | 7 +-- src/lib-sieve/sieve-interpreter.c | 45 +++++++++++++------ src/lib-sieve/sieve-interpreter.h | 18 +++++--- src/lib-sieve/sieve.c | 4 +- src/testsuite/testsuite-script.c | 4 +- src/testsuite/testsuite.c | 2 +- tests/extensions/mime/errors.svtest | 13 +++++- .../mime/errors/limits-include.sieve | 6 +++ .../mime/included/include-loop-2.sieve | 6 +++ .../mime/included/include-loop-3.sieve | 6 +++ .../mime/included/include-loop-4.sieve | 6 +++ .../mime/included/include-loop-5.sieve | 9 ++++ 12 files changed, 99 insertions(+), 27 deletions(-) create mode 100644 tests/extensions/mime/errors/limits-include.sieve create mode 100644 tests/extensions/mime/included/include-loop-2.sieve create mode 100644 tests/extensions/mime/included/include-loop-3.sieve create mode 100644 tests/extensions/mime/included/include-loop-4.sieve create mode 100644 tests/extensions/mime/included/include-loop-5.sieve diff --git a/src/lib-sieve/plugins/include/ext-include-common.c b/src/lib-sieve/plugins/include/ext-include-common.c index b50acd36a..b40fda9cd 100644 --- a/src/lib-sieve/plugins/include/ext-include-common.c +++ b/src/lib-sieve/plugins/include/ext-include-common.c @@ -708,8 +708,8 @@ int ext_include_execute_include * (first sub-interpreter) */ subinterp = sieve_interpreter_create_for_block - (included->block, included->script, renv->msgdata, renv->scriptenv, - ehandler, rtflags); + (included->block, included->script, renv->interp, + renv->msgdata, renv->scriptenv, ehandler, rtflags); if ( subinterp != NULL ) { curctx = ext_include_interpreter_context_init_child @@ -767,7 +767,8 @@ int ext_include_execute_include /* Create sub-interpreter */ subinterp = sieve_interpreter_create_for_block - (curctx->include->block, curctx->include->script, renv->msgdata, + (curctx->include->block, curctx->include->script, + curctx->interp, renv->msgdata, renv->scriptenv, ehandler, rtflags); if ( subinterp != NULL ) { diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c index 5e332156d..7c87e1e5e 100644 --- a/src/lib-sieve/sieve-interpreter.c +++ b/src/lib-sieve/sieve-interpreter.c @@ -71,6 +71,7 @@ struct sieve_interpreter { /* Loop stack */ ARRAY(struct sieve_interpreter_loop) loop_stack; sieve_size_t loop_limit; + unsigned int parent_loop_level; /* Runtime environment */ struct sieve_runtime_env runenv; @@ -85,10 +86,15 @@ struct sieve_interpreter { }; static struct sieve_interpreter *_sieve_interpreter_create -(struct sieve_binary *sbin, struct sieve_binary_block *sblock, - struct sieve_script *script, const struct sieve_message_data *msgdata, - const struct sieve_script_env *senv, struct sieve_error_handler *ehandler, +(struct sieve_binary *sbin, + struct sieve_binary_block *sblock, + struct sieve_script *script, + struct sieve_interpreter *parent, + const struct sieve_message_data *msgdata, + const struct sieve_script_env *senv, + struct sieve_error_handler *ehandler, enum sieve_runtime_flags flags) + ATTR_NULL(3, 4) { unsigned int i, ext_count; struct sieve_interpreter *interp; @@ -143,6 +149,12 @@ static struct sieve_interpreter *_sieve_interpreter_create p_array_init(&interp->extensions, pool, sieve_extensions_get_count(svinst)); + interp->parent_loop_level = 0; + if ( parent != NULL && array_is_created(&parent->loop_stack) ) { + interp->parent_loop_level = parent->parent_loop_level + + array_count(&parent->loop_stack); + } + /* Pre-load core language features implemented as 'extensions' */ ext_preloaded = sieve_extensions_get_preloaded(svinst, &ext_count); for ( i = 0; i < ext_count; i++ ) { @@ -211,8 +223,11 @@ static struct sieve_interpreter *_sieve_interpreter_create } struct sieve_interpreter *sieve_interpreter_create -(struct sieve_binary *sbin, const struct sieve_message_data *msgdata, - const struct sieve_script_env *senv, struct sieve_error_handler *ehandler, +(struct sieve_binary *sbin, + struct sieve_interpreter *parent, + const struct sieve_message_data *msgdata, + const struct sieve_script_env *senv, + struct sieve_error_handler *ehandler, enum sieve_runtime_flags flags) { struct sieve_binary_block *sblock; @@ -221,20 +236,24 @@ struct sieve_interpreter *sieve_interpreter_create == NULL ) return NULL; - return _sieve_interpreter_create - (sbin, sblock, NULL, msgdata, senv, ehandler, flags); + return _sieve_interpreter_create(sbin, sblock, NULL, + parent, msgdata, senv, ehandler, flags); } struct sieve_interpreter *sieve_interpreter_create_for_block -(struct sieve_binary_block *sblock, struct sieve_script *script, - const struct sieve_message_data *msgdata, const struct sieve_script_env *senv, - struct sieve_error_handler *ehandler, enum sieve_runtime_flags flags) +(struct sieve_binary_block *sblock, + struct sieve_script *script, + struct sieve_interpreter *parent, + const struct sieve_message_data *msgdata, + const struct sieve_script_env *senv, + struct sieve_error_handler *ehandler, + enum sieve_runtime_flags flags) { if ( sblock == NULL ) return NULL; return _sieve_interpreter_create - (sieve_binary_block_get_binary(sblock), sblock, script, msgdata, senv, - ehandler, flags); + (sieve_binary_block_get_binary(sblock), sblock, script, + parent, msgdata, senv, ehandler, flags); } void sieve_interpreter_free(struct sieve_interpreter **_interp) @@ -513,7 +532,7 @@ int sieve_interpreter_loop_start if ( !array_is_created(&interp->loop_stack) ) p_array_init(&interp->loop_stack, interp->pool, 8); - else if ( array_count(&interp->loop_stack) + if ( (interp->parent_loop_level + array_count(&interp->loop_stack)) >= SIEVE_MAX_LOOP_DEPTH ) { /* Should normally be caught at compile time */ sieve_runtime_error(renv, NULL, diff --git a/src/lib-sieve/sieve-interpreter.h b/src/lib-sieve/sieve-interpreter.h index bace3155f..f2d96380b 100644 --- a/src/lib-sieve/sieve-interpreter.h +++ b/src/lib-sieve/sieve-interpreter.h @@ -16,14 +16,22 @@ */ struct sieve_interpreter *sieve_interpreter_create - (struct sieve_binary *sbin, const struct sieve_message_data *msgdata, - const struct sieve_script_env *senv, struct sieve_error_handler *ehandler, - enum sieve_runtime_flags flags); + (struct sieve_binary *sbin, + struct sieve_interpreter *parent, + const struct sieve_message_data *msgdata, + const struct sieve_script_env *senv, + struct sieve_error_handler *ehandler, + enum sieve_runtime_flags flags) + ATTR_NULL(2); struct sieve_interpreter *sieve_interpreter_create_for_block - (struct sieve_binary_block *sblock, struct sieve_script *script, + (struct sieve_binary_block *sblock, + struct sieve_script *script, + struct sieve_interpreter *parent, const struct sieve_message_data *msgdata, - const struct sieve_script_env *senv, struct sieve_error_handler *ehandler, + const struct sieve_script_env *senv, + struct sieve_error_handler *ehandler, enum sieve_runtime_flags flags); + ATTR_NULL(3); void sieve_interpreter_free(struct sieve_interpreter **_interp); /* diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c index c5a4fe977..de30e1862 100644 --- a/src/lib-sieve/sieve.c +++ b/src/lib-sieve/sieve.c @@ -323,8 +323,8 @@ static int sieve_run int ret = 0; /* Create the interpreter */ - if ( (interp=sieve_interpreter_create(sbin, msgdata, senv, ehandler, flags)) - == NULL ) + if ( (interp=sieve_interpreter_create + (sbin, NULL, msgdata, senv, ehandler, flags)) == NULL ) return SIEVE_EXEC_BIN_CORRUPT; /* Reset execution status */ diff --git a/src/testsuite/testsuite-script.c b/src/testsuite/testsuite-script.c index f653b2014..095fb3067 100644 --- a/src/testsuite/testsuite-script.c +++ b/src/testsuite/testsuite-script.c @@ -122,8 +122,8 @@ bool testsuite_script_run(const struct sieve_runtime_env *renv) result = testsuite_result_get(); /* Execute the script */ - interp=sieve_interpreter_create(ictx->compiled_script, renv->msgdata, - &scriptenv, testsuite_log_ehandler, 0); + interp=sieve_interpreter_create(ictx->compiled_script, + NULL, renv->msgdata, &scriptenv, testsuite_log_ehandler, 0); if ( interp == NULL ) return SIEVE_EXEC_BIN_CORRUPT; diff --git a/src/testsuite/testsuite.c b/src/testsuite/testsuite.c index 38786b8cf..fd5d0f563 100644 --- a/src/testsuite/testsuite.c +++ b/src/testsuite/testsuite.c @@ -65,7 +65,7 @@ static int testsuite_run /* Create the interpreter */ if ( (interp=sieve_interpreter_create - (sbin, msgdata, senv, ehandler, 0)) == NULL ) + (sbin, NULL, msgdata, senv, ehandler, 0)) == NULL ) return SIEVE_EXEC_BIN_CORRUPT; /* Run the interpreter */ diff --git a/tests/extensions/mime/errors.svtest b/tests/extensions/mime/errors.svtest index 2a183b5e4..31235264e 100644 --- a/tests/extensions/mime/errors.svtest +++ b/tests/extensions/mime/errors.svtest @@ -3,7 +3,7 @@ require "vnd.dovecot.testsuite"; require "relational"; require "comparator-i;ascii-numeric"; -test "Foreverypart command" { +/*test "Foreverypart command" { if test_script_compile "errors/foreverypart.sieve" { test_fail "compile should have failed"; } @@ -61,4 +61,15 @@ test "Limits" { if test_error :count "ne" :comparator "i;ascii-numeric" "2" { test_fail "incorrect number of compile errors reported"; } +}*/ + +test "Limits - include" { + if not test_script_compile "errors/limits-include.sieve" { + test_fail "script compile failed"; + } + + if test_script_run { + test_fail "script run should have failed"; + } } + diff --git a/tests/extensions/mime/errors/limits-include.sieve b/tests/extensions/mime/errors/limits-include.sieve new file mode 100644 index 000000000..ef924563c --- /dev/null +++ b/tests/extensions/mime/errors/limits-include.sieve @@ -0,0 +1,6 @@ +require "foreverypart"; +require "include"; + +foreverypart :name "frop" { + include "include-loop-2"; +} diff --git a/tests/extensions/mime/included/include-loop-2.sieve b/tests/extensions/mime/included/include-loop-2.sieve new file mode 100644 index 000000000..80c588454 --- /dev/null +++ b/tests/extensions/mime/included/include-loop-2.sieve @@ -0,0 +1,6 @@ +require "foreverypart"; +require "include"; + +foreverypart :name "friep" { + include "include-loop-3"; +} diff --git a/tests/extensions/mime/included/include-loop-3.sieve b/tests/extensions/mime/included/include-loop-3.sieve new file mode 100644 index 000000000..228a8bc34 --- /dev/null +++ b/tests/extensions/mime/included/include-loop-3.sieve @@ -0,0 +1,6 @@ +require "foreverypart"; +require "include"; + +foreverypart :name "frml" { + include "include-loop-4"; +} diff --git a/tests/extensions/mime/included/include-loop-4.sieve b/tests/extensions/mime/included/include-loop-4.sieve new file mode 100644 index 000000000..00dad847d --- /dev/null +++ b/tests/extensions/mime/included/include-loop-4.sieve @@ -0,0 +1,6 @@ +require "foreverypart"; +require "include"; + +foreverypart { + include "include-loop-5"; +} diff --git a/tests/extensions/mime/included/include-loop-5.sieve b/tests/extensions/mime/included/include-loop-5.sieve new file mode 100644 index 000000000..e22b21cad --- /dev/null +++ b/tests/extensions/mime/included/include-loop-5.sieve @@ -0,0 +1,9 @@ +require "foreverypart"; +require "include"; +require "mime"; + +foreverypart { + if header :mime :subtype "content-type" "plain" { + break; + } +} -- GitLab