diff --git a/src/lib-sieve/plugins/include/ext-include-common.c b/src/lib-sieve/plugins/include/ext-include-common.c index b50acd36ae5876f5fe5abf8182ecfdcbacba8b18..b40fda9cd3dceb6b79f04d658c08ab375fa03e77 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 5e332156de32e7d6ecf86457d09393ddcf86867d..7c87e1e5eb88e73b7ab944ecd207f65abfa2e328 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 bace3155f2b482108dfbd8f9df1a77aea9c8065e..f2d96380b14bac2a0fdb13d0f63b1ec103ae5064 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 c5a4fe9773c4886a694bc8791225e86a53ef8fe8..de30e186210711bbbd00c47a1542ad495145e824 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 f653b2014ae84dd7d1bb0330e022b8faefff9bcc..095fb3067bac60616b8d9361bb1f72dcb02e623c 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 38786b8cf90349a62b7b60e7b31ce2be7d8ef650..fd5d0f563907c979f50fb04ace75017cdbe27542 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 2a183b5e4bc0db8a5242e05a794be019cdb7a897..31235264e06436de0c95d4243297b625930c5d0c 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 0000000000000000000000000000000000000000..ef924563c47d7af2ad6e48642221e6bb634aa161 --- /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 0000000000000000000000000000000000000000..80c5884540e5d3404a68f47ffae1ff8a1049c2eb --- /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 0000000000000000000000000000000000000000..228a8bc34509b9d66d8ee776d3197d2f52b805c4 --- /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 0000000000000000000000000000000000000000..00dad847dcd1093004de3c512a47a79a444955bd --- /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 0000000000000000000000000000000000000000..e22b21cad1063ef3d7e8e91253d5699455f80278 --- /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; + } +}