From acf33c8b3f31ac6ca7cb9e65da9006ab63f7952f Mon Sep 17 00:00:00 2001 From: Stephan Bosch <stephan@rename-it.nl> Date: Sun, 31 Aug 2008 22:07:20 +0200 Subject: [PATCH] Added the concept of a script code header to list the extensions actually used by a script (was using all extensions listed in the binary). --- .../plugins/include/ext-include-binary.c | 4 ++ .../plugins/include/ext-include-common.c | 71 +++++++++++-------- src/lib-sieve/sieve-ast.c | 12 +++- src/lib-sieve/sieve-binary-dumper.c | 6 +- src/lib-sieve/sieve-code-dumper.c | 42 ++++++++++- src/lib-sieve/sieve-generator.c | 6 +- src/lib-sieve/sieve-interpreter.c | 42 +++++++---- src/lib-sieve/sieve.c | 8 ++- src/testsuite/testsuite-common.c | 3 + src/testsuite/testsuite.c | 13 ++-- 10 files changed, 155 insertions(+), 52 deletions(-) diff --git a/src/lib-sieve/plugins/include/ext-include-binary.c b/src/lib-sieve/plugins/include/ext-include-binary.c index 530243ac6..cf1b4bc52 100644 --- a/src/lib-sieve/plugins/include/ext-include-binary.c +++ b/src/lib-sieve/plugins/include/ext-include-binary.c @@ -395,6 +395,10 @@ bool ext_include_binary_dump(struct sieve_dumptime_env *denv) } denv->cdumper = sieve_code_dumper_create(denv); + + if ( denv->cdumper == NULL ) + return FALSE; + sieve_code_dumper_run(denv->cdumper); sieve_code_dumper_free(&(denv->cdumper)); } diff --git a/src/lib-sieve/plugins/include/ext-include-common.c b/src/lib-sieve/plugins/include/ext-include-common.c index 19538aad7..a35b31ead 100644 --- a/src/lib-sieve/plugins/include/ext-include-common.c +++ b/src/lib-sieve/plugins/include/ext-include-common.c @@ -478,7 +478,7 @@ bool ext_include_execute_include include_id, sieve_script_name(included->script), block_id); if ( ctx->parent == NULL ) { - struct ext_include_interpreter_context *curctx; + struct ext_include_interpreter_context *curctx = NULL; struct sieve_error_handler *ehandler = sieve_interpreter_get_error_handler(renv->interp); struct sieve_interpreter *subinterp; @@ -487,22 +487,29 @@ bool ext_include_execute_include /* We are the top-level interpreter instance */ - /* Create interpreter for top-level included script (first sub-interpreter) - */ - subinterp = sieve_interpreter_create - (renv->sbin, ehandler, renv->trace_stream); - curctx = ext_include_interpreter_context_init_child - (subinterp, ctx, NULL, block_id); - - /* Activate and start the top-level included script */ - if ( sieve_binary_block_set_active(renv->sbin, block_id, &this_block_id) ) - result = ( sieve_interpreter_start - (subinterp, renv->msgdata, renv->scriptenv, renv->msgctx, renv->result, - &interrupted) == 1 ); - else { + /* Activate block for included script */ + if ( !sieve_binary_block_set_active(renv->sbin, block_id, &this_block_id) ) { sieve_runtime_trace_error(renv, "invalid block id: %d", block_id); result = SIEVE_EXEC_BIN_CORRUPT; } + + if ( result > 0 ) { + /* Create interpreter for top-level included script (first sub-interpreter) + */ + subinterp = sieve_interpreter_create + (renv->sbin, ehandler, renv->trace_stream); + + if ( subinterp != NULL ) { + curctx = ext_include_interpreter_context_init_child + (subinterp, ctx, NULL, block_id); + + /* Activate and start the top-level included script */ + result = ( sieve_interpreter_start + (subinterp, renv->msgdata, renv->scriptenv, renv->msgctx, renv->result, + &interrupted) == 1 ); + } else + result = SIEVE_EXEC_BIN_CORRUPT; + } /* Included scripts can have includes of their own. This is not implemented * recursively. Rather, the sub-interpreter interrupts and defers the @@ -538,25 +545,31 @@ bool ext_include_execute_include /* FIXME: Check circular include during interpretation as well. * Let's not trust user-owned binaries. */ - - /* Create sub-interpreter */ - subinterp = sieve_interpreter_create - (renv->sbin, ehandler, renv->trace_stream); - curctx = ext_include_interpreter_context_init_child - (subinterp, curctx, NULL, curctx->inc_block_id); /* Activate the sub-include's block */ - if ( sieve_binary_block_set_active + if ( !sieve_binary_block_set_active (renv->sbin, curctx->block_id, NULL) ) { - /* Start the sub-include's interpreter */ - curctx->inc_block_id = 0; - curctx->returned = FALSE; - result = ( sieve_interpreter_start - (subinterp, renv->msgdata, renv->scriptenv, renv->msgctx, - renv->result, &interrupted) == 1 ); - } else { sieve_runtime_trace_error(renv, "invalid block id: %d", curctx->block_id); - result = SIEVE_EXEC_BIN_CORRUPT; + result = SIEVE_EXEC_BIN_CORRUPT; + } + + if ( result > 0 ) { + /* Create sub-interpreter */ + subinterp = sieve_interpreter_create + (renv->sbin, ehandler, renv->trace_stream); + + if ( subinterp != NULL ) { + curctx = ext_include_interpreter_context_init_child + (subinterp, curctx, NULL, curctx->inc_block_id); + + /* Start the sub-include's interpreter */ + curctx->inc_block_id = 0; + curctx->returned = FALSE; + result = ( sieve_interpreter_start + (subinterp, renv->msgdata, renv->scriptenv, renv->msgctx, + renv->result, &interrupted) == 1 ); + } else + result = SIEVE_EXEC_BIN_CORRUPT; } } else { /* Sub-interpreter was interrupted outside this extension, probably diff --git a/src/lib-sieve/sieve-ast.c b/src/lib-sieve/sieve-ast.c index 082c57db2..ea271fe63 100644 --- a/src/lib-sieve/sieve-ast.c +++ b/src/lib-sieve/sieve-ast.c @@ -126,9 +126,19 @@ void sieve_ast_extension_link (struct sieve_ast *ast, const struct sieve_extension *ext) { int ext_id = *ext->id; - + unsigned int i, ext_count; + const struct sieve_extension *const *extensions; + if ( ext_id < 0 ) return; + + /* Prevent duplicates */ + extensions = array_get(&ast->linked_extensions, &ext_count); + for ( i = 0; i < ext_count; i++ ) { + if ( extensions[i] == ext ) + return; + } + /* Add extension */ array_append(&ast->linked_extensions, &ext, 1); } diff --git a/src/lib-sieve/sieve-binary-dumper.c b/src/lib-sieve/sieve-binary-dumper.c index f5ae28729..43caa79bc 100644 --- a/src/lib-sieve/sieve-binary-dumper.c +++ b/src/lib-sieve/sieve-binary-dumper.c @@ -135,9 +135,11 @@ bool sieve_binary_dumper_run dumper->dumpenv.cdumper = sieve_code_dumper_create(&(dumper->dumpenv)); - sieve_code_dumper_run(dumper->dumpenv.cdumper); + if ( dumper->dumpenv.cdumper != NULL ) { + sieve_code_dumper_run(dumper->dumpenv.cdumper); - sieve_code_dumper_free(&dumper->dumpenv.cdumper); + sieve_code_dumper_free(&dumper->dumpenv.cdumper); + } /* Finish with empty line */ sieve_binary_dumpf(denv, "\n"); diff --git a/src/lib-sieve/sieve-code-dumper.c b/src/lib-sieve/sieve-code-dumper.c index b9ab277b0..4284437e3 100644 --- a/src/lib-sieve/sieve-code-dumper.c +++ b/src/lib-sieve/sieve-code-dumper.c @@ -165,10 +165,48 @@ static bool sieve_code_dumper_print_operation void sieve_code_dumper_run(struct sieve_code_dumper *dumper) { - struct sieve_binary *sbin = dumper->dumpenv->sbin; - + const struct sieve_dumptime_env *denv = dumper->dumpenv; + struct sieve_binary *sbin = denv->sbin; + unsigned int ext_count; + bool success = TRUE; + dumper->pc = 0; + /* Load and dump extensions listed in code */ + sieve_code_mark(denv); + + if ( sieve_binary_read_integer(sbin, &dumper->pc, &ext_count) ) { + unsigned int i; + + sieve_code_dumpf(denv, "EXTENSIONS (%d):", ext_count); + sieve_code_descend(denv); + + for ( i = 0; i < ext_count; i++ ) { + unsigned int code = 0; + const struct sieve_extension *ext; + + sieve_code_mark(denv); + + if ( !sieve_binary_read_extension(sbin, &dumper->pc, &code, &ext) ) + { + success = FALSE; + break; + } + + sieve_code_dumpf(denv, "%s", ext->name); + + /* Load ? */ + } + + sieve_code_ascend(denv); + } else + success = FALSE; + + if ( !success ) { + sieve_code_dumpf(denv, "Binary code header is corrupt."); + return; + } + while ( dumper->pc < sieve_binary_get_code_size(sbin) ) { if ( !sieve_code_dumper_print_operation(dumper) ) { diff --git a/src/lib-sieve/sieve-generator.c b/src/lib-sieve/sieve-generator.c index 71443ade5..fb5cf2c93 100644 --- a/src/lib-sieve/sieve-generator.c +++ b/src/lib-sieve/sieve-generator.c @@ -374,14 +374,18 @@ bool sieve_generator_run gentr->genenv.sbin = *sbin; - /* Load extensions linked to the AST */ + /* Load extensions linked to the AST and emit a list in code */ extensions = sieve_ast_extensions_get(gentr->genenv.ast, &ext_count); + (void) sieve_binary_emit_integer(*sbin, ext_count); for ( i = 0; i < ext_count; i++ ) { const struct sieve_extension *ext = extensions[i]; /* Link to binary */ (void)sieve_binary_extension_link(*sbin, ext); + /* Emit */ + sieve_binary_emit_extension(*sbin, ext, 0); + /* Load */ if ( ext->generator_load != NULL && !ext->generator_load(&gentr->genenv) ) return FALSE; diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c index eb8e35073..21988f6ef 100644 --- a/src/lib-sieve/sieve-interpreter.c +++ b/src/lib-sieve/sieve-interpreter.c @@ -45,6 +45,8 @@ struct sieve_interpreter { /* Runtime data for extensions */ ARRAY_DEFINE(extensions, struct sieve_interpreter_extension_reg); + + sieve_size_t reset_vector; /* Execution status */ @@ -66,8 +68,8 @@ struct sieve_interpreter *sieve_interpreter_create (struct sieve_binary *sbin, struct sieve_error_handler *ehandler, struct ostream *trace_stream) { - unsigned int i; - int idx; + unsigned int i, ext_count; + bool success = TRUE; pool_t pool; struct sieve_interpreter *interp; @@ -97,13 +99,29 @@ struct sieve_interpreter *sieve_interpreter_create (void)ext->interpreter_load(interp); } - /* Load other extensions listed in the binary */ - for ( idx = 0; idx < sieve_binary_extensions_count(sbin); idx++ ) { - const struct sieve_extension *ext = - sieve_binary_extension_get_by_index(sbin, idx); - - if ( ext->interpreter_load != NULL ) - ext->interpreter_load(interp); + /* Load other extensions listed in code */ + if ( sieve_binary_read_integer(sbin, &interp->pc, &ext_count) ) { + for ( i = 0; i < ext_count; i++ ) { + unsigned int code = 0; + const struct sieve_extension *ext; + + if ( !sieve_binary_read_extension(sbin, &interp->pc, &code, &ext) ) { + success = FALSE; + break; + } + + if ( ext->interpreter_load != NULL && !ext->interpreter_load(interp) ) { + success = FALSE; + break; + } + } + } else + success = FALSE; + + if ( !success ) { + sieve_interpreter_free(&interp); + } else { + interp->reset_vector = interp->pc; } return interp; @@ -291,7 +309,7 @@ void *sieve_interpreter_extension_get_context void sieve_interpreter_reset(struct sieve_interpreter *interp) { - interp->pc = 0; + interp->pc = interp->reset_vector; interp->interrupted = FALSE; interp->test_result = FALSE; interp->runenv.msgdata = NULL; @@ -460,8 +478,8 @@ int sieve_interpreter_start const struct sieve_script_env *senv, struct sieve_message_context *msgctx, struct sieve_result *result, bool *interrupted) { - const struct sieve_interpreter_extension_reg *extrs; - unsigned int ext_count, i; + const struct sieve_interpreter_extension_reg *extrs; + unsigned int ext_count, i; interp->runenv.msgdata = msgdata; interp->runenv.result = result; diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c index 8b4628155..2657cb608 100644 --- a/src/lib-sieve/sieve.c +++ b/src/lib-sieve/sieve.c @@ -241,7 +241,10 @@ int sieve_test struct sieve_interpreter *interp = sieve_interpreter_create(sbin, ehandler, trace_stream); int ret = 0; - + + if ( interp == NULL ) + return SIEVE_EXEC_BIN_CORRUPT; + ret = sieve_interpreter_run(interp, msgdata, senv, &sres); if ( ret > 0 ) @@ -265,6 +268,9 @@ int sieve_execute struct sieve_interpreter *interp = sieve_interpreter_create(sbin, ehandler, trace_stream); int ret = 0; + + if ( interp == NULL ) + return SIEVE_EXEC_BIN_CORRUPT; ret = sieve_interpreter_run(interp, msgdata, senv, &sres); diff --git a/src/testsuite/testsuite-common.c b/src/testsuite/testsuite-common.c index d0a3521e4..c0f563b70 100644 --- a/src/testsuite/testsuite-common.c +++ b/src/testsuite/testsuite-common.c @@ -445,6 +445,9 @@ bool testsuite_script_execute(const struct sieve_runtime_env *renv) /* Execute the script */ interp=sieve_interpreter_create(_testsuite_compiled_script, test_script_ehandler, NULL); + if ( interp == NULL ) + return SIEVE_EXEC_BIN_CORRUPT; + ret = sieve_interpreter_run(interp, renv->msgdata, &scriptenv, &result); sieve_interpreter_free(&interp); diff --git a/src/testsuite/testsuite.c b/src/testsuite/testsuite.c index 16cca8dc7..9695895b5 100644 --- a/src/testsuite/testsuite.c +++ b/src/testsuite/testsuite.c @@ -159,18 +159,23 @@ static int testsuite_run interp=sieve_interpreter_create(sbin, ehandler, tstream); - ret = sieve_interpreter_run(interp, &testsuite_msgdata, scriptenv, &sres); + if ( interp != NULL ) + ret = sieve_interpreter_run(interp, &testsuite_msgdata, scriptenv, &sres); o_stream_destroy(&tstream); } else { interp=sieve_interpreter_create(sbin, ehandler, NULL); - ret = sieve_interpreter_run(interp, &testsuite_msgdata, scriptenv, &sres); + if ( interp != NULL ) + ret = sieve_interpreter_run(interp, &testsuite_msgdata, scriptenv, &sres); } - sieve_interpreter_free(&interp); - sieve_result_unref(&sres); + if ( interp != NULL ) + sieve_interpreter_free(&interp); + else + ret = SIEVE_EXEC_BIN_CORRUPT; + sieve_result_unref(&sres); sieve_error_handler_unref(&ehandler); return ret; -- GitLab