From c0c60be5908b4497c302f7cb2e27e76ebb4f3eb8 Mon Sep 17 00:00:00 2001 From: Stephan Bosch <stephan@rename-it.nl> Date: Sun, 16 May 2010 14:43:43 +0200 Subject: [PATCH] Restructured and cleaned up trace debugging and optional operand fetching. --- src/lib-sieve/Makefile.am | 3 + src/lib-sieve/cmd-discard.c | 6 +- src/lib-sieve/cmd-keep.c | 21 +- src/lib-sieve/cmd-redirect.c | 27 ++- src/lib-sieve/cmd-stop.c | 2 +- src/lib-sieve/ext-envelope.c | 27 ++- src/lib-sieve/ext-fileinto.c | 19 +- src/lib-sieve/ext-reject.c | 43 ++-- src/lib-sieve/plugins/body/ext-body-common.c | 5 +- src/lib-sieve/plugins/body/tst-body.c | 58 ++--- src/lib-sieve/plugins/date/ext-date-common.c | 3 +- src/lib-sieve/plugins/date/tst-date.c | 66 +++-- src/lib-sieve/plugins/enotify/cmd-notify.c | 164 ++++++------- .../plugins/enotify/ext-enotify-common.c | 4 +- .../enotify/tst-notify-method-capability.c | 33 +-- .../plugins/enotify/tst-valid-notify-method.c | 7 +- .../plugins/environment/tst-environment.c | 30 +-- src/lib-sieve/plugins/imap4flags/cmd-flag.c | 49 ++-- .../imap4flags/ext-imap4flags-common.c | 10 +- src/lib-sieve/plugins/imap4flags/tag-flags.c | 15 +- .../plugins/imap4flags/tst-hasflag.c | 65 ++--- src/lib-sieve/plugins/include/cmd-global.c | 10 +- src/lib-sieve/plugins/include/cmd-include.c | 2 +- src/lib-sieve/plugins/include/cmd-return.c | 2 - .../plugins/include/ext-include-common.c | 50 ++-- .../plugins/mailbox/tst-mailboxexists.c | 7 +- src/lib-sieve/plugins/notify/cmd-denotify.c | 129 +++++----- src/lib-sieve/plugins/notify/cmd-notify.c | 147 ++++++------ .../plugins/notify/ext-notify-common.c | 2 +- .../spamvirustest/ext-spamvirustest-common.c | 42 ++-- .../plugins/spamvirustest/tst-spamvirustest.c | 41 ++-- src/lib-sieve/plugins/vacation/cmd-vacation.c | 177 ++++++-------- src/lib-sieve/plugins/variables/cmd-set.c | 17 +- .../variables/ext-variables-modifiers.h | 8 +- .../variables/ext-variables-operands.c | 33 ++- .../plugins/variables/sieve-ext-variables.h | 9 +- src/lib-sieve/plugins/variables/tst-string.c | 29 +-- src/lib-sieve/sieve-actions.c | 75 ++++++ src/lib-sieve/sieve-actions.h | 12 + src/lib-sieve/sieve-address-parts.c | 125 +++++----- src/lib-sieve/sieve-address-parts.h | 9 +- src/lib-sieve/sieve-code-dumper.c | 132 +++++----- src/lib-sieve/sieve-code.c | 160 ++++++++----- src/lib-sieve/sieve-code.h | 72 +++++- src/lib-sieve/sieve-common.h | 4 +- src/lib-sieve/sieve-dump.h | 14 +- src/lib-sieve/sieve-interpreter.c | 226 ++++++++---------- src/lib-sieve/sieve-interpreter.h | 82 ++----- src/lib-sieve/sieve-match.c | 99 ++++---- src/lib-sieve/sieve-match.h | 4 +- src/lib-sieve/sieve-runtime-trace.c | 139 +++++++++++ src/lib-sieve/sieve-runtime-trace.h | 132 ++++++++++ src/lib-sieve/sieve-runtime.h | 43 ++++ src/lib-sieve/sieve-types.h | 16 +- src/lib-sieve/sieve.c | 5 +- src/lib-sieve/tst-address.c | 20 +- src/lib-sieve/tst-exists.c | 17 +- src/lib-sieve/tst-header.c | 37 +-- src/lib-sieve/tst-size.c | 25 +- src/sieve-tools/debug/cmd-debug-print.c | 6 +- src/sieve-tools/sieve-test.c | 1 + src/testsuite/cmd-test-binary.c | 23 +- src/testsuite/cmd-test-config.c | 30 +-- src/testsuite/cmd-test-fail.c | 7 +- src/testsuite/cmd-test-mailbox.c | 16 +- src/testsuite/cmd-test-message.c | 30 +-- src/testsuite/cmd-test-set.c | 7 +- src/testsuite/cmd-test.c | 9 +- src/testsuite/testsuite-script.c | 8 +- src/testsuite/testsuite.c | 9 +- src/testsuite/tst-test-error.c | 53 ++-- src/testsuite/tst-test-multiscript.c | 7 +- src/testsuite/tst-test-result-execute.c | 2 +- src/testsuite/tst-test-result.c | 53 ++-- src/testsuite/tst-test-script-compile.c | 9 +- src/testsuite/tst-test-script-run.c | 72 +++--- 76 files changed, 1772 insertions(+), 1380 deletions(-) create mode 100644 src/lib-sieve/sieve-runtime-trace.c create mode 100644 src/lib-sieve/sieve-runtime-trace.h create mode 100644 src/lib-sieve/sieve-runtime.h diff --git a/src/lib-sieve/Makefile.am b/src/lib-sieve/Makefile.am index 9ad44e736..6aca9080c 100644 --- a/src/lib-sieve/Makefile.am +++ b/src/lib-sieve/Makefile.am @@ -84,6 +84,7 @@ libdovecot_sieve_la_SOURCES = \ sieve-validator.c \ sieve-generator.c \ sieve-interpreter.c \ + sieve-runtime-trace.c \ sieve-code-dumper.c \ sieve-binary-dumper.c \ sieve-result.c \ @@ -125,6 +126,8 @@ headers = \ sieve-validator.h \ sieve-generator.h \ sieve-interpreter.h \ + sieve-runtime-trace.h \ + sieve-runtime.h \ sieve-code-dumper.h \ sieve-binary-dumper.h \ sieve-dump.h \ diff --git a/src/lib-sieve/cmd-discard.c b/src/lib-sieve/cmd-discard.c index c85b86dda..1d43cb26c 100644 --- a/src/lib-sieve/cmd-discard.c +++ b/src/lib-sieve/cmd-discard.c @@ -94,7 +94,7 @@ static bool cmd_discard_operation_dump sieve_code_dumpf(denv, "DISCARD"); sieve_code_descend(denv); - return sieve_code_dumper_print_optional_operands(denv, address); + return ( sieve_action_opr_optional_dump(denv, address, NULL) == 0 ); } /* @@ -108,9 +108,9 @@ static int cmd_discard_operation_execute unsigned int source_line; /* Source line */ - source_line = sieve_runtime_get_source_location(renv, renv->oprtn.address); + source_line = sieve_runtime_get_command_location(renv); - sieve_runtime_trace(renv, "DISCARD action"); + sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, "discard action"); return ( sieve_result_add_action (renv, NULL, &act_discard, NULL, source_line, NULL, 0) >= 0 ); diff --git a/src/lib-sieve/cmd-keep.c b/src/lib-sieve/cmd-keep.c index eff2f0903..2838fd892 100644 --- a/src/lib-sieve/cmd-keep.c +++ b/src/lib-sieve/cmd-keep.c @@ -73,7 +73,7 @@ static bool cmd_keep_operation_dump sieve_code_dumpf(denv, "KEEP"); sieve_code_descend(denv); - return sieve_code_dumper_print_optional_operands(denv, address); + return ( sieve_action_opr_optional_dump(denv, address, NULL) == 0 ); } /* @@ -85,17 +85,24 @@ static int cmd_keep_operation_execute { struct sieve_side_effects_list *slist = NULL; unsigned int source_line; - int ret = 0; + int ret = 0; + + /* + * Read data + */ /* Source line */ - source_line = sieve_runtime_get_source_location(renv, renv->oprtn.address); + source_line = sieve_runtime_get_command_location(renv); /* Optional operands (side effects only) */ - if ( (ret=sieve_interpreter_handle_optional_operands - (renv, address, &slist)) <= 0 ) - return ret; + if ( (ret=sieve_action_opr_optional_read(renv, address, NULL, &slist)) != 0 ) + return SIEVE_EXEC_BIN_CORRUPT; + + /* + * Perform operation + */ - sieve_runtime_trace(renv, "KEEP action"); + sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, "keep action"); /* Add keep action to result. */ diff --git a/src/lib-sieve/cmd-redirect.c b/src/lib-sieve/cmd-redirect.c index 13d0c8d85..98f26ae9e 100644 --- a/src/lib-sieve/cmd-redirect.c +++ b/src/lib-sieve/cmd-redirect.c @@ -176,14 +176,14 @@ static bool cmd_redirect_operation_dump sieve_code_dumpf(denv, "REDIRECT"); sieve_code_descend(denv); - if ( !sieve_code_dumper_print_optional_operands(denv, address) ) + if ( sieve_action_opr_optional_dump(denv, address, NULL) != 0 ) return FALSE; return sieve_opr_string_dump(denv, address, "reason"); } /* - * Intepretation + * Code execution */ static int cmd_redirect_operation_execute @@ -197,24 +197,29 @@ static int cmd_redirect_operation_execute pool_t pool; int ret = 0; + /* + * Read data + */ + /* Source line */ - source_line = sieve_runtime_get_source_location(renv, renv->oprtn.address); + source_line = sieve_runtime_get_command_location(renv); - /* Optional operands (side effects) */ - if ( (ret=sieve_interpreter_handle_optional_operands - (renv, address, &slist)) <= 0 ) - return ret; + /* Optional operands (side effects only) */ + if ( (ret=sieve_action_opr_optional_read(renv, address, NULL, &slist)) < 0 ) + return SIEVE_EXEC_BIN_CORRUPT; /* Read the address */ - if ( !sieve_opr_string_read(renv, address, &redirect) ) { - sieve_runtime_trace_error(renv, "invalid address string"); + if ( !sieve_opr_string_read(renv, address, "address", &redirect) ) return SIEVE_EXEC_BIN_CORRUPT; - } + + /* + * Perform operation + */ /* FIXME: perform address normalization if the string is not a string literal */ - sieve_runtime_trace(renv, "REDIRECT action (\"%s\")", + sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, "redirect action (\"%s\")", str_sanitize(str_c(redirect), 64)); /* Add redirect action to the result */ diff --git a/src/lib-sieve/cmd-stop.c b/src/lib-sieve/cmd-stop.c index eaae8affe..f908285e7 100644 --- a/src/lib-sieve/cmd-stop.c +++ b/src/lib-sieve/cmd-stop.c @@ -77,7 +77,7 @@ static bool cmd_stop_generate static int opc_stop_execute (const struct sieve_runtime_env *renv, sieve_size_t *address ATTR_UNUSED) { - sieve_runtime_trace(renv, "STOP"); + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "STOP"); sieve_interpreter_interrupt(renv->interp); diff --git a/src/lib-sieve/ext-envelope.c b/src/lib-sieve/ext-envelope.c index 2c294226b..1dbe5e80e 100644 --- a/src/lib-sieve/ext-envelope.c +++ b/src/lib-sieve/ext-envelope.c @@ -308,7 +308,7 @@ static bool ext_envelope_operation_dump sieve_code_descend(denv); /* Handle any optional arguments */ - if ( !sieve_addrmatch_default_dump_optionals(denv, address) ) + if ( sieve_addrmatch_opr_optional_dump(denv, address, NULL) != 0 ) return FALSE; return @@ -426,24 +426,27 @@ static int ext_envelope_operation_execute /* * Read operands */ - - sieve_runtime_trace(renv, "ENVELOPE test"); - if ( (ret=sieve_addrmatch_default_get_optionals - (renv, address, &addrp, &mcht, &cmp)) <= 0 ) - return ret; + /* Read optional operands */ + if ( (ret=sieve_addrmatch_opr_optional_read + (renv, address, NULL, &addrp, &mcht, &cmp)) < 0 ) + return SIEVE_EXEC_BIN_CORRUPT; /* Read envelope-part */ - if ( (envp_list=sieve_opr_stringlist_read(renv, address)) == NULL ) { - sieve_runtime_trace_error(renv, "invalid envelope-part operand"); + if ( (envp_list=sieve_opr_stringlist_read(renv, address, "envelope-part")) + == NULL ) return SIEVE_EXEC_BIN_CORRUPT; - } /* Read key-list */ - if ( (key_list=sieve_opr_stringlist_read(renv, address)) == NULL ) { - sieve_runtime_trace_error(renv, "invalid key-list operand"); + if ( (key_list=sieve_opr_stringlist_read(renv, address, "key-list")) + == NULL ) return SIEVE_EXEC_BIN_CORRUPT; - } + + /* + * Perform test + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "envelope test"); /* Initialize match */ mctx = sieve_match_begin(renv->interp, &mcht, &cmp, NULL, key_list); diff --git a/src/lib-sieve/ext-fileinto.c b/src/lib-sieve/ext-fileinto.c index 994cf5137..0197c5503 100644 --- a/src/lib-sieve/ext-fileinto.c +++ b/src/lib-sieve/ext-fileinto.c @@ -139,9 +139,8 @@ static bool ext_fileinto_operation_dump sieve_code_dumpf(denv, "FILEINTO"); sieve_code_descend(denv); - if ( !sieve_code_dumper_print_optional_operands(denv, address) ) { + if ( sieve_action_opr_optional_dump(denv, address, NULL) != 0 ) return FALSE; - } return sieve_opr_string_dump(denv, address, "folder"); } @@ -164,25 +163,23 @@ static int ext_fileinto_operation_execute */ /* Source line */ - source_line = sieve_runtime_get_source_location(renv, renv->oprtn.address); + source_line = sieve_runtime_get_command_location(renv); - /* Optional operands */ - if ( (ret=sieve_interpreter_handle_optional_operands(renv, address, &slist)) - <= 0 ) - return ret; + /* Optional operands (side effects only) */ + if ( (ret=sieve_action_opr_optional_read(renv, address, NULL, &slist)) < 0 ) + return SIEVE_EXEC_BIN_CORRUPT; /* Folder operand */ - if ( !sieve_opr_string_read(renv, address, &folder) ) { - sieve_runtime_trace_error(renv, "invalid folder operand"); + if ( !sieve_opr_string_read(renv, address, "folder", &folder) ) return SIEVE_EXEC_BIN_CORRUPT; - } /* * Perform operation */ mailbox = str_sanitize(str_c(folder), 64); - sieve_runtime_trace(renv, "FILEINTO action (\"%s\")", mailbox); + sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, + "fileinto action (\"%s\")", mailbox); /* Add action to result */ ret = sieve_act_store_add_to_result diff --git a/src/lib-sieve/ext-reject.c b/src/lib-sieve/ext-reject.c index 7907303db..8736b6537 100644 --- a/src/lib-sieve/ext-reject.c +++ b/src/lib-sieve/ext-reject.c @@ -246,12 +246,10 @@ static bool cmd_reject_generate static bool ext_reject_operation_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address) { - const struct sieve_operation *op = &denv->oprtn; - - sieve_code_dumpf(denv, "%s", sieve_operation_mnemonic(op)); + sieve_code_dumpf(denv, "%s", sieve_operation_mnemonic(denv->oprtn)); sieve_code_descend(denv); - if ( !sieve_code_dumper_print_optional_operands(denv, address) ) + if ( sieve_action_opr_optional_dump(denv, address, NULL) != 0 ) return FALSE; return sieve_opr_string_dump(denv, address, "reason"); @@ -264,8 +262,8 @@ static bool ext_reject_operation_dump static int ext_reject_operation_execute (const struct sieve_runtime_env *renv, sieve_size_t *address) { - const struct sieve_operation *op = &renv->oprtn; - const struct sieve_extension *this_ext = op->ext; + const struct sieve_operation *oprtn = renv->oprtn; + const struct sieve_extension *this_ext = oprtn->ext; struct sieve_side_effects_list *slist = NULL; struct act_reject_context *act; string_t *reason; @@ -273,28 +271,37 @@ static int ext_reject_operation_execute pool_t pool; int ret; + /* + * Read data + */ + /* Source line */ - source_line = sieve_runtime_get_source_location(renv, op->address); - - /* Optional operands (side effects) */ - if ( (ret=sieve_interpreter_handle_optional_operands - (renv, address, &slist)) <= 0 ) - return ret; + source_line = sieve_runtime_get_command_location(renv); + + /* Optional operands (side effects only) */ + if ( (ret=sieve_action_opr_optional_read(renv, address, NULL, &slist)) < 0 ) + return SIEVE_EXEC_BIN_CORRUPT; /* Read rejection reason */ - if ( !sieve_opr_string_read(renv, address, &reason) ) { - sieve_runtime_trace_error(renv, "invalid reason operand"); + if ( !sieve_opr_string_read(renv, address, "reason", &reason) ) return SIEVE_EXEC_BIN_CORRUPT; - } - sieve_runtime_trace(renv, "%s action (\"%s\")", sieve_operation_mnemonic(op), - str_sanitize(str_c(reason), 64)); + /* + * Perform operation + */ + + if ( sieve_operation_is(oprtn, ereject_operation) ) + sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, + "ereject action (\"%s\")", str_sanitize(str_c(reason), 64)); + else + sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, + "reject action (\"%s\")", str_sanitize(str_c(reason), 64)); /* Add reject action to the result */ pool = sieve_result_pool(renv->result); act = p_new(pool, struct act_reject_context, 1); act->reason = p_strdup(pool, str_c(reason)); - act->ereject = ( sieve_operation_is(op, ereject_operation) ); + act->ereject = ( sieve_operation_is(oprtn, ereject_operation) ); ret = sieve_result_add_action (renv, this_ext, &act_reject, slist, source_line, (void *) act, 0); diff --git a/src/lib-sieve/plugins/body/ext-body-common.c b/src/lib-sieve/plugins/body/ext-body-common.c index b2710aa05..559588688 100644 --- a/src/lib-sieve/plugins/body/ext-body-common.c +++ b/src/lib-sieve/plugins/body/ext-body-common.c @@ -13,6 +13,7 @@ #include "message-decoder.h" #include "sieve-common.h" +#include "sieve-code.h" #include "sieve-message.h" #include "sieve-interpreter.h" @@ -328,7 +329,7 @@ bool ext_body_get_content (const struct sieve_runtime_env *renv, const char * const *content_types, int decode_to_plain, struct ext_body_part **parts_r) { - const struct sieve_extension *this_ext = renv->oprtn.ext; + const struct sieve_extension *this_ext = renv->oprtn->ext; struct ext_body_message_context *ctx = ext_body_get_context(this_ext, renv->msgctx); bool result = TRUE; @@ -353,7 +354,7 @@ bool ext_body_get_content bool ext_body_get_raw (const struct sieve_runtime_env *renv, struct ext_body_part **parts_r) { - const struct sieve_extension *this_ext = renv->oprtn.ext; + const struct sieve_extension *this_ext = renv->oprtn->ext; struct ext_body_message_context *ctx = ext_body_get_context(this_ext, renv->msgctx); struct ext_body_part *return_part; diff --git a/src/lib-sieve/plugins/body/tst-body.c b/src/lib-sieve/plugins/body/tst-body.c index 91f4ba386..f28252952 100644 --- a/src/lib-sieve/plugins/body/tst-body.c +++ b/src/lib-sieve/plugins/body/tst-body.c @@ -263,14 +263,16 @@ static bool ext_body_operation_dump sieve_code_descend(denv); /* Handle any optional arguments */ - do { - - if ( !sieve_match_dump_optional_operands(denv, address, &opt_code) ) + for (;;) { + int ret; + + if ( (ret=sieve_match_opr_optional_dump(denv, address, &opt_code)) + < 0 ) return FALSE; + if ( ret == 0 ) break; + switch ( opt_code ) { - case SIEVE_MATCH_OPT_END: - break; case OPT_BODY_TRANSFORM: if ( !sieve_binary_read_byte(denv->sblock, address, &transform) ) return FALSE; @@ -297,7 +299,7 @@ static bool ext_body_operation_dump default: return FALSE; } - } while ( opt_code != SIEVE_MATCH_OPT_END ); + }; return sieve_opr_stringlist_dump(denv, address, "key list"); } @@ -329,43 +331,45 @@ static int ext_body_operation_execute * Read operands */ - /* Handle any optional operands */ - do { - if ( (ret=sieve_match_read_optional_operands - (renv, address, &opt_code, &cmp, &mtch)) <= 0 ) - return ret; + /* Optional operands */ + + for (;;) { + bool opok = TRUE; + int ret; + + if ( (ret=sieve_match_opr_optional_read + (renv, address, &opt_code, &cmp, &mtch)) < 0 ) + return SIEVE_EXEC_BIN_CORRUPT; + + if ( ret == 0 ) break; switch ( opt_code ) { - case SIEVE_MATCH_OPT_END: - break; case OPT_BODY_TRANSFORM: if ( !sieve_binary_read_byte(renv->sblock, address, &transform) || transform > TST_BODY_TRANSFORM_TEXT ) { sieve_runtime_trace_error(renv, "invalid body transform type"); - return SIEVE_EXEC_BIN_CORRUPT; + opok = FALSE; } - if ( transform == TST_BODY_TRANSFORM_CONTENT ) { - if ( (ctype_list=sieve_opr_stringlist_read(renv, address)) - == NULL ) { - sieve_runtime_trace_error(renv, - "invalid :content body transform operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } + if ( opok && transform == TST_BODY_TRANSFORM_CONTENT ) { + ctype_list = sieve_opr_stringlist_read + (renv, address, "content-type-list"); + opok = ( ctype_list != NULL ); } break; default: sieve_runtime_trace_error(renv, "unknown optional operand"); - return SIEVE_EXEC_BIN_CORRUPT; + opok = FALSE; } - } while ( opt_code != SIEVE_MATCH_OPT_END ); + + if ( !opok) return SIEVE_EXEC_BIN_CORRUPT; + } /* Read key-list */ - if ( (key_list=sieve_opr_stringlist_read(renv, address)) == NULL ) { - sieve_runtime_trace_error(renv, "invalid key-list operand"); + + if ( (key_list=sieve_opr_stringlist_read(renv, address, "key-list")) == NULL ) return SIEVE_EXEC_BIN_CORRUPT; - } if ( ctype_list != NULL && !sieve_coded_stringlist_read_all (ctype_list, pool_datastack_create(), &content_types) ) { @@ -377,7 +381,7 @@ static int ext_body_operation_execute * Perform operation */ - sieve_runtime_trace(renv, "BODY action"); + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "body test"); /* Extract requested parts */ diff --git a/src/lib-sieve/plugins/date/ext-date-common.c b/src/lib-sieve/plugins/date/ext-date-common.c index 9fdc56feb..28ce60634 100644 --- a/src/lib-sieve/plugins/date/ext-date-common.c +++ b/src/lib-sieve/plugins/date/ext-date-common.c @@ -5,6 +5,7 @@ #include "utc-offset.h" #include "sieve-common.h" +#include "sieve-code.h" #include "sieve-interpreter.h" #include "sieve-message.h" @@ -104,7 +105,7 @@ bool ext_date_parse_timezone time_t ext_date_get_current_date (const struct sieve_runtime_env *renv, int *zone_offset_r) { - const struct sieve_extension *this_ext = renv->oprtn.ext; + const struct sieve_extension *this_ext = renv->oprtn->ext; struct ext_date_context *dctx = (struct ext_date_context *) sieve_message_context_extension_get(renv->msgctx, this_ext); diff --git a/src/lib-sieve/plugins/date/tst-date.c b/src/lib-sieve/plugins/date/tst-date.c index 53e6d67e7..aa99017f4 100644 --- a/src/lib-sieve/plugins/date/tst-date.c +++ b/src/lib-sieve/plugins/date/tst-date.c @@ -328,20 +328,22 @@ static bool tst_date_operation_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address) { int opt_code = 0; - const struct sieve_operation *op = &denv->oprtn; + const struct sieve_operation *op = denv->oprtn; struct sieve_operand operand; sieve_code_dumpf(denv, "%s", sieve_operation_mnemonic(op)); sieve_code_descend(denv); /* Handle any optional arguments */ - do { - if ( !sieve_match_dump_optional_operands(denv, address, &opt_code) ) + for (;;) { + int ret; + + if ( (ret=sieve_match_opr_optional_dump(denv, address, &opt_code)) < 0 ) return FALSE; + if ( ret == 0 ) break; + switch ( opt_code ) { - case SIEVE_MATCH_OPT_END: - break; case OPT_DATE_ZONE: if ( !sieve_operand_read(denv->sblock, address, &operand) ) { sieve_code_dumpf(denv, "ERROR: INVALID OPERAND"); @@ -359,7 +361,7 @@ static bool tst_date_operation_dump default: return FALSE; } - } while ( opt_code != SIEVE_MATCH_OPT_END ); + } if ( sieve_operation_is(op, date_operation) && !sieve_opr_string_dump(denv, address, "header name") ) @@ -377,7 +379,7 @@ static bool tst_date_operation_dump static int tst_date_operation_execute (const struct sieve_runtime_env *renv, sieve_size_t *address) { - const struct sieve_operation *op = &renv->oprtn; + const struct sieve_operation *op = renv->oprtn; bool result = TRUE, zone_specified = FALSE, got_date = FALSE, matched = FALSE; int opt_code = 0; const struct sieve_message_data *msgdata = renv->msgdata; @@ -396,26 +398,24 @@ static int tst_date_operation_execute int ret; /* Read optional operands */ - do { - if ( (ret=sieve_match_read_optional_operands - (renv, address, &opt_code, &cmp, &mcht)) <= 0 ) - return ret; + for (;;) { + int ret; + + if ( (ret=sieve_match_opr_optional_read + (renv, address, &opt_code, &cmp, &mcht)) < 0 ) + return SIEVE_EXEC_BIN_CORRUPT; + if ( ret == 0 ) break; + switch ( opt_code ) { - case SIEVE_MATCH_OPT_END: - break; case OPT_DATE_ZONE: - if ( !sieve_operand_read(renv->sblock, address, &operand) ) { - sieve_runtime_trace_error(renv, "invalid operand"); + if ( !sieve_operand_runtime_read(renv, address, "zone", &operand) ) return SIEVE_EXEC_BIN_CORRUPT; - } if ( !sieve_operand_is_omitted(&operand) ) { if ( !sieve_opr_string_read_data - (renv, &operand, address, &zone) ) { - sieve_runtime_trace_error(renv, "invalid zone operand"); + (renv, &operand, address, "zone", &zone) ) return SIEVE_EXEC_BIN_CORRUPT; - } } zone_specified = TRUE; @@ -424,32 +424,26 @@ static int tst_date_operation_execute sieve_runtime_trace_error(renv, "unknown optional operand"); return SIEVE_EXEC_BIN_CORRUPT; } - } while ( opt_code != SIEVE_MATCH_OPT_END ); - + } if ( sieve_operation_is(op, date_operation) ) { /* Read header name */ - if ( !sieve_opr_string_read(renv, address, &header_name) ) { - sieve_runtime_trace_error(renv, "invalid header-name operand"); + if ( !sieve_opr_string_read(renv, address, "header-name", &header_name) ) return SIEVE_EXEC_BIN_CORRUPT; - } } /* Read date part */ - if ( !sieve_opr_string_read(renv, address, &date_part) ) { - sieve_runtime_trace_error(renv, "invalid date-part operand"); + if ( !sieve_opr_string_read(renv, address, "date-part", &date_part) ) return SIEVE_EXEC_BIN_CORRUPT; - } /* Read key-list */ - if ( (key_list=sieve_opr_stringlist_read(renv, address)) == NULL ) { - sieve_runtime_trace_error(renv, "invalid key-list operand"); + if ( (key_list=sieve_opr_stringlist_read(renv, address, "key-list")) + == NULL ) return SIEVE_EXEC_BIN_CORRUPT; - } - - /* Perform test */ - - sieve_runtime_trace(renv, "%s test", sieve_operation_mnemonic(op)); + + /* + * Perform test + */ /* Get the date value */ @@ -459,6 +453,8 @@ static int tst_date_operation_execute const char *header_value; const char *date_string; + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "date test"); + /* Get date from the message */ /* Read first header @@ -486,6 +482,8 @@ static int tst_date_operation_execute } else if ( sieve_operation_is(op, currentdate_operation) ) { /* Use time stamp recorded at the time the script first started */ + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "currentdatedate test"); + date_value = local_time; original_zone = local_zone; got_date = TRUE; diff --git a/src/lib-sieve/plugins/enotify/cmd-notify.c b/src/lib-sieve/plugins/enotify/cmd-notify.c index 8dc834d5b..2db21f783 100644 --- a/src/lib-sieve/plugins/enotify/cmd-notify.c +++ b/src/lib-sieve/plugins/enotify/cmd-notify.c @@ -347,47 +347,44 @@ static bool cmd_notify_generate static bool cmd_notify_operation_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address) { - int opt_code = 1; + int opt_code = 0; sieve_code_dumpf(denv, "NOTIFY"); sieve_code_descend(denv); /* Dump optional operands */ - if ( sieve_operand_optional_present(denv->sblock, address) ) { - while ( opt_code != 0 ) { - sieve_code_mark(denv); - - if ( !sieve_operand_optional_read(denv->sblock, address, &opt_code) ) - return FALSE; - - switch ( opt_code ) { - case 0: - break; - case CMD_NOTIFY_OPT_IMPORTANCE: - if ( !sieve_opr_number_dump(denv, address, "importance") ) - return FALSE; - break; - case CMD_NOTIFY_OPT_FROM: - if ( !sieve_opr_string_dump(denv, address, "from") ) - return FALSE; - break; - case CMD_NOTIFY_OPT_OPTIONS: - if ( !sieve_opr_stringlist_dump(denv, address, "options") ) - return FALSE; - break; - case CMD_NOTIFY_OPT_MESSAGE: - if ( !sieve_opr_string_dump(denv, address, "message") ) - return FALSE; - break; - default: - return FALSE; - } + + for (;;) { + int ret; + bool opok = TRUE; + + if ( (ret=sieve_opr_optional_dump(denv, address, &opt_code)) < 0 ) + return FALSE; + + if ( ret == 0 ) break; + + switch ( opt_code ) { + case CMD_NOTIFY_OPT_IMPORTANCE: + opok = sieve_opr_number_dump(denv, address, "importance"); + break; + case CMD_NOTIFY_OPT_FROM: + opok = sieve_opr_string_dump(denv, address, "from"); + break; + case CMD_NOTIFY_OPT_OPTIONS: + opok = sieve_opr_stringlist_dump(denv, address, "options"); + break; + case CMD_NOTIFY_OPT_MESSAGE: + opok = sieve_opr_string_dump(denv, address, "message"); + break; + default: + return FALSE; } + + if ( !opok ) return FALSE; } - /* Dump reason and handle operands */ - return - sieve_opr_string_dump(denv, address, "method"); + /* Dump method operand */ + return sieve_opr_string_dump(denv, address, "method"); } /* @@ -397,12 +394,12 @@ static bool cmd_notify_operation_dump static int cmd_notify_operation_execute (const struct sieve_runtime_env *renv, sieve_size_t *address) { - const struct sieve_extension *this_ext = renv->oprtn.ext; + const struct sieve_extension *this_ext = renv->oprtn->ext; struct sieve_side_effects_list *slist = NULL; struct sieve_enotify_action *act; void *method_context; pool_t pool; - int opt_code = 1, result = SIEVE_EXEC_OK; + int opt_code = 0, result = SIEVE_EXEC_OK; sieve_number_t importance = 2; struct sieve_coded_stringlist *options = NULL; const struct sieve_enotify_method *method; @@ -414,68 +411,61 @@ static int cmd_notify_operation_execute */ /* Source line */ - source_line = sieve_runtime_get_source_location(renv, renv->oprtn.address); - - /* Optional operands */ - if ( sieve_operand_optional_present(renv->sblock, address) ) { - while ( opt_code != 0 ) { - if ( !sieve_operand_optional_read(renv->sblock, address, &opt_code) ) { - sieve_runtime_trace_error(renv, "invalid optional operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } - - switch ( opt_code ) { - case 0: - break; - case CMD_NOTIFY_OPT_IMPORTANCE: - if ( !sieve_opr_number_read(renv, address, &importance) ) { - sieve_runtime_trace_error(renv, "invalid importance operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } + + source_line = sieve_runtime_get_command_location(renv); - /* Enforce 0 < importance < 4 (just to be sure) */ - if ( importance < 1 ) - importance = 1; - else if ( importance > 3 ) - importance = 3; - break; - case CMD_NOTIFY_OPT_FROM: - if ( !sieve_opr_string_read(renv, address, &from) ) { - sieve_runtime_trace_error(renv, "invalid from operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } - break; - case CMD_NOTIFY_OPT_MESSAGE: - if ( !sieve_opr_string_read(renv, address, &message) ) { - sieve_runtime_trace_error(renv, "invalid from operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } - break; - case CMD_NOTIFY_OPT_OPTIONS: - if ( (options=sieve_opr_stringlist_read(renv, address)) == NULL ) { - sieve_runtime_trace_error(renv, "invalid options operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } - break; - default: - sieve_runtime_trace_error(renv, "unknown optional operand: %d", - opt_code); - return SIEVE_EXEC_BIN_CORRUPT; - } + /* Optional operands */ + + for (;;) { + bool opok = TRUE; + int ret; + + if ( (ret=sieve_opr_optional_read(renv, address, &opt_code)) < 0 ) + return SIEVE_EXEC_BIN_CORRUPT; + + if ( ret == 0 ) break; + + switch ( opt_code ) { + case CMD_NOTIFY_OPT_IMPORTANCE: + opok = sieve_opr_number_read(renv, address, "importance", &importance); + break; + case CMD_NOTIFY_OPT_FROM: + opok = sieve_opr_string_read(renv, address, "from", &from); + break; + case CMD_NOTIFY_OPT_MESSAGE: + opok = sieve_opr_string_read(renv, address, "message", &message); + break; + case CMD_NOTIFY_OPT_OPTIONS: + options = sieve_opr_stringlist_read(renv, address, "options"); + opok = ( options != NULL ); + break; + default: + sieve_runtime_trace_error(renv, "unknown optional operand"); + return SIEVE_EXEC_BIN_CORRUPT; } + + if ( !opok ) return SIEVE_EXEC_BIN_CORRUPT; } - /* Reason operand */ - if ( !sieve_opr_string_read(renv, address, &method_uri) ) { - sieve_runtime_trace_error(renv, "invalid method operand"); + /* Method operand */ + + if ( !sieve_opr_string_read(renv, address, "method", &method_uri) ) return SIEVE_EXEC_BIN_CORRUPT; - } /* * Perform operation */ - sieve_runtime_trace(renv, "NOTIFY action"); + /* Enforce 0 < importance < 4 (just to be sure) */ + + if ( importance < 1 ) + importance = 1; + else if ( importance > 3 ) + importance = 3; + + /* Trace */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, "notify action"); /* Check operands */ diff --git a/src/lib-sieve/plugins/enotify/ext-enotify-common.c b/src/lib-sieve/plugins/enotify/ext-enotify-common.c index 4a9a66c87..ac77d628a 100644 --- a/src/lib-sieve/plugins/enotify/ext-enotify-common.c +++ b/src/lib-sieve/plugins/enotify/ext-enotify-common.c @@ -474,7 +474,7 @@ bool ext_enotify_runtime_method_validate (const struct sieve_runtime_env *renv, unsigned int source_line, string_t *method_uri) { - const struct sieve_extension *this_ext = renv->oprtn.ext; + const struct sieve_extension *this_ext = renv->oprtn->ext; const struct sieve_enotify_method *method; const char *uri = str_c(method_uri); const char *scheme; @@ -513,7 +513,7 @@ static const struct sieve_enotify_method *ext_enotify_get_method (const struct sieve_runtime_env *renv, unsigned int source_line, string_t *method_uri, const char **uri_body_r) { - const struct sieve_extension *this_ext = renv->oprtn.ext; + const struct sieve_extension *this_ext = renv->oprtn->ext; const struct sieve_enotify_method *method; const char *uri = str_c(method_uri); const char *scheme; diff --git a/src/lib-sieve/plugins/enotify/tst-notify-method-capability.c b/src/lib-sieve/plugins/enotify/tst-notify-method-capability.c index 7d87b017b..9037bff7a 100644 --- a/src/lib-sieve/plugins/enotify/tst-notify-method-capability.c +++ b/src/lib-sieve/plugins/enotify/tst-notify-method-capability.c @@ -160,10 +160,7 @@ static bool tst_notifymc_operation_dump sieve_code_descend(denv); /* Handle any optional arguments */ - if ( !sieve_match_dump_optional_operands(denv, address, &opt_code) ) - return FALSE; - - if ( opt_code != SIEVE_MATCH_OPT_END ) + if ( sieve_match_opr_optional_dump(denv, address, &opt_code) != 0 ) return FALSE; return @@ -197,39 +194,35 @@ static int tst_notifymc_operation_execute */ /* Handle match-type and comparator operands */ - if ( (ret=sieve_match_read_optional_operands - (renv, address, &opt_code, &cmp, &mcht)) <= 0 ) - return ret; - - /* Check whether we neatly finished the list of optional operands */ - if ( opt_code != SIEVE_MATCH_OPT_END) { + if ( (ret=sieve_match_opr_optional_read + (renv, address, &opt_code, &cmp, &mcht)) < 0 ) + return SIEVE_EXEC_BIN_CORRUPT; + + /* Check whether we neatly finished the list of optional operands*/ + if ( ret > 0 ) { sieve_runtime_trace_error(renv, "invalid optional operand"); return SIEVE_EXEC_BIN_CORRUPT; } /* Read notify uri */ - if ( !sieve_opr_string_read(renv, address, ¬ify_uri) ) { - sieve_runtime_trace_error(renv, "invalid notify-uri operand"); + if ( !sieve_opr_string_read(renv, address, "notify-uri", ¬ify_uri) ) return SIEVE_EXEC_BIN_CORRUPT; - } /* Read notify capability */ - if ( !sieve_opr_string_read(renv, address, ¬ify_capability) ) { - sieve_runtime_trace_error(renv, "invalid notify-uri operand"); + if ( !sieve_opr_string_read + (renv, address, "notify-capability", ¬ify_capability) ) return SIEVE_EXEC_BIN_CORRUPT; - } /* Read key-list */ - if ( (key_list=sieve_opr_stringlist_read(renv, address)) == NULL ) { - sieve_runtime_trace_error(renv, "invalid key-list operand"); + if ( (key_list=sieve_opr_stringlist_read(renv, address, "key-list")) + == NULL ) return SIEVE_EXEC_BIN_CORRUPT; - } /* * Perform operation */ - sieve_runtime_trace(renv, "NOTIFY_METHOD_CAPABILITY test"); + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "notify_method_capability test"); cap_value = ext_enotify_runtime_get_method_capability (renv, 0 /* FIXME */, notify_uri, str_c(notify_capability)); diff --git a/src/lib-sieve/plugins/enotify/tst-valid-notify-method.c b/src/lib-sieve/plugins/enotify/tst-valid-notify-method.c index db45c68f3..20fc00da6 100644 --- a/src/lib-sieve/plugins/enotify/tst-valid-notify-method.c +++ b/src/lib-sieve/plugins/enotify/tst-valid-notify-method.c @@ -113,16 +113,15 @@ static int tst_vnotifym_operation_execute */ /* Read notify uris */ - if ( (notify_uris=sieve_opr_stringlist_read(renv, address)) == NULL ) { - sieve_runtime_trace_error(renv, "invalid notify-uris operand"); + if ( (notify_uris=sieve_opr_stringlist_read(renv, address, "notify-uris")) + == NULL ) return SIEVE_EXEC_BIN_CORRUPT; - } /* * Perform operation */ - sieve_runtime_trace(renv, "VALID_NOTIFY_METHOD test"); + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "valid_notify_method test"); uri_item = NULL; while ( (result=sieve_coded_stringlist_next_item(notify_uris, &uri_item)) diff --git a/src/lib-sieve/plugins/environment/tst-environment.c b/src/lib-sieve/plugins/environment/tst-environment.c index 110f053e1..28bd55e53 100644 --- a/src/lib-sieve/plugins/environment/tst-environment.c +++ b/src/lib-sieve/plugins/environment/tst-environment.c @@ -137,11 +137,8 @@ static bool tst_environment_operation_dump sieve_code_dumpf(denv, "ENVIRONMENT"); sieve_code_descend(denv); - /* Handle any optional arguments */ - if ( !sieve_match_dump_optional_operands(denv, address, &opt_code) ) - return FALSE; - - if ( opt_code != SIEVE_MATCH_OPT_END ) + /* Optional operands */ + if ( sieve_match_opr_optional_dump(denv, address, &opt_code) != 0 ) return FALSE; return @@ -156,7 +153,7 @@ static bool tst_environment_operation_dump static int tst_environment_operation_execute (const struct sieve_runtime_env *renv, sieve_size_t *address) { - const struct sieve_extension *this_ext = renv->oprtn.ext; + const struct sieve_extension *this_ext = renv->oprtn->ext; int ret, mret; bool result = TRUE; int opt_code = 0; @@ -175,33 +172,30 @@ static int tst_environment_operation_execute */ /* Handle match-type and comparator operands */ - if ( (ret=sieve_match_read_optional_operands - (renv, address, &opt_code, &cmp, &mcht)) <= 0 ) - return ret; - + if ( (ret=sieve_match_opr_optional_read + (renv, address, &opt_code, &cmp, &mcht)) < 0 ) + return SIEVE_EXEC_BIN_CORRUPT; + /* Check whether we neatly finished the list of optional operands*/ - if ( opt_code != SIEVE_MATCH_OPT_END) { + if ( ret > 0 ) { sieve_runtime_trace_error(renv, "invalid optional operand"); return SIEVE_EXEC_BIN_CORRUPT; } /* Read source */ - if ( !sieve_opr_string_read(renv, address, &name) ) { - sieve_runtime_trace_error(renv, "invalid name operand"); + if ( !sieve_opr_string_read(renv, address, "name", &name) ) return SIEVE_EXEC_BIN_CORRUPT; - } /* Read key-list */ - if ( (key_list=sieve_opr_stringlist_read(renv, address)) == NULL ) { - sieve_runtime_trace_error(renv, "invalid key-list operand"); + if ( (key_list=sieve_opr_stringlist_read(renv, address, "key-list")) + == NULL ) return SIEVE_EXEC_BIN_CORRUPT; - } /* * Perform operation */ - sieve_runtime_trace(renv, "ENVIRONMENT test"); + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "environment test"); env_item = ext_environment_item_get_value (this_ext, str_c(name), renv->scriptenv); diff --git a/src/lib-sieve/plugins/imap4flags/cmd-flag.c b/src/lib-sieve/plugins/imap4flags/cmd-flag.c index 8cc194a0d..805e79acb 100644 --- a/src/lib-sieve/plugins/imap4flags/cmd-flag.c +++ b/src/lib-sieve/plugins/imap4flags/cmd-flag.c @@ -145,7 +145,7 @@ bool cmd_flag_operation_dump { struct sieve_operand operand; - sieve_code_dumpf(denv, "%s", sieve_operation_mnemonic(&denv->oprtn)); + sieve_code_dumpf(denv, "%s", sieve_operation_mnemonic(denv->oprtn)); sieve_code_descend(denv); sieve_code_mark(denv); @@ -174,7 +174,7 @@ bool cmd_flag_operation_dump static int cmd_flag_operation_execute (const struct sieve_runtime_env *renv, sieve_size_t *address) { - const struct sieve_operation *op = &renv->oprtn; + const struct sieve_operation *op = renv->oprtn; struct sieve_operand operand; bool result = TRUE; string_t *flag_item; @@ -188,40 +188,37 @@ static int cmd_flag_operation_execute * Read operands */ - if ( !sieve_operand_read(renv->sblock, address, &operand) ) { - sieve_runtime_trace_error(renv, "invalid operand"); + /* Read bare operand (two types possible) */ + if ( !sieve_operand_runtime_read(renv, address, NULL, &operand) ) return SIEVE_EXEC_BIN_CORRUPT; - } + /* Variable operand (optional) */ if ( sieve_operand_is_variable(&operand) ) { - /* Read the variable operand */ if ( !sieve_variable_operand_read_data - (renv, &operand, address, &storage, &var_index) ) { - sieve_runtime_trace_error(renv, "invalid variable operand"); + (renv, &operand, address, "variable", &storage, &var_index) ) return SIEVE_EXEC_BIN_CORRUPT; - } - + /* Read flag list */ - if ( (flag_list=sieve_opr_stringlist_read(renv, address)) == NULL ) { - sieve_runtime_trace_error(renv, "invalid flag-list operand"); + if ( (flag_list=sieve_opr_stringlist_read(renv, address, "flag-list")) + == NULL ) return SIEVE_EXEC_BIN_CORRUPT; - } - + + /* Flag-list operand */ } else if ( sieve_operand_is_stringlist(&operand) ) { storage = NULL; var_index = 0; /* Read flag list */ if ( (flag_list=sieve_opr_stringlist_read_data - (renv, &operand, address)) == NULL ) { - sieve_runtime_trace_error(renv, "invalid flag-list operand"); + (renv, &operand, address, "flag-list")) == NULL ) return SIEVE_EXEC_BIN_CORRUPT; - } + /* Invalid */ } else { - sieve_runtime_trace_error(renv, "unexpected operand '%s'", - sieve_operand_name(&operand)); + sieve_runtime_trace_error + (renv, "expected variable or string-list (flag-list) operand " + "but found %s", sieve_operand_name(&operand)); return SIEVE_EXEC_BIN_CORRUPT; } @@ -229,18 +226,20 @@ static int cmd_flag_operation_execute * Perform operation */ - sieve_runtime_trace(renv, "%s command", sieve_operation_mnemonic(op)); - /* Determine what to do */ - if ( sieve_operation_is(op, setflag_operation) ) + if ( sieve_operation_is(op, setflag_operation) ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "setflag command"); flag_op = ext_imap4flags_set_flags; - else if ( sieve_operation_is(op, addflag_operation) ) + } else if ( sieve_operation_is(op, addflag_operation) ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "addflag command"); flag_op = ext_imap4flags_add_flags; - else if ( sieve_operation_is(op, removeflag_operation) ) + } else if ( sieve_operation_is(op, removeflag_operation) ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "removeflag command"); flag_op = ext_imap4flags_remove_flags; - else + } else { i_unreached(); + } /* Iterate through all flags and perform requested operation */ diff --git a/src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c b/src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c index 3f04a81be..44dae44b3 100644 --- a/src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +++ b/src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c @@ -445,7 +445,7 @@ int ext_imap4flags_set_flags if ( !sieve_variable_get_modifiable(storage, var_index, &cur_flags) ) return SIEVE_EXEC_BIN_CORRUPT; } else - cur_flags = _get_flags_string(renv->oprtn.ext, renv->result); + cur_flags = _get_flags_string(renv->oprtn->ext, renv->result); if ( cur_flags != NULL ) flags_list_set_flags(cur_flags, flags); @@ -463,7 +463,7 @@ int ext_imap4flags_add_flags if ( !sieve_variable_get_modifiable(storage, var_index, &cur_flags) ) return SIEVE_EXEC_BIN_CORRUPT; } else - cur_flags = _get_flags_string(renv->oprtn.ext, renv->result); + cur_flags = _get_flags_string(renv->oprtn->ext, renv->result); if ( cur_flags != NULL ) flags_list_add_flags(cur_flags, flags); @@ -481,7 +481,7 @@ int ext_imap4flags_remove_flags if ( !sieve_variable_get_modifiable(storage, var_index, &cur_flags) ) return SIEVE_EXEC_BIN_CORRUPT; } else - cur_flags = _get_flags_string(renv->oprtn.ext, renv->result); + cur_flags = _get_flags_string(renv->oprtn->ext, renv->result); if ( cur_flags != NULL ) flags_list_remove_flags(cur_flags, flags); @@ -499,7 +499,7 @@ int ext_imap4flags_get_flags_string if ( !sieve_variable_get_modifiable(storage, var_index, &cur_flags) ) return SIEVE_EXEC_BIN_CORRUPT; } else - cur_flags = _get_flags_string(renv->oprtn.ext, renv->result); + cur_flags = _get_flags_string(renv->oprtn->ext, renv->result); if ( cur_flags == NULL ) *flags = ""; @@ -521,7 +521,7 @@ void ext_imap4flags_get_flags_init flags_list_set_flags(cur_flags, flags_list); } else - cur_flags = _get_flags_string(renv->oprtn.ext, renv->result); + cur_flags = _get_flags_string(renv->oprtn->ext, renv->result); ext_imap4flags_iter_init(iter, cur_flags); } diff --git a/src/lib-sieve/plugins/imap4flags/tag-flags.c b/src/lib-sieve/plugins/imap4flags/tag-flags.c index 1645a0871..b7115d4db 100644 --- a/src/lib-sieve/plugins/imap4flags/tag-flags.c +++ b/src/lib-sieve/plugins/imap4flags/tag-flags.c @@ -269,13 +269,12 @@ static bool seff_flags_read_context t_push(); /* Check whether explicit flag list operand is present */ - if ( !sieve_operand_read(renv->sblock, address, &operand) ) { - sieve_runtime_trace_error(renv, "invalid operand"); - t_pop(); - return FALSE; - } - - if ( sieve_operand_is_omitted(&operand) ) { + if ( !sieve_operand_runtime_read(renv, address, NULL, &operand) ) { + t_pop(); + return FALSE; + } + + if ( sieve_operand_is_omitted(&operand) ) { /* Flag list is omitted, use current value of internal * variable to construct side effect context. */ @@ -287,7 +286,7 @@ static bool seff_flags_read_context /* Read flag-list */ if ( (flag_list=sieve_opr_stringlist_read_data - (renv, &operand, address)) == NULL ) { + (renv, &operand, address, NULL)) == NULL ) { t_pop(); return FALSE; } diff --git a/src/lib-sieve/plugins/imap4flags/tst-hasflag.c b/src/lib-sieve/plugins/imap4flags/tst-hasflag.c index cbcec03de..aa18d90c0 100644 --- a/src/lib-sieve/plugins/imap4flags/tst-hasflag.c +++ b/src/lib-sieve/plugins/imap4flags/tst-hasflag.c @@ -140,21 +140,28 @@ static bool tst_hasflag_operation_dump sieve_code_dumpf(denv, "HASFLAG"); sieve_code_descend(denv); - /* Handle any optional arguments */ - do { - if ( !sieve_match_dump_optional_operands(denv, address, &opt_code) ) + /* Optional operands */ + + for (;;) { + bool opok = TRUE; + int ret; + + if ( (ret=sieve_match_opr_optional_dump(denv, address, &opt_code)) + < 0 ) return FALSE; + if ( ret == 0 ) break; + switch ( opt_code ) { - case SIEVE_MATCH_OPT_END: - break; case OPT_VARIABLES: - sieve_opr_stringlist_dump(denv, address, "variables"); + opok = sieve_opr_stringlist_dump(denv, address, "variables"); break; default: return FALSE; } - } while ( opt_code != SIEVE_MATCH_OPT_END ); + + if ( !opok ) return FALSE; + } return sieve_opr_stringlist_dump(denv, address, "list of flags"); @@ -197,7 +204,7 @@ static const struct sieve_match_key_extractor _flag_extractor = { static int tst_hasflag_operation_execute (const struct sieve_runtime_env *renv, sieve_size_t *address) { - int ret, mret; + int mret; bool result = TRUE; int opt_code = 0; struct sieve_comparator cmp = @@ -214,39 +221,43 @@ static int tst_hasflag_operation_execute * Read operands */ - /* Handle match-type and comparator operands */ - do { - if ( (ret=sieve_match_read_optional_operands - (renv, address, &opt_code, &cmp, &mtch)) <= 0 ) - return ret; + /* Optional operands */ + + for (;;) { + bool opok = TRUE; + int ret; + + if ( (ret=sieve_match_opr_optional_read + (renv, address, &opt_code, &cmp, &mtch)) < 0 ) + return SIEVE_EXEC_BIN_CORRUPT; + + if ( ret == 0 ) break; - /* Check whether we neatly finished the list of optional operands*/ switch ( opt_code ) { - case SIEVE_MATCH_OPT_END: - break; case OPT_VARIABLES: - if ( (variables_list=sieve_opr_stringlist_read(renv, address)) == NULL ) { - sieve_runtime_trace_error(renv, "invalid variables-list operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } + variables_list = sieve_opr_stringlist_read + (renv, address, "variables-list"); + opok = ( variables_list != NULL ); break; default: sieve_runtime_trace_error(renv, "invalid optional operand"); return SIEVE_EXEC_BIN_CORRUPT; } - } while ( opt_code != SIEVE_MATCH_OPT_END ); - - /* Read flag list */ - if ( (flag_list=sieve_opr_stringlist_read(renv, address)) == NULL ) { - sieve_runtime_trace_error(renv, "invalid flag-list operand"); + + if ( !opok ) return SIEVE_EXEC_BIN_CORRUPT; + } + + /* Fixed operands */ + + if ( (flag_list=sieve_opr_stringlist_read(renv, address, "flag-list")) + == NULL ) return SIEVE_EXEC_BIN_CORRUPT; - } /* * Perform operation */ - sieve_runtime_trace(renv, "HASFLAG test"); + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "hasflag test"); matched = FALSE; mctx = sieve_match_begin diff --git a/src/lib-sieve/plugins/include/cmd-global.c b/src/lib-sieve/plugins/include/cmd-global.c index 1c50483bc..834f9d519 100644 --- a/src/lib-sieve/plugins/include/cmd-global.c +++ b/src/lib-sieve/plugins/include/cmd-global.c @@ -239,7 +239,7 @@ static bool cmd_global_generate static bool opc_global_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address) { - const struct sieve_extension *this_ext = denv->oprtn.ext; + const struct sieve_extension *this_ext = denv->oprtn->ext; unsigned int count, i, var_count; struct sieve_variable_scope *scope; struct sieve_variable * const *vars; @@ -275,7 +275,7 @@ static bool opc_global_dump static int opc_global_execute (const struct sieve_runtime_env *renv, sieve_size_t *address) { - const struct sieve_extension *this_ext = renv->oprtn.ext; + const struct sieve_extension *this_ext = renv->oprtn->ext; struct sieve_variable_scope *scope; struct sieve_variable_storage *storage; struct sieve_variable * const *vars; @@ -289,7 +289,7 @@ static int opc_global_execute scope = ext_include_binary_get_global_scope(this_ext, renv->sbin); vars = sieve_variable_scope_get_variables(scope, &var_count); storage = ext_include_interpreter_get_global_variables - (renv->oprtn.ext, renv->interp); + (this_ext, renv->interp); for ( i = 0; i < count; i++ ) { unsigned int index; @@ -304,6 +304,10 @@ static int opc_global_execute index, var_count); return SIEVE_EXEC_BIN_CORRUPT; } + + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, + "exporting global variable '%s' (index: %u)", vars[index]->identifier, + index); /* Make sure variable is initialized (export) */ (void)sieve_variable_get_modifiable(storage, index, NULL); diff --git a/src/lib-sieve/plugins/include/cmd-include.c b/src/lib-sieve/plugins/include/cmd-include.c index 2be54eee2..c36f31e5b 100644 --- a/src/lib-sieve/plugins/include/cmd-include.c +++ b/src/lib-sieve/plugins/include/cmd-include.c @@ -314,7 +314,7 @@ static bool opc_include_dump if ( !sieve_binary_read_byte(denv->sblock, address, &flags) ) return FALSE; - binctx = ext_include_binary_get_context(denv->oprtn.ext, denv->sbin); + binctx = ext_include_binary_get_context(denv->oprtn->ext, denv->sbin); included = ext_include_binary_script_get_included(binctx, include_id); if ( included == NULL ) return FALSE; diff --git a/src/lib-sieve/plugins/include/cmd-return.c b/src/lib-sieve/plugins/include/cmd-return.c index 37625400b..3b5a71546 100644 --- a/src/lib-sieve/plugins/include/cmd-return.c +++ b/src/lib-sieve/plugins/include/cmd-return.c @@ -64,8 +64,6 @@ static bool cmd_return_generate static int opc_return_execute (const struct sieve_runtime_env *renv, sieve_size_t *address ATTR_UNUSED) { - sieve_runtime_trace(renv, "RETURN command"); - ext_include_execute_return(renv); return SIEVE_EXEC_OK; } diff --git a/src/lib-sieve/plugins/include/ext-include-common.c b/src/lib-sieve/plugins/include/ext-include-common.c index 6a3289030..1be4152ca 100644 --- a/src/lib-sieve/plugins/include/ext-include-common.c +++ b/src/lib-sieve/plugins/include/ext-include-common.c @@ -540,7 +540,7 @@ static bool ext_include_runtime_include_mark int ext_include_execute_include (const struct sieve_runtime_env *renv, unsigned int include_id, bool once) { - const struct sieve_extension *this_ext = renv->oprtn.ext; + const struct sieve_extension *this_ext = renv->oprtn->ext; int result = SIEVE_EXEC_OK; struct ext_include_interpreter_context *ctx; const struct ext_include_script_info *included; @@ -559,16 +559,17 @@ int ext_include_execute_include block_id = sieve_binary_block_get_id(included->block); - sieve_runtime_trace(renv, - "INCLUDE command (script: %s, id: %d block: %d) START::", - sieve_script_name(included->script), include_id, block_id); - /* If :once modifier is specified, check for duplicate include */ - if ( !ext_include_runtime_include_mark(ctx, included, once) ) { + if ( ext_include_runtime_include_mark(ctx, included, once) ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_MINIMUM, + "include script '%s' (id: %d, block: %d) STARTED ::", + sieve_script_name(included->script), include_id, block_id); + } else { /* skip */ - - sieve_runtime_trace(renv, - "INCLUDE command (block: %d) SKIPPED ::", block_id); + sieve_runtime_trace(renv, SIEVE_TRLVL_MINIMUM, + "include script '%s' (id: %d, block: %d); " + "SKIPPED, because already run once", + sieve_script_name(included->script), include_id, block_id); return result; } @@ -598,7 +599,8 @@ int ext_include_execute_include * (first sub-interpreter) */ subinterp = sieve_interpreter_create_for_block - (included->block, ehandler); + (included->block, included->script, renv->msgdata, renv->scriptenv, + ehandler); if ( subinterp != NULL ) { curctx = ext_include_interpreter_context_init_child @@ -606,8 +608,7 @@ int ext_include_execute_include /* Activate and start the top-level included script */ result = ( sieve_interpreter_start - (subinterp, renv->msgdata, renv->scriptenv, renv->result, - &interrupted) == 1 ); + (subinterp, renv->result, &interrupted) == 1 ); } else result = SIEVE_EXEC_BIN_CORRUPT; } @@ -624,7 +625,10 @@ int ext_include_execute_include /* Sub-interpreter ended or executed return */ - sieve_runtime_trace(renv, "INCLUDE command (block: %d) END ::", + sieve_runtime_trace(renv, SIEVE_TRLVL_MINIMUM, + "included script '%s' (id: %d, block: %d) ENDED ::", + sieve_script_name(curctx->script_info->script), + curctx->script_info->id, sieve_binary_block_get_id(curctx->script_info->block)); /* Ascend interpreter stack */ @@ -649,7 +653,8 @@ int ext_include_execute_include if ( result == SIEVE_EXEC_OK ) { /* Create sub-interpreter */ subinterp = sieve_interpreter_create_for_block - (curctx->include->block, ehandler); + (curctx->include->block, curctx->include->script, renv->msgdata, + renv->scriptenv, ehandler); if ( subinterp != NULL ) { curctx = ext_include_interpreter_context_init_child @@ -659,9 +664,8 @@ int ext_include_execute_include /* Start the sub-include's interpreter */ curctx->include = NULL; curctx->returned = FALSE; - result = ( sieve_interpreter_start - (subinterp, renv->msgdata, renv->scriptenv, renv->result, - &interrupted) == 1 ); + result = ( sieve_interpreter_start(subinterp, renv->result, + &interrupted) == 1 ); } else result = SIEVE_EXEC_BIN_CORRUPT; } @@ -675,9 +679,13 @@ int ext_include_execute_include } } } - } else - sieve_runtime_trace(renv, "INCLUDE command (block: %d) END ::", + } else { + sieve_runtime_trace(renv, SIEVE_TRLVL_MINIMUM, + "included script '%s' (id: %d, block: %d) ENDED ::", + sieve_script_name(curctx->script_info->script), + curctx->script_info->id, sieve_binary_block_get_id(curctx->script_info->block)); + } /* Free any sub-interpreters that might still be active */ while ( curctx != NULL && curctx->parent != NULL ) { @@ -704,10 +712,12 @@ int ext_include_execute_include void ext_include_execute_return (const struct sieve_runtime_env *renv) { - const struct sieve_extension *this_ext = renv->oprtn.ext; + const struct sieve_extension *this_ext = renv->oprtn->ext; struct ext_include_interpreter_context *ctx = ext_include_get_interpreter_context(this_ext, renv->interp); + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "return"); + ctx->returned = TRUE; sieve_interpreter_interrupt(renv->interp); } diff --git a/src/lib-sieve/plugins/mailbox/tst-mailboxexists.c b/src/lib-sieve/plugins/mailbox/tst-mailboxexists.c index ac9044e64..208f806ee 100644 --- a/src/lib-sieve/plugins/mailbox/tst-mailboxexists.c +++ b/src/lib-sieve/plugins/mailbox/tst-mailboxexists.c @@ -114,16 +114,15 @@ static int tst_mailboxexists_operation_execute */ /* Read notify uris */ - if ( (mailbox_names=sieve_opr_stringlist_read(renv, address)) == NULL ) { - sieve_runtime_trace_error(renv, "invalid mailbox-names operand"); + if ( (mailbox_names=sieve_opr_stringlist_read(renv, address, "mailbox-names")) + == NULL ) return SIEVE_EXEC_BIN_CORRUPT; - } /* * Perform operation */ - sieve_runtime_trace(renv, "MAILBOXEXISTS command"); + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "mailboxexists test"); if ( renv->scriptenv->namespaces != NULL ) { mailbox_item = NULL; diff --git a/src/lib-sieve/plugins/notify/cmd-denotify.c b/src/lib-sieve/plugins/notify/cmd-denotify.c index 870f646af..36b2dcc33 100644 --- a/src/lib-sieve/plugins/notify/cmd-denotify.c +++ b/src/lib-sieve/plugins/notify/cmd-denotify.c @@ -231,39 +231,36 @@ static bool cmd_denotify_generate static bool cmd_denotify_operation_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address) { - const struct sieve_operation *op = &denv->oprtn; - int opt_code = 1; + const struct sieve_operation *op = denv->oprtn; + int opt_code = 0; sieve_code_dumpf(denv, "%s", sieve_operation_mnemonic(op)); sieve_code_descend(denv); - /* Dump optional operands */ - if ( sieve_operand_optional_present(denv->sblock, address) ) { - while ( opt_code != 0 ) { - sieve_code_mark(denv); - - if ( !sieve_operand_optional_read(denv->sblock, address, &opt_code) ) - return FALSE; - - switch ( opt_code ) { - case 0: - break; - case OPT_MATCH_KEY: - if ( !sieve_opr_string_dump(denv, address, "key-string") ) - return FALSE; - break; - case OPT_MATCH_TYPE: - if ( !sieve_opr_match_type_dump(denv, address) ) - return FALSE; - break; - case OPT_IMPORTANCE: - if ( !sieve_opr_number_dump(denv, address, "importance") ) - return FALSE; - break; - default: - return FALSE; - } + for (;;) { + int ret; + bool opok = TRUE; + + if ( (ret=sieve_opr_optional_dump(denv, address, &opt_code)) < 0 ) + return FALSE; + + if ( ret == 0 ) break; + + switch ( opt_code ) { + case OPT_MATCH_KEY: + opok = sieve_opr_string_dump(denv, address, "key-string"); + break; + case OPT_MATCH_TYPE: + opok = sieve_opr_match_type_dump(denv, address); + break; + case OPT_IMPORTANCE: + opok = sieve_opr_number_dump(denv, address, "importance"); + break; + default: + return FALSE; } + + if ( !opok ) return FALSE; } return TRUE; @@ -277,7 +274,7 @@ static int cmd_denotify_operation_execute (const struct sieve_runtime_env *renv, sieve_size_t *address) { bool result = TRUE; - int opt_code = 1; + int opt_code = 0; struct sieve_match_type mcht = SIEVE_MATCH_TYPE_DEFAULT(is_match_type); const struct sieve_comparator cmp = @@ -294,53 +291,49 @@ static int cmd_denotify_operation_execute */ /* Optional operands */ - if ( sieve_operand_optional_present(renv->sblock, address) ) { - while ( opt_code != 0 ) { - if ( !sieve_operand_optional_read(renv->sblock, address, &opt_code) ) { - sieve_runtime_trace_error(renv, "invalid optional operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } - switch ( opt_code ) { - case 0: - break; - case OPT_MATCH_TYPE: - if ( !sieve_opr_match_type_read(renv, address, &mcht) ) { - sieve_runtime_trace_error(renv, "invalid match type operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } - break; - case OPT_MATCH_KEY: - if ( (match_key=sieve_opr_stringlist_read(renv, address)) == NULL ) { - sieve_runtime_trace_error(renv, "invalid match key operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } - break; - case OPT_IMPORTANCE: - if ( !sieve_opr_number_read(renv, address, &importance) ) { - sieve_runtime_trace_error(renv, "invalid importance operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } - - /* Enforce 0 < importance < 4 (just to be sure) */ - if ( importance < 1 ) - importance = 1; - else if ( importance > 3 ) - importance = 3; - break; - default: - sieve_runtime_trace_error(renv, "unknown optional operand: %d", - opt_code); - return SIEVE_EXEC_BIN_CORRUPT; - } + for (;;) { + bool opok = TRUE; + int ret; + + if ( (ret=sieve_opr_optional_read(renv, address, &opt_code)) < 0 ) + return SIEVE_EXEC_BIN_CORRUPT; + + if ( ret == 0 ) break; + + switch ( opt_code ) { + case OPT_MATCH_TYPE: + opok = sieve_opr_match_type_read(renv, address, &mcht); + break; + case OPT_MATCH_KEY: + match_key = sieve_opr_stringlist_read(renv, address, "match key"); + opok = ( match_key != NULL ); + break; + case OPT_IMPORTANCE: + opok = sieve_opr_number_read(renv, address, "importance", &importance); + break; + default: + sieve_runtime_trace_error(renv, "unknown optional operand"); + return SIEVE_EXEC_BIN_CORRUPT; } + + if ( !opok ) return SIEVE_EXEC_BIN_CORRUPT; } /* * Perform operation */ - sieve_runtime_trace(renv, "DENOTIFY action"); + /* Enforce 0 < importance < 4 (just to be sure) */ + + if ( importance < 1 ) + importance = 1; + else if ( importance > 3 ) + importance = 3; + + /* Trace */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, "denotify action"); /* Either do string matching or just kill all notify actions */ if ( match_key != NULL ) { diff --git a/src/lib-sieve/plugins/notify/cmd-notify.c b/src/lib-sieve/plugins/notify/cmd-notify.c index aa38e5e4e..813d07d23 100644 --- a/src/lib-sieve/plugins/notify/cmd-notify.c +++ b/src/lib-sieve/plugins/notify/cmd-notify.c @@ -366,42 +366,39 @@ static bool cmd_notify_generate static bool cmd_notify_operation_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address) { - int opt_code = 1; + int opt_code = 0; sieve_code_dumpf(denv, "NOTIFY"); sieve_code_descend(denv); /* Dump optional operands */ - if ( sieve_operand_optional_present(denv->sblock, address) ) { - while ( opt_code != 0 ) { - sieve_code_mark(denv); - - if ( !sieve_operand_optional_read(denv->sblock, address, &opt_code) ) - return FALSE; - - switch ( opt_code ) { - case 0: - break; - case OPT_IMPORTANCE: - if ( !sieve_opr_number_dump(denv, address, "importance") ) - return FALSE; - break; - case OPT_ID: - if ( !sieve_opr_string_dump(denv, address, "id") ) - return FALSE; - break; - case OPT_OPTIONS: - if ( !sieve_opr_stringlist_dump(denv, address, "options") ) - return FALSE; - break; - case OPT_MESSAGE: - if ( !sieve_opr_string_dump(denv, address, "message") ) - return FALSE; - break; - default: - return FALSE; - } + for (;;) { + int ret; + bool opok = TRUE; + + if ( (ret=sieve_opr_optional_dump(denv, address, &opt_code)) < 0 ) + return FALSE; + + if ( ret == 0 ) break; + + switch ( opt_code ) { + case OPT_IMPORTANCE: + opok = sieve_opr_number_dump(denv, address, "importance"); + break; + case OPT_ID: + opok = sieve_opr_string_dump(denv, address, "id"); + break; + case OPT_OPTIONS: + opok = sieve_opr_stringlist_dump(denv, address, "options"); + break; + case OPT_MESSAGE: + opok = sieve_opr_string_dump(denv, address, "message"); + break; + default: + return FALSE; } + + if ( !opok ) return FALSE; } return TRUE; @@ -415,10 +412,10 @@ static bool cmd_notify_operation_dump static int cmd_notify_operation_execute (const struct sieve_runtime_env *renv, sieve_size_t *address) { - const struct sieve_extension *this_ext = renv->oprtn.ext; + const struct sieve_extension *this_ext = renv->oprtn->ext; struct ext_notify_action *act; pool_t pool; - int opt_code = 1; + int opt_code = 0; sieve_number_t importance = 1; struct sieve_coded_stringlist *options = NULL; string_t *message = NULL, *id = NULL; @@ -429,62 +426,56 @@ static int cmd_notify_operation_execute */ /* Source line */ - source_line = sieve_runtime_get_source_location(renv, renv->oprtn.address); + + source_line = sieve_runtime_get_command_location(renv); /* Optional operands */ - if ( sieve_operand_optional_present(renv->sblock, address) ) { - while ( opt_code != 0 ) { - if ( !sieve_operand_optional_read(renv->sblock, address, &opt_code) ) { - sieve_runtime_trace_error(renv, "invalid optional operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } - switch ( opt_code ) { - case 0: - break; - case OPT_IMPORTANCE: - if ( !sieve_opr_number_read(renv, address, &importance) ) { - sieve_runtime_trace_error(renv, "invalid importance operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } - - /* Enforce 0 < importance < 4 (just to be sure) */ - if ( importance < 1 ) - importance = 1; - else if ( importance > 3 ) - importance = 3; - break; - case OPT_ID: - if ( !sieve_opr_string_read(renv, address, &id) ) { - sieve_runtime_trace_error(renv, "invalid id operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } - break; - case OPT_MESSAGE: - if ( !sieve_opr_string_read(renv, address, &message) ) { - sieve_runtime_trace_error(renv, "invalid from operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } - break; - case OPT_OPTIONS: - if ( (options=sieve_opr_stringlist_read(renv, address)) == NULL ) { - sieve_runtime_trace_error(renv, "invalid options operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } - break; - default: - sieve_runtime_trace_error(renv, "unknown optional operand: %d", - opt_code); - return SIEVE_EXEC_BIN_CORRUPT; - } + for (;;) { + bool opok = TRUE; + int ret; + + if ( (ret=sieve_opr_optional_read(renv, address, &opt_code)) < 0 ) + return SIEVE_EXEC_BIN_CORRUPT; + + if ( ret == 0 ) break; + + switch ( opt_code ) { + case OPT_IMPORTANCE: + opok = sieve_opr_number_read(renv, address, "importance", &importance); + break; + case OPT_ID: + opok = sieve_opr_string_read(renv, address, "id", &id); + break; + case OPT_MESSAGE: + opok = sieve_opr_string_read(renv, address, "from", &message); + break; + case OPT_OPTIONS: + options = sieve_opr_stringlist_read(renv, address, "options"); + opok = ( options != NULL ); + break; + default: + sieve_runtime_trace_error(renv, "unknown optional operand"); + return SIEVE_EXEC_BIN_CORRUPT; } + + if ( !opok ) return SIEVE_EXEC_BIN_CORRUPT; } /* * Perform operation */ - sieve_runtime_trace(renv, "NOTIFY action"); + /* Enforce 0 < importance < 4 (just to be sure) */ + + if ( importance < 1 ) + importance = 1; + else if ( importance > 3 ) + importance = 3; + + /* Trace */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, "notify action"); /* Compose action */ if ( options != NULL ) { diff --git a/src/lib-sieve/plugins/notify/ext-notify-common.c b/src/lib-sieve/plugins/notify/ext-notify-common.c index 717ea5c1c..f5039824f 100644 --- a/src/lib-sieve/plugins/notify/ext-notify-common.c +++ b/src/lib-sieve/plugins/notify/ext-notify-common.c @@ -150,7 +150,7 @@ static bool _is_text_content(const struct message_header_line *hdr) static buffer_t *cmd_notify_extract_body_text (const struct sieve_runtime_env *renv) { - const struct sieve_extension *this_ext = renv->oprtn.ext; + const struct sieve_extension *this_ext = renv->oprtn->ext; struct ext_notify_message_context *mctx; struct message_parser_ctx *parser; struct message_decoder_context *decoder; diff --git a/src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c b/src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c index 05a531a86..06f95f77a 100644 --- a/src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c +++ b/src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c @@ -10,6 +10,7 @@ #include "sieve-extensions.h" #include "sieve-message.h" #include "sieve-interpreter.h" +#include "sieve-runtime-trace.h" #include "ext-spamvirustest-common.h" @@ -459,7 +460,8 @@ const char *ext_spamvirustest_get_value * Check whether extension is properly configured */ if ( ext_data == NULL ) { - sieve_runtime_trace(renv, "%s: extension not configured", ext_name); + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "%s: extension not configured", ext_name); return "0"; } @@ -492,7 +494,8 @@ const char *ext_spamvirustest_get_value if ( mail_get_first_header_utf8 (msgdata->mail, max_header->header_name, &header_value) < 0 || header_value == NULL ) { - sieve_runtime_trace(renv, "%s: header '%s' not found in message", + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "%s: header '%s' not found in message", ext_name, max_header->header_name); goto failed; } @@ -501,14 +504,16 @@ const char *ext_spamvirustest_get_value /* Execute regex */ if ( regexec(&max_header->regexp, header_value, 2, match_values, 0) != 0 ) { - sieve_runtime_trace(renv, "%s: regexp for header '%s' did not match " + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "%s: regexp for header '%s' did not match " "on value '%s'", ext_name, max_header->header_name, header_value); goto failed; } max = _regexp_match_get_value(header_value, 1, match_values, 2); if ( max == NULL ) { - sieve_runtime_trace(renv, "%s: regexp did not return match value " + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "%s: regexp did not return match value " "for string '%s'", ext_name, header_value); goto failed; } @@ -517,8 +522,8 @@ const char *ext_spamvirustest_get_value } if ( !ext_spamvirustest_parse_decimal_value(max, &max_value, &error) ) { - sieve_runtime_trace(renv, "%s: failed to parse maximum value: %s", - ext_name, error); + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "%s: failed to parse maximum value: %s", ext_name, error); goto failed; } } else { @@ -526,7 +531,8 @@ const char *ext_spamvirustest_get_value } if ( max_value == 0 ) { - sieve_runtime_trace(renv, "%s: max value is 0", ext_name); + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "%s: max value is 0", ext_name); goto failed; } } else { @@ -541,7 +547,8 @@ const char *ext_spamvirustest_get_value if ( mail_get_first_header_utf8 (msgdata->mail, status_header->header_name, &header_value) < 0 || header_value == NULL ) { - sieve_runtime_trace(renv, "%s: header '%s' not found in message", + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "%s: header '%s' not found in message", ext_name, status_header->header_name); goto failed; } @@ -550,15 +557,17 @@ const char *ext_spamvirustest_get_value if ( status_header->regexp_match ) { if ( regexec(&status_header->regexp, header_value, 2, match_values, 0) != 0 ) { - sieve_runtime_trace(renv, "%s: regexp for header '%s' did not match " - "on value '%s'", ext_name, status_header->header_name, header_value); + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "%s: regexp for header '%s' did not match on value '%s'", + ext_name, status_header->header_name, header_value); goto failed; } status = _regexp_match_get_value(header_value, 1, match_values, 2); if ( status == NULL ) { - sieve_runtime_trace(renv, "%s: regexp did not return match value " - "for string '%s'", ext_name, header_value); + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "%s: regexp did not return match value for string '%s'", + ext_name, header_value); goto failed; } } else { @@ -569,7 +578,8 @@ const char *ext_spamvirustest_get_value case EXT_SPAMVIRUSTEST_STATUS_TYPE_SCORE: if ( !ext_spamvirustest_parse_decimal_value (status, &status_value, &error) ) { - sieve_runtime_trace(renv, "%s: failed to parse status value '%s': %s", + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "%s: failed to parse status value '%s': %s", ext_name, status, error); goto failed; } @@ -577,7 +587,8 @@ const char *ext_spamvirustest_get_value case EXT_SPAMVIRUSTEST_STATUS_TYPE_STRLEN: if ( !ext_spamvirustest_parse_strlen_value (status, &status_value, &error) ) { - sieve_runtime_trace(renv, "%s: failed to parse status value '%s': %s", + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "%s: failed to parse status value '%s': %s", ext_name, status, error); goto failed; } @@ -597,7 +608,8 @@ const char *ext_spamvirustest_get_value } if ( i > max_text ) { - sieve_runtime_trace(renv, "%s: failed to match textstatus value '%s'", + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "%s: failed to match textstatus value '%s'", ext_name, status); goto failed; } diff --git a/src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c b/src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c index 3f1103d8a..f13fe943e 100644 --- a/src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c +++ b/src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c @@ -205,26 +205,28 @@ static bool tst_spamvirustest_operation_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address) { int opt_code = 0; - const struct sieve_operation *op = &denv->oprtn; + const struct sieve_operation *op = denv->oprtn; sieve_code_dumpf(denv, "%s", sieve_operation_mnemonic(op)); sieve_code_descend(denv); - /* Handle any optional arguments */ - do { - if ( !sieve_match_dump_optional_operands(denv, address, &opt_code) ) + /* Optional operands */ + for (;;) { + int ret; + + if ( (ret=sieve_match_opr_optional_dump(denv, address, &opt_code)) < 0 ) return FALSE; + if ( ret == 0 ) break; + switch ( opt_code ) { - case SIEVE_MATCH_OPT_END: - break; case OPT_SPAMTEST_PERCENT: sieve_code_dumpf(denv, "percent"); break; default: return FALSE; } - } while ( opt_code != SIEVE_MATCH_OPT_END ); + } return sieve_opr_string_dump(denv, address, "value"); @@ -237,7 +239,7 @@ static bool tst_spamvirustest_operation_dump static int tst_spamvirustest_operation_execute (const struct sieve_runtime_env *renv, sieve_size_t *address) { - const struct sieve_operation *op = &renv->oprtn; + const struct sieve_operation *op = renv->oprtn; const struct sieve_extension *this_ext = op->ext; bool result = TRUE, matched = FALSE; int opt_code = 0; @@ -252,14 +254,16 @@ static int tst_spamvirustest_operation_execute int ret; /* Read optional operands */ - do { - if ( (ret=sieve_match_read_optional_operands - (renv, address, &opt_code, &cmp, &mcht)) <= 0 ) - return ret; + for (;;) { + int ret; + + if ( (ret=sieve_match_opr_optional_read + (renv, address, &opt_code, &cmp, &mcht)) < 0 ) + return SIEVE_EXEC_BIN_CORRUPT; + if ( ret == 0 ) break; + switch ( opt_code ) { - case SIEVE_MATCH_OPT_END: - break; case OPT_SPAMTEST_PERCENT: percent = TRUE; break; @@ -267,17 +271,16 @@ static int tst_spamvirustest_operation_execute sieve_runtime_trace_error(renv, "unknown optional operand"); return SIEVE_EXEC_BIN_CORRUPT; } - } while ( opt_code != SIEVE_MATCH_OPT_END ); + } /* Read value part */ - if ( (key_value=sieve_opr_stringlist_read(renv, address)) == NULL ) { - sieve_runtime_trace_error(renv, "invalid value operand"); + if ( (key_value=sieve_opr_stringlist_read(renv, address, "value")) == NULL ) return SIEVE_EXEC_BIN_CORRUPT; - } /* Perform test */ - sieve_runtime_trace(renv, "%s test", sieve_operation_mnemonic(op)); + sieve_runtime_trace + (renv, SIEVE_TRLVL_TESTS, "%s test", sieve_operation_mnemonic(op)); /* Initialize match */ mctx = sieve_match_begin(renv->interp, &mcht, &cmp, NULL, key_value); diff --git a/src/lib-sieve/plugins/vacation/cmd-vacation.c b/src/lib-sieve/plugins/vacation/cmd-vacation.c index 48d8e5a30..6152eaf0c 100644 --- a/src/lib-sieve/plugins/vacation/cmd-vacation.c +++ b/src/lib-sieve/plugins/vacation/cmd-vacation.c @@ -482,46 +482,43 @@ static bool cmd_vacation_generate static bool ext_vacation_operation_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address) { - int opt_code = 1; + int opt_code = 0; sieve_code_dumpf(denv, "VACATION"); sieve_code_descend(denv); /* Dump optional operands */ - if ( sieve_operand_optional_present(denv->sblock, address) ) { - while ( opt_code != 0 ) { - sieve_code_mark(denv); - - if ( !sieve_operand_optional_read(denv->sblock, address, &opt_code) ) - return FALSE; - switch ( opt_code ) { - case 0: - break; - case OPT_DAYS: - if ( !sieve_opr_number_dump(denv, address, "days") ) - return FALSE; - break; - case OPT_SUBJECT: - if ( !sieve_opr_string_dump(denv, address, "subject") ) - return FALSE; - break; - case OPT_FROM: - if ( !sieve_opr_string_dump(denv, address, "from") ) - return FALSE; - break; - case OPT_ADDRESSES: - if ( !sieve_opr_stringlist_dump(denv, address, "addresses") ) - return FALSE; - break; - case OPT_MIME: - sieve_code_dumpf(denv, "mime"); - break; - - default: - return FALSE; - } + for (;;) { + int ret; + bool opok = TRUE; + + if ( (ret=sieve_opr_optional_dump(denv, address, &opt_code)) < 0 ) + return FALSE; + + if ( ret == 0 ) break; + + switch ( opt_code ) { + case OPT_DAYS: + opok = sieve_opr_number_dump(denv, address, "days"); + break; + case OPT_SUBJECT: + opok = sieve_opr_string_dump(denv, address, "subject"); + break; + case OPT_FROM: + opok = sieve_opr_string_dump(denv, address, "from"); + break; + case OPT_ADDRESSES: + opok = sieve_opr_stringlist_dump(denv, address, "addresses"); + break; + case OPT_MIME: + sieve_code_dumpf(denv, "mime"); + break; + default: + return FALSE; } + + if ( !opok ) return FALSE; } /* Dump reason and handle operands */ @@ -537,11 +534,11 @@ static bool ext_vacation_operation_dump static int ext_vacation_operation_execute (const struct sieve_runtime_env *renv, sieve_size_t *address) { - const struct sieve_extension *this_ext = renv->oprtn.ext; + const struct sieve_extension *this_ext = renv->oprtn->ext; struct sieve_side_effects_list *slist = NULL; struct act_vacation_context *act; pool_t pool; - int opt_code = 1; + int opt_code = 0; sieve_number_t days = 7; bool mime = FALSE; struct sieve_coded_stringlist *addresses = NULL; @@ -550,76 +547,53 @@ static int ext_vacation_operation_execute const char *from_normalized = NULL; /* - * Read operands + * Read code */ /* Source line */ - source_line = sieve_runtime_get_source_location(renv, renv->oprtn.address); - - /* Optional operands */ - if ( sieve_operand_optional_present(renv->sblock, address) ) { - while ( opt_code != 0 ) { - if ( !sieve_operand_optional_read(renv->sblock, address, &opt_code) ) { - sieve_runtime_trace_error(renv, "invalid optional operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } - switch ( opt_code ) { - case 0: - break; - case OPT_DAYS: - if ( !sieve_opr_number_read(renv, address, &days) ) { - sieve_runtime_trace_error(renv, - "invalid days operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } + source_line = sieve_runtime_get_command_location(renv); - /* Enforce days > 0 (just to be sure) */ - if ( days == 0 ) - days = 1; - break; - case OPT_SUBJECT: - if ( !sieve_opr_string_read(renv, address, &subject) ) { - sieve_runtime_trace_error(renv, - "invalid subject operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } - break; - case OPT_FROM: - if ( !sieve_opr_string_read(renv, address, &from) ) { - sieve_runtime_trace_error(renv, - "invalid from address operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } - break; - case OPT_ADDRESSES: - if ( (addresses=sieve_opr_stringlist_read(renv, address)) - == NULL ) { - sieve_runtime_trace_error(renv, - "invalid addresses operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } - break; - case OPT_MIME: - mime = TRUE; - break; - default: - sieve_runtime_trace_error(renv, - "unknown optional operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } + /* Optional operands */ + + for (;;) { + bool opok = TRUE; + int ret; + + if ( (ret=sieve_opr_optional_read(renv, address, &opt_code)) < 0 ) + return SIEVE_EXEC_BIN_CORRUPT; + + if ( ret == 0 ) break; + + switch ( opt_code ) { + case OPT_DAYS: + opok = sieve_opr_number_read(renv, address, "days", &days); + break; + case OPT_SUBJECT: + opok = sieve_opr_string_read(renv, address, "subject", &subject); + break; + case OPT_FROM: + opok = sieve_opr_string_read(renv, address, "from", &from); + break; + case OPT_ADDRESSES: + addresses = sieve_opr_stringlist_read(renv, address, "addresses"); + opok = ( addresses != NULL ); + break; + case OPT_MIME: + mime = TRUE; + break; + default: + sieve_runtime_trace_error(renv, "unknown optional operand"); + opok = FALSE; } + + if ( !opok ) return SIEVE_EXEC_BIN_CORRUPT; } - /* Reason operand */ - if ( !sieve_opr_string_read(renv, address, &reason) ) { - sieve_runtime_trace_error(renv, "invalid reason operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } - - /* Handle operand */ - if ( !sieve_opr_string_read(renv, address, &handle) ) { - sieve_runtime_trace_error(renv, "invalid handle operand"); + /* Fixed operands */ + + if ( !sieve_opr_string_read(renv, address, "reason", &reason) || + !sieve_opr_string_read(renv, address, "handle", &handle) ) { return SIEVE_EXEC_BIN_CORRUPT; } @@ -627,7 +601,14 @@ static int ext_vacation_operation_execute * Perform operation */ - sieve_runtime_trace(renv, "VACATION action"); + /* Enforce days > 0 (just to be sure) */ + + if ( days == 0 ) + days = 1; + + /* Trace */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, "vacation action"); /* Check and normalize :from address */ if ( from != NULL ) { diff --git a/src/lib-sieve/plugins/variables/cmd-set.c b/src/lib-sieve/plugins/variables/cmd-set.c index 1870a07aa..35bd7dfa2 100644 --- a/src/lib-sieve/plugins/variables/cmd-set.c +++ b/src/lib-sieve/plugins/variables/cmd-set.c @@ -291,20 +291,13 @@ static int cmd_set_operation_execute * Read the normal operands */ - /* Read the variable */ if ( !sieve_variable_operand_read - (renv, address, &storage, &var_index) ) { - sieve_runtime_trace_error(renv, "invalid variable operand"); + (renv, address, "variable", &storage, &var_index) ) return SIEVE_EXEC_BIN_CORRUPT; - } - /* Read the raw string value */ - if ( !sieve_opr_string_read(renv, address, &value) ) { - sieve_runtime_trace_error(renv, "invalid string operand"); + if ( !sieve_opr_string_read(renv, address, "string", &value) ) return SIEVE_EXEC_BIN_CORRUPT; - } - - /* Read the number of modifiers used */ + if ( !sieve_binary_read_byte(renv->sblock, address, &mdfs) ) { sieve_runtime_trace_error(renv, "invalid modifier count"); return SIEVE_EXEC_BIN_CORRUPT; @@ -314,7 +307,7 @@ static int cmd_set_operation_execute * Determine and assign the value */ - sieve_runtime_trace(renv, "SET action"); + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "set command"); /* Hold value within limits */ if ( str_len(value) > EXT_VARIABLES_MAX_VARIABLE_SIZE ) @@ -329,8 +322,6 @@ static int cmd_set_operation_execute if ( !ext_variables_opr_modifier_read(renv, address, &modf) ) { value = NULL; - - sieve_runtime_trace_error(renv, "invalid modifier operand"); ret = SIEVE_EXEC_BIN_CORRUPT; break; } diff --git a/src/lib-sieve/plugins/variables/ext-variables-modifiers.h b/src/lib-sieve/plugins/variables/ext-variables-modifiers.h index 92ee6cceb..64dc163fa 100644 --- a/src/lib-sieve/plugins/variables/ext-variables-modifiers.h +++ b/src/lib-sieve/plugins/variables/ext-variables-modifiers.h @@ -4,8 +4,10 @@ #ifndef __EXT_VARIABLES_MODIFIERS_H #define __EXT_VARIABLES_MODIFIERS_H +#include "sieve-common.h" +#include "sieve-runtime-trace.h" + #include "ext-variables-common.h" -#include "sieve-ext-variables.h" #define ext_variables_namespace_name(nspc) \ (nspc)->object->def->name @@ -45,8 +47,10 @@ static inline bool ext_variables_opr_modifier_read struct sieve_variables_modifier *modf) { if ( !sieve_opr_object_read - (renv, &sieve_variables_modifier_operand_class, address, &modf->object) ) + (renv, &sieve_variables_modifier_operand_class, address, &modf->object) ) { + sieve_runtime_trace_error(renv, "invalid modifier operand"); return FALSE; + } modf->def = (const struct sieve_variables_modifier_def *) modf->object.def; return TRUE; diff --git a/src/lib-sieve/plugins/variables/ext-variables-operands.c b/src/lib-sieve/plugins/variables/ext-variables-operands.c index fccfd673f..bb2b76d22 100644 --- a/src/lib-sieve/plugins/variables/ext-variables-operands.c +++ b/src/lib-sieve/plugins/variables/ext-variables-operands.c @@ -137,42 +137,55 @@ static bool opr_variable_read_value bool sieve_variable_operand_read_data (const struct sieve_runtime_env *renv, const struct sieve_operand *operand, - sieve_size_t *address, struct sieve_variable_storage **storage, - unsigned int *var_index) + sieve_size_t *address, const char *field_name, + struct sieve_variable_storage **storage, unsigned int *var_index) { const struct sieve_extension *ext; unsigned int code = 1; /* Initially set to offset value */ unsigned int idx = 0; if ( !sieve_operand_is_variable(operand) ) { + sieve_runtime_trace_operand_error + (renv, operand, field_name, "expected variable operand but found %s", + sieve_operand_name(operand)); return FALSE; } - if ( !sieve_binary_read_extension(renv->sblock, address, &code, &ext) ) + if ( !sieve_binary_read_extension(renv->sblock, address, &code, &ext) ) { + sieve_runtime_trace_operand_error + (renv, operand, field_name, "variable operand: failed to read extension"); return FALSE; + } *storage = sieve_ext_variables_get_storage(operand->ext, renv->interp, ext); - if ( *storage == NULL ) + if ( *storage == NULL ) { + sieve_runtime_trace_operand_error(renv, operand, field_name, + "variable operand: failed to get variable storage"); return FALSE; + } - if ( !sieve_binary_read_unsigned(renv->sblock, address, &idx) ) - return FALSE; + if ( !sieve_binary_read_unsigned(renv->sblock, address, &idx) ) { + sieve_runtime_trace_operand_error + (renv, operand, field_name, "variable operand: failed to read index"); + return FALSE; + } *var_index = idx; return TRUE; } bool sieve_variable_operand_read -(const struct sieve_runtime_env *renv, sieve_size_t *address, - struct sieve_variable_storage **storage, unsigned int *var_index) +(const struct sieve_runtime_env *renv, sieve_size_t *address, + const char *field_name, struct sieve_variable_storage **storage, + unsigned int *var_index) { struct sieve_operand operand; - if ( !sieve_operand_read(renv->sblock, address, &operand) ) + if ( !sieve_operand_runtime_read(renv, address, field_name, &operand) ) return FALSE; return sieve_variable_operand_read_data - (renv, &operand, address, storage, var_index); + (renv, &operand, address, field_name, storage, var_index); } /* diff --git a/src/lib-sieve/plugins/variables/sieve-ext-variables.h b/src/lib-sieve/plugins/variables/sieve-ext-variables.h index 3a6aa7208..2779e44c5 100644 --- a/src/lib-sieve/plugins/variables/sieve-ext-variables.h +++ b/src/lib-sieve/plugins/variables/sieve-ext-variables.h @@ -212,11 +212,12 @@ void sieve_variables_opr_match_value_emit bool sieve_variable_operand_read_data (const struct sieve_runtime_env *renv, const struct sieve_operand *operand, - sieve_size_t *address, struct sieve_variable_storage **storage, - unsigned int *var_index); -bool sieve_variable_operand_read - (const struct sieve_runtime_env *renv, sieve_size_t *address, + sieve_size_t *address, const char *field_name, struct sieve_variable_storage **storage, unsigned int *var_index); +bool sieve_variable_operand_read + (const struct sieve_runtime_env *renv, sieve_size_t *address, + const char *field_name, struct sieve_variable_storage **storage, + unsigned int *var_index); static inline bool sieve_operand_is_variable (const struct sieve_operand *operand) diff --git a/src/lib-sieve/plugins/variables/tst-string.c b/src/lib-sieve/plugins/variables/tst-string.c index 7ca25ab36..fc05636ac 100644 --- a/src/lib-sieve/plugins/variables/tst-string.c +++ b/src/lib-sieve/plugins/variables/tst-string.c @@ -147,13 +147,10 @@ static bool tst_string_operation_dump sieve_code_dumpf(denv, "STRING-TEST"); sieve_code_descend(denv); - /* Handle any optional arguments */ - if ( !sieve_match_dump_optional_operands(denv, address, &opt_code) ) + /* Optional operands */ + if ( sieve_match_opr_optional_dump(denv, address, &opt_code) != 0 ) return FALSE; - if ( opt_code != SIEVE_MATCH_OPT_END ) - return FALSE; - return sieve_opr_stringlist_dump(denv, address, "source") && sieve_opr_stringlist_dump(denv, address, "key list"); @@ -184,33 +181,29 @@ static int tst_string_operation_execute */ /* Handle match-type and comparator operands */ - if ( (ret=sieve_match_read_optional_operands - (renv, address, &opt_code, &cmp, &mcht)) <= 0 ) - return ret; - + if ( (ret=sieve_match_opr_optional_read + (renv, address, &opt_code, &cmp, &mcht)) < 0 ) + return SIEVE_EXEC_BIN_CORRUPT; + /* Check whether we neatly finished the list of optional operands*/ - if ( opt_code != SIEVE_MATCH_OPT_END) { + if ( ret > 0 ) { sieve_runtime_trace_error(renv, "invalid optional operand"); return SIEVE_EXEC_BIN_CORRUPT; } - + /* Read source */ - if ( (source=sieve_opr_stringlist_read(renv, address)) == NULL ) { - sieve_runtime_trace_error(renv, "invalid source operand"); + if ( (source=sieve_opr_stringlist_read(renv, address, "source")) == NULL ) return SIEVE_EXEC_BIN_CORRUPT; - } /* Read key-list */ - if ( (key_list=sieve_opr_stringlist_read(renv, address)) == NULL ) { - sieve_runtime_trace_error(renv, "invalid key-list operand"); + if ( (key_list=sieve_opr_stringlist_read(renv, address, "key-list")) == NULL ) return SIEVE_EXEC_BIN_CORRUPT; - } /* * Perform operation */ - sieve_runtime_trace(renv, "STRING test"); + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "string test"); mctx = sieve_match_begin(renv->interp, &mcht, &cmp, NULL, key_list); diff --git a/src/lib-sieve/sieve-actions.c b/src/lib-sieve/sieve-actions.c index d1d0e30ee..1d61d3a85 100644 --- a/src/lib-sieve/sieve-actions.c +++ b/src/lib-sieve/sieve-actions.c @@ -73,6 +73,81 @@ bool sieve_opr_side_effect_dump return TRUE; } +/* + * Optional operands + */ + +int sieve_action_opr_optional_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address, + signed int *opt_code) +{ + signed int _opt_code = 0; + bool final = FALSE, opok = TRUE; + + if ( opt_code == NULL ) { + opt_code = &_opt_code; + final = TRUE; + } + + while ( opok ) { + int ret; + + if ( (ret=sieve_opr_optional_dump(denv, address, opt_code)) <= 0 ) + return ret; + + if ( *opt_code == SIEVE_OPT_SIDE_EFFECT ) { + opok = sieve_opr_side_effect_dump(denv, address); + } else { + return ( final ? -1 : 1 ); + } + } + + return -1; +} + +int sieve_action_opr_optional_read +(const struct sieve_runtime_env *renv, sieve_size_t *address, + signed int *opt_code, struct sieve_side_effects_list **list) +{ + signed int _opt_code = 0; + bool final = FALSE; + + if ( opt_code == NULL ) { + opt_code = &_opt_code; + final = TRUE; + } + + for ( ;; ) { + int ret; + + if ( (ret=sieve_opr_optional_read(renv, address, opt_code)) <= 0 ) + return ret; + + if ( *opt_code == SIEVE_OPT_SIDE_EFFECT ) { + struct sieve_side_effect seffect; + + if ( list == NULL ) + return -1; + + if ( !sieve_opr_side_effect_read(renv, address, &seffect) ) + return -1; + + if ( *list == NULL ) + *list = sieve_side_effects_list_create(renv->result); + + sieve_side_effects_list_add(*list, &seffect); + } else { + if ( final ) { + sieve_runtime_trace_error(renv, "invalid optional operand"); + return -1; + } + return 1; + } + } + + return -1; +} + /* * Store action */ diff --git a/src/lib-sieve/sieve-actions.h b/src/lib-sieve/sieve-actions.h index 211f5606e..f84a7aaae 100644 --- a/src/lib-sieve/sieve-actions.h +++ b/src/lib-sieve/sieve-actions.h @@ -183,6 +183,18 @@ bool sieve_opr_side_effect_read bool sieve_opr_side_effect_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address); +/* + * Optional operands + */ + +int sieve_action_opr_optional_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address, + signed int *opt_code); + +int sieve_action_opr_optional_read + (const struct sieve_runtime_env *renv, sieve_size_t *address, + signed int *opt_code, struct sieve_side_effects_list **list); + /* * Core actions */ diff --git a/src/lib-sieve/sieve-address-parts.c b/src/lib-sieve/sieve-address-parts.c index 247848aa5..d163e8ce7 100644 --- a/src/lib-sieve/sieve-address-parts.c +++ b/src/lib-sieve/sieve-address-parts.c @@ -290,74 +290,81 @@ int sieve_address_match * Default ADDRESS-PART, MATCH-TYPE, COMPARATOR access */ -bool sieve_addrmatch_default_dump_optionals -(const struct sieve_dumptime_env *denv, sieve_size_t *address) +int sieve_addrmatch_opr_optional_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address, + signed int *opt_code) { - int opt_code = 1; - - if ( sieve_operand_optional_present(denv->sblock, address) ) { - while ( opt_code != 0 ) { - if ( !sieve_operand_optional_read(denv->sblock, address, &opt_code) ) - return FALSE; - - switch ( opt_code ) { - case 0: - break; - case SIEVE_AM_OPT_COMPARATOR: - if ( !sieve_opr_comparator_dump(denv, address) ) - return FALSE; - break; - case SIEVE_AM_OPT_MATCH_TYPE: - if ( !sieve_opr_match_type_dump(denv, address) ) - return FALSE; - break; - case SIEVE_AM_OPT_ADDRESS_PART: - if ( !sieve_opr_address_part_dump(denv, address) ) - return FALSE; - break; - default: - return FALSE; - } + signed int _opt_code = 0; + bool final = FALSE, opok = TRUE; + + if ( opt_code == NULL ) { + opt_code = &_opt_code; + final = TRUE; + } + + while ( opok ) { + int ret; + + if ( (ret=sieve_opr_optional_dump(denv, address, opt_code)) <= 0 ) + return ret; + + switch ( *opt_code ) { + case SIEVE_AM_OPT_COMPARATOR: + opok = sieve_opr_comparator_dump(denv, address); + break; + case SIEVE_AM_OPT_MATCH_TYPE: + opok = sieve_opr_match_type_dump(denv, address); + break; + case SIEVE_AM_OPT_ADDRESS_PART: + opok = sieve_opr_address_part_dump(denv, address); + break; + default: + return ( final ? -1 : 1 ); } } - - return TRUE; + + return -1; } -bool sieve_addrmatch_default_get_optionals -(const struct sieve_runtime_env *renv, sieve_size_t *address, - struct sieve_address_part *addrp, struct sieve_match_type *mtch, - struct sieve_comparator *cmp) +int sieve_addrmatch_opr_optional_read +(const struct sieve_runtime_env *renv, sieve_size_t *address, + signed int *opt_code, struct sieve_address_part *addrp, + struct sieve_match_type *mtch, struct sieve_comparator *cmp) { - int opt_code = 1; - - if ( sieve_operand_optional_present(renv->sblock, address) ) { - while ( opt_code != 0 ) { - if ( !sieve_operand_optional_read(renv->sblock, address, &opt_code) ) - return FALSE; - - switch ( opt_code ) { - case 0: - break; - case SIEVE_AM_OPT_COMPARATOR: - if ( !sieve_opr_comparator_read(renv, address, cmp) ) - return FALSE; - break; - case SIEVE_AM_OPT_MATCH_TYPE: - if ( !sieve_opr_match_type_read(renv, address, mtch) ) - return FALSE; - break; - case SIEVE_AM_OPT_ADDRESS_PART: - if ( !sieve_opr_address_part_read(renv, address, addrp) ) - return FALSE; - break; - default: - return FALSE; + signed int _opt_code = 0; + bool final = FALSE, opok = TRUE; + + if ( opt_code == NULL ) { + opt_code = &_opt_code; + final = TRUE; + } + + while ( opok ) { + int ret; + + if ( (ret=sieve_opr_optional_read(renv, address, opt_code)) <= 0 ) + return ret; + + switch ( *opt_code ) { + case SIEVE_AM_OPT_COMPARATOR: + opok = sieve_opr_comparator_read(renv, address, cmp); + break; + case SIEVE_AM_OPT_MATCH_TYPE: + opok = sieve_opr_match_type_read(renv, address, mtch); + break; + case SIEVE_AM_OPT_ADDRESS_PART: + opok = sieve_opr_address_part_read(renv, address, addrp); + break; + default: + if ( final ) { + sieve_runtime_trace_error(renv, "invalid optional operand"); + return -1; } + return 1; } } - - return TRUE; + + return -1; } /* diff --git a/src/lib-sieve/sieve-address-parts.h b/src/lib-sieve/sieve-address-parts.h index 699bf2398..3df79c380 100644 --- a/src/lib-sieve/sieve-address-parts.h +++ b/src/lib-sieve/sieve-address-parts.h @@ -121,12 +121,13 @@ enum sieve_addrmatch_opt_operand { SIEVE_AM_OPT_MATCH_TYPE }; -bool sieve_addrmatch_default_dump_optionals - (const struct sieve_dumptime_env *denv, sieve_size_t *address); +int sieve_addrmatch_opr_optional_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address, + signed int *opt_code); -bool sieve_addrmatch_default_get_optionals +int sieve_addrmatch_opr_optional_read (const struct sieve_runtime_env *renv, sieve_size_t *address, - struct sieve_address_part *addrp, + signed int *opt_code, struct sieve_address_part *addrp, struct sieve_match_type *mtch, struct sieve_comparator *cmp); #endif /* __SIEVE_ADDRESS_PARTS_H */ diff --git a/src/lib-sieve/sieve-code-dumper.c b/src/lib-sieve/sieve-code-dumper.c index 1c224c13c..cd12e700f 100644 --- a/src/lib-sieve/sieve-code-dumper.c +++ b/src/lib-sieve/sieve-code-dumper.c @@ -34,10 +34,8 @@ struct sieve_code_dumper_extension_reg { struct sieve_code_dumper { pool_t pool; - /* Dump status */ - sieve_size_t pc; /* Program counter */ - - const struct sieve_operation *operation; + /* Dump status */ + struct sieve_operation oprtn; sieve_size_t mark_address; unsigned int mark_line; unsigned int mark_last_line; @@ -55,71 +53,70 @@ struct sieve_code_dumper *sieve_code_dumper_create (struct sieve_dumptime_env *denv) { pool_t pool; - struct sieve_code_dumper *dumper; + struct sieve_code_dumper *cdumper; pool = pool_alloconly_create("sieve_code_dumper", 4096); - dumper = p_new(pool, struct sieve_code_dumper, 1); - dumper->pool = pool; - dumper->dumpenv = denv; - dumper->pc = 0; + cdumper = p_new(pool, struct sieve_code_dumper, 1); + cdumper->pool = pool; + cdumper->dumpenv = denv; /* Setup storage for extension contexts */ - p_array_init(&dumper->extensions, pool, + p_array_init(&cdumper->extensions, pool, sieve_extensions_get_count(denv->svinst)); - return dumper; + return cdumper; } -void sieve_code_dumper_free(struct sieve_code_dumper **dumper) +void sieve_code_dumper_free(struct sieve_code_dumper **cdumper) { - sieve_binary_debug_reader_deinit(&(*dumper)->dreader); + sieve_binary_debug_reader_deinit(&(*cdumper)->dreader); - pool_unref(&((*dumper)->pool)); - *dumper = NULL; + pool_unref(&((*cdumper)->pool)); + *cdumper = NULL; } -pool_t sieve_code_dumper_pool(struct sieve_code_dumper *dumper) +pool_t sieve_code_dumper_pool(struct sieve_code_dumper *cdumper) { - return dumper->pool; + return cdumper->pool; } /* EXtension support */ void sieve_dump_extension_register -(struct sieve_code_dumper *dumper, const struct sieve_extension *ext, +(struct sieve_code_dumper *cdumper, const struct sieve_extension *ext, const struct sieve_code_dumper_extension *cdmpext, void *context) { struct sieve_code_dumper_extension_reg *reg; if ( ext->id < 0 ) return; - reg = array_idx_modifiable(&dumper->extensions, (unsigned int) ext->id); + reg = array_idx_modifiable(&cdumper->extensions, (unsigned int) ext->id); reg->cdmpext = cdmpext; reg->ext = ext; reg->context = context; } void sieve_dump_extension_set_context -(struct sieve_code_dumper *dumper, const struct sieve_extension *ext, +(struct sieve_code_dumper *cdumper, const struct sieve_extension *ext, void *context) { struct sieve_code_dumper_extension_reg *reg; if ( ext->id < 0 ) return; - reg = array_idx_modifiable(&dumper->extensions, (unsigned int) ext->id); + reg = array_idx_modifiable(&cdumper->extensions, (unsigned int) ext->id); reg->context = context; } void *sieve_dump_extension_get_context -(struct sieve_code_dumper *dumper, const struct sieve_extension *ext) +(struct sieve_code_dumper *cdumper, const struct sieve_extension *ext) { const struct sieve_code_dumper_extension_reg *reg; - if ( ext->id < 0 || ext->id >= (int) array_count(&dumper->extensions) ) + if ( ext->id < 0 || ext->id >= (int) array_count(&cdumper->extensions) ) return NULL; - reg = array_idx(&dumper->extensions, (unsigned int) ext->id); + reg = array_idx(&cdumper->extensions, (unsigned int) ext->id); return reg->context; } @@ -169,8 +166,8 @@ static inline void sieve_code_line_mark void sieve_code_mark(const struct sieve_dumptime_env *denv) { - denv->cdumper->mark_address = denv->cdumper->pc; - sieve_code_line_mark(denv, denv->cdumper->pc); + denv->cdumper->mark_address = denv->offset; + sieve_code_line_mark(denv, denv->offset); } void sieve_code_mark_specific @@ -190,53 +187,30 @@ void sieve_code_ascend(const struct sieve_dumptime_env *denv) if ( denv->cdumper->indent > 0 ) denv->cdumper->indent--; } - -/* Operations and operands */ - -bool sieve_code_dumper_print_optional_operands - (const struct sieve_dumptime_env *denv, sieve_size_t *address) -{ - int opt_code = -1; - - if ( sieve_operand_optional_present(denv->sblock, address) ) { - - while ( opt_code != 0 ) { - if ( !sieve_operand_optional_read(denv->sblock, address, &opt_code) ) { - return FALSE; - } - - if ( opt_code == SIEVE_OPT_SIDE_EFFECT ) { - if ( !sieve_opr_side_effect_dump(denv, address) ) - return FALSE; - } - } - } - return TRUE; -} /* Code Dump */ static bool sieve_code_dumper_print_operation - (struct sieve_code_dumper *dumper) +(struct sieve_code_dumper *cdumper) { - struct sieve_dumptime_env *denv = dumper->dumpenv; - struct sieve_operation *oprtn = &denv->oprtn; - sieve_size_t address; - + struct sieve_dumptime_env *denv = cdumper->dumpenv; + struct sieve_operation *oprtn = &(cdumper->oprtn); + sieve_size_t *address = &(denv->offset); + /* Mark start address of operation */ - dumper->indent = 0; - address = dumper->mark_address = dumper->pc; + cdumper->indent = 0; + cdumper->mark_address = *address; - sieve_code_line_mark(denv, address); + sieve_code_line_mark(denv, *address); /* Read operation */ - if ( sieve_operation_read(denv->sblock, &(dumper->pc), oprtn) ) { - const struct sieve_operation_def *op = oprtn->def; + if ( sieve_operation_read(denv->sblock, address, oprtn) ) { + const struct sieve_operation_def *opdef = oprtn->def; - if ( op->dump != NULL ) - return op->dump(denv, &(dumper->pc)); - else if ( op->mnemonic != NULL ) - sieve_code_dumpf(denv, "%s", op->mnemonic); + if ( opdef->dump != NULL ) + return opdef->dump(denv, address); + else if ( opdef->mnemonic != NULL ) + sieve_code_dumpf(denv, "%s", opdef->mnemonic); else return FALSE; @@ -247,15 +221,18 @@ static bool sieve_code_dumper_print_operation return FALSE; } -void sieve_code_dumper_run(struct sieve_code_dumper *dumper) +void sieve_code_dumper_run(struct sieve_code_dumper *cdumper) { - const struct sieve_dumptime_env *denv = dumper->dumpenv; + struct sieve_dumptime_env *denv = cdumper->dumpenv; struct sieve_binary *sbin = denv->sbin; struct sieve_binary_block *sblock = denv->sblock; unsigned int debug_block_id, ext_count; bool success = TRUE; + sieve_size_t *address; - dumper->pc = 0; + denv->offset = 0; + denv->oprtn = &(cdumper->oprtn); + address = &(denv->offset); /* Heading */ o_stream_send_str(denv->stream, "Address Line Code\n"); @@ -263,7 +240,7 @@ void sieve_code_dumper_run(struct sieve_code_dumper *dumper) /* Load debug block */ sieve_code_mark(denv); - if ( sieve_binary_read_unsigned(sblock, &dumper->pc, &debug_block_id) ) { + if ( sieve_binary_read_unsigned(sblock, address, &debug_block_id) ) { struct sieve_binary_block *debug_block = sieve_binary_block_get(sbin, debug_block_id); @@ -272,7 +249,7 @@ void sieve_code_dumper_run(struct sieve_code_dumper *dumper) return; } else { /* Initialize debug reader */ - dumper->dreader = sieve_binary_debug_reader_init(debug_block); + cdumper->dreader = sieve_binary_debug_reader_init(debug_block); /* Dump block id */ sieve_code_dumpf(denv, "DEBUG BLOCK: %d", debug_block_id); @@ -285,7 +262,7 @@ void sieve_code_dumper_run(struct sieve_code_dumper *dumper) /* Load and dump extensions listed in code */ sieve_code_mark(denv); - if ( sieve_binary_read_unsigned(sblock, &dumper->pc, &ext_count) ) { + if ( sieve_binary_read_unsigned(sblock, address, &ext_count) ) { unsigned int i; sieve_code_dumpf(denv, "EXTENSIONS [%d]:", ext_count); @@ -298,7 +275,7 @@ void sieve_code_dumper_run(struct sieve_code_dumper *dumper) T_BEGIN { sieve_code_mark(denv); - if ( !sieve_binary_read_extension(sblock, &dumper->pc, &code, &ext) ) { + if ( !sieve_binary_read_extension(sblock, address, &code, &ext) ) { success = FALSE; break; } @@ -307,7 +284,7 @@ void sieve_code_dumper_run(struct sieve_code_dumper *dumper) if ( ext->def != NULL && ext->def->code_dump != NULL ) { sieve_code_descend(denv); - if ( !ext->def->code_dump(ext, denv, &dumper->pc) ) { + if ( !ext->def->code_dump(ext, denv, address) ) { success = FALSE; break; } @@ -325,21 +302,20 @@ void sieve_code_dumper_run(struct sieve_code_dumper *dumper) return; } - while ( dumper->pc < - sieve_binary_block_get_size(sblock) ) { + while ( *address < sieve_binary_block_get_size(sblock) ) { T_BEGIN { - success = sieve_code_dumper_print_operation(dumper); + success = sieve_code_dumper_print_operation(cdumper); } T_END; if ( !success ) { - sieve_code_dumpf(dumper->dumpenv, "Binary is corrupt."); + sieve_code_dumpf(denv, "Binary is corrupt."); return; } } /* Mark end of the binary */ - dumper->indent = 0; - dumper->mark_address = sieve_binary_block_get_size(sblock); - sieve_code_dumpf(dumper->dumpenv, "[End of code]"); + cdumper->indent = 0; + cdumper->mark_address = sieve_binary_block_get_size(sblock); + sieve_code_dumpf(denv, "[End of code]"); } diff --git a/src/lib-sieve/sieve-code.c b/src/lib-sieve/sieve-code.c index c63a10482..6f15607ac 100644 --- a/src/lib-sieve/sieve-code.c +++ b/src/lib-sieve/sieve-code.c @@ -62,7 +62,7 @@ bool sieve_coded_stringlist_next_item else { address = strlist->current_offset; - if ( sieve_opr_string_read(strlist->runenv, &address, str_r) ) { + if ( sieve_opr_string_read(strlist->runenv, &address, NULL, str_r) ) { strlist->index++; strlist->current_offset = address; return TRUE; @@ -233,30 +233,31 @@ bool sieve_operand_read return ( operand->def != NULL ); } -bool sieve_operand_optional_present -(struct sieve_binary_block *sblock, sieve_size_t *address) +/* + * Optional operand + */ + +int sieve_opr_optional_next +(struct sieve_binary_block *sblock, sieve_size_t *address, signed int *opt_code) { - sieve_size_t tmp_addr = *address; - unsigned int op = -1; + /* Start of optional operand block */ + if ( *opt_code == 0 ) { + sieve_size_t tmp_addr = *address; + unsigned int op; + + if ( !sieve_binary_read_byte(sblock, &tmp_addr, &op) || + op != SIEVE_OPERAND_OPTIONAL ) + return 0; - if ( sieve_binary_read_byte(sblock, &tmp_addr, &op) && - (op == SIEVE_OPERAND_OPTIONAL) ) { *address = tmp_addr; - return TRUE; } - - return FALSE; -} -bool sieve_operand_optional_read -(struct sieve_binary_block *sblock, sieve_size_t *address, signed int *id_code) -{ - if ( sieve_binary_read_code(sblock, address, id_code) ) - return TRUE; + /* Read optional operand code */ + if ( !sieve_binary_read_code(sblock, address, opt_code) ) + return -1; - *id_code = 0; - - return FALSE; + /* Return 0 at end of list */ + return ( *opt_code != 0 ? 1 : 0 ); } /* @@ -418,32 +419,42 @@ bool sieve_opr_number_dump } bool sieve_opr_number_read_data -(const struct sieve_runtime_env *renv, const struct sieve_operand *opr, - sieve_size_t *address, sieve_number_t *number_r) +(const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, const char *field_name, sieve_number_t *number_r) { const struct sieve_opr_number_interface *intf; - if ( !sieve_operand_is_number(opr) ) - return FALSE; + if ( !sieve_operand_is_number(oprnd) ) { + sieve_runtime_trace_operand_error(renv, oprnd, field_name, + "expected number operand but found %s", sieve_operand_name(oprnd)); + return FALSE; + } - intf = (const struct sieve_opr_number_interface *) opr->def->interface; + intf = (const struct sieve_opr_number_interface *) oprnd->def->interface; if ( intf->read == NULL ) return FALSE; - return intf->read(renv, address, number_r); + if ( !intf->read(renv, address, number_r) ) { + sieve_runtime_trace_operand_error(renv, oprnd, field_name, + "invalid number operand"); + return FALSE; + } + + return TRUE; } bool sieve_opr_number_read (const struct sieve_runtime_env *renv, sieve_size_t *address, - sieve_number_t *number_r) + const char *field_name, sieve_number_t *number_r) { struct sieve_operand operand; - if ( !sieve_operand_read(renv->sblock, address, &operand) ) + if ( !sieve_operand_runtime_read(renv, address, field_name, &operand) ) return FALSE; - return sieve_opr_number_read_data(renv, &operand, address, number_r); + return sieve_opr_number_read_data + (renv, &operand, address, field_name, number_r); } static bool opr_number_dump @@ -536,47 +547,52 @@ bool sieve_opr_string_dump_ex } bool sieve_opr_string_read_data -(const struct sieve_runtime_env *renv, const struct sieve_operand *opr, - sieve_size_t *address, string_t **str_r) +(const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, const char *field_name, string_t **str_r) { const struct sieve_opr_string_interface *intf; - if ( opr == NULL || opr->def == NULL || opr->def->class != &string_class ) + if ( !sieve_operand_is_string(oprnd) ) { + sieve_runtime_trace_operand_error(renv, oprnd, field_name, + "expected string operand but found %s", sieve_operand_name(oprnd)); return FALSE; + } - intf = (const struct sieve_opr_string_interface *) opr->def->interface; + intf = (const struct sieve_opr_string_interface *) oprnd->def->interface; - if ( intf->read == NULL ) + if ( intf->read == NULL ) { + sieve_runtime_trace_operand_error(renv, oprnd, field_name, + "invalid string operand"); return FALSE; + } - return intf->read(renv, opr, address, str_r); + return intf->read(renv, oprnd, address, str_r); } bool sieve_opr_string_read -(const struct sieve_runtime_env *renv, sieve_size_t *address, string_t **str_r) +(const struct sieve_runtime_env *renv, sieve_size_t *address, + const char *field_name, string_t **str_r) { struct sieve_operand operand; - if ( !sieve_operand_read(renv->sblock, address, &operand) ) { + if ( !sieve_operand_runtime_read(renv, address, field_name, &operand) ) return FALSE; - } - return sieve_opr_string_read_data(renv, &operand, address, str_r); + return sieve_opr_string_read_data(renv, &operand, address, field_name, str_r); } bool sieve_opr_string_read_ex -(const struct sieve_runtime_env *renv, sieve_size_t *address, string_t **str_r, - bool *literal_r) +(const struct sieve_runtime_env *renv, sieve_size_t *address, + const char *field_name, string_t **str_r, bool *literal_r) { struct sieve_operand operand; - if ( !sieve_operand_read(renv->sblock, address, &operand) ) { + if ( !sieve_operand_runtime_read(renv, address, field_name, &operand) ) return FALSE; - } *literal_r = sieve_operand_is(&operand, string_operand); - return sieve_opr_string_read_data(renv, &operand, address, str_r); + return sieve_opr_string_read_data(renv, &operand, address, field_name, str_r); } static void _dump_string @@ -700,45 +716,57 @@ bool sieve_opr_stringlist_dump } struct sieve_coded_stringlist *sieve_opr_stringlist_read_data -(const struct sieve_runtime_env *renv, const struct sieve_operand *opr, - sieve_size_t *address) +(const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, const char *field_name) { - if ( opr == NULL || opr->def == NULL ) + if ( oprnd == NULL || oprnd->def == NULL ) return NULL; - if ( opr->def->class == &stringlist_class ) { + if ( oprnd->def->class == &stringlist_class ) { const struct sieve_opr_stringlist_interface *intf = - (const struct sieve_opr_stringlist_interface *) opr->def->interface; + (const struct sieve_opr_stringlist_interface *) oprnd->def->interface; + struct sieve_coded_stringlist *strlist; if ( intf->read == NULL ) return NULL; - return intf->read(renv, address); - } else if ( opr->def->class == &string_class ) { + if ( (strlist=intf->read(renv, address)) == NULL ) { + sieve_runtime_trace_operand_error(renv, oprnd, field_name, + "invalid stringlist operand"); + return NULL; + } + + return strlist; + } else if ( oprnd->def->class == &string_class ) { /* Special case, accept single string as string list as well. */ const struct sieve_opr_string_interface *intf = - (const struct sieve_opr_string_interface *) opr->def->interface; + (const struct sieve_opr_string_interface *) oprnd->def->interface; - if ( intf->read == NULL || !intf->read(renv, opr, address, NULL) ) { + if ( intf->read == NULL || !intf->read(renv, oprnd, address, NULL) ) { + sieve_runtime_trace_operand_error(renv, oprnd, field_name, + "invalid stringlist string operand"); return NULL; } - return sieve_coded_stringlist_create(renv, opr->address, 1, *address); + return sieve_coded_stringlist_create(renv, oprnd->address, 1, *address); } - + + sieve_runtime_trace_operand_error(renv, oprnd, field_name, + "expected stringlist or string operand but found %s", + sieve_operand_name(oprnd)); return NULL; } struct sieve_coded_stringlist *sieve_opr_stringlist_read -(const struct sieve_runtime_env *renv, sieve_size_t *address) +(const struct sieve_runtime_env *renv, sieve_size_t *address, + const char *field_name) { struct sieve_operand operand; - if ( !sieve_operand_read(renv->sblock, address, &operand) ) { + if ( !sieve_operand_runtime_read(renv, address, field_name, &operand) ) return NULL; - } - return sieve_opr_stringlist_read_data(renv, &operand, address); + return sieve_opr_stringlist_read_data(renv, &operand, address, field_name); } static bool opr_stringlist_dump @@ -838,7 +866,7 @@ static bool opr_catenated_string_read */ if ( str == NULL ) { for ( i = 0; i < (unsigned int) elements; i++ ) { - if ( !sieve_opr_string_read(renv, address, NULL) ) + if ( !sieve_opr_string_read(renv, address, NULL, NULL) ) return FALSE; } } else { @@ -848,7 +876,7 @@ static bool opr_catenated_string_read *str = t_str_new(128); for ( i = 0; i < (unsigned int) elements; i++ ) { - if ( !sieve_opr_string_read(renv, address, elm) ) + if ( !sieve_opr_string_read(renv, address, NULL, elm) ) return FALSE; if ( elm != NULL ) { @@ -1002,13 +1030,13 @@ bool sieve_operation_read static bool opc_jmp_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address) { - const struct sieve_operation *op = &denv->oprtn; + const struct sieve_operation *oprtn = denv->oprtn; unsigned int pc = *address; int offset; if ( sieve_binary_read_offset(denv->sblock, address, &offset) ) sieve_code_dumpf(denv, "%s %d [%08x]", - sieve_operation_mnemonic(op), offset, pc + offset); + sieve_operation_mnemonic(oprtn), offset, pc + offset); else return FALSE; @@ -1020,7 +1048,7 @@ static bool opc_jmp_dump static int opc_jmp_execute (const struct sieve_runtime_env *renv, sieve_size_t *address ATTR_UNUSED) { - sieve_runtime_trace(renv, "JMP"); + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "jump"); return sieve_interpreter_program_jump(renv->interp, TRUE); } @@ -1030,7 +1058,8 @@ static int opc_jmptrue_execute { bool result = sieve_interpreter_get_test_result(renv->interp); - sieve_runtime_trace(renv, "JMPTRUE (%s)", result ? "true" : "false"); + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "jump if true (%s)", + result ? "true" : "false"); return sieve_interpreter_program_jump(renv->interp, result); } @@ -1040,7 +1069,8 @@ static int opc_jmpfalse_execute { bool result = sieve_interpreter_get_test_result(renv->interp); - sieve_runtime_trace(renv, "JMPFALSE (%s)", result ? "true" : "false" ); + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "jump if false (%s)", + result ? "true" : "false" ); return sieve_interpreter_program_jump(renv->interp, !result); } diff --git a/src/lib-sieve/sieve-code.h b/src/lib-sieve/sieve-code.h index 47583d141..a350ecc5e 100644 --- a/src/lib-sieve/sieve-code.h +++ b/src/lib-sieve/sieve-code.h @@ -10,6 +10,9 @@ #include "array.h" #include "sieve-common.h" +#include "sieve-runtime.h" +#include "sieve-runtime-trace.h" +#include "sieve-dump.h" /* * Coded string list @@ -68,11 +71,52 @@ bool sieve_operand_read (struct sieve_binary_block *sblock, sieve_size_t *address, struct sieve_operand *oprnd); -bool sieve_operand_optional_present - (struct sieve_binary_block *sblock, sieve_size_t *address); -bool sieve_operand_optional_read - (struct sieve_binary_block *sblock, sieve_size_t *address, - signed int *id_code); +static inline bool sieve_operand_runtime_read +(const struct sieve_runtime_env *renv, sieve_size_t *address, + const char *field_name, struct sieve_operand *operand) +{ + if ( !sieve_operand_read(renv->sblock, address, operand) ) { + sieve_runtime_trace_operand_error + (renv, operand, field_name, "invalid operand"); + return FALSE; + } + + return TRUE; +} + +/* + * Optional operands + */ + +int sieve_opr_optional_next +(struct sieve_binary_block *sblock, sieve_size_t *address, + signed int *opt_code); + +static inline int sieve_opr_optional_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address, + signed int *opt_code) +{ + sieve_size_t pc = *address; + int ret; + + if ( (ret=sieve_opr_optional_next(denv->sblock, address, opt_code)) <= 0 ) + return ret; + + sieve_code_mark_specific(denv, pc); + return ret; +} + +static inline int sieve_opr_optional_read +(const struct sieve_runtime_env *renv, sieve_size_t *address, + signed int *opt_code) +{ + int ret; + + if ( (ret=sieve_opr_optional_next(renv->sblock, address, opt_code)) < 0 ) + sieve_runtime_trace_error(renv, "invalid optional operand code"); + + return ret; +} /* * Core operands @@ -165,10 +209,10 @@ bool sieve_opr_number_dump const char *field_name); bool sieve_opr_number_read_data (const struct sieve_runtime_env *renv, const struct sieve_operand *operand, - sieve_size_t *address, sieve_number_t *number_r); + sieve_size_t *address, const char *field_name, sieve_number_t *number_r); bool sieve_opr_number_read (const struct sieve_runtime_env *renv, sieve_size_t *address, - sieve_number_t *number_r); + const char *field_name, sieve_number_t *number_r); static inline bool sieve_operand_is_number (const struct sieve_operand *operand) @@ -192,12 +236,13 @@ bool sieve_opr_string_dump_ex const char *field_name, bool *literal_r); bool sieve_opr_string_read_data (const struct sieve_runtime_env *renv, const struct sieve_operand *operand, - sieve_size_t *address, string_t **str_r); + sieve_size_t *address, const char *field_name, string_t **str_r); bool sieve_opr_string_read - (const struct sieve_runtime_env *renv, sieve_size_t *address, string_t **str_r); + (const struct sieve_runtime_env *renv, sieve_size_t *address, + const char *field_name, string_t **str_r); bool sieve_opr_string_read_ex - (const struct sieve_runtime_env *renv, sieve_size_t *address, string_t **str_r, - bool *literal_r); + (const struct sieve_runtime_env *renv, sieve_size_t *address, + const char *field_name, string_t **str_r, bool *literal_r); static inline bool sieve_operand_is_string (const struct sieve_operand *operand) @@ -223,9 +268,10 @@ bool sieve_opr_stringlist_dump const char *field_name); struct sieve_coded_stringlist *sieve_opr_stringlist_read_data (const struct sieve_runtime_env *renv, const struct sieve_operand *operand, - sieve_size_t *address); + sieve_size_t *address, const char *field_name); struct sieve_coded_stringlist *sieve_opr_stringlist_read - (const struct sieve_runtime_env *renv, sieve_size_t *address); + (const struct sieve_runtime_env *renv, sieve_size_t *address, + const char *field_name); static inline bool sieve_operand_is_stringlist (const struct sieve_operand *operand) diff --git a/src/lib-sieve/sieve-common.h b/src/lib-sieve/sieve-common.h index a6f996322..a2edd81ab 100644 --- a/src/lib-sieve/sieve-common.h +++ b/src/lib-sieve/sieve-common.h @@ -65,8 +65,10 @@ struct sieve_codegen_env; struct sieve_runtime_env; struct sieve_interpreter; -/* sieve-binary-dumper.h */ +/* sieve-dump.h */ struct sieve_dumptime_env; + +/* sieve-binary-dumper.h */ struct sieve_binary_dumper; /* sieve-code-dumper.h */ diff --git a/src/lib-sieve/sieve-dump.h b/src/lib-sieve/sieve-dump.h index 5e0a96f3c..a5c20ca77 100644 --- a/src/lib-sieve/sieve-dump.h +++ b/src/lib-sieve/sieve-dump.h @@ -5,26 +5,28 @@ #define __SIEVE_DUMP_H #include "sieve-common.h" - -#include "sieve-code.h" -#include "sieve-binary-dumper.h" #include "sieve-code-dumper.h" +#include "sieve-binary-dumper.h" /* * Dumptime environment */ struct sieve_dumptime_env { + /* Dumpers */ + struct sieve_instance *svinst; struct sieve_binary_dumper *dumper; struct sieve_code_dumper *cdumper; - struct sieve_instance *svinst; - + /* Binary */ struct sieve_binary *sbin; struct sieve_binary_block *sblock; - struct sieve_operation oprtn; + /* Code position */ + const struct sieve_operation *oprtn; + sieve_size_t offset; + /* Output stream */ struct ostream *stream; }; diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c index c0da74b36..d301c266f 100644 --- a/src/lib-sieve/sieve-interpreter.c +++ b/src/lib-sieve/sieve-interpreter.c @@ -57,14 +57,20 @@ struct sieve_interpreter { bool test_result; /* Result of previous test command */ /* Runtime environment */ - struct sieve_runtime_env runenv; + struct sieve_runtime_env runenv; + /* Current operation */ + struct sieve_operation oprtn; + + /* Location information */ struct sieve_binary_debug_reader *dreader; + unsigned int command_line; }; static struct sieve_interpreter *_sieve_interpreter_create (struct sieve_binary *sbin, struct sieve_binary_block *sblock, - struct sieve_error_handler *ehandler) + struct sieve_script *script, const struct sieve_message_data *msgdata, + const struct sieve_script_env *senv, struct sieve_error_handler *ehandler) { unsigned int i, ext_count; struct sieve_interpreter *interp; @@ -72,6 +78,7 @@ static struct sieve_interpreter *_sieve_interpreter_create struct sieve_instance *svinst; const struct sieve_extension *const *ext_preloaded; unsigned int debug_block_id; + sieve_size_t *address; bool success = TRUE; pool = pool_alloconly_create("sieve_interpreter", 4096); @@ -81,17 +88,34 @@ static struct sieve_interpreter *_sieve_interpreter_create interp->ehandler = ehandler; sieve_error_handler_ref(ehandler); - interp->runenv.interp = interp; + interp->runenv.interp = interp; + interp->runenv.oprtn = &interp->oprtn; interp->runenv.sbin = sbin; interp->runenv.sblock = sblock; sieve_binary_ref(sbin); svinst = sieve_binary_svinst(sbin); - interp->runenv.svinst = svinst; - interp->runenv.script = sieve_binary_script(sbin); + interp->runenv.svinst = svinst; + interp->runenv.msgdata = msgdata; + interp->runenv.scriptenv = senv; + interp->runenv.trace_stream = senv->trace_stream; + interp->runenv.trace_level = senv->trace_level; + + if ( senv->exec_status == NULL ) + interp->runenv.exec_status = p_new(interp->pool, struct sieve_exec_status, 1); + else + interp->runenv.exec_status = senv->exec_status; + + if ( script == NULL ) + interp->runenv.script = sieve_binary_script(sbin); + else + interp->runenv.script = script; - interp->pc = 0; + interp->runenv.pc = 0; + address = &(interp->runenv.pc); + + sieve_runtime_trace_begin(&(interp->runenv)); p_array_init(&interp->extensions, pool, sieve_extensions_get_count(svinst)); @@ -102,11 +126,11 @@ static struct sieve_interpreter *_sieve_interpreter_create if ( ext_def != NULL && ext_def->interpreter_load != NULL ) (void)ext_def->interpreter_load - (ext_preloaded[i], &interp->runenv, &interp->pc); + (ext_preloaded[i], &interp->runenv, address); } /* Load debug block */ - if ( sieve_binary_read_unsigned(sblock, &interp->pc, &debug_block_id) ) { + if ( sieve_binary_read_unsigned(sblock, address, &debug_block_id) ) { struct sieve_binary_block *debug_block = sieve_binary_block_get(sbin, debug_block_id); @@ -121,19 +145,19 @@ static struct sieve_interpreter *_sieve_interpreter_create /* Load other extensions listed in code */ if ( success && - sieve_binary_read_unsigned(sblock, &interp->pc, &ext_count) ) { + sieve_binary_read_unsigned(sblock, address, &ext_count) ) { for ( i = 0; i < ext_count; i++ ) { unsigned int code = 0; const struct sieve_extension *ext; - if ( !sieve_binary_read_extension(sblock, &interp->pc, &code, &ext) ) { + if ( !sieve_binary_read_extension(sblock, address, &code, &ext) ) { success = FALSE; break; } if ( ext->def != NULL && ext->def->interpreter_load != NULL && - !ext->def->interpreter_load(ext, &interp->runenv, &interp->pc) ) { + !ext->def->interpreter_load(ext, &interp->runenv, address) ) { success = FALSE; break; } @@ -144,27 +168,31 @@ static struct sieve_interpreter *_sieve_interpreter_create if ( !success ) { sieve_interpreter_free(&interp); } else { - interp->reset_vector = interp->pc; + interp->reset_vector = *address; } return interp; } struct sieve_interpreter *sieve_interpreter_create -(struct sieve_binary *sbin, struct sieve_error_handler *ehandler) +(struct sieve_binary *sbin, const struct sieve_message_data *msgdata, + const struct sieve_script_env *senv, struct sieve_error_handler *ehandler) { struct sieve_binary_block *sblock = sieve_binary_block_get(sbin, SBIN_SYSBLOCK_MAIN_PROGRAM); - return _sieve_interpreter_create(sbin, sblock, ehandler); + return _sieve_interpreter_create(sbin, sblock, NULL, msgdata, senv, ehandler); } struct sieve_interpreter *sieve_interpreter_create_for_block -(struct sieve_binary_block *sblock, struct sieve_error_handler *ehandler) +(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 = sieve_binary_block_get_binary(sblock); - return _sieve_interpreter_create(sbin, sblock, ehandler); + return _sieve_interpreter_create + (sbin, sblock, script, msgdata, senv, ehandler); } void sieve_interpreter_free(struct sieve_interpreter **interp) @@ -172,6 +200,8 @@ void sieve_interpreter_free(struct sieve_interpreter **interp) const struct sieve_interpreter_extension_reg *eregs; unsigned int ext_count, i; + sieve_runtime_trace_end(&((*interp)->runenv)); + /* Signal registered extensions that the interpreter is being destroyed */ eregs = array_get(&(*interp)->extensions, &ext_count); for ( i = 0; i < ext_count; i++ ) { @@ -231,12 +261,11 @@ void sieve_interpreter_set_result /* This is not particularly user friendly, so avoid using this */ -const char *sieve_runtime_location(const struct sieve_runtime_env *runenv) +const char *sieve_runtime_location(const struct sieve_runtime_env *renv) { - const char *op = runenv->oprtn.def == NULL ? - "<<NOOP>>" : runenv->oprtn.def->mnemonic; - return t_strdup_printf("%s: #%08llx: %s", sieve_script_name(runenv->script), - (unsigned long long) runenv->oprtn.address, op); + const char *op = sieve_operation_mnemonic(renv->oprtn); + return t_strdup_printf("%s: #%08llx: %s", sieve_script_name(renv->script), + (unsigned long long) renv->oprtn->address, op); } void sieve_runtime_error @@ -279,50 +308,39 @@ void sieve_runtime_log } /* - * Runtime trace + * Source location */ unsigned int sieve_runtime_get_source_location (const struct sieve_runtime_env *renv, sieve_size_t code_address) { - if ( renv->interp->dreader != NULL ) - return sieve_binary_debug_read_line(renv->interp->dreader, code_address); + struct sieve_interpreter *interp = renv->interp; - return 0; -} + if ( interp->dreader == NULL ) + return 0; -#ifdef SIEVE_RUNTIME_TRACE -void _sieve_runtime_trace -(const struct sieve_runtime_env *runenv, const char *fmt, ...) -{ - string_t *outbuf = t_str_new(128); - va_list args; - - va_start(args, fmt); - str_printfa(outbuf, "%08llx: ", (unsigned long long) runenv->oprtn.address); - str_vprintfa(outbuf, fmt, args); - str_append_c(outbuf, '\n'); - va_end(args); - - o_stream_send(runenv->trace_stream, str_data(outbuf), str_len(outbuf)); + if ( interp->command_line == 0 ) { + interp->command_line = sieve_binary_debug_read_line + (interp->dreader, renv->oprtn->address); + } + + return sieve_binary_debug_read_line(interp->dreader, code_address); } -void _sieve_runtime_trace_error -(const struct sieve_runtime_env *runenv, const char *fmt, ...) +unsigned int sieve_runtime_get_command_location +(const struct sieve_runtime_env *renv) { - string_t *outbuf = t_str_new(128); - va_list args; + struct sieve_interpreter *interp = renv->interp; - va_start(args, fmt); - str_printfa(outbuf, "%08llx: [[ERROR: %s: ", - (unsigned long long) runenv->interp->pc, runenv->oprtn.def->mnemonic); - str_vprintfa(outbuf, fmt, args); - str_append(outbuf, "]]\n"); - va_end(args); + if ( interp->dreader == NULL ) + return 0; + + if ( interp->command_line == 0 ) + interp->command_line = sieve_binary_debug_read_line + (interp->dreader, renv->oprtn->address); - o_stream_send(runenv->trace_stream, str_data(outbuf), str_len(outbuf)); + return interp->command_line; } -#endif /* * Extension support @@ -373,10 +391,9 @@ void *sieve_interpreter_extension_get_context void sieve_interpreter_reset(struct sieve_interpreter *interp) { - interp->pc = interp->reset_vector; + interp->runenv.pc = interp->reset_vector; interp->interrupted = FALSE; interp->test_result = FALSE; - interp->runenv.msgdata = NULL; interp->runenv.result = NULL; } @@ -387,27 +404,32 @@ void sieve_interpreter_interrupt(struct sieve_interpreter *interp) sieve_size_t sieve_interpreter_program_counter(struct sieve_interpreter *interp) { - return interp->pc; + return interp->runenv.pc; } int sieve_interpreter_program_jump (struct sieve_interpreter *interp, bool jump) { const struct sieve_runtime_env *renv = &interp->runenv; - sieve_size_t pc = interp->pc; - int offset; + sieve_size_t *address = &(interp->runenv.pc); + sieve_size_t jmp_start = *address; + int jmp_offset; - if ( !sieve_binary_read_offset(renv->sblock, &(interp->pc), &offset) ) + if ( !sieve_binary_read_offset(renv->sblock, address, &jmp_offset) ) { sieve_runtime_trace_error(renv, "invalid jump offset"); return SIEVE_EXEC_BIN_CORRUPT; } - if ( pc + offset <= sieve_binary_block_get_size(renv->sblock) && - pc + offset > 0 ) + if ( jmp_start + jmp_offset <= sieve_binary_block_get_size(renv->sblock) && + jmp_start + jmp_offset > 0 ) { - if ( jump ) - interp->pc = pc + offset; + if ( jump ) { + sieve_runtime_trace_here(renv, SIEVE_TRLVL_COMMANDS, "jump to #%08llx", + (long long unsigned int) jmp_start + jmp_offset); + + *address = jmp_start + jmp_offset; + } return SIEVE_EXEC_OK; } @@ -432,44 +454,6 @@ bool sieve_interpreter_get_test_result return interp->test_result; } -/* - * Operations and operands - */ - -int sieve_interpreter_handle_optional_operands -(const struct sieve_runtime_env *renv, sieve_size_t *address, - struct sieve_side_effects_list **list) -{ - signed int opt_code = -1; - - if ( sieve_operand_optional_present(renv->sblock, address) ) { - while ( opt_code != 0 ) { - if ( !sieve_operand_optional_read(renv->sblock, address, &opt_code) ) { - sieve_runtime_trace_error(renv, "invalid optional operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } - - if ( opt_code == SIEVE_OPT_SIDE_EFFECT ) { - struct sieve_side_effect seffect; - - if ( list == NULL ) - return SIEVE_EXEC_BIN_CORRUPT; - - if ( !sieve_opr_side_effect_read(renv, address, &seffect) ) { - sieve_runtime_trace_error(renv, "invalid side effect operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } - - if ( *list == NULL ) - *list = sieve_side_effects_list_create(renv->result); - - sieve_side_effects_list_add(*list, &seffect); - } - } - } - return TRUE; -} - /* * Code execute */ @@ -477,31 +461,40 @@ int sieve_interpreter_handle_optional_operands static int sieve_interpreter_operation_execute (struct sieve_interpreter *interp) { - struct sieve_operation *oprtn = &(interp->runenv.oprtn); + struct sieve_operation *oprtn = &(interp->oprtn); + sieve_size_t *address = &(interp->runenv.pc); - if ( sieve_operation_read(interp->runenv.sblock, &(interp->pc), oprtn) ) { + /* Read the operation */ + if ( sieve_operation_read(interp->runenv.sblock, address, oprtn) ) { const struct sieve_operation_def *op = oprtn->def; - int result = SIEVE_EXEC_OK; + /* Reset cached command location */ + interp->command_line = 0; + + /* Execute the operation */ if ( op->execute != NULL ) { /* Noop ? */ T_BEGIN { - result = op->execute(&(interp->runenv), &(interp->pc)); + result = op->execute(&(interp->runenv), address); } T_END; } else { - sieve_runtime_trace(&interp->runenv, "OP: %s (NOOP)", op->mnemonic); + sieve_runtime_trace + (&interp->runenv, SIEVE_TRLVL_COMMANDS, "OP: %s (NOOP)", + sieve_operation_mnemonic(oprtn)); } return result; } - sieve_runtime_trace(&interp->runenv, "Encountered invalid operation"); + /* Binary corrupt */ + sieve_runtime_trace_error(&interp->runenv, "Encountered invalid operation"); return SIEVE_EXEC_BIN_CORRUPT; } int sieve_interpreter_continue (struct sieve_interpreter *interp, bool *interrupted) { + sieve_size_t *address = &(interp->runenv.pc); int ret = SIEVE_EXEC_OK; sieve_result_ref(interp->runenv.result); @@ -511,12 +504,13 @@ int sieve_interpreter_continue *interrupted = FALSE; while ( ret == SIEVE_EXEC_OK && !interp->interrupted && - interp->pc < sieve_binary_block_get_size(interp->runenv.sblock) ) { + *address < sieve_binary_block_get_size(interp->runenv.sblock) ) { ret = sieve_interpreter_operation_execute(interp); if ( ret != SIEVE_EXEC_OK ) { - sieve_runtime_trace(&interp->runenv, "[[EXECUTION ABORTED]]"); + sieve_runtime_trace(&interp->runenv, SIEVE_TRLVL_MINIMUM, + "[[EXECUTION ABORTED]]"); } } @@ -528,22 +522,13 @@ int sieve_interpreter_continue } int sieve_interpreter_start -(struct sieve_interpreter *interp, const struct sieve_message_data *msgdata, - const struct sieve_script_env *senv, struct sieve_result *result, bool *interrupted) +(struct sieve_interpreter *interp, struct sieve_result *result, bool *interrupted) { const struct sieve_interpreter_extension_reg *eregs; unsigned int ext_count, i; - interp->runenv.msgdata = msgdata; interp->runenv.result = result; interp->runenv.msgctx = sieve_result_get_message_context(result); - interp->runenv.scriptenv = senv; - interp->runenv.trace_stream = senv->trace_stream; - - if ( senv->exec_status == NULL ) - interp->runenv.exec_status = p_new(interp->pool, struct sieve_exec_status, 1); - else - interp->runenv.exec_status = senv->exec_status; /* Signal registered extensions that the interpreter is being run */ eregs = array_get(&interp->extensions, &ext_count); @@ -556,15 +541,14 @@ int sieve_interpreter_start } int sieve_interpreter_run -(struct sieve_interpreter *interp, const struct sieve_message_data *msgdata, - const struct sieve_script_env *senv, struct sieve_result *result) +(struct sieve_interpreter *interp, struct sieve_result *result) { int ret = 0; sieve_interpreter_reset(interp); sieve_result_ref(result); - ret = sieve_interpreter_start(interp, msgdata, senv, result, NULL); + ret = sieve_interpreter_start(interp, result, NULL); sieve_result_unref(&result); diff --git a/src/lib-sieve/sieve-interpreter.h b/src/lib-sieve/sieve-interpreter.h index ba08f8f63..15d3f9ad4 100644 --- a/src/lib-sieve/sieve-interpreter.h +++ b/src/lib-sieve/sieve-interpreter.h @@ -10,46 +10,19 @@ #include "mail-storage.h" #include "sieve-common.h" -#include "sieve-code.h" - -/* - * Forward declarations - */ - -struct sieve_interpreter; - -/* - * Runtime environment - */ - -struct sieve_runtime_env { - struct sieve_interpreter *interp; - struct sieve_instance *svinst; - - struct sieve_binary *sbin; - struct sieve_binary_block *sblock; - struct sieve_operation oprtn; - - struct sieve_script *script; - const struct sieve_script_env *scriptenv; - - const struct sieve_message_data *msgdata; - struct sieve_message_context *msgctx; - - struct sieve_result *result; - - struct sieve_exec_status *exec_status; - struct ostream *trace_stream; -}; +#include "sieve-runtime.h" /* * Interpreter */ struct sieve_interpreter *sieve_interpreter_create - (struct sieve_binary *sbin, struct sieve_error_handler *ehandler); + (struct sieve_binary *sbin, const struct sieve_message_data *msgdata, + const struct sieve_script_env *senv, struct sieve_error_handler *ehandler); struct sieve_interpreter *sieve_interpreter_create_for_block - (struct sieve_binary_block *sblock, struct sieve_error_handler *ehandler); + (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); void sieve_interpreter_free(struct sieve_interpreter **interp); /* @@ -94,12 +67,18 @@ void sieve_interpreter_set_test_result bool sieve_interpreter_get_test_result (struct sieve_interpreter *interp); -/* - * Error handling +/* + * Source location */ unsigned int sieve_runtime_get_source_location (const struct sieve_runtime_env *renv, sieve_size_t code_address); +unsigned int sieve_runtime_get_command_location + (const struct sieve_runtime_env *renv); + +/* + * Error handling + */ /* This is not particularly user-friendly, so avoid using this.. */ const char *sieve_runtime_location(const struct sieve_runtime_env *runenv); @@ -114,33 +93,6 @@ void sieve_runtime_log (const struct sieve_runtime_env *runenv, const char *location, const char *fmt, ...) ATTR_FORMAT(3, 4); -/* - * Runtime Trace - */ - -#ifdef SIEVE_RUNTIME_TRACE - -void _sieve_runtime_trace - (const struct sieve_runtime_env *runenv, const char *fmt, ...) - ATTR_FORMAT(2, 3); -void _sieve_runtime_trace_error - (const struct sieve_runtime_env *runenv, const char *fmt, ...) - ATTR_FORMAT(2, 3); - -# define sieve_runtime_trace(runenv, ...) STMT_START { \ - if ( (runenv)->trace_stream != NULL ) \ - _sieve_runtime_trace((runenv), __VA_ARGS__); \ - } STMT_END -# define sieve_runtime_trace_error(runenv, ...) STMT_START { \ - if ( (runenv)->trace_stream != NULL ) \ - _sieve_runtime_trace_error((runenv), __VA_ARGS__); \ - } STMT_END - -#else -# define sieve_runtime_trace(runenv, ...) -# define sieve_runtime_trace_error(runenv, ...) -#endif - /* * Extension support */ @@ -180,11 +132,9 @@ int sieve_interpreter_handle_optional_operands int sieve_interpreter_continue (struct sieve_interpreter *interp, bool *interrupted); int sieve_interpreter_start - (struct sieve_interpreter *interp, const struct sieve_message_data *msgdata, - const struct sieve_script_env *senv, struct sieve_result *result, + (struct sieve_interpreter *interp, struct sieve_result *result, bool *interrupted); int sieve_interpreter_run - (struct sieve_interpreter *interp, const struct sieve_message_data *msgdata, - const struct sieve_script_env *senv, struct sieve_result *result); + (struct sieve_interpreter *interp, struct sieve_result *result); #endif /* __SIEVE_INTERPRETER_H */ diff --git a/src/lib-sieve/sieve-match.c b/src/lib-sieve/sieve-match.c index 88aa4e517..7797fb192 100644 --- a/src/lib-sieve/sieve-match.c +++ b/src/lib-sieve/sieve-match.c @@ -136,69 +136,56 @@ int sieve_match_end(struct sieve_match_context **mctx) * Reading match operands */ -bool sieve_match_dump_optional_operands +int sieve_match_opr_optional_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address, int *opt_code) { - if ( *opt_code != SIEVE_MATCH_OPT_END || - sieve_operand_optional_present(denv->sblock, address) ) { - do { - if ( !sieve_operand_optional_read(denv->sblock, address, opt_code) ) - return FALSE; - - switch ( *opt_code ) { - case SIEVE_MATCH_OPT_END: - break; - case SIEVE_MATCH_OPT_COMPARATOR: - if ( !sieve_opr_comparator_dump(denv, address) ) - return FALSE; - break; - case SIEVE_MATCH_OPT_MATCH_TYPE: - if ( !sieve_opr_match_type_dump(denv, address) ) - return FALSE; - break; - default: - return TRUE; - } - } while ( *opt_code != SIEVE_MATCH_OPT_END ); + bool opok = TRUE; + + while ( opok ) { + int ret; + + if ( (ret=sieve_opr_optional_dump(denv, address, opt_code)) <= 0 ) + return ret; + + switch ( *opt_code ) { + case SIEVE_MATCH_OPT_COMPARATOR: + opok = sieve_opr_comparator_dump(denv, address); + break; + case SIEVE_MATCH_OPT_MATCH_TYPE: + opok = sieve_opr_match_type_dump(denv, address); + break; + default: + return 1; + } } - - return TRUE; + + return -1; } -int sieve_match_read_optional_operands +int sieve_match_opr_optional_read (const struct sieve_runtime_env *renv, sieve_size_t *address, int *opt_code, struct sieve_comparator *cmp, struct sieve_match_type *mcht) -{ - /* Handle any optional arguments */ - if ( *opt_code != SIEVE_MATCH_OPT_END || - sieve_operand_optional_present(renv->sblock, address) ) { - do { - if ( !sieve_operand_optional_read(renv->sblock, address, opt_code) ) { - sieve_runtime_trace_error(renv, "invalid optional operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } - - switch ( *opt_code ) { - case SIEVE_MATCH_OPT_END: - break; - case SIEVE_MATCH_OPT_COMPARATOR: - if ( !sieve_opr_comparator_read(renv, address, cmp) ) { - sieve_runtime_trace_error(renv, "invalid comparator operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } - break; - case SIEVE_MATCH_OPT_MATCH_TYPE: - if ( !sieve_opr_match_type_read(renv, address, mcht) ) { - sieve_runtime_trace_error(renv, "invalid match type operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } - break; - default: - return SIEVE_EXEC_OK; - } - } while ( *opt_code != SIEVE_MATCH_OPT_END ); +{ + bool opok = TRUE; + + while ( opok ) { + int ret; + + if ( (ret=sieve_opr_optional_read(renv, address, opt_code)) <= 0 ) + return ret; + + switch ( *opt_code ) { + case SIEVE_MATCH_OPT_COMPARATOR: + opok = sieve_opr_comparator_read(renv, address, cmp); + break; + case SIEVE_MATCH_OPT_MATCH_TYPE: + opok = sieve_opr_match_type_read(renv, address, mcht); + break; + default: + return 1; + } } - - return SIEVE_EXEC_OK; + + return -1; } diff --git a/src/lib-sieve/sieve-match.h b/src/lib-sieve/sieve-match.h index e76931804..89d13c6aa 100644 --- a/src/lib-sieve/sieve-match.h +++ b/src/lib-sieve/sieve-match.h @@ -53,10 +53,10 @@ enum sieve_match_opt_operand { SIEVE_MATCH_OPT_LAST }; -bool sieve_match_dump_optional_operands +int sieve_match_opr_optional_dump (const struct sieve_dumptime_env *denv, sieve_size_t *addres, int *opt_code); -int sieve_match_read_optional_operands +int sieve_match_opr_optional_read (const struct sieve_runtime_env *renv, sieve_size_t *address, int *opt_code, struct sieve_comparator *cmp, struct sieve_match_type *mcht); diff --git a/src/lib-sieve/sieve-runtime-trace.c b/src/lib-sieve/sieve-runtime-trace.c new file mode 100644 index 000000000..b570fa017 --- /dev/null +++ b/src/lib-sieve/sieve-runtime-trace.c @@ -0,0 +1,139 @@ +#include "lib.h" +#include "str.h" +#include "ostream.h" + +#include "sieve-common.h" +#include "sieve-script.h" +#include "sieve-binary.h" +#include "sieve-code.h" +#include "sieve-interpreter.h" +#include "sieve-runtime.h" +#include "sieve-runtime-trace.h" + +static inline string_t *_trace_line_new +(sieve_size_t address, unsigned int cmd_line) +{ + string_t *trline; + + trline = t_str_new(128); + str_printfa(trline, "%08llx: ", (unsigned long long) address); + if ( cmd_line > 0 ) + str_printfa(trline, "%4d: ", cmd_line); + else + str_append(trline, " "); + + return trline; +} + +static inline void _trace_line_print +(string_t *trline, const struct sieve_runtime_env *renv) +{ + str_append_c(trline, '\n'); + + o_stream_send(renv->trace_stream, str_data(trline), str_len(trline)); +} + +static inline void _trace_line_print_empty +(const struct sieve_runtime_env *renv) +{ + o_stream_send_str(renv->trace_stream, "\n"); +} + +/* + * Trace errors + */ + +void _sieve_runtime_trace_error +(const struct sieve_runtime_env *renv, const char *fmt, va_list args) +{ + string_t *trline = _trace_line_new(renv->pc, 0); + + str_printfa(trline, "%s: #ERROR#: ", sieve_operation_mnemonic(renv->oprtn)); + str_vprintfa(trline, fmt, args); + + _trace_line_print(trline, renv); +} + +void _sieve_runtime_trace_operand_error +(const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + const char *field_name, const char *fmt, va_list args) +{ + string_t *trline = _trace_line_new + (oprnd->address, sieve_runtime_get_source_location(renv, oprnd->address)); + + str_printfa(trline, "%s: #ERROR#: ", sieve_operation_mnemonic(renv->oprtn)); + + if ( field_name != NULL ) + str_printfa(trline, "%s: ", field_name); + + str_vprintfa(trline, fmt, args); + + _trace_line_print(trline, renv); +} + +/* + * Trace info + */ + +static inline void _sieve_runtime_trace_vprintf +(const struct sieve_runtime_env *renv, sieve_size_t address, + unsigned int cmd_line, const char *fmt, va_list args) +{ + string_t *trline = _trace_line_new(address, cmd_line); + + str_vprintfa(trline, fmt, args); + + _trace_line_print(trline, renv); +} + +static inline void _sieve_runtime_trace_printf +(const struct sieve_runtime_env *renv, sieve_size_t address, + unsigned int cmd_line, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + _sieve_runtime_trace_vprintf(renv, address, cmd_line, fmt, args); + va_end(args); +} + +void _sieve_runtime_trace +(const struct sieve_runtime_env *renv, const char *fmt, va_list args) +{ + _sieve_runtime_trace_vprintf + (renv, renv->oprtn->address, sieve_runtime_get_command_location(renv), + fmt, args); +} + +void _sieve_runtime_trace_address +(const struct sieve_runtime_env *renv, sieve_size_t address, + const char *fmt, va_list args) +{ + _sieve_runtime_trace_vprintf + (renv, address, sieve_runtime_get_source_location(renv, address), fmt, + args); +} + +/* + * Trace boundaries + */ + +void _sieve_runtime_trace_begin(const struct sieve_runtime_env *renv) +{ + const char *script_name = ( renv->script != NULL ? + sieve_script_name(renv->script) : sieve_binary_path(renv->sbin) ); + + _trace_line_print_empty(renv); + _sieve_runtime_trace_printf(renv, renv->pc, 0, + "## Started executing script '%s'", script_name); +} + +void _sieve_runtime_trace_end(const struct sieve_runtime_env *renv) +{ + const char *script_name = ( renv->script != NULL ? + sieve_script_name(renv->script) : sieve_binary_path(renv->sbin) ); + + _sieve_runtime_trace_printf(renv, renv->pc, 0, + "## Finished executing script '%s'", script_name); + _trace_line_print_empty(renv); +} diff --git a/src/lib-sieve/sieve-runtime-trace.h b/src/lib-sieve/sieve-runtime-trace.h new file mode 100644 index 000000000..6210b4fb2 --- /dev/null +++ b/src/lib-sieve/sieve-runtime-trace.h @@ -0,0 +1,132 @@ +#ifndef __SIEVE_TRACE_H +#define __SIEVE_TRACE_H + +#include "sieve-common.h" +#include "sieve-runtime.h" + +/* + * Runtime trace + */ + +/* Trace errors */ + +void _sieve_runtime_trace_error + (const struct sieve_runtime_env *renv, const char *fmt, va_list args); + +void _sieve_runtime_trace_operand_error + (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + const char *field_name, const char *fmt, va_list args); + +static inline void sieve_runtime_trace_error + (const struct sieve_runtime_env *renv, const char *fmt, ...) + ATTR_FORMAT(2, 3); + +static inline void sieve_runtime_trace_operand_error + (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + const char *field_name, const char *fmt, ...) ATTR_FORMAT(4, 5); + +static inline void sieve_runtime_trace_error + (const struct sieve_runtime_env *renv, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + if ( renv->trace_stream != NULL ) + _sieve_runtime_trace_error(renv, fmt, args); + va_end(args); +} + +static inline void sieve_runtime_trace_operand_error + (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + const char *field_name, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + if ( renv->trace_stream != NULL ) + _sieve_runtime_trace_operand_error(renv, oprnd, field_name, fmt, args); + va_end(args); +} + +/* Trace info */ + +void _sieve_runtime_trace + (const struct sieve_runtime_env *renv, const char *fmt, va_list args); + +static inline void sieve_runtime_trace + (const struct sieve_runtime_env *renv, sieve_trace_level_t trace_level, + const char *fmt, ...) ATTR_FORMAT(3, 4); + +static inline void sieve_runtime_trace +(const struct sieve_runtime_env *renv, sieve_trace_level_t trace_level, + const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + + if ( renv->trace_stream != NULL && trace_level <= renv->trace_level ) { + _sieve_runtime_trace(renv, fmt, args); + } + + va_end(args); +} + +void _sieve_runtime_trace_address + (const struct sieve_runtime_env *renv, sieve_size_t address, + const char *fmt, va_list args); + +static inline void sieve_runtime_trace_address + (const struct sieve_runtime_env *renv, sieve_trace_level_t trace_level, + sieve_size_t address, const char *fmt, ...) ATTR_FORMAT(4, 5); + +static inline void sieve_runtime_trace_address +(const struct sieve_runtime_env *renv, sieve_trace_level_t trace_level, + sieve_size_t address, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + + if ( renv->trace_stream != NULL && trace_level <= renv->trace_level ) { + _sieve_runtime_trace_address(renv, address, fmt, args); + } + + va_end(args); +} + +static inline void sieve_runtime_trace_here +(const struct sieve_runtime_env *renv, sieve_trace_level_t trace_level, + const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + + if ( renv->trace_stream != NULL && trace_level <= renv->trace_level ) { + _sieve_runtime_trace_address(renv, renv->pc, fmt, args); + } + + va_end(args); +} + +/* Trace boundaries */ + +void _sieve_runtime_trace_begin(const struct sieve_runtime_env *renv); +void _sieve_runtime_trace_end(const struct sieve_runtime_env *renv); + +static inline void sieve_runtime_trace_begin +(const struct sieve_runtime_env *renv) +{ + if ( renv->trace_stream != NULL ) + _sieve_runtime_trace_begin(renv); +} + +static inline void sieve_runtime_trace_end +(const struct sieve_runtime_env *renv) +{ + if ( renv->trace_stream != NULL ) + _sieve_runtime_trace_end(renv); +} + +#endif /* __SIEVE_TRACE_H */ diff --git a/src/lib-sieve/sieve-runtime.h b/src/lib-sieve/sieve-runtime.h new file mode 100644 index 000000000..ab304dd7b --- /dev/null +++ b/src/lib-sieve/sieve-runtime.h @@ -0,0 +1,43 @@ +/* Copyright (c) 2002-2010 Dovecot Sieve authors, see the included COPYING file + */ + +#ifndef __SIEVE_RUNTIME_H +#define __SIEVE_RUNTIME_H + +#include "sieve-common.h" + +/* + * Runtime environment + */ + +struct sieve_runtime_env { + /* Interpreter */ + struct sieve_instance *svinst; + struct sieve_interpreter *interp; + + /* Executing script */ + struct sieve_script *script; + const struct sieve_script_env *scriptenv; + struct sieve_exec_status *exec_status; + + /* Executing binary */ + struct sieve_binary *sbin; + struct sieve_binary_block *sblock; + + /* Current code */ + sieve_size_t pc; + const struct sieve_operation *oprtn; + + /* Tested message */ + const struct sieve_message_data *msgdata; + struct sieve_message_context *msgctx; + + /* Filter result */ + struct sieve_result *result; + + /* Runtime tracing */ + struct ostream *trace_stream; + sieve_trace_level_t trace_level; +}; + +#endif /* __SIEVE_RUNTIME_H */ diff --git a/src/lib-sieve/sieve-types.h b/src/lib-sieve/sieve-types.h index 6eb44d905..5dc3de9c5 100644 --- a/src/lib-sieve/sieve-types.h +++ b/src/lib-sieve/sieve-types.h @@ -48,6 +48,19 @@ struct sieve_message_data { const char *id; }; +/* + * Runtime trace level + */ + +typedef enum { + SIEVE_TRLVL_MINIMUM, + SIEVE_TRLVL_ACTIONS, + SIEVE_TRLVL_COMMANDS, + SIEVE_TRLVL_TESTS, + SIEVE_TRLVL_MATCH, + SIEVE_TRLVL_DEBUG +} sieve_trace_level_t; + /* * Script environment * @@ -91,8 +104,9 @@ struct sieve_script_env { /* Execution status record */ struct sieve_exec_status *exec_status; - /* Trace stream */ + /* Runtime trace*/ struct ostream *trace_stream; + sieve_trace_level_t trace_level; }; #define SIEVE_SCRIPT_DEFAULT_MAILBOX(senv) \ diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c index 2dc7198af..9328ab15a 100644 --- a/src/lib-sieve/sieve.c +++ b/src/lib-sieve/sieve.c @@ -237,7 +237,8 @@ static int sieve_run int ret = 0; /* Create the interpreter */ - if ( (interp=sieve_interpreter_create(sbin, ehandler)) == NULL ) + if ( (interp=sieve_interpreter_create(sbin, msgdata, senv, ehandler)) + == NULL ) return SIEVE_EXEC_BIN_CORRUPT; /* Reset execution status */ @@ -253,7 +254,7 @@ static int sieve_run } /* Run the interpreter */ - ret = sieve_interpreter_run(interp, msgdata, senv, *result); + ret = sieve_interpreter_run(interp, *result); /* Free the interpreter */ sieve_interpreter_free(&interp); diff --git a/src/lib-sieve/tst-address.c b/src/lib-sieve/tst-address.c index 44e52cb49..daede9ae0 100644 --- a/src/lib-sieve/tst-address.c +++ b/src/lib-sieve/tst-address.c @@ -208,7 +208,7 @@ static bool tst_address_operation_dump sieve_code_descend(denv); /* Handle any optional arguments */ - if ( !sieve_addrmatch_default_dump_optionals(denv, address) ) + if ( sieve_addrmatch_opr_optional_dump(denv, address, NULL) != 0 ) return FALSE; return @@ -238,23 +238,21 @@ static int tst_address_operation_execute int ret; /* Read optional operands */ - if ( (ret=sieve_addrmatch_default_get_optionals - (renv, address, &addrp, &mcht, &cmp)) <= 0 ) - return ret; + if ( (ret=sieve_addrmatch_opr_optional_read + (renv, address, NULL, &addrp, &mcht, &cmp)) < 0 ) + return SIEVE_EXEC_BIN_CORRUPT; /* Read header-list */ - if ( (hdr_list=sieve_opr_stringlist_read(renv, address)) == NULL ) { - sieve_runtime_trace_error(renv, "invalid header-list operand"); + if ( (hdr_list=sieve_opr_stringlist_read(renv, address, "header-list")) + == NULL ) return SIEVE_EXEC_BIN_CORRUPT; - } /* Read key-list */ - if ( (key_list=sieve_opr_stringlist_read(renv, address)) == NULL ) { - sieve_runtime_trace_error(renv, "invalid key-list operand"); + if ( (key_list=sieve_opr_stringlist_read(renv, address, "key-list")) + == NULL ) return SIEVE_EXEC_BIN_CORRUPT; - } - sieve_runtime_trace(renv, "ADDRESS test"); + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "address test"); /* Initialize match context */ mctx = sieve_match_begin(renv->interp, &mcht, &cmp, NULL, key_list); diff --git a/src/lib-sieve/tst-exists.c b/src/lib-sieve/tst-exists.c index e70b064a1..ee3851ac6 100644 --- a/src/lib-sieve/tst-exists.c +++ b/src/lib-sieve/tst-exists.c @@ -89,7 +89,7 @@ static bool tst_exists_generate static bool tst_exists_operation_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address) { - sieve_code_dumpf(denv, "EXISTS"); + sieve_code_dumpf(denv, "EXISTS"); sieve_code_descend(denv); return sieve_opr_stringlist_dump(denv, address, "header names"); @@ -107,13 +107,20 @@ static int tst_exists_operation_execute string_t *hdr_item; bool matched; + /* + * Read operands + */ + /* Read header-list */ - if ( (hdr_list=sieve_opr_stringlist_read(renv, address)) == NULL ) { - sieve_runtime_trace_error(renv, "invalid header-list operand"); + if ( (hdr_list=sieve_opr_stringlist_read(renv, address, "header-list")) + == NULL ) return SIEVE_EXEC_BIN_CORRUPT; - } - sieve_runtime_trace(renv, "EXISTS test"); + /* + * Perfrom test + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "exists test"); /* Iterate through all requested headers to match (must find all specified) */ hdr_item = NULL; diff --git a/src/lib-sieve/tst-header.c b/src/lib-sieve/tst-header.c index 872b3e5da..4e25b3d8b 100644 --- a/src/lib-sieve/tst-header.c +++ b/src/lib-sieve/tst-header.c @@ -135,11 +135,8 @@ static bool tst_header_operation_dump sieve_code_dumpf(denv, "HEADER"); sieve_code_descend(denv); - /* Handle any optional arguments */ - if ( !sieve_match_dump_optional_operands(denv, address, &opt_code) ) - return FALSE; - - if ( opt_code != SIEVE_MATCH_OPT_END ) + /* Optional operands */ + if ( sieve_match_opr_optional_dump(denv, address, &opt_code) != 0 ) return FALSE; return @@ -181,30 +178,36 @@ static int tst_header_operation_execute bool matched; int ret; + /* + * Read operands + */ + /* Handle match-type and comparator operands */ - if ( (ret=sieve_match_read_optional_operands - (renv, address, &opt_code, &cmp, &mcht)) <= 0 ) - return ret; - + if ( (ret=sieve_match_opr_optional_read + (renv, address, &opt_code, &cmp, &mcht)) < 0 ) + return SIEVE_EXEC_BIN_CORRUPT; + /* Check whether we neatly finished the list of optional operands*/ - if ( opt_code != SIEVE_MATCH_OPT_END) { + if ( ret > 0 ) { sieve_runtime_trace_error(renv, "invalid optional operand"); return SIEVE_EXEC_BIN_CORRUPT; } /* Read header-list */ - if ( (hdr_list=sieve_opr_stringlist_read(renv, address)) == NULL ) { - sieve_runtime_trace_error(renv, "invalid header-list operand"); + if ( (hdr_list=sieve_opr_stringlist_read(renv, address, "header-list")) + == NULL ) return SIEVE_EXEC_BIN_CORRUPT; - } /* Read key-list */ - if ( (key_list=sieve_opr_stringlist_read(renv, address)) == NULL ) { - sieve_runtime_trace_error(renv, "invalid key-list operand"); + if ( (key_list=sieve_opr_stringlist_read(renv, address, "key-list")) + == NULL ) return SIEVE_EXEC_BIN_CORRUPT; - } - sieve_runtime_trace(renv, "HEADER test"); + /* + * Perform test + */ + + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "header test"); /* Initialize match */ mctx = sieve_match_begin(renv->interp, &mcht, &cmp, NULL, key_list); diff --git a/src/lib-sieve/tst-size.c b/src/lib-sieve/tst-size.c index 437a224f1..d5fd31a56 100644 --- a/src/lib-sieve/tst-size.c +++ b/src/lib-sieve/tst-size.c @@ -218,8 +218,7 @@ bool tst_size_generate static bool tst_size_operation_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address) { - const struct sieve_operation *op = &denv->oprtn; - sieve_code_dumpf(denv, "%s", sieve_operation_mnemonic(op)); + sieve_code_dumpf(denv, "%s", sieve_operation_mnemonic(denv->oprtn)); sieve_code_descend(denv); return @@ -246,16 +245,19 @@ static inline bool tst_size_get static int tst_size_operation_execute (const struct sieve_runtime_env *renv, sieve_size_t *address) { - const struct sieve_operation *op = &renv->oprtn; sieve_number_t mail_size, limit; + /* + * Read operands + */ + /* Read size limit */ - if ( !sieve_opr_number_read(renv, address, &limit) ) { - sieve_runtime_trace_error(renv, "invalid limit operand"); + if ( !sieve_opr_number_read(renv, address, "limit", &limit) ) return SIEVE_EXEC_BIN_CORRUPT; - } - sieve_runtime_trace(renv, "%s test", sieve_operation_mnemonic(op)); + /* + * Perform test + */ /* Get the size of the message */ if ( !tst_size_get(renv, &mail_size) ) { @@ -265,10 +267,15 @@ static int tst_size_operation_execute } /* Perform the test */ - if ( sieve_operation_is(op, tst_size_over_operation) ) + if ( sieve_operation_is(renv->oprtn, tst_size_over_operation) ) { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "size :over test"); + sieve_interpreter_set_test_result(renv->interp, (mail_size > limit)); - else + } else { + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "size :under test"); + sieve_interpreter_set_test_result(renv->interp, (mail_size < limit)); + } return SIEVE_EXEC_OK; } diff --git a/src/sieve-tools/debug/cmd-debug-print.c b/src/sieve-tools/debug/cmd-debug-print.c index c6e3cfda5..2fb27867e 100644 --- a/src/sieve-tools/debug/cmd-debug-print.c +++ b/src/sieve-tools/debug/cmd-debug-print.c @@ -111,16 +111,14 @@ static int cmd_debug_print_operation_execute /* Read message */ - if ( sieve_opr_string_read(renv, address, &message) < 0 ) { - sieve_runtime_trace_error(renv, "invalid message operand"); + if ( sieve_opr_string_read(renv, address, "message", &message) < 0 ) return SIEVE_EXEC_BIN_CORRUPT; - } /* * Perform operation */ - sieve_runtime_trace(renv, "DEBUG_PRINT"); + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "DEBUG_PRINT"); /* FIXME: give this proper source location */ sieve_runtime_log(renv, "DEBUG", "%s", str_c(message)); diff --git a/src/sieve-tools/sieve-test.c b/src/sieve-tools/sieve-test.c index d8feb1877..c459b69ac 100644 --- a/src/sieve-tools/sieve-test.c +++ b/src/sieve-tools/sieve-test.c @@ -337,6 +337,7 @@ int main(int argc, char **argv) scriptenv.duplicate_mark = duplicate_mark; scriptenv.duplicate_check = duplicate_check; scriptenv.trace_stream = ( trace ? teststream : NULL ); + scriptenv.trace_level = SIEVE_TRLVL_TESTS; scriptenv.exec_status = &estatus; /* Run the test */ diff --git a/src/testsuite/cmd-test-binary.c b/src/testsuite/cmd-test-binary.c index c7361a505..6f9d48608 100644 --- a/src/testsuite/cmd-test-binary.c +++ b/src/testsuite/cmd-test-binary.c @@ -205,9 +205,7 @@ static bool cmd_test_binary_generate static bool cmd_test_binary_operation_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address) { - const struct sieve_operation *op = &denv->oprtn; - - sieve_code_dumpf(denv, "%s:", sieve_operation_mnemonic(op)); + sieve_code_dumpf(denv, "%s:", sieve_operation_mnemonic(denv->oprtn)); sieve_code_descend(denv); @@ -222,7 +220,7 @@ static bool cmd_test_binary_operation_dump static int cmd_test_binary_operation_execute (const struct sieve_runtime_env *renv, sieve_size_t *address) { - const struct sieve_operation *op = &renv->oprtn; + const struct sieve_operation *oprtn = renv->oprtn; string_t *binary_name = NULL; /* @@ -231,21 +229,19 @@ static int cmd_test_binary_operation_execute /* Binary Name */ - if ( !sieve_opr_string_read(renv, address, &binary_name) ) { - sieve_runtime_trace_error(renv, "invalid mailbox operand"); + if ( !sieve_opr_string_read(renv, address, "binary-name", &binary_name) ) return SIEVE_EXEC_BIN_CORRUPT; - } /* * Perform operation */ - - sieve_runtime_trace - (renv, "%s %s", sieve_operation_mnemonic(op), str_c(binary_name)); - if ( sieve_operation_is(op, test_binary_load_operation) ) { + if ( sieve_operation_is(oprtn, test_binary_load_operation) ) { struct sieve_binary *sbin = testsuite_binary_load(str_c(binary_name)); + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, + "binary :load %s", str_c(binary_name)); + if ( sbin != NULL ) { testsuite_script_set_binary(sbin); @@ -255,9 +251,12 @@ static int cmd_test_binary_operation_execute return SIEVE_EXEC_FAILURE; } - } else if ( sieve_operation_is(op, test_binary_save_operation) ) { + } else if ( sieve_operation_is(oprtn, test_binary_save_operation) ) { struct sieve_binary *sbin = testsuite_script_get_binary(); + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, + "binary :save %s", str_c(binary_name)); + if ( sbin != NULL ) testsuite_binary_save(sbin, str_c(binary_name)); else { diff --git a/src/testsuite/cmd-test-config.c b/src/testsuite/cmd-test-config.c index 194946936..23afc7c9d 100644 --- a/src/testsuite/cmd-test-config.c +++ b/src/testsuite/cmd-test-config.c @@ -324,25 +324,19 @@ static int cmd_test_config_set_operation_execute */ /* Setting */ - - if ( !sieve_opr_string_read(renv, address, &setting) ) { - sieve_runtime_trace_error(renv, "invalid setting operand"); + if ( !sieve_opr_string_read(renv, address, "setting", &setting) ) return SIEVE_EXEC_BIN_CORRUPT; - } /* Value */ - - if ( !sieve_opr_string_read(renv, address, &value) ) { - sieve_runtime_trace_error(renv, "invalid value operand"); + if ( !sieve_opr_string_read(renv, address, "value", &value) ) return SIEVE_EXEC_BIN_CORRUPT; - } /* * Perform operation */ - sieve_runtime_trace(renv, "TEST_CONFIG_SET %s = '%s'", - str_c(setting), str_c(value)); + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, + "TEST_CONFIG_SET %s = '%s'", str_c(setting), str_c(value)); testsuite_setting_set(str_c(setting), str_c(value)); @@ -358,16 +352,16 @@ static int cmd_test_config_unset_operation_execute * Read operands */ - if ( !sieve_opr_string_read(renv, address, &setting) ) { - sieve_runtime_trace_error(renv, "invalid setting operand"); + /* Setting */ + if ( !sieve_opr_string_read(renv, address, "setting", &setting) ) return SIEVE_EXEC_BIN_CORRUPT; - } /* * Perform operation */ - sieve_runtime_trace(renv, "TEST_CONFIG_UNSET %s", str_c(setting)); + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, + "TEST_CONFIG_UNSET %s", str_c(setting)); testsuite_setting_unset(str_c(setting)); @@ -385,17 +379,15 @@ static int cmd_test_config_reload_operation_execute */ /* Extension */ - - if ( !sieve_opr_string_read(renv, address, &extension) ) { - sieve_runtime_trace_error(renv, "invalid extension operand"); + if ( !sieve_opr_string_read(renv, address, "extension", &extension) ) return SIEVE_EXEC_BIN_CORRUPT; - } /* * Perform operation */ - sieve_runtime_trace(renv, "TEST_CONFIG_RELOAD [%s]", str_c(extension)); + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, + "TEST_CONFIG_RELOAD [%s]", str_c(extension)); ext = sieve_extension_get_by_name(renv->svinst, str_c(extension)); if ( ext == NULL ) { diff --git a/src/testsuite/cmd-test-fail.c b/src/testsuite/cmd-test-fail.c index ac43cdda3..e5921ed31 100644 --- a/src/testsuite/cmd-test-fail.c +++ b/src/testsuite/cmd-test-fail.c @@ -132,12 +132,11 @@ static int cmd_test_fail_operation_execute { string_t *reason; - if ( !sieve_opr_string_read(renv, address, &reason) ) { - sieve_runtime_trace_error(renv, "invalid reason operand"); + if ( !sieve_opr_string_read(renv, address, "reason", &reason) ) return SIEVE_EXEC_BIN_CORRUPT; - } - sieve_runtime_trace(renv, "TEST FAIL"); + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "TEST FAIL"); + testsuite_test_fail(reason); return sieve_interpreter_program_jump(renv->interp, TRUE); diff --git a/src/testsuite/cmd-test-mailbox.c b/src/testsuite/cmd-test-mailbox.c index e61cc44d6..53e97d4bf 100644 --- a/src/testsuite/cmd-test-mailbox.c +++ b/src/testsuite/cmd-test-mailbox.c @@ -206,9 +206,7 @@ static bool cmd_test_mailbox_generate static bool cmd_test_mailbox_operation_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address) { - const struct sieve_operation *op = &denv->oprtn; - - sieve_code_dumpf(denv, "%s:", sieve_operation_mnemonic(op)); + sieve_code_dumpf(denv, "%s:", sieve_operation_mnemonic(denv->oprtn)); sieve_code_descend(denv); @@ -223,7 +221,7 @@ static bool cmd_test_mailbox_operation_dump static int cmd_test_mailbox_operation_execute (const struct sieve_runtime_env *renv, sieve_size_t *address) { - const struct sieve_operation *op = &renv->oprtn; + const struct sieve_operation *oprtn = renv->oprtn; string_t *mailbox = NULL; /* @@ -232,19 +230,17 @@ static int cmd_test_mailbox_operation_execute /* Index */ - if ( !sieve_opr_string_read(renv, address, &mailbox) ) { - sieve_runtime_trace_error(renv, "invalid mailbox operand"); + if ( !sieve_opr_string_read(renv, address, "mailbox", &mailbox) ) return SIEVE_EXEC_BIN_CORRUPT; - } /* * Perform operation */ - sieve_runtime_trace - (renv, "%s %s:", sieve_operation_mnemonic(op), str_c(mailbox)); + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, + "%s %s:", sieve_operation_mnemonic(oprtn), str_c(mailbox)); - if ( sieve_operation_is(op, test_mailbox_create_operation) ) + if ( sieve_operation_is(oprtn, test_mailbox_create_operation) ) testsuite_mailstore_mailbox_create(renv, str_c(mailbox)); return SIEVE_EXEC_OK; diff --git a/src/testsuite/cmd-test-message.c b/src/testsuite/cmd-test-message.c index 8df89a0ba..afb99848d 100644 --- a/src/testsuite/cmd-test-message.c +++ b/src/testsuite/cmd-test-message.c @@ -315,17 +315,19 @@ static int cmd_test_message_smtp_operation_execute /* Index */ - if ( !sieve_opr_number_read(renv, address, &msg_index) ) { - sieve_runtime_trace_error(renv, "invalid index operand"); + if ( !sieve_opr_number_read(renv, address, "index", &msg_index) ) return SIEVE_EXEC_BIN_CORRUPT; - } /* * Perform operation */ - sieve_runtime_trace(renv, "TEST_MESSAGE_SMTP (%s) [%d]", - ( is_test ? "TEST" : "COMMAND" ), msg_index); + if ( is_test ) + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "TEST_MESSAGE_SMTP test [%d]", msg_index); + else + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, + "TEST_MESSAGE_SMTP command [%d]", msg_index); result = testsuite_smtp_get(renv, msg_index); @@ -359,23 +361,23 @@ static int cmd_test_message_mailbox_operation_execute } /* Folder */ - if ( !sieve_opr_string_read(renv, address, &folder) ) { - sieve_runtime_trace_error(renv, "invalid folder operand"); + if ( !sieve_opr_string_read(renv, address, "folder", &folder) ) return SIEVE_EXEC_BIN_CORRUPT; - } /* Index */ - if ( !sieve_opr_number_read(renv, address, &msg_index) ) { - sieve_runtime_trace_error(renv, "invalid index operand"); + if ( !sieve_opr_number_read(renv, address, "index", &msg_index) ) return SIEVE_EXEC_BIN_CORRUPT; - } /* * Perform operation */ - - sieve_runtime_trace(renv, "TEST_MESSAGE_MAILBOX (%s) \"%s\" [%d]", - ( is_test ? "TEST" : "COMMAND" ), str_c(folder), msg_index); + + if ( is_test ) + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "TEST_MESSAGE_MAILBOX test \"%s\" [%d]", str_c(folder), msg_index); + else + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, + "TEST_MESSAGE_MAILBOX command \"%s\" [%d]", str_c(folder), msg_index); result = testsuite_mailstore_mail_index(renv, str_c(folder), msg_index); diff --git a/src/testsuite/cmd-test-set.c b/src/testsuite/cmd-test-set.c index 590934c33..459e4e86f 100644 --- a/src/testsuite/cmd-test-set.c +++ b/src/testsuite/cmd-test-set.c @@ -135,12 +135,11 @@ static int cmd_test_set_operation_execute return SIEVE_EXEC_BIN_CORRUPT; } - if ( !sieve_opr_string_read(renv, address, &value) ) { - sieve_runtime_trace_error(renv, "invalid string operand"); + if ( !sieve_opr_string_read(renv, address, "string", &value) ) return SIEVE_EXEC_BIN_CORRUPT; - } - sieve_runtime_trace(renv, "TEST SET command (%s = \"%s\")", + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, + "test_set '%s' = \"%s\"", testsuite_object_member_name(&tobj, member_id), str_c(value)); if ( tobj.def == NULL || tobj.def->set_member == NULL ) { diff --git a/src/testsuite/cmd-test.c b/src/testsuite/cmd-test.c index b81382571..b60758979 100644 --- a/src/testsuite/cmd-test.c +++ b/src/testsuite/cmd-test.c @@ -152,12 +152,11 @@ static int cmd_test_operation_execute { string_t *test_name; - if ( !sieve_opr_string_read(renv, address, &test_name) ) { - sieve_runtime_trace_error(renv, "invalid test name operand"); + if ( !sieve_opr_string_read(renv, address, "test name", &test_name) ) return SIEVE_EXEC_BIN_CORRUPT; - } - sieve_runtime_trace(renv, "TEST \"%s\"", str_c(test_name)); + sieve_runtime_trace(renv, SIEVE_TRLVL_MINIMUM, + "** Test start: \"%s\"", str_c(test_name)); testsuite_test_start(test_name); return SIEVE_EXEC_OK; @@ -167,7 +166,7 @@ static int cmd_test_finish_operation_execute (const struct sieve_runtime_env *renv ATTR_UNUSED, sieve_size_t *address ATTR_UNUSED) { - sieve_runtime_trace(renv, "TEST FINISHED"); + sieve_runtime_trace(renv, SIEVE_TRLVL_MINIMUM, "** Test end"); testsuite_test_succeed(NULL); return SIEVE_EXEC_OK; diff --git a/src/testsuite/testsuite-script.c b/src/testsuite/testsuite-script.c index 91bc7e9dd..f939ce4be 100644 --- a/src/testsuite/testsuite-script.c +++ b/src/testsuite/testsuite-script.c @@ -105,18 +105,18 @@ bool testsuite_script_run(const struct sieve_runtime_env *renv) scriptenv.duplicate_check = NULL; scriptenv.namespaces = renv->scriptenv->namespaces; scriptenv.trace_stream = renv->scriptenv->trace_stream; + scriptenv.trace_level = renv->scriptenv->trace_level; result = testsuite_result_get(); /* Execute the script */ - interp=sieve_interpreter_create - (_testsuite_compiled_script, testsuite_log_ehandler); + interp=sieve_interpreter_create(_testsuite_compiled_script, renv->msgdata, + &scriptenv, testsuite_log_ehandler); if ( interp == NULL ) return SIEVE_EXEC_BIN_CORRUPT; - ret = sieve_interpreter_run - (interp, renv->msgdata, &scriptenv, result); + ret = sieve_interpreter_run(interp, result); sieve_interpreter_free(&interp); diff --git a/src/testsuite/testsuite.c b/src/testsuite/testsuite.c index 4739cc07f..4964965a9 100644 --- a/src/testsuite/testsuite.c +++ b/src/testsuite/testsuite.c @@ -77,17 +77,13 @@ static int testsuite_run int ret = 0; /* Create the interpreter */ - if ( (interp=sieve_interpreter_create(sbin, ehandler)) == NULL ) + if ( (interp=sieve_interpreter_create(sbin, msgdata, senv, ehandler)) == NULL ) return SIEVE_EXEC_BIN_CORRUPT; - /* Reset execution status */ - if ( senv->exec_status != NULL ) - memset(senv->exec_status, 0, sizeof(*senv->exec_status)); - /* Run the interpreter */ result = testsuite_result_get(); sieve_result_ref(result); - ret = sieve_interpreter_run(interp, msgdata, senv, result); + ret = sieve_interpreter_run(interp, result); sieve_result_unref(&result); /* Free the interpreter */ @@ -253,6 +249,7 @@ int main(int argc, char **argv) scriptenv.smtp_open = testsuite_smtp_open; scriptenv.smtp_close = testsuite_smtp_close; scriptenv.trace_stream = ( trace ? o_stream_create_fd(1, 0, FALSE) : NULL ); + scriptenv.trace_level = SIEVE_TRLVL_TESTS; testsuite_scriptenv = &scriptenv; diff --git a/src/testsuite/tst-test-error.c b/src/testsuite/tst-test-error.c index cb3b9ae24..9dcbac7fc 100644 --- a/src/testsuite/tst-test-error.c +++ b/src/testsuite/tst-test-error.c @@ -182,21 +182,22 @@ static bool tst_test_error_operation_dump sieve_code_descend(denv); /* Handle any optional arguments */ - do { - if ( !sieve_match_dump_optional_operands(denv, address, &opt_code) ) + for (;;) { + int ret; + + if ( (ret=sieve_match_opr_optional_dump(denv, address, &opt_code)) + < 0 ) return FALSE; - switch ( opt_code ) { - case SIEVE_MATCH_OPT_END: - break; - case OPT_INDEX: + if ( ret == 0 ) break; + + if ( opt_code == OPT_INDEX ) { if ( !sieve_opr_number_dump(denv, address, "index") ) return FALSE; - break; - default: + } else { return FALSE; } - } while ( opt_code != SIEVE_MATCH_OPT_END ); + } return sieve_opr_stringlist_dump(denv, address, "key list"); } @@ -223,41 +224,37 @@ static int tst_test_error_operation_execute * Read operands */ - /* Handle optional operands */ - do { + /* Read optional operands */ + for (;;) { sieve_number_t number; + int ret; - if ( (ret=sieve_match_read_optional_operands - (renv, address, &opt_code, &cmp, &mcht)) <= 0 ) - return ret; + if ( (ret=sieve_match_opr_optional_read + (renv, address, &opt_code, &cmp, &mcht)) < 0 ) + return SIEVE_EXEC_BIN_CORRUPT; - switch ( opt_code ) { - case SIEVE_MATCH_OPT_END: - break; - case OPT_INDEX: - if ( !sieve_opr_number_read(renv, address, &number) ) { - sieve_runtime_trace_error(renv, "invalid index operand"); + if ( ret == 0 ) break; + + if ( opt_code == OPT_INDEX ) { + if ( !sieve_opr_number_read(renv, address, "index", &number) ) return SIEVE_EXEC_BIN_CORRUPT; - } index = (int) number; - break; - default: + } else { sieve_runtime_trace_error(renv, "invalid optional operand"); return SIEVE_EXEC_BIN_CORRUPT; } - } while ( opt_code != SIEVE_MATCH_OPT_END); + } /* Read key-list */ - if ( (key_list=sieve_opr_stringlist_read(renv, address)) == NULL ) { - sieve_runtime_trace_error(renv, "invalid key-list operand"); + if ( (key_list=sieve_opr_stringlist_read(renv, address, "key_list")) == NULL ) return SIEVE_EXEC_BIN_CORRUPT; - } /* * Perform operation */ - sieve_runtime_trace(renv, "TEST_ERROR test (index: %d)", index); + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "TEST_ERROR test (index: %d)", index); testsuite_log_get_error_init(); diff --git a/src/testsuite/tst-test-multiscript.c b/src/testsuite/tst-test-multiscript.c index 7dba89b68..5ab3a6fac 100644 --- a/src/testsuite/tst-test-multiscript.c +++ b/src/testsuite/tst-test-multiscript.c @@ -117,16 +117,15 @@ static int tst_test_multiscript_operation_execute * Read operands */ - if ( (scripts_list=sieve_opr_stringlist_read(renv, address)) == NULL ) { - sieve_runtime_trace_error(renv, "invalid scripts operand"); + if ( (scripts_list=sieve_opr_stringlist_read(renv, address, "scripts")) + == NULL ) return SIEVE_EXEC_BIN_CORRUPT; - } /* * Perform operation */ - sieve_runtime_trace(renv, "TEST MULTISCRIPT"); + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "TEST MULTISCRIPT"); t_array_init(&scriptfiles, 16); diff --git a/src/testsuite/tst-test-result-execute.c b/src/testsuite/tst-test-result-execute.c index b7bfe28fe..285e789c7 100644 --- a/src/testsuite/tst-test-result-execute.c +++ b/src/testsuite/tst-test-result-execute.c @@ -74,7 +74,7 @@ static int tst_test_result_execute_operation_execute * Perform operation */ - sieve_runtime_trace(renv, "TEST_RESULT_EXECUTE test"); + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "TEST_RESULT_EXECUTE test"); result = testsuite_result_execute(renv); diff --git a/src/testsuite/tst-test-result.c b/src/testsuite/tst-test-result.c index 1c0e5a21a..d6cccc071 100644 --- a/src/testsuite/tst-test-result.c +++ b/src/testsuite/tst-test-result.c @@ -187,21 +187,22 @@ static bool tst_test_result_operation_dump sieve_code_descend(denv); /* Handle any optional arguments */ - do { - if ( !sieve_match_dump_optional_operands(denv, address, &opt_code) ) + for (;;) { + int ret; + + if ( (ret=sieve_match_opr_optional_dump(denv, address, &opt_code)) + < 0 ) return FALSE; - switch ( opt_code ) { - case SIEVE_MATCH_OPT_END: - break; - case OPT_INDEX: + if ( ret == 0 ) break; + + if ( opt_code == OPT_INDEX ) { if ( !sieve_opr_number_dump(denv, address, "index") ) return FALSE; - break; - default: + } else { return FALSE; } - } while ( opt_code != SIEVE_MATCH_OPT_END ); + } return sieve_opr_stringlist_dump(denv, address, "key list"); } @@ -230,41 +231,37 @@ static int tst_test_result_operation_execute * Read operands */ - /* Handle optional operands */ - do { + /* Read optional operands */ + for (;;) { sieve_number_t number; + int ret; - if ( (ret=sieve_match_read_optional_operands - (renv, address, &opt_code, &cmp, &mcht)) <= 0 ) - return ret; + if ( (ret=sieve_match_opr_optional_read + (renv, address, &opt_code, &cmp, &mcht)) < 0 ) + return SIEVE_EXEC_BIN_CORRUPT; - switch ( opt_code ) { - case SIEVE_MATCH_OPT_END: - break; - case OPT_INDEX: - if ( !sieve_opr_number_read(renv, address, &number) ) { - sieve_runtime_trace_error(renv, "invalid index operand"); + if ( ret == 0 ) break; + + if ( opt_code == OPT_INDEX ) { + if ( !sieve_opr_number_read(renv, address, "index", &number) ) return SIEVE_EXEC_BIN_CORRUPT; - } index = (int) number; - break; - default: + } else { sieve_runtime_trace_error(renv, "invalid optional operand"); return SIEVE_EXEC_BIN_CORRUPT; } - } while ( opt_code != SIEVE_MATCH_OPT_END); + } /* Read key-list */ - if ( (key_list=sieve_opr_stringlist_read(renv, address)) == NULL ) { - sieve_runtime_trace_error(renv, "invalid key-list operand"); + if ( (key_list=sieve_opr_stringlist_read(renv, address, "key-list")) == NULL ) return SIEVE_EXEC_BIN_CORRUPT; - } /* * Perform operation */ - sieve_runtime_trace(renv, "TEST_RESULT test (index: %d)", index); + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "TEST_RESULT test (index: %d)", index); rictx = testsuite_result_iterate_init(); diff --git a/src/testsuite/tst-test-script-compile.c b/src/testsuite/tst-test-script-compile.c index ad1705289..c76699e9d 100644 --- a/src/testsuite/tst-test-script-compile.c +++ b/src/testsuite/tst-test-script-compile.c @@ -94,7 +94,7 @@ static bool tst_test_script_compile_operation_dump sieve_code_dumpf(denv, "TEST_SCRIPT_COMPILE:"); sieve_code_descend(denv); - if ( !sieve_opr_string_dump(denv, address, "script") ) + if ( !sieve_opr_string_dump(denv, address, "script-name") ) return FALSE; return TRUE; @@ -115,16 +115,15 @@ static int tst_test_script_compile_operation_execute * Read operands */ - if ( !sieve_opr_string_read(renv, address, &script_name) ) { - sieve_runtime_trace_error(renv, "invalid script name operand"); + if ( !sieve_opr_string_read(renv, address, "script-name", &script_name) ) return SIEVE_EXEC_BIN_CORRUPT; - } /* * Perform operation */ - sieve_runtime_trace(renv, "TEST COMPILE: %s", str_c(script_name)); + sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, + "testsuite: compile script '%s'", str_c(script_name)); script_path = sieve_script_dirpath(renv->script); if ( script_path == NULL ) diff --git a/src/testsuite/tst-test-script-run.c b/src/testsuite/tst-test-script-run.c index 8c2bf0e2c..262da7ed9 100644 --- a/src/testsuite/tst-test-script-run.c +++ b/src/testsuite/tst-test-script-run.c @@ -104,29 +104,26 @@ static bool tst_test_script_run_generate static bool tst_test_script_run_operation_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address) { - int opt_code = 1; + int opt_code = 0; sieve_code_dumpf(denv, "TEST_SCRIPT_RUN"); sieve_code_descend(denv); /* Dump optional operands */ - if ( sieve_operand_optional_present(denv->sblock, address) ) { - while ( opt_code != 0 ) { - sieve_code_mark(denv); - - if ( !sieve_operand_optional_read(denv->sblock, address, &opt_code) ) - return FALSE; - - switch ( opt_code ) { - case 0: - break; - case OPT_APPEND_RESULT: - sieve_code_dumpf(denv, "append_result"); - break; - - default: - return FALSE; - } + for (;;) { + int ret; + + if ( (ret=sieve_opr_optional_dump(denv, address, &opt_code)) < 0 ) + return FALSE; + + if ( ret == 0 ) break; + + switch ( opt_code ) { + case OPT_APPEND_RESULT: + sieve_code_dumpf(denv, "append_result"); + break; + default: + return FALSE; } } @@ -142,7 +139,7 @@ static int tst_test_script_run_operation_execute (const struct sieve_runtime_env *renv, sieve_size_t *address) { bool append_result = FALSE; - int opt_code = 1; + int opt_code = 0; bool result = TRUE; /* @@ -150,24 +147,22 @@ static int tst_test_script_run_operation_execute */ /* Optional operands */ - if ( sieve_operand_optional_present(renv->sblock, address) ) { - while ( opt_code != 0 ) { - if ( !sieve_operand_optional_read(renv->sblock, address, &opt_code) ) { - sieve_runtime_trace_error(renv, "invalid optional operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } - - switch ( opt_code ) { - case 0: - break; - case OPT_APPEND_RESULT: - append_result = TRUE; - break; - default: - sieve_runtime_trace_error(renv, - "unknown optional operand"); - return SIEVE_EXEC_BIN_CORRUPT; - } + for (;;) { + int ret; + + if ( (ret=sieve_opr_optional_read(renv, address, &opt_code)) < 0 ) + return SIEVE_EXEC_BIN_CORRUPT; + + if ( ret == 0 ) break; + + switch ( opt_code ) { + case OPT_APPEND_RESULT: + append_result = TRUE; + break; + default: + sieve_runtime_trace_error(renv, + "unknown optional operand"); + return SIEVE_EXEC_BIN_CORRUPT; } } @@ -175,6 +170,9 @@ static int tst_test_script_run_operation_execute * Perform operation */ + sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, + "testsuite: run compiled script"); + /* Reset result object */ if ( !append_result ) testsuite_result_reset(renv); -- GitLab