From 8f90c58ce38ca85ff54c71c5cc8da9d6078ca96e Mon Sep 17 00:00:00 2001 From: Stephan Bosch <stephan@rename-it.nl> Date: Sat, 14 Aug 2010 00:06:22 +0200 Subject: [PATCH] Improved runtime error handing. - Changed operand read functions to prove exec status return codes in stead of boolean. - Restructured optional-operand, stringlist and string-match APIs to provide execution status (error code) upon failure. - Corruption errors are only produced when the binary is actually corrupt. Normal failures should never cause a recompile attempt anymore. - Simplified optional-operand API. - Cleaned up test command implementations that use the string-match API. --- TODO | 1 - src/lib-sieve/cmd-discard.c | 7 +- src/lib-sieve/cmd-keep.c | 9 +- src/lib-sieve/cmd-redirect.c | 17 +- src/lib-sieve/ext-envelope.c | 35 +- src/lib-sieve/ext-fileinto.c | 15 +- src/lib-sieve/ext-reject.c | 15 +- src/lib-sieve/plugins/body/tst-body.c | 58 ++- src/lib-sieve/plugins/date/ext-date-common.c | 1 + src/lib-sieve/plugins/date/tst-date.c | 68 ++-- src/lib-sieve/plugins/enotify/cmd-notify.c | 44 +-- .../enotify/tst-notify-method-capability.c | 54 ++- .../plugins/enotify/tst-valid-notify-method.c | 6 +- .../plugins/environment/tst-environment.c | 47 +-- src/lib-sieve/plugins/imap4flags/cmd-flag.c | 51 ++- .../imap4flags/ext-imap4flags-common.c | 2 + src/lib-sieve/plugins/imap4flags/tag-flags.c | 38 +- .../plugins/imap4flags/tst-hasflag.c | 50 ++- .../plugins/mailbox/tst-mailboxexists.c | 7 +- src/lib-sieve/plugins/notify/cmd-denotify.c | 55 ++- src/lib-sieve/plugins/notify/cmd-notify.c | 30 +- src/lib-sieve/plugins/regex/mcht-regex.c | 29 +- src/lib-sieve/plugins/relational/mcht-count.c | 19 +- .../plugins/spamvirustest/tst-spamvirustest.c | 34 +- src/lib-sieve/plugins/vacation/cmd-vacation.c | 41 ++- src/lib-sieve/plugins/variables/cmd-set.c | 16 +- .../variables/ext-variables-namespaces.c | 63 ++-- .../variables/ext-variables-operands.c | 167 +++++---- .../plugins/variables/sieve-ext-variables.h | 24 +- src/lib-sieve/plugins/variables/tst-string.c | 43 +-- src/lib-sieve/sieve-actions.c | 35 +- src/lib-sieve/sieve-actions.h | 5 +- src/lib-sieve/sieve-address-parts.c | 35 +- src/lib-sieve/sieve-address-parts.h | 22 +- src/lib-sieve/sieve-address.c | 1 + src/lib-sieve/sieve-code.c | 339 ++++++++++-------- src/lib-sieve/sieve-code.h | 72 ++-- src/lib-sieve/sieve-comparators.h | 19 +- src/lib-sieve/sieve-match-types.h | 20 +- src/lib-sieve/sieve-match.c | 114 ++++-- src/lib-sieve/sieve-match.h | 12 +- src/lib-sieve/sieve-message.c | 1 + src/lib-sieve/sieve-objects.c | 4 +- src/lib-sieve/sieve-runtime-trace.c | 6 +- src/lib-sieve/sieve-runtime-trace.h | 8 +- src/lib-sieve/sieve-stringlist.c | 5 +- src/lib-sieve/sieve-stringlist.h | 6 +- src/lib-sieve/tst-address.c | 34 +- src/lib-sieve/tst-exists.c | 8 +- src/lib-sieve/tst-header.c | 45 +-- src/lib-sieve/tst-size.c | 5 +- src/managesieve/cmd-putscript.c | 2 +- src/sieve-tools/debug/cmd-debug-print.c | 8 +- src/testsuite/cmd-test-binary.c | 6 +- src/testsuite/cmd-test-config.c | 20 +- src/testsuite/cmd-test-fail.c | 5 +- src/testsuite/cmd-test-mailbox.c | 5 +- src/testsuite/cmd-test-message.c | 14 +- src/testsuite/cmd-test-set.c | 5 +- src/testsuite/cmd-test.c | 6 +- src/testsuite/testsuite-log.c | 1 + src/testsuite/testsuite-objects.c | 6 +- src/testsuite/testsuite-result.c | 1 + src/testsuite/testsuite-substitutions.c | 42 ++- src/testsuite/tst-test-error.c | 39 +- src/testsuite/tst-test-multiscript.c | 6 +- src/testsuite/tst-test-result.c | 39 +- src/testsuite/tst-test-script-compile.c | 6 +- src/testsuite/tst-test-script-run.c | 12 +- 69 files changed, 1087 insertions(+), 978 deletions(-) diff --git a/TODO b/TODO index f4c28665a..da882720d 100644 --- a/TODO +++ b/TODO @@ -1,7 +1,6 @@ Current activities: * Improve error handling and logging - - Improve runtime error handling - Avoid reporting user-caused errors to the master log. - Review logging and error handling; add more warning/info/debug messages where useful. diff --git a/src/lib-sieve/cmd-discard.c b/src/lib-sieve/cmd-discard.c index 089cbc59f..0fcece096 100644 --- a/src/lib-sieve/cmd-discard.c +++ b/src/lib-sieve/cmd-discard.c @@ -113,8 +113,11 @@ static int cmd_discard_operation_execute sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, "discard action; cancel implicit keep"); - return ( sieve_result_add_action - (renv, NULL, &act_discard, NULL, source_line, NULL, 0) >= 0 ); + if ( sieve_result_add_action + (renv, NULL, &act_discard, NULL, source_line, NULL, 0) < 0 ) + return SIEVE_EXEC_FAILURE; + + return SIEVE_EXEC_OK; } /* diff --git a/src/lib-sieve/cmd-keep.c b/src/lib-sieve/cmd-keep.c index 27f3782c9..7f5614930 100644 --- a/src/lib-sieve/cmd-keep.c +++ b/src/lib-sieve/cmd-keep.c @@ -95,8 +95,8 @@ static int cmd_keep_operation_execute 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; + if ( sieve_action_opr_optional_read(renv, address, NULL, &ret, &slist) != 0 ) + return ret; /* * Perform operation @@ -107,9 +107,10 @@ static int cmd_keep_operation_execute /* Add keep action to result. */ - ret = sieve_result_add_keep(renv, slist, source_line); + if ( sieve_result_add_keep(renv, slist, source_line) < 0 ) + return SIEVE_EXEC_FAILURE; - return ( ret >= 0 ); + return SIEVE_EXEC_OK; } diff --git a/src/lib-sieve/cmd-redirect.c b/src/lib-sieve/cmd-redirect.c index 4d439b4a1..dcf991647 100644 --- a/src/lib-sieve/cmd-redirect.c +++ b/src/lib-sieve/cmd-redirect.c @@ -195,7 +195,7 @@ static int cmd_redirect_operation_execute string_t *redirect; unsigned int source_line; pool_t pool; - int ret = 0; + int ret; /* * Read data @@ -205,12 +205,12 @@ static int cmd_redirect_operation_execute 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; + if ( sieve_action_opr_optional_read(renv, address, NULL, &ret, &slist) != 0 ) + return ret; /* Read the address */ - if ( !sieve_opr_string_read(renv, address, "address", &redirect) ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_string_read(renv, address, "address", &redirect)) <= 0 ) + return ret; /* * Perform operation @@ -232,11 +232,12 @@ static int cmd_redirect_operation_execute act = p_new(pool, struct act_redirect_context, 1); act->to_address = p_strdup(pool, str_c(redirect)); - ret = sieve_result_add_action + if ( sieve_result_add_action (renv, NULL, &act_redirect, slist, source_line, (void *) act, - svinst->max_redirects); + svinst->max_redirects) < 0 ) + return SIEVE_EXEC_FAILURE; - return ( ret >= 0 ); + return SIEVE_EXEC_OK; } /* diff --git a/src/lib-sieve/ext-envelope.c b/src/lib-sieve/ext-envelope.c index f50698ba5..2de499620 100644 --- a/src/lib-sieve/ext-envelope.c +++ b/src/lib-sieve/ext-envelope.c @@ -299,6 +299,7 @@ static struct sieve_address_list *sieve_envelope_address_list_create addrlist = t_new(struct sieve_envelope_address_list, 1); addrlist->addrlist.strlist.runenv = renv; + addrlist->addrlist.strlist.exec_status = SIEVE_EXEC_OK; addrlist->addrlist.strlist.next_item = sieve_envelope_address_list_next_string_item; addrlist->addrlist.strlist.reset = sieve_envelope_address_list_reset; @@ -582,26 +583,26 @@ static int ext_envelope_operation_execute SIEVE_ADDRESS_PART_DEFAULT(all_address_part); struct sieve_stringlist *env_part_list, *value_list, *key_list; struct sieve_address_list *addr_list; - int ret; + int match, ret; /* * Read operands */ /* Read optional operands */ - if ( (ret=sieve_addrmatch_opr_optional_read - (renv, address, NULL, &addrp, &mcht, &cmp)) < 0 ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( sieve_addrmatch_opr_optional_read + (renv, address, NULL, &ret, &addrp, &mcht, &cmp) < 0 ) + return ret; /* Read envelope-part */ - if ( (env_part_list=sieve_opr_stringlist_read(renv, address, "envelope-part")) - == NULL ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_stringlist_read + (renv, address, "envelope-part", &env_part_list)) <= 0 ) + return ret; /* Read key-list */ - if ( (key_list=sieve_opr_stringlist_read(renv, address, "key-list")) - == NULL ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_stringlist_read(renv, address, "key-list", &key_list)) + <= 0 ) + return ret; /* * Perform test @@ -614,15 +615,11 @@ static int ext_envelope_operation_execute value_list = sieve_address_part_stringlist_create(renv, &addrp, addr_list); /* Perform match */ - ret = sieve_match(renv, &mcht, &cmp, value_list, key_list); - - /* Set test result for subsequent conditional jump */ - if ( ret >= 0 ) { - sieve_interpreter_set_test_result(renv->interp, ret > 0); - return SIEVE_EXEC_OK; - } + if ( (match=sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret)) < 0 ) + return ret; - sieve_runtime_trace_error(renv, "invalid string-list item"); - return SIEVE_EXEC_BIN_CORRUPT; + /* Set test result for subsequent conditional jump */ + sieve_interpreter_set_test_result(renv->interp, match > 0); + return SIEVE_EXEC_OK; } diff --git a/src/lib-sieve/ext-fileinto.c b/src/lib-sieve/ext-fileinto.c index da5607a7c..80b4b8b9e 100644 --- a/src/lib-sieve/ext-fileinto.c +++ b/src/lib-sieve/ext-fileinto.c @@ -166,12 +166,12 @@ static int ext_fileinto_operation_execute 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; + if ( sieve_action_opr_optional_read(renv, address, NULL, &ret, &slist) != 0 ) + return ret; /* Folder operand */ - if ( !sieve_opr_string_read(renv, address, "folder", &folder) ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_string_read(renv, address, "folder", &folder)) <= 0 ) + return ret; /* * Perform operation @@ -187,10 +187,11 @@ static int ext_fileinto_operation_execute } /* Add action to result */ - ret = sieve_act_store_add_to_result - (renv, slist, str_c(folder), source_line); + if ( sieve_act_store_add_to_result + (renv, slist, str_c(folder), source_line) < 0 ) + return SIEVE_EXEC_FAILURE; - return ( ret >= 0 ); + return SIEVE_EXEC_OK; } diff --git a/src/lib-sieve/ext-reject.c b/src/lib-sieve/ext-reject.c index 5ca7ed783..8663da25c 100644 --- a/src/lib-sieve/ext-reject.c +++ b/src/lib-sieve/ext-reject.c @@ -279,12 +279,12 @@ static int ext_reject_operation_execute 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; + if ( sieve_action_opr_optional_read(renv, address, NULL, &ret, &slist) != 0 ) + return ret; /* Read rejection reason */ - if ( !sieve_opr_string_read(renv, address, "reason", &reason) ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_string_read(renv, address, "reason", &reason)) <= 0 ) + return ret; /* * Perform operation @@ -307,10 +307,11 @@ static int ext_reject_operation_execute act->reason = p_strdup(pool, str_c(reason)); act->ereject = ( sieve_operation_is(oprtn, ereject_operation) ); - ret = sieve_result_add_action - (renv, this_ext, &act_reject, slist, source_line, (void *) act, 0); + if ( sieve_result_add_action + (renv, this_ext, &act_reject, slist, source_line, (void *) act, 0) < 0 ) + return SIEVE_EXEC_FAILURE; - return ( ret >= 0 ); + return SIEVE_EXEC_OK; } /* diff --git a/src/lib-sieve/plugins/body/tst-body.c b/src/lib-sieve/plugins/body/tst-body.c index f3033bc87..36b4a6cf8 100644 --- a/src/lib-sieve/plugins/body/tst-body.c +++ b/src/lib-sieve/plugins/body/tst-body.c @@ -255,13 +255,13 @@ static bool ext_body_operation_dump /* Handle any optional arguments */ for (;;) { - int ret; + int opt; - if ( (ret=sieve_match_opr_optional_dump(denv, address, &opt_code)) + if ( (opt=sieve_match_opr_optional_dump(denv, address, &opt_code)) < 0 ) return FALSE; - if ( ret == 0 ) break; + if ( opt == 0 ) break; switch ( opt_code ) { case OPT_BODY_TRANSFORM: @@ -302,7 +302,6 @@ static bool ext_body_operation_dump static int ext_body_operation_execute (const struct sieve_runtime_env *renv, sieve_size_t *address) { - int ret; int opt_code = 0; struct sieve_comparator cmp = SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); @@ -312,6 +311,7 @@ static int ext_body_operation_execute struct sieve_stringlist *ctype_list, *value_list, *key_list; bool mvalues_active; const char * const *content_types = NULL; + int match, ret; /* * Read operands @@ -321,46 +321,44 @@ static int ext_body_operation_execute ctype_list = NULL; for (;;) { - bool opok = TRUE; + int opt; - if ( (ret=sieve_match_opr_optional_read - (renv, address, &opt_code, &cmp, &mcht)) < 0 ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (opt=sieve_match_opr_optional_read + (renv, address, &opt_code, &ret, &cmp, &mcht)) < 0 ) + return ret; - if ( ret == 0 ) break; + if ( opt == 0 ) break; switch ( opt_code ) { 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"); - opok = FALSE; + 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 ); - } + if ( transform == TST_BODY_TRANSFORM_CONTENT && + (ret=sieve_opr_stringlist_read + (renv, address, "content-type-list", &ctype_list)) <= 0 ) + return ret; break; default: sieve_runtime_trace_error(renv, "unknown optional operand"); - opok = FALSE; + return SIEVE_EXEC_BIN_CORRUPT; } - - if ( !opok) return SIEVE_EXEC_BIN_CORRUPT; } /* Read key-list */ - if ( (key_list=sieve_opr_stringlist_read(renv, address, "key-list")) == NULL ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_stringlist_read(renv, address, "key-list", &key_list)) + <= 0 ) + return ret; - if ( ctype_list != NULL && !sieve_stringlist_read_all - (ctype_list, pool_datastack_create(), &content_types) ) { + if ( ctype_list != NULL && sieve_stringlist_read_all + (ctype_list, pool_datastack_create(), &content_types) < 0 ) { sieve_runtime_trace_error(renv, "failed to read content-type-list operand"); - return SIEVE_EXEC_BIN_CORRUPT; + return ctype_list->exec_status; } /* @@ -378,17 +376,15 @@ static int ext_body_operation_execute mvalues_active = sieve_match_values_set_enabled(renv, FALSE); /* Perform match */ - ret = sieve_match(renv, &mcht, &cmp, value_list, key_list); + match = sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret); /* Restore match values processing */ (void)sieve_match_values_set_enabled(renv, mvalues_active); - /* Set test result for subsequent conditional jump */ - if ( ret >= 0 ) { - sieve_interpreter_set_test_result(renv->interp, ret > 0); - return SIEVE_EXEC_OK; - } + if ( match < 0 ) + return ret; - sieve_runtime_trace_error(renv, "invalid string-list item"); - return SIEVE_EXEC_BIN_CORRUPT; + /* Set test result for subsequent conditional jump */ + sieve_interpreter_set_test_result(renv->interp, match > 0); + return SIEVE_EXEC_OK; } diff --git a/src/lib-sieve/plugins/date/ext-date-common.c b/src/lib-sieve/plugins/date/ext-date-common.c index 7891b17e5..ce6911250 100644 --- a/src/lib-sieve/plugins/date/ext-date-common.c +++ b/src/lib-sieve/plugins/date/ext-date-common.c @@ -502,6 +502,7 @@ struct sieve_stringlist *ext_date_stringlist_create strlist = t_new(struct ext_date_stringlist, 1); strlist->strlist.runenv = renv; + strlist->strlist.exec_status = SIEVE_EXEC_OK; strlist->strlist.next_item = ext_date_stringlist_next_item; strlist->strlist.reset = ext_date_stringlist_reset; strlist->field_values = field_values; diff --git a/src/lib-sieve/plugins/date/tst-date.c b/src/lib-sieve/plugins/date/tst-date.c index 90b62c3b5..201cf4047 100644 --- a/src/lib-sieve/plugins/date/tst-date.c +++ b/src/lib-sieve/plugins/date/tst-date.c @@ -336,16 +336,16 @@ static bool tst_date_operation_dump /* Handle any optional arguments */ for (;;) { - int ret; + int opt; - if ( (ret=sieve_match_opr_optional_dump(denv, address, &opt_code)) < 0 ) + if ( (opt=sieve_match_opr_optional_dump(denv, address, &opt_code)) < 0 ) return FALSE; - if ( ret == 0 ) break; + if ( opt == 0 ) break; switch ( opt_code ) { case OPT_DATE_ZONE: - if ( !sieve_operand_read(denv->sblock, address, &operand) ) { + if ( !sieve_operand_read(denv->sblock, address, "zone", &operand) ) { sieve_code_dumpf(denv, "ERROR: INVALID OPERAND"); return FALSE; } @@ -386,33 +386,34 @@ static int tst_date_operation_execute SIEVE_MATCH_TYPE_DEFAULT(is_match_type); struct sieve_comparator cmp = SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); - struct sieve_operand operand; + struct sieve_operand oprnd; string_t *date_part = NULL, *zone = NULL; struct sieve_stringlist *hdr_list = NULL, *hdr_value_list; struct sieve_stringlist *value_list, *key_list; bool zone_specified = FALSE; int time_zone; - int ret; + int match, ret; /* Read optional operands */ for (;;) { - int ret; + int opt; - if ( (ret=sieve_match_opr_optional_read - (renv, address, &opt_code, &cmp, &mcht)) < 0 ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (opt=sieve_match_opr_optional_read + (renv, address, &opt_code, &ret, &cmp, &mcht)) < 0 ) + return ret; - if ( ret == 0 ) break; + if ( opt == 0 ) break; switch ( opt_code ) { case OPT_DATE_ZONE: - 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", &zone) ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_operand_runtime_read(renv, address, "zone", &oprnd)) + <= 0 ) + return ret; + + if ( !sieve_operand_is_omitted(&oprnd) ) { + if ( (ret=sieve_opr_string_read_data + (renv, &oprnd, address, "zone", &zone)) <= 0 ) + return ret; } zone_specified = TRUE; @@ -425,19 +426,20 @@ static int tst_date_operation_execute if ( sieve_operation_is(op, date_operation) ) { /* Read header name as stringlist */ - if ( (hdr_list=sieve_opr_stringlist_read(renv, address, "header-name")) - == NULL ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_stringlist_read + (renv, address, "header-name", &hdr_list)) <= 0 ) + return ret; } /* Read date part */ - if ( !sieve_opr_string_read(renv, address, "date-part", &date_part) ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_string_read(renv, address, "date-part", &date_part)) + <= 0 ) + return ret; /* Read key-list */ - if ( (key_list=sieve_opr_stringlist_read(renv, address, "key-list")) - == NULL ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_stringlist_read(renv, address, "key-list", &key_list)) + <= 0 ) + return ret; /* Determine what time zone to use in the result */ if ( !zone_specified ) { @@ -475,14 +477,10 @@ static int tst_date_operation_execute } /* Perform match */ - ret = sieve_match(renv, &mcht, &cmp, value_list, key_list); - - /* Set test result for subsequent conditional jump */ - if ( ret >= 0 ) { - sieve_interpreter_set_test_result(renv->interp, ret > 0); - return SIEVE_EXEC_OK; - } + if ( (match=sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret)) < 0 ) + return ret; - sieve_runtime_trace_error(renv, "invalid string-list item"); - return SIEVE_EXEC_BIN_CORRUPT; + /* Set test result for subsequent conditional jump */ + sieve_interpreter_set_test_result(renv->interp, match > 0); + return SIEVE_EXEC_OK; } diff --git a/src/lib-sieve/plugins/enotify/cmd-notify.c b/src/lib-sieve/plugins/enotify/cmd-notify.c index 69a4f0530..b331e76ac 100644 --- a/src/lib-sieve/plugins/enotify/cmd-notify.c +++ b/src/lib-sieve/plugins/enotify/cmd-notify.c @@ -356,13 +356,13 @@ static bool cmd_notify_operation_dump /* Dump optional operands */ for (;;) { - int ret; + int opt; bool opok = TRUE; - if ( (ret=sieve_opr_optional_dump(denv, address, &opt_code)) < 0 ) + if ( (opt=sieve_opr_optional_dump(denv, address, &opt_code)) < 0 ) return FALSE; - if ( ret == 0 ) break; + if ( opt == 0 ) break; switch ( opt_code ) { case CMD_NOTIFY_OPT_IMPORTANCE: @@ -400,12 +400,13 @@ static int cmd_notify_operation_execute struct sieve_enotify_action *act; void *method_context; pool_t pool; - int opt_code = 0, result = SIEVE_EXEC_OK; + int opt_code = 0; sieve_number_t importance = 2; struct sieve_stringlist *options = NULL; const struct sieve_enotify_method *method; string_t *method_uri, *message = NULL, *from = NULL; unsigned int source_line; + int ret; /* * Read operands @@ -418,40 +419,38 @@ static int cmd_notify_operation_execute /* Optional operands */ for (;;) { - bool opok = TRUE; - int ret; + int opt; - if ( (ret=sieve_opr_optional_read(renv, address, &opt_code)) < 0 ) + if ( (opt=sieve_opr_optional_read(renv, address, &opt_code)) < 0 ) return SIEVE_EXEC_BIN_CORRUPT; - if ( ret == 0 ) break; + if ( opt == 0 ) break; switch ( opt_code ) { case CMD_NOTIFY_OPT_IMPORTANCE: - opok = sieve_opr_number_read(renv, address, "importance", &importance); + ret = sieve_opr_number_read(renv, address, "importance", &importance); break; case CMD_NOTIFY_OPT_FROM: - opok = sieve_opr_string_read(renv, address, "from", &from); + ret = sieve_opr_string_read(renv, address, "from", &from); break; case CMD_NOTIFY_OPT_MESSAGE: - opok = sieve_opr_string_read(renv, address, "message", &message); + ret = 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 ); + ret = sieve_opr_stringlist_read(renv, address, "options", &options); break; default: sieve_runtime_trace_error(renv, "unknown optional operand"); return SIEVE_EXEC_BIN_CORRUPT; } - if ( !opok ) return SIEVE_EXEC_BIN_CORRUPT; + if ( ret <= 0 ) return ret; } /* Method operand */ - if ( !sieve_opr_string_read(renv, address, "method", &method_uri) ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_string_read(renv, address, "method", &method_uri)) <= 0 ) + return ret; /* * Perform operation @@ -475,9 +474,9 @@ static int cmd_notify_operation_execute /* Check operands */ - if ( (result=ext_enotify_runtime_check_operands + if ( (ret=ext_enotify_runtime_check_operands (renv, source_line, method_uri, message, from, options, &method, - &method_context)) ) + &method_context)) > 0 ) { /* Add notify action to the result */ @@ -491,11 +490,14 @@ static int cmd_notify_operation_execute if ( from != NULL ) act->from = p_strdup(pool, str_c(from)); - return ( sieve_result_add_action - (renv, this_ext, &act_notify, slist, source_line, (void *) act, 0) >= 0 ); + if ( sieve_result_add_action + (renv, this_ext, &act_notify, slist, source_line, (void *) act, 0) < 0 ) + return SIEVE_EXEC_FAILURE; + + return SIEVE_EXEC_OK; } - return result; + return ret; } /* 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 8ee7fb53f..73c982929 100644 --- a/src/lib-sieve/plugins/enotify/tst-notify-method-capability.c +++ b/src/lib-sieve/plugins/enotify/tst-notify-method-capability.c @@ -155,13 +155,11 @@ static bool tst_notifymc_generate static bool tst_notifymc_operation_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address) { - int opt_code = 0; - sieve_code_dumpf(denv, "NOTIFY_METHOD_CAPABILITY"); sieve_code_descend(denv); /* Handle any optional arguments */ - if ( sieve_match_opr_optional_dump(denv, address, &opt_code) != 0 ) + if ( sieve_match_opr_optional_dump(denv, address, NULL) != 0 ) return FALSE; return @@ -177,8 +175,6 @@ static bool tst_notifymc_operation_dump static int tst_notifymc_operation_execute (const struct sieve_runtime_env *renv, sieve_size_t *address) { - int ret; - int opt_code = 0; struct sieve_match_type mcht = SIEVE_MATCH_TYPE_DEFAULT(is_match_type); struct sieve_comparator cmp = @@ -186,35 +182,31 @@ static int tst_notifymc_operation_execute string_t *notify_uri, *notify_capability; struct sieve_stringlist *value_list, *key_list; const char *cap_value; + int match, ret; /* * Read operands */ /* Handle match-type and comparator operands */ - 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; - } + if ( sieve_match_opr_optional_read + (renv, address, NULL, &ret, &cmp, &mcht) < 0 ) + return ret; /* Read notify uri */ - if ( !sieve_opr_string_read(renv, address, "notify-uri", ¬ify_uri) ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_string_read(renv, address, "notify-uri", ¬ify_uri)) + <= 0 ) + return ret; /* Read notify capability */ - if ( !sieve_opr_string_read - (renv, address, "notify-capability", ¬ify_capability) ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_string_read + (renv, address, "notify-capability", ¬ify_capability)) <= 0 ) + return ret; /* Read key-list */ - if ( (key_list=sieve_opr_stringlist_read(renv, address, "key-list")) - == NULL ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_stringlist_read(renv, address, "key-list", &key_list)) + <= 0) + return ret; /* * Perform operation @@ -229,16 +221,14 @@ static int tst_notifymc_operation_execute value_list = sieve_single_stringlist_create_cstr(renv, cap_value, TRUE); /* Perform match */ - ret = sieve_match(renv, &mcht, &cmp, value_list, key_list); + if ( (match=sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret)) + < 0 ) + return ret; } else { - ret = 0; - } - - if ( ret >= 0 ) { - sieve_interpreter_set_test_result(renv->interp, ret > 0); - return SIEVE_EXEC_OK; + match = 0; } - - sieve_runtime_trace_error(renv, "invalid string list item"); - return SIEVE_EXEC_BIN_CORRUPT; + + /* Set test result for subsequent conditional jump */ + sieve_interpreter_set_test_result(renv->interp, match > 0); + return SIEVE_EXEC_OK; } 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 493bc3dc8..1774de2cc 100644 --- a/src/lib-sieve/plugins/enotify/tst-valid-notify-method.c +++ b/src/lib-sieve/plugins/enotify/tst-valid-notify-method.c @@ -115,9 +115,9 @@ static int tst_vnotifym_operation_execute */ /* Read notify uris */ - if ( (notify_uris=sieve_opr_stringlist_read(renv, address, "notify-uris")) - == NULL ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_stringlist_read + (renv, address, "notify-uris", ¬ify_uris)) <= 0 ) + return ret; /* * Perform operation diff --git a/src/lib-sieve/plugins/environment/tst-environment.c b/src/lib-sieve/plugins/environment/tst-environment.c index 5f9496d0f..b25ac49cb 100644 --- a/src/lib-sieve/plugins/environment/tst-environment.c +++ b/src/lib-sieve/plugins/environment/tst-environment.c @@ -133,13 +133,11 @@ static bool tst_environment_generate static bool tst_environment_operation_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address) { - int opt_code = 0; - sieve_code_dumpf(denv, "ENVIRONMENT"); sieve_code_descend(denv); /* Optional operands */ - if ( sieve_match_opr_optional_dump(denv, address, &opt_code) != 0 ) + if ( sieve_match_opr_optional_dump(denv, address, NULL) != 0 ) return FALSE; return @@ -155,8 +153,6 @@ 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; - int ret; - int opt_code = 0; struct sieve_match_type mcht = SIEVE_MATCH_TYPE_DEFAULT(is_match_type); struct sieve_comparator cmp = @@ -164,30 +160,25 @@ static int tst_environment_operation_execute string_t *name; struct sieve_stringlist *value_list, *key_list; const char *env_item; + int match, ret; /* * Read operands */ /* Handle match-type and comparator operands */ - 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; - } + if ( sieve_match_opr_optional_read + (renv, address, NULL, &ret, &cmp, &mcht) < 0 ) + return ret; /* Read source */ - if ( !sieve_opr_string_read(renv, address, "name", &name) ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_string_read(renv, address, "name", &name)) <= 0 ) + return ret; /* Read key-list */ - if ( (key_list=sieve_opr_stringlist_read(renv, address, "key-list")) - == NULL ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_stringlist_read(renv, address, "key-list", &key_list)) + <= 0 ) + return ret; /* * Perform operation @@ -203,16 +194,14 @@ static int tst_environment_operation_execute value_list = sieve_single_stringlist_create_cstr(renv, env_item, FALSE); /* Perform match */ - ret = sieve_match(renv, &mcht, &cmp, value_list, key_list); + if ( (match=sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret)) + < 0 ) + return ret; } else { - ret = 0; - } - - if ( ret >= 0 ) { - sieve_interpreter_set_test_result(renv->interp, ret > 0); - return SIEVE_EXEC_OK; + match = 0; } - - sieve_runtime_trace_error(renv, "invalid key list item"); - return SIEVE_EXEC_BIN_CORRUPT; + + /* Set test result for subsequent conditional jump */ + sieve_interpreter_set_test_result(renv->interp, match > 0); + return SIEVE_EXEC_OK; } diff --git a/src/lib-sieve/plugins/imap4flags/cmd-flag.c b/src/lib-sieve/plugins/imap4flags/cmd-flag.c index 71471d352..59564da88 100644 --- a/src/lib-sieve/plugins/imap4flags/cmd-flag.c +++ b/src/lib-sieve/plugins/imap4flags/cmd-flag.c @@ -144,28 +144,25 @@ static bool cmd_flag_generate bool cmd_flag_operation_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address) { - struct sieve_operand operand; + struct sieve_operand oprnd; sieve_code_dumpf(denv, "%s", sieve_operation_mnemonic(denv->oprtn)); sieve_code_descend(denv); sieve_code_mark(denv); - if ( !sieve_operand_read(denv->sblock, address, &operand) ) { + if ( !sieve_operand_read(denv->sblock, address, NULL, &oprnd) ) { sieve_code_dumpf(denv, "ERROR: INVALID OPERAND"); return FALSE; } - if ( sieve_operand_is_variable(&operand) ) { + if ( sieve_operand_is_variable(&oprnd) ) { return - sieve_opr_string_dump_data(denv, &operand, address, - "variable name") && - sieve_opr_stringlist_dump(denv, address, - "list of flags"); + sieve_opr_string_dump_data(denv, &oprnd, address, "variable name") && + sieve_opr_stringlist_dump(denv, address, "list of flags"); } return - sieve_opr_stringlist_dump_data(denv, &operand, address, - "list of flags"); + sieve_opr_stringlist_dump_data(denv, &oprnd, address, "list of flags"); } /* @@ -176,47 +173,49 @@ static int cmd_flag_operation_execute (const struct sieve_runtime_env *renv, sieve_size_t *address) { const struct sieve_operation *op = renv->oprtn; - struct sieve_operand operand; + struct sieve_operand oprnd; struct sieve_stringlist *flag_list; struct sieve_variable_storage *storage; unsigned int var_index; ext_imapflag_flag_operation_t flag_op; + int ret; /* * Read operands */ /* Read bare operand (two types possible) */ - if ( !sieve_operand_runtime_read(renv, address, NULL, &operand) ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_operand_runtime_read + (renv, address, NULL, &oprnd)) <= 0 ) + return ret; /* Variable operand (optional) */ - if ( sieve_operand_is_variable(&operand) ) { + if ( sieve_operand_is_variable(&oprnd) ) { /* Read the variable operand */ - if ( !sieve_variable_operand_read_data - (renv, &operand, address, "variable", &storage, &var_index) ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_variable_operand_read_data + (renv, &oprnd, address, "variable", &storage, &var_index)) <= 0 ) + return ret; /* Read flag list */ - if ( (flag_list=sieve_opr_stringlist_read(renv, address, "flag-list")) - == NULL ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_stringlist_read(renv, address, "flag-list", &flag_list)) + <= 0 ) + return ret; /* Flag-list operand */ - } else if ( sieve_operand_is_stringlist(&operand) ) { + } else if ( sieve_operand_is_stringlist(&oprnd) ) { storage = NULL; var_index = 0; /* Read flag list */ - if ( (flag_list=sieve_opr_stringlist_read_data - (renv, &operand, address, "flag-list")) == NULL ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_stringlist_read_data + (renv, &oprnd, address, "flag-list", &flag_list)) <= 0 ) + return ret; /* Invalid */ } else { - sieve_runtime_trace_error - (renv, "expected variable or string-list (flag-list) operand " - "but found %s", sieve_operand_name(&operand)); + sieve_runtime_trace_operand_error + (renv, &oprnd, "expected variable or string-list (flag-list) operand " + "but found %s", sieve_operand_name(&oprnd)); return SIEVE_EXEC_BIN_CORRUPT; } diff --git a/src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c b/src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c index 51ba9602d..63003e25a 100644 --- a/src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c +++ b/src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c @@ -592,6 +592,7 @@ static struct sieve_stringlist *ext_imap4flags_stringlist_create struct ext_imap4flags_stringlist *strlist; strlist = t_new(struct ext_imap4flags_stringlist, 1); + strlist->strlist.exec_status = SIEVE_EXEC_OK; strlist->strlist.runenv = renv; strlist->strlist.next_item = ext_imap4flags_stringlist_next_item; strlist->strlist.reset = ext_imap4flags_stringlist_reset; @@ -608,6 +609,7 @@ static struct sieve_stringlist *ext_imap4flags_stringlist_create_single struct ext_imap4flags_stringlist *strlist; strlist = t_new(struct ext_imap4flags_stringlist, 1); + strlist->strlist.exec_status = SIEVE_EXEC_OK; strlist->strlist.runenv = renv; strlist->strlist.next_item = ext_imap4flags_stringlist_next_item; strlist->strlist.reset = ext_imap4flags_stringlist_reset; diff --git a/src/lib-sieve/plugins/imap4flags/tag-flags.c b/src/lib-sieve/plugins/imap4flags/tag-flags.c index 2cf116e61..fc7e70834 100644 --- a/src/lib-sieve/plugins/imap4flags/tag-flags.c +++ b/src/lib-sieve/plugins/imap4flags/tag-flags.c @@ -57,7 +57,7 @@ const struct sieve_argument_def tag_flags_implicit = { static bool seff_flags_dump_context (const struct sieve_side_effect *seffect, const struct sieve_dumptime_env *denv, sieve_size_t *address); -static bool seff_flags_read_context +static int seff_flags_read_context (const struct sieve_side_effect *seffect, const struct sieve_runtime_env *renv, sieve_size_t *address, void **context); @@ -197,19 +197,19 @@ static bool seff_flags_dump_context (const struct sieve_side_effect *seffect ATTR_UNUSED, const struct sieve_dumptime_env *denv, sieve_size_t *address) { - struct sieve_operand operand; + struct sieve_operand oprnd; - if ( !sieve_operand_read(denv->sblock, address, &operand) ) { + if ( !sieve_operand_read(denv->sblock, address, "flags", &oprnd) ) { sieve_code_dumpf(denv, "ERROR: INVALID OPERAND"); return FALSE; } - if ( sieve_operand_is_omitted(&operand) ) { + if ( sieve_operand_is_omitted(&oprnd) ) { sieve_code_dumpf(denv, "flags: INTERNAL"); return TRUE; } - return sieve_opr_stringlist_dump_data(denv, &operand, address, "flags"); + return sieve_opr_stringlist_dump_data(denv, &oprnd, address, "flags"); } static struct seff_flags_context *seff_flags_get_implicit_context @@ -252,46 +252,46 @@ static struct seff_flags_context *seff_flags_get_implicit_context return ctx; } -static bool seff_flags_read_context +static int seff_flags_read_context (const struct sieve_side_effect *seffect, const struct sieve_runtime_env *renv, sieve_size_t *address, void **se_context) { - int ret; - struct sieve_operand operand; + struct sieve_operand oprnd; pool_t pool = sieve_result_pool(renv->result); struct seff_flags_context *ctx; string_t *flags_item; struct sieve_stringlist *flag_list; - - ctx = p_new(pool, struct seff_flags_context, 1); - p_array_init(&ctx->keywords, pool, 2); + int ret; t_push(); /* Check whether explicit flag list operand is present */ - if ( !sieve_operand_runtime_read(renv, address, NULL, &operand) ) { + if ( (ret=sieve_operand_runtime_read(renv, address, "flags", &oprnd)) <= 0 ) { t_pop(); - return FALSE; + return ret; } - if ( sieve_operand_is_omitted(&operand) ) { + if ( sieve_operand_is_omitted(&oprnd) ) { /* Flag list is omitted, use current value of internal * variable to construct side effect context. */ *se_context = seff_flags_get_implicit_context (SIEVE_OBJECT_EXTENSION(seffect), renv->result); t_pop(); - return TRUE; + return SIEVE_EXEC_OK; } /* Read flag-list */ - if ( (flag_list=sieve_opr_stringlist_read_data - (renv, &operand, address, NULL)) == NULL ) { + if ( (ret=sieve_opr_stringlist_read_data + (renv, &oprnd, address, NULL, &flag_list)) <= 0 ) { t_pop(); - return FALSE; + return ret; } + ctx = p_new(pool, struct seff_flags_context, 1); + p_array_init(&ctx->keywords, pool, 2); + /* Unpack */ flags_item = NULL; while ( (ret=sieve_stringlist_next_item(flag_list, &flags_item)) > 0 ) { @@ -328,7 +328,7 @@ static bool seff_flags_read_context t_pop(); - return ( ret >= 0 ); + return SIEVE_EXEC_OK; } /* Result verification */ diff --git a/src/lib-sieve/plugins/imap4flags/tst-hasflag.c b/src/lib-sieve/plugins/imap4flags/tst-hasflag.c index b6ea02ed5..a3e6837a1 100644 --- a/src/lib-sieve/plugins/imap4flags/tst-hasflag.c +++ b/src/lib-sieve/plugins/imap4flags/tst-hasflag.c @@ -145,13 +145,13 @@ static bool tst_hasflag_operation_dump for (;;) { bool opok = TRUE; - int ret; + int opt; - if ( (ret=sieve_match_opr_optional_dump(denv, address, &opt_code)) + if ( (opt=sieve_match_opr_optional_dump(denv, address, &opt_code)) < 0 ) return FALSE; - if ( ret == 0 ) break; + if ( opt == 0 ) break; switch ( opt_code ) { case OPT_VARIABLES: @@ -181,7 +181,7 @@ static int tst_hasflag_operation_execute struct sieve_match_type mcht = SIEVE_MATCH_TYPE_DEFAULT(is_match_type); struct sieve_stringlist *flag_list, *variables_list, *value_list, *key_list; - int ret; + int match, ret; /* * Read operands @@ -191,33 +191,32 @@ static int tst_hasflag_operation_execute variables_list = NULL; for (;;) { - bool opok = TRUE; + int opt; - if ( (ret=sieve_match_opr_optional_read - (renv, address, &opt_code, &cmp, &mcht)) < 0 ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (opt=sieve_match_opr_optional_read + (renv, address, &opt_code, &ret, &cmp, &mcht)) < 0 ) + return ret; - if ( ret == 0 ) break; + if ( opt == 0 ) break; switch ( opt_code ) { case OPT_VARIABLES: - variables_list = sieve_opr_stringlist_read - (renv, address, "variables-list"); - opok = ( variables_list != NULL ); + ret = sieve_opr_stringlist_read + (renv, address, "variables-list", &variables_list); break; default: sieve_runtime_trace_error(renv, "invalid optional operand"); - return SIEVE_EXEC_BIN_CORRUPT; + ret = SIEVE_EXEC_BIN_CORRUPT; } - if ( !opok ) return SIEVE_EXEC_BIN_CORRUPT; + if ( ret <= 0 ) return ret; } /* Fixed operands */ - if ( (flag_list=sieve_opr_stringlist_read(renv, address, "flag-list")) - == NULL ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_stringlist_read(renv, address, "flag-list", &flag_list)) + <= 0 ) + return ret; /* * Perform operation @@ -233,16 +232,13 @@ static int tst_hasflag_operation_execute else key_list = flag_list; - ret = sieve_match(renv, &mcht, &cmp, value_list, key_list); - - /* Assign test result */ - if ( ret >= 0 ) { - sieve_interpreter_set_test_result(renv->interp, ret > 0); - return SIEVE_EXEC_OK; - } - - sieve_runtime_trace_error(renv, "invalid string list item"); - return SIEVE_EXEC_BIN_CORRUPT; + /* Perform match */ + if ( (match=sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret)) < 0 ) + return ret; + + /* Set test result for subsequent conditional jump */ + sieve_interpreter_set_test_result(renv->interp, match > 0); + return SIEVE_EXEC_OK; } diff --git a/src/lib-sieve/plugins/mailbox/tst-mailboxexists.c b/src/lib-sieve/plugins/mailbox/tst-mailboxexists.c index 972e987d7..4c50b3f19 100644 --- a/src/lib-sieve/plugins/mailbox/tst-mailboxexists.c +++ b/src/lib-sieve/plugins/mailbox/tst-mailboxexists.c @@ -111,15 +111,16 @@ static int tst_mailboxexists_operation_execute string_t *mailbox_item; bool trace = FALSE; bool all_exist = TRUE; + int ret; /* * Read operands */ /* Read notify uris */ - if ( (mailbox_names=sieve_opr_stringlist_read(renv, address, "mailbox-names")) - == NULL ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_stringlist_read + (renv, address, "mailbox-names", &mailbox_names)) <= 0 ) + return ret; /* * Perform operation diff --git a/src/lib-sieve/plugins/notify/cmd-denotify.c b/src/lib-sieve/plugins/notify/cmd-denotify.c index 0a920006d..5c68d9de3 100644 --- a/src/lib-sieve/plugins/notify/cmd-denotify.c +++ b/src/lib-sieve/plugins/notify/cmd-denotify.c @@ -239,13 +239,13 @@ static bool cmd_denotify_operation_dump sieve_code_descend(denv); for (;;) { - int ret; + int opt; bool opok = TRUE; - if ( (ret=sieve_opr_optional_dump(denv, address, &opt_code)) < 0 ) + if ( (opt=sieve_opr_optional_dump(denv, address, &opt_code)) < 0 ) return FALSE; - if ( ret == 0 ) break; + if ( opt == 0 ) break; switch ( opt_code ) { case OPT_MATCH_KEY: @@ -274,7 +274,6 @@ static bool cmd_denotify_operation_dump static int cmd_denotify_operation_execute (const struct sieve_runtime_env *renv, sieve_size_t *address) { - bool result = TRUE; int opt_code = 0; struct sieve_match_type mcht = SIEVE_MATCH_TYPE_DEFAULT(is_match_type); @@ -294,31 +293,29 @@ static int cmd_denotify_operation_execute /* Optional operands */ for (;;) { - bool opok = TRUE; - int ret; + int opt; - if ( (ret=sieve_opr_optional_read(renv, address, &opt_code)) < 0 ) + if ( (opt=sieve_opr_optional_read(renv, address, &opt_code)) < 0 ) return SIEVE_EXEC_BIN_CORRUPT; - if ( ret == 0 ) break; + if ( opt == 0 ) break; switch ( opt_code ) { case OPT_MATCH_TYPE: - opok = sieve_opr_match_type_read(renv, address, &mcht); + ret = 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 ); + ret = sieve_opr_stringlist_read(renv, address, "match key", &match_key); break; case OPT_IMPORTANCE: - opok = sieve_opr_number_read(renv, address, "importance", &importance); + ret = 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; + if ( ret <= 0 ) return ret; } /* @@ -337,46 +334,40 @@ static int cmd_denotify_operation_execute sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, "denotify action"); /* Either do string matching or just kill all notify actions */ - if ( match_key != NULL ) { - + if ( match_key != NULL ) { /* Initialize match */ mctx = sieve_match_begin(renv, &mcht, &cmp); - /* Iterate through all actions */ + /* Iterate through all notify actions and delete those that match */ rictx = sieve_result_iterate_init(renv->result); - while ( result && - (action=sieve_result_iterate_next(rictx, NULL)) != NULL ) { + while ( (action=sieve_result_iterate_next(rictx, NULL)) != NULL ) { if ( sieve_action_is(action, act_notify_old) ) { struct ext_notify_action *nact = (struct ext_notify_action *) action->context; if ( importance == 0 || nact->importance == importance ) { - if ( (ret=sieve_match_value - (mctx, nact->id, strlen(nact->id), match_key)) < 0 ) { - result = FALSE; + int match; + + if ( (match=sieve_match_value + (mctx, nact->id, strlen(nact->id), match_key)) < 0 ) break; - } - if ( ret > 0 ) + if ( match > 0 ) sieve_result_iterate_delete(rictx); } } } /* Finish match */ - (void)sieve_match_end(&mctx); - - if ( !result ) { - sieve_runtime_trace_error(renv, "invalid string-list item"); - return SIEVE_EXEC_BIN_CORRUPT; - } + if ( sieve_match_end(&mctx, &ret) < 0 ) + return ret; + } else { - /* Iterate through all actions */ + /* Delete all notify actions */ rictx = sieve_result_iterate_init(renv->result); - while ( result && - (action=sieve_result_iterate_next(rictx, NULL)) != NULL ) { + while ( (action=sieve_result_iterate_next(rictx, NULL)) != NULL ) { if ( sieve_action_is(action, act_notify_old) ) { struct ext_notify_action *nact = diff --git a/src/lib-sieve/plugins/notify/cmd-notify.c b/src/lib-sieve/plugins/notify/cmd-notify.c index e0e03ba76..b50620b08 100644 --- a/src/lib-sieve/plugins/notify/cmd-notify.c +++ b/src/lib-sieve/plugins/notify/cmd-notify.c @@ -374,13 +374,13 @@ static bool cmd_notify_operation_dump /* Dump optional operands */ for (;;) { - int ret; + int opt; bool opok = TRUE; - if ( (ret=sieve_opr_optional_dump(denv, address, &opt_code)) < 0 ) + if ( (opt=sieve_opr_optional_dump(denv, address, &opt_code)) < 0 ) return FALSE; - if ( ret == 0 ) break; + if ( opt == 0 ) break; switch ( opt_code ) { case OPT_IMPORTANCE: @@ -421,6 +421,7 @@ static int cmd_notify_operation_execute struct sieve_stringlist *options = NULL; string_t *message = NULL, *id = NULL; unsigned int source_line; + int ret; /* * Read operands @@ -433,34 +434,32 @@ static int cmd_notify_operation_execute /* Optional operands */ for (;;) { - bool opok = TRUE; - int ret; + int opt; - if ( (ret=sieve_opr_optional_read(renv, address, &opt_code)) < 0 ) + if ( (opt=sieve_opr_optional_read(renv, address, &opt_code)) < 0 ) return SIEVE_EXEC_BIN_CORRUPT; - if ( ret == 0 ) break; + if ( opt == 0 ) break; switch ( opt_code ) { case OPT_IMPORTANCE: - opok = sieve_opr_number_read(renv, address, "importance", &importance); + ret = sieve_opr_number_read(renv, address, "importance", &importance); break; case OPT_ID: - opok = sieve_opr_string_read(renv, address, "id", &id); + ret = sieve_opr_string_read(renv, address, "id", &id); break; case OPT_MESSAGE: - opok = sieve_opr_string_read(renv, address, "from", &message); + ret = sieve_opr_string_read(renv, address, "from", &message); break; case OPT_OPTIONS: - options = sieve_opr_stringlist_read(renv, address, "options"); - opok = ( options != NULL ); + ret = sieve_opr_stringlist_read(renv, address, "options", &options); break; default: sieve_runtime_trace_error(renv, "unknown optional operand"); return SIEVE_EXEC_BIN_CORRUPT; } - if ( !opok ) return SIEVE_EXEC_BIN_CORRUPT; + if ( ret <= 0 ) return ret; } /* @@ -562,9 +561,10 @@ static int cmd_notify_operation_execute return SIEVE_EXEC_BIN_CORRUPT; } - return ( sieve_result_add_action + if ( sieve_result_add_action (renv, this_ext, &act_notify_old, NULL, source_line, (void *) act, 0) - >= 0 ); + < 0 ) + return SIEVE_EXEC_FAILURE; } return SIEVE_EXEC_OK; diff --git a/src/lib-sieve/plugins/regex/mcht-regex.c b/src/lib-sieve/plugins/regex/mcht-regex.c index dd98841c9..ea70c23de 100644 --- a/src/lib-sieve/plugins/regex/mcht-regex.c +++ b/src/lib-sieve/plugins/regex/mcht-regex.c @@ -267,7 +267,7 @@ static int mcht_regex_match_keys bool trace = sieve_runtime_trace_active(renv, SIEVE_TRLVL_MATCHING); struct mcht_regex_context *ctx = (struct mcht_regex_context *) mctx->data; const struct sieve_comparator *cmp = mctx->comparator; - int result = 0; + int match; if ( !ctx->all_compiled ) { string_t *key_item = NULL; @@ -280,7 +280,8 @@ static int mcht_regex_match_keys p_array_init(&ctx->reg_expressions, mctx->pool, 16); i = 0; - while ( result == 0 && + match = 0; + while ( match == 0 && (ret=sieve_stringlist_next_item(key_list, &key_item)) > 0 ) { T_BEGIN { @@ -316,13 +317,13 @@ static int mcht_regex_match_keys } if ( rkey->status > 0 ) { - result = mcht_regex_match_key(mctx, val, &rkey->regexp); + match = mcht_regex_match_key(mctx, val, &rkey->regexp); if ( trace ) { sieve_runtime_trace(renv, 0, "with regex `%s' [id=%d] => %d", str_sanitize(str_c(key_item), 80), - array_count(&ctx->reg_expressions)-1, result); + array_count(&ctx->reg_expressions)-1, match); } } } T_END; @@ -330,7 +331,12 @@ static int mcht_regex_match_keys i++; } - if ( ret < 0 ) result = -1; + if ( ret == 0 ) { + ctx->all_compiled = TRUE; + } else if ( ret < 0 ) { + mctx->exec_status = key_list->exec_status; + match = -1; + } } else { const struct mcht_regex_key *rkeys; @@ -340,24 +346,23 @@ static int mcht_regex_match_keys rkeys = array_get(&ctx->reg_expressions, &count); - i = 0; - while ( result == 0 && i < count ) { + i = 0; + match = 0; + while ( match == 0 && i < count ) { if ( rkeys[i].status > 0 ) { - result = mcht_regex_match_key(mctx, val, &rkeys[i].regexp); + match = mcht_regex_match_key(mctx, val, &rkeys[i].regexp); if ( trace ) { sieve_runtime_trace(renv, 0, - "with compiled regex [id=%d] => %d", i, result); + "with compiled regex [id=%d] => %d", i, match); } } i++; } - - if ( i == count ) ctx->all_compiled = TRUE; } - return result; + return match; } void mcht_regex_match_deinit diff --git a/src/lib-sieve/plugins/relational/mcht-count.c b/src/lib-sieve/plugins/relational/mcht-count.c index 98b417319..e4c45809a 100644 --- a/src/lib-sieve/plugins/relational/mcht-count.c +++ b/src/lib-sieve/plugins/relational/mcht-count.c @@ -71,10 +71,12 @@ static int mcht_count_match bool trace = sieve_runtime_trace_active(renv, SIEVE_TRLVL_MATCHING); int count; string_t *key_item; - int ret; + int match, ret; - if ( (count=sieve_stringlist_get_length(value_list)) < 0 ) + if ( (count=sieve_stringlist_get_length(value_list)) < 0 ) { + mctx->exec_status = value_list->exec_status; return -1; + } sieve_stringlist_reset(key_list); @@ -90,11 +92,11 @@ static int mcht_count_match /* Match to all key values */ key_item = NULL; - ret = 0; - while ( ret == 0 && + match = 0; + while ( match == 0 && (ret=sieve_stringlist_next_item(key_list, &key_item)) > 0 ) { - ret = mcht_value_match_key + match = mcht_value_match_key (mctx, str_c(value), str_len(value), str_c(key_item), str_len(key_item)); if ( trace ) { @@ -105,7 +107,12 @@ static int mcht_count_match sieve_runtime_trace_ascend(renv); - return ret; + if ( ret < 0 ) { + mctx->exec_status = key_list->exec_status; + match = -1; + } + + return match; } diff --git a/src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c b/src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c index cda0a3e3a..8a9777244 100644 --- a/src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c +++ b/src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c @@ -213,12 +213,12 @@ static bool tst_spamvirustest_operation_dump /* Optional operands */ for (;;) { - int ret; + int opt; - if ( (ret=sieve_match_opr_optional_dump(denv, address, &opt_code)) < 0 ) + if ( (opt=sieve_match_opr_optional_dump(denv, address, &opt_code)) < 0 ) return FALSE; - if ( ret == 0 ) break; + if ( opt == 0 ) break; switch ( opt_code ) { case OPT_SPAMTEST_PERCENT: @@ -250,17 +250,17 @@ static int tst_spamvirustest_operation_execute bool percent = FALSE; struct sieve_stringlist *value_list, *key_list; const char *score_value; - int ret; + int match, ret; /* Read optional operands */ for (;;) { - int ret; + int opt; - if ( (ret=sieve_match_opr_optional_read - (renv, address, &opt_code, &cmp, &mcht)) < 0 ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (opt=sieve_match_opr_optional_read + (renv, address, &opt_code, &ret, &cmp, &mcht)) < 0 ) + return ret; - if ( ret == 0 ) break; + if ( opt == 0 ) break; switch ( opt_code ) { case OPT_SPAMTEST_PERCENT: @@ -273,8 +273,8 @@ static int tst_spamvirustest_operation_execute } /* Read value part */ - if ( (key_list=sieve_opr_stringlist_read(renv, address, "value")) == NULL ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_stringlist_read(renv, address, "value", &key_list)) <= 0 ) + return ret; /* Perform test */ @@ -294,14 +294,10 @@ static int tst_spamvirustest_operation_execute value_list = sieve_single_stringlist_create_cstr(renv, score_value, TRUE); /* Perform match */ - ret = sieve_match(renv, &mcht, &cmp, value_list, key_list); + if ( (match=sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret)) < 0 ) + return ret; /* Set test result for subsequent conditional jump */ - if ( ret >= 0 ) { - sieve_interpreter_set_test_result(renv->interp, ret > 0); - return SIEVE_EXEC_OK; - } - - sieve_runtime_trace_error(renv, "invalid string-list item"); - return SIEVE_EXEC_BIN_CORRUPT; + sieve_interpreter_set_test_result(renv->interp, match > 0); + return SIEVE_EXEC_OK; } diff --git a/src/lib-sieve/plugins/vacation/cmd-vacation.c b/src/lib-sieve/plugins/vacation/cmd-vacation.c index ec2d452f8..45736768e 100644 --- a/src/lib-sieve/plugins/vacation/cmd-vacation.c +++ b/src/lib-sieve/plugins/vacation/cmd-vacation.c @@ -491,13 +491,13 @@ static bool ext_vacation_operation_dump /* Dump optional operands */ for (;;) { - int ret; + int opt; bool opok = TRUE; - if ( (ret=sieve_opr_optional_dump(denv, address, &opt_code)) < 0 ) + if ( (opt=sieve_opr_optional_dump(denv, address, &opt_code)) < 0 ) return FALSE; - if ( ret == 0 ) break; + if ( opt == 0 ) break; switch ( opt_code ) { case OPT_DAYS: @@ -546,6 +546,7 @@ static int ext_vacation_operation_execute string_t *reason, *subject = NULL, *from = NULL, *handle = NULL; unsigned int source_line; const char *from_normalized = NULL; + int ret; /* * Read code @@ -558,44 +559,43 @@ static int ext_vacation_operation_execute /* Optional operands */ for (;;) { - bool opok = TRUE; - int ret; + int opt; - if ( (ret=sieve_opr_optional_read(renv, address, &opt_code)) < 0 ) + if ( (opt=sieve_opr_optional_read(renv, address, &opt_code)) < 0 ) return SIEVE_EXEC_BIN_CORRUPT; - if ( ret == 0 ) break; + if ( opt == 0 ) break; switch ( opt_code ) { case OPT_DAYS: - opok = sieve_opr_number_read(renv, address, "days", &days); + ret = sieve_opr_number_read(renv, address, "days", &days); break; case OPT_SUBJECT: - opok = sieve_opr_string_read(renv, address, "subject", &subject); + ret = sieve_opr_string_read(renv, address, "subject", &subject); break; case OPT_FROM: - opok = sieve_opr_string_read(renv, address, "from", &from); + ret = sieve_opr_string_read(renv, address, "from", &from); break; case OPT_ADDRESSES: - addresses = sieve_opr_stringlist_read(renv, address, "addresses"); - opok = ( addresses != NULL ); + ret = sieve_opr_stringlist_read(renv, address, "addresses", &addresses); break; case OPT_MIME: mime = TRUE; + ret = SIEVE_EXEC_OK; break; default: sieve_runtime_trace_error(renv, "unknown optional operand"); - opok = FALSE; + ret = SIEVE_EXEC_BIN_CORRUPT; } - if ( !opok ) return SIEVE_EXEC_BIN_CORRUPT; + if ( ret <= 0 ) return ret; } /* Fixed operands */ - if ( !sieve_opr_string_read(renv, address, "reason", &reason) || - !sieve_opr_string_read(renv, address, "handle", &handle) ) { - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_string_read(renv, address, "reason", &reason)) <= 0 || + (ret=sieve_opr_string_read(renv, address, "handle", &handle)) <= 0 ) { + return ret; } /* @@ -678,8 +678,11 @@ static int ext_vacation_operation_execute act->addresses = array_idx(&norm_addresses, 0); } - return ( sieve_result_add_action - (renv, this_ext, &act_vacation, slist, source_line, (void *) act, 0) >= 0 ); + if ( sieve_result_add_action + (renv, this_ext, &act_vacation, slist, source_line, (void *) act, 0) < 0 ) + return SIEVE_EXEC_FAILURE; + + return SIEVE_EXEC_OK; } /* diff --git a/src/lib-sieve/plugins/variables/cmd-set.c b/src/lib-sieve/plugins/variables/cmd-set.c index aafcb523e..d2ec4cb48 100644 --- a/src/lib-sieve/plugins/variables/cmd-set.c +++ b/src/lib-sieve/plugins/variables/cmd-set.c @@ -291,12 +291,12 @@ static int cmd_set_operation_execute * Read the normal operands */ - if ( !sieve_variable_operand_read - (renv, address, "variable", &storage, &var_index) ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_variable_operand_read + (renv, address, "variable", &storage, &var_index)) <= 0 ) + return ret; - if ( !sieve_opr_string_read(renv, address, "string", &value) ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_string_read(renv, address, "string", &value)) <= 0 ) + return ret; if ( !sieve_binary_read_byte(renv->sblock, address, &mdfs) ) { sieve_runtime_trace_error(renv, "invalid modifier count"); @@ -367,10 +367,10 @@ static int cmd_set_operation_execute } } T_END; - if ( ret <= 0 ) - return ret; + if ( ret <= 0 ) return ret; + if ( value == NULL ) return SIEVE_EXEC_FAILURE; - return ( value != NULL ); + return SIEVE_EXEC_OK; } diff --git a/src/lib-sieve/plugins/variables/ext-variables-namespaces.c b/src/lib-sieve/plugins/variables/ext-variables-namespaces.c index 2f8897de9..9ee1aec0a 100644 --- a/src/lib-sieve/plugins/variables/ext-variables-namespaces.c +++ b/src/lib-sieve/plugins/variables/ext-variables-namespaces.c @@ -157,12 +157,12 @@ static bool arg_namespace_generate const struct sieve_operand_class sieve_variables_namespace_operand_class = { "variable-namespace" }; -static bool opr_namespace_variable_read - (const struct sieve_runtime_env *renv, const struct sieve_operand *operand, - sieve_size_t *address, string_t **str); static bool opr_namespace_variable_dump - (const struct sieve_dumptime_env *denv, const struct sieve_operand *operand, - sieve_size_t *address, const char *field_name); + (const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address); +static int opr_namespace_variable_read + (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, string_t **str_r); static const struct sieve_opr_string_interface namespace_variable_interface = { opr_namespace_variable_dump, @@ -186,39 +186,19 @@ void sieve_variables_opr_namespace_variable_emit sieve_opr_object_emit(sblock, ext, &nspc_def->obj_def); } -static bool opr_namespace_variable_read -(const struct sieve_runtime_env *renv, - const struct sieve_operand *operand ATTR_UNUSED, - sieve_size_t *address, string_t **str) -{ - struct sieve_variables_namespace nspc; - - if ( !sieve_opr_object_read - (renv, &sieve_variables_namespace_operand_class, address, &nspc.object) ) - return FALSE; - - nspc.def = (const struct sieve_variables_namespace_def *) nspc.object.def; - - if ( nspc.def == NULL || nspc.def->read_variable == NULL ) - return FALSE; - - return nspc.def->read_variable(renv, &nspc, address, str); -} - static bool opr_namespace_variable_dump -(const struct sieve_dumptime_env *denv, - const struct sieve_operand *operand ATTR_UNUSED, - sieve_size_t *address, const char *field_name) +(const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address) { struct sieve_variables_namespace nspc; - struct sieve_operand oprnd; + struct sieve_operand nsoprnd; - if ( !sieve_operand_read(denv->sblock, address, &oprnd) ) { + if ( !sieve_operand_read(denv->sblock, address, NULL, &nsoprnd) ) { return FALSE; } if ( !sieve_opr_object_read_data - (denv->sblock, &oprnd, &sieve_variables_namespace_operand_class, address, + (denv->sblock, &nsoprnd, &sieve_variables_namespace_operand_class, address, &nspc.object) ) { return FALSE; } @@ -228,7 +208,28 @@ static bool opr_namespace_variable_dump if ( nspc.def == NULL || nspc.def->dump_variable == NULL ) return FALSE; - return nspc.def->dump_variable(denv, &nspc, address, field_name); + return nspc.def->dump_variable(denv, &nspc, oprnd, address); +} + +static int opr_namespace_variable_read +(const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, string_t **str_r) +{ + struct sieve_variables_namespace nspc; + + if ( !sieve_opr_object_read + (renv, &sieve_variables_namespace_operand_class, address, &nspc.object) ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "variable namespace operand corrupt: failed to read"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + nspc.def = (const struct sieve_variables_namespace_def *) nspc.object.def; + + if ( nspc.def == NULL || nspc.def->read_variable == NULL ) + return SIEVE_EXEC_FAILURE; + + return nspc.def->read_variable(renv, &nspc, oprnd, address, str_r); } diff --git a/src/lib-sieve/plugins/variables/ext-variables-operands.c b/src/lib-sieve/plugins/variables/ext-variables-operands.c index 11ef01731..0e294d8e5 100644 --- a/src/lib-sieve/plugins/variables/ext-variables-operands.c +++ b/src/lib-sieve/plugins/variables/ext-variables-operands.c @@ -28,12 +28,12 @@ * Variable operand */ -static bool opr_variable_read_value - (const struct sieve_runtime_env *renv, const struct sieve_operand *operand, - sieve_size_t *address, string_t **str); static bool opr_variable_dump - (const struct sieve_dumptime_env *denv, const struct sieve_operand *operand, - sieve_size_t *address, const char *field_name); + (const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address); +static int opr_variable_read_value + (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, string_t **str_r); const struct sieve_opr_string_interface variable_interface = { opr_variable_dump, @@ -66,10 +66,10 @@ void sieve_variables_opr_variable_emit } static bool opr_variable_dump -(const struct sieve_dumptime_env *denv, const struct sieve_operand *operand, - sieve_size_t *address, const char *field_name) +(const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address) { - const struct sieve_extension *this_ext = operand->ext; + const struct sieve_extension *this_ext = oprnd->ext; unsigned int index = 0; const struct sieve_extension *ext; unsigned int code = 1; /* Initially set to offset value */ @@ -84,9 +84,9 @@ static bool opr_variable_dump identifier = ext_variables_dump_get_identifier(this_ext, denv, ext, index); identifier = identifier == NULL ? "??" : identifier; - if ( field_name != NULL ) + if ( oprnd->field_name != NULL ) sieve_code_dumpf(denv, "%s: VAR[%s] ${%s}", - field_name, sieve_ext_variables_get_varid(ext, index), identifier); + oprnd->field_name, sieve_ext_variables_get_varid(ext, index), identifier); else sieve_code_dumpf(denv, "VAR[%s] ${%s}", sieve_ext_variables_get_varid(ext, index), identifier); @@ -94,104 +94,116 @@ static bool opr_variable_dump return TRUE; } -static bool opr_variable_read_value -(const struct sieve_runtime_env *renv, const struct sieve_operand *operand, - sieve_size_t *address, string_t **str) +static int opr_variable_read_value +(const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, string_t **str_r) { - const struct sieve_extension *this_ext = operand->ext; + const struct sieve_extension *this_ext = oprnd->ext; const struct sieve_extension *ext; unsigned int code = 1; /* Initially set to offset value */ struct sieve_variable_storage *storage; unsigned int index = 0; - if ( !sieve_binary_read_extension(renv->sblock, address, &code, &ext) ) - return FALSE; + if ( !sieve_binary_read_extension(renv->sblock, address, &code, &ext) ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "variable operand corrupt: invalid extension byte"); + return SIEVE_EXEC_BIN_CORRUPT; + } storage = sieve_ext_variables_runtime_get_storage (this_ext, renv, ext); - if ( storage == NULL ) - return FALSE; + if ( storage == NULL ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "variable operand corrupt: extension has no storage"); + return SIEVE_EXEC_BIN_CORRUPT; + } - if (sieve_binary_read_unsigned(renv->sblock, address, &index) ) { + if ( sieve_binary_read_unsigned(renv->sblock, address, &index) ) { /* Parameter str can be NULL if we are requested to only skip and not * actually read the argument. */ - if ( str != NULL ) { - if ( !sieve_variable_get(storage, index, str) ) - return FALSE; + if ( str_r != NULL ) { + if ( !sieve_variable_get(storage, index, str_r) ) + return SIEVE_EXEC_FAILURE; - if ( *str == NULL ) *str = t_str_new(0); + if ( *str_r == NULL ) *str_r = t_str_new(0); } - return TRUE; + + return SIEVE_EXEC_OK; } - return FALSE; + sieve_runtime_trace_operand_error(renv, oprnd, + "variable operand corrupt: invalid variable index"); + return SIEVE_EXEC_BIN_CORRUPT; } -bool sieve_variable_operand_read_data -(const struct sieve_runtime_env *renv, const struct sieve_operand *operand, - sieve_size_t *address, const char *field_name, - struct sieve_variable_storage **storage, unsigned int *var_index) +int sieve_variable_operand_read_data +(const struct sieve_runtime_env *renv, struct sieve_operand *oprnd, + sieve_size_t *address, const char *field_name, + struct sieve_variable_storage **storage_r, unsigned int *var_index_r) { const struct sieve_extension *ext; unsigned int code = 1; /* Initially set to offset value */ unsigned int idx = 0; + + oprnd->field_name = field_name; - 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_operand_is_variable(oprnd) ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "expected variable operand but found %s", sieve_operand_name(oprnd)); + return SIEVE_EXEC_BIN_CORRUPT; } 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; + sieve_runtime_trace_operand_error(renv, oprnd, + "variable operand corrupt: invalid extension byte"); + return SIEVE_EXEC_BIN_CORRUPT; } - *storage = sieve_ext_variables_runtime_get_storage - (operand->ext, renv, ext); - if ( *storage == NULL ) { - sieve_runtime_trace_operand_error(renv, operand, field_name, - "variable operand: failed to get variable storage"); - return FALSE; + *storage_r = sieve_ext_variables_runtime_get_storage + (oprnd->ext, renv, ext); + if ( *storage_r == NULL ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "variable operand corrupt: extension has no storage"); + return SIEVE_EXEC_BIN_CORRUPT; } 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; + sieve_runtime_trace_operand_error(renv, oprnd, + "variable operand corrupt: invalid variable index"); + return SIEVE_EXEC_BIN_CORRUPT; } - *var_index = idx; - return TRUE; + *var_index_r = idx; + return SIEVE_EXEC_OK; } -bool sieve_variable_operand_read +int 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) + const char *field_name, struct sieve_variable_storage **storage_r, + unsigned int *var_index_r) { struct sieve_operand operand; + int ret; - if ( !sieve_operand_runtime_read(renv, address, field_name, &operand) ) - return FALSE; + if ( (ret=sieve_operand_runtime_read(renv, address, field_name, &operand)) + <= 0) + return ret; return sieve_variable_operand_read_data - (renv, &operand, address, field_name, storage, var_index); + (renv, &operand, address, field_name, storage_r, var_index_r); } /* * Match value operand */ -static bool opr_match_value_read - (const struct sieve_runtime_env *renv, const struct sieve_operand *operand, - sieve_size_t *address, string_t **str); static bool opr_match_value_dump - (const struct sieve_dumptime_env *denv, const struct sieve_operand *operand, - sieve_size_t *address, const char *field_name); + (const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address); +static int opr_match_value_read + (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, string_t **str_r); const struct sieve_opr_string_interface match_value_interface = { opr_match_value_dump, @@ -215,16 +227,15 @@ void sieve_variables_opr_match_value_emit } static bool opr_match_value_dump -(const struct sieve_dumptime_env *denv, - const struct sieve_operand *operand ATTR_UNUSED, - sieve_size_t *address, const char *field_name) +(const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address) { unsigned int index = 0; if (sieve_binary_read_unsigned(denv->sblock, address, &index) ) { - if ( field_name != NULL ) + if ( oprnd->field_name != NULL ) sieve_code_dumpf - (denv, "%s: MATCHVAL %lu", field_name, (unsigned long) index); + (denv, "%s: MATCHVAL %lu", oprnd->field_name, (unsigned long) index); else sieve_code_dumpf(denv, "MATCHVAL %lu", (unsigned long) index); @@ -234,27 +245,29 @@ static bool opr_match_value_dump return FALSE; } -static bool opr_match_value_read -(const struct sieve_runtime_env *renv, - const struct sieve_operand *operand ATTR_UNUSED, - sieve_size_t *address, string_t **str) +static int opr_match_value_read +(const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, string_t **str_r) { unsigned int index = 0; - if (sieve_binary_read_unsigned(renv->sblock, address, &index) ) { + if ( sieve_binary_read_unsigned(renv->sblock, address, &index) ) { /* Parameter str can be NULL if we are requested to only skip and not * actually read the argument. */ - if ( str != NULL ) { - sieve_match_values_get(renv, index, str); + if ( str_r != NULL ) { + sieve_match_values_get(renv, index, str_r); - if ( *str == NULL ) - *str = t_str_new(0); - else if ( str_len(*str) > EXT_VARIABLES_MAX_VARIABLE_SIZE ) - str_truncate(*str, EXT_VARIABLES_MAX_VARIABLE_SIZE); + if ( *str_r == NULL ) + *str_r = t_str_new(0); + else if ( str_len(*str_r) > EXT_VARIABLES_MAX_VARIABLE_SIZE ) + str_truncate(*str_r, EXT_VARIABLES_MAX_VARIABLE_SIZE); } - return TRUE; + + return SIEVE_EXEC_OK; } - return FALSE; + sieve_runtime_trace_operand_error(renv, oprnd, + "match value operand corrupt: invalid index data"); + return SIEVE_EXEC_BIN_CORRUPT; } diff --git a/src/lib-sieve/plugins/variables/sieve-ext-variables.h b/src/lib-sieve/plugins/variables/sieve-ext-variables.h index 5ef1e9f1d..6d1f74ecc 100644 --- a/src/lib-sieve/plugins/variables/sieve-ext-variables.h +++ b/src/lib-sieve/plugins/variables/sieve-ext-variables.h @@ -121,14 +121,14 @@ struct sieve_variables_namespace_def { struct sieve_ast_argument *arg, struct sieve_command *cmd, void *var_data); - bool (*read_variable) - (const struct sieve_runtime_env *renv, - const struct sieve_variables_namespace *nspc, sieve_size_t *address, - string_t **str); bool (*dump_variable) (const struct sieve_dumptime_env *denv, - const struct sieve_variables_namespace *nspc, sieve_size_t *address, - const char *field_name); + const struct sieve_variables_namespace *nspc, + const struct sieve_operand *oprnd, sieve_size_t *address); + int (*read_variable) + (const struct sieve_runtime_env *renv, + const struct sieve_variables_namespace *nspc, + const struct sieve_operand *oprnd, sieve_size_t *address, string_t **str); }; #define SIEVE_VARIABLES_DEFINE_NAMESPACE(OP) SIEVE_EXT_DEFINE_OBJECT(OP) @@ -251,14 +251,14 @@ void sieve_variables_opr_match_value_emit (struct sieve_binary_block *sblock, const struct sieve_extension *var_ext, unsigned int index); -bool sieve_variable_operand_read_data - (const struct sieve_runtime_env *renv, const struct sieve_operand *operand, +int sieve_variable_operand_read_data + (const struct sieve_runtime_env *renv, struct sieve_operand *operand, sieve_size_t *address, const char *field_name, - struct sieve_variable_storage **storage, unsigned int *var_index); -bool sieve_variable_operand_read + struct sieve_variable_storage **storage_r, unsigned int *var_index_r); +int 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); + const char *field_name, struct sieve_variable_storage **storage_r, + unsigned int *var_index_r); 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 b4184f1ec..5d7f0bdd6 100644 --- a/src/lib-sieve/plugins/variables/tst-string.c +++ b/src/lib-sieve/plugins/variables/tst-string.c @@ -143,13 +143,11 @@ static bool tst_string_generate static bool tst_string_operation_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address) { - int opt_code = 0; - sieve_code_dumpf(denv, "STRING-TEST"); sieve_code_descend(denv); /* Optional operands */ - if ( sieve_match_opr_optional_dump(denv, address, &opt_code) != 0 ) + if ( sieve_match_opr_optional_dump(denv, address, NULL) != 0 ) return FALSE; return @@ -181,6 +179,7 @@ static struct sieve_stringlist *tst_string_stringlist_create strlist = t_new(struct tst_string_stringlist, 1); strlist->strlist.runenv = renv; + strlist->strlist.exec_status = SIEVE_EXEC_OK; strlist->strlist.next_item = tst_string_stringlist_next_item; strlist->strlist.reset = tst_string_stringlist_reset; strlist->strlist.get_length = tst_string_stringlist_get_length; @@ -227,36 +226,30 @@ static int tst_string_stringlist_get_length static int tst_string_operation_execute (const struct sieve_runtime_env *renv, sieve_size_t *address) { - int ret; - int opt_code = 0; struct sieve_match_type mcht = SIEVE_MATCH_TYPE_DEFAULT(is_match_type); struct sieve_comparator cmp = SIEVE_COMPARATOR_DEFAULT(i_octet_comparator); struct sieve_stringlist *source, *value_list, *key_list; + int match, ret; /* * Read operands */ /* Handle match-type and comparator operands */ - 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; - } + if ( sieve_match_opr_optional_read + (renv, address, NULL, &ret, &cmp, &mcht) < 0 ) + return ret; /* Read source */ - if ( (source=sieve_opr_stringlist_read(renv, address, "source")) == NULL ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_stringlist_read(renv, address, "source", &source)) <= 0 ) + return ret; /* Read key-list */ - if ( (key_list=sieve_opr_stringlist_read(renv, address, "key-list")) == NULL ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_stringlist_read(renv, address, "key-list", &key_list)) + <= 0 ) + return ret; /* * Perform operation @@ -268,14 +261,10 @@ static int tst_string_operation_execute value_list = tst_string_stringlist_create(renv, source); /* Perform match */ - ret = sieve_match(renv, &mcht, &cmp, value_list, key_list); - - /* Set test result for subsequent conditional jump */ - if ( ret >= 0 ) { - sieve_interpreter_set_test_result(renv->interp, ret > 0); - return SIEVE_EXEC_OK; - } + if ( (match=sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret)) < 0 ) + return ret; - sieve_runtime_trace_error(renv, "invalid string-list item"); - return SIEVE_EXEC_BIN_CORRUPT; + /* Set test result for subsequent conditional jump */ + sieve_interpreter_set_test_result(renv->interp, match > 0); + return SIEVE_EXEC_OK; } diff --git a/src/lib-sieve/sieve-actions.c b/src/lib-sieve/sieve-actions.c index 4aa3f5990..a2e8a439b 100644 --- a/src/lib-sieve/sieve-actions.c +++ b/src/lib-sieve/sieve-actions.c @@ -90,10 +90,10 @@ int sieve_action_opr_optional_dump } while ( opok ) { - int ret; + int opt; - if ( (ret=sieve_opr_optional_dump(denv, address, opt_code)) <= 0 ) - return ret; + if ( (opt=sieve_opr_optional_dump(denv, address, opt_code)) <= 0 ) + return opt; if ( *opt_code == SIEVE_OPT_SIDE_EFFECT ) { opok = sieve_opr_side_effect_dump(denv, address); @@ -107,30 +107,40 @@ int sieve_action_opr_optional_dump 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, int *exec_status, + struct sieve_side_effects_list **list) { signed int _opt_code = 0; bool final = FALSE; + int ret; if ( opt_code == NULL ) { opt_code = &_opt_code; final = TRUE; } + if ( exec_status != NULL ) + *exec_status = SIEVE_EXEC_OK; + for ( ;; ) { - int ret; + int opt; - if ( (ret=sieve_opr_optional_read(renv, address, opt_code)) <= 0 ) - return ret; + if ( (opt=sieve_opr_optional_read(renv, address, opt_code)) <= 0 ) { + if ( opt < 0 && exec_status != NULL ) + *exec_status = SIEVE_EXEC_BIN_CORRUPT; + return opt; + } if ( *opt_code == SIEVE_OPT_SIDE_EFFECT ) { struct sieve_side_effect seffect; - if ( list == NULL ) - return -1; + i_assert( list != NULL ); - if ( !sieve_opr_side_effect_read(renv, address, &seffect) ) + if ( (ret=sieve_opr_side_effect_read(renv, address, &seffect)) <= 0 ) { + if ( exec_status != NULL ) + *exec_status = ret; return -1; + } if ( *list == NULL ) *list = sieve_side_effects_list_create(renv->result); @@ -139,12 +149,15 @@ int sieve_action_opr_optional_read } else { if ( final ) { sieve_runtime_trace_error(renv, "invalid optional operand"); - return -1; + if ( exec_status != NULL ) + *exec_status = SIEVE_EXEC_BIN_CORRUPT; + return -1; } return 1; } } + i_unreached(); return -1; } diff --git a/src/lib-sieve/sieve-actions.h b/src/lib-sieve/sieve-actions.h index c858580e6..9ab035209 100644 --- a/src/lib-sieve/sieve-actions.h +++ b/src/lib-sieve/sieve-actions.h @@ -115,7 +115,7 @@ struct sieve_side_effect_def { bool (*dump_context) (const struct sieve_side_effect *seffect, const struct sieve_dumptime_env *renv, sieve_size_t *address); - bool (*read_context) + int (*read_context) (const struct sieve_side_effect *seffect, const struct sieve_runtime_env *renv, sieve_size_t *address, void **se_context); @@ -193,7 +193,8 @@ int sieve_action_opr_optional_dump 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, int *exec_status, + 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 5971dbf76..13b696a54 100644 --- a/src/lib-sieve/sieve-address-parts.c +++ b/src/lib-sieve/sieve-address-parts.c @@ -360,10 +360,10 @@ int sieve_addrmatch_opr_optional_dump } while ( opok ) { - int ret; + int opt; - if ( (ret=sieve_opr_optional_dump(denv, address, opt_code)) <= 0 ) - return ret; + if ( (opt=sieve_opr_optional_dump(denv, address, opt_code)) <= 0 ) + return opt; switch ( *opt_code ) { case SIEVE_AM_OPT_COMPARATOR: @@ -385,42 +385,53 @@ int sieve_addrmatch_opr_optional_dump 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, + signed int *opt_code, int *exec_status, struct sieve_address_part *addrp, struct sieve_match_type *mtch, struct sieve_comparator *cmp) { signed int _opt_code = 0; - bool final = FALSE, opok = TRUE; + bool final = FALSE; + int status = SIEVE_EXEC_OK; if ( opt_code == NULL ) { opt_code = &_opt_code; final = TRUE; } - while ( opok ) { - int ret; + if ( exec_status != NULL ) + *exec_status = SIEVE_EXEC_OK; - if ( (ret=sieve_opr_optional_read(renv, address, opt_code)) <= 0 ) - return ret; + while ( status == SIEVE_EXEC_OK ) { + int opt; + + if ( (opt=sieve_opr_optional_read(renv, address, opt_code)) <= 0 ){ + if ( opt < 0 && exec_status != NULL ) + *exec_status = SIEVE_EXEC_BIN_CORRUPT; + return opt; + } switch ( *opt_code ) { case SIEVE_AM_OPT_COMPARATOR: - opok = sieve_opr_comparator_read(renv, address, cmp); + status = sieve_opr_comparator_read(renv, address, cmp); break; case SIEVE_AM_OPT_MATCH_TYPE: - opok = sieve_opr_match_type_read(renv, address, mtch); + status = sieve_opr_match_type_read(renv, address, mtch); break; case SIEVE_AM_OPT_ADDRESS_PART: - opok = sieve_opr_address_part_read(renv, address, addrp); + status = sieve_opr_address_part_read(renv, address, addrp); break; default: if ( final ) { sieve_runtime_trace_error(renv, "invalid optional operand"); + if ( exec_status != NULL ) + *exec_status = SIEVE_EXEC_BIN_CORRUPT; return -1; } return 1; } } + if ( exec_status != NULL ) + *exec_status = status; return -1; } diff --git a/src/lib-sieve/sieve-address-parts.h b/src/lib-sieve/sieve-address-parts.h index 8c8797e01..3e7a09524 100644 --- a/src/lib-sieve/sieve-address-parts.h +++ b/src/lib-sieve/sieve-address-parts.h @@ -89,23 +89,23 @@ static inline void sieve_opr_address_part_emit sieve_opr_object_emit(sblock, addrp->object.ext, addrp->object.def); } -static inline bool sieve_opr_address_part_read +static inline bool sieve_opr_address_part_dump + (const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + return sieve_opr_object_dump + (denv, &sieve_address_part_operand_class, address, NULL); +} + +static inline int sieve_opr_address_part_read (const struct sieve_runtime_env *renv, sieve_size_t *address, struct sieve_address_part *addrp) { if ( !sieve_opr_object_read (renv, &sieve_address_part_operand_class, address, &addrp->object) ) - return FALSE; + return SIEVE_EXEC_BIN_CORRUPT; addrp->def = (const struct sieve_address_part_def *) addrp->object.def; - return TRUE; -} - -static inline bool sieve_opr_address_part_dump - (const struct sieve_dumptime_env *denv, sieve_size_t *address) -{ - return sieve_opr_object_dump - (denv, &sieve_address_part_operand_class, address, NULL); + return SIEVE_EXEC_OK; } /* @@ -133,7 +133,7 @@ int sieve_addrmatch_opr_optional_dump 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, + signed int *opt_code, int *exec_status, 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-address.c b/src/lib-sieve/sieve-address.c index e89b40a5e..0d983b750 100644 --- a/src/lib-sieve/sieve-address.c +++ b/src/lib-sieve/sieve-address.c @@ -46,6 +46,7 @@ struct sieve_address_list *sieve_header_address_list_create addrlist = t_new(struct sieve_header_address_list, 1); addrlist->addrlist.strlist.runenv = renv; + addrlist->addrlist.strlist.exec_status = SIEVE_EXEC_OK; addrlist->addrlist.strlist.next_item = sieve_header_address_list_next_string_item; addrlist->addrlist.strlist.reset = sieve_header_address_list_reset; diff --git a/src/lib-sieve/sieve-code.c b/src/lib-sieve/sieve-code.c index d64f77d4b..1c237a9de 100644 --- a/src/lib-sieve/sieve-code.c +++ b/src/lib-sieve/sieve-code.c @@ -55,6 +55,7 @@ static struct sieve_stringlist *sieve_code_stringlist_create strlist = t_new(struct sieve_code_stringlist, 1); strlist->strlist.runenv = renv; + strlist->strlist.exec_status = SIEVE_EXEC_OK; strlist->strlist.next_item = sieve_code_stringlist_next_item; strlist->strlist.reset = sieve_code_stringlist_reset; strlist->strlist.get_length = sieve_code_stringlist_get_length; @@ -76,6 +77,7 @@ static int sieve_code_stringlist_next_item (struct sieve_code_stringlist *) _strlist; sieve_size_t address; *str_r = NULL; + int ret; /* Check for end of list */ if ( strlist->index >= strlist->length ) @@ -83,12 +85,14 @@ static int sieve_code_stringlist_next_item /* Read next item */ address = strlist->current_offset; - if ( sieve_opr_string_read(_strlist->runenv, &address, NULL, str_r) ) { + if ( (ret=sieve_opr_string_read(_strlist->runenv, &address, NULL, str_r)) + == SIEVE_EXEC_OK ) { strlist->index++; strlist->current_offset = address; return 1; } + _strlist->exec_status = ret; return -1; } @@ -193,17 +197,18 @@ sieve_size_t sieve_operand_emit } bool sieve_operand_read -(struct sieve_binary_block *sblock, sieve_size_t *address, - struct sieve_operand *operand) +(struct sieve_binary_block *sblock, sieve_size_t *address, + const char *field_name, struct sieve_operand *operand) { unsigned int code = sieve_operand_count; operand->address = *address; + operand->field_name = field_name; operand->ext = NULL; operand->def = NULL; if ( !sieve_binary_read_extension(sblock, address, &code, &operand->ext) ) - return NULL; + return FALSE; if ( operand->ext == NULL ) { if ( code < sieve_operand_count ) @@ -267,11 +272,11 @@ const struct sieve_operand_def omitted_operand = { /* Number */ static bool opr_number_dump - (const struct sieve_dumptime_env *denv, sieve_size_t *address, - const char *field_name); -static bool opr_number_read - (const struct sieve_runtime_env *renv, sieve_size_t *address, - sieve_number_t *number_r); + (const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address); +static int opr_number_read + (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, sieve_number_t *number_r); const struct sieve_opr_number_interface number_interface = { opr_number_dump, @@ -291,10 +296,10 @@ const struct sieve_operand_def number_operand = { /* String */ static bool opr_string_dump - (const struct sieve_dumptime_env *denv, const struct sieve_operand *opr, - sieve_size_t *address, const char *field_name); -static bool opr_string_read - (const struct sieve_runtime_env *renv, const struct sieve_operand *opr, + (const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address); +static int opr_string_read + (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, sieve_size_t *address, string_t **str_r); const struct sieve_opr_string_interface string_interface ={ @@ -315,10 +320,11 @@ const struct sieve_operand_def string_operand = { /* String List */ static bool opr_stringlist_dump - (const struct sieve_dumptime_env *denv, sieve_size_t *address, - const char *field_name); -static struct sieve_stringlist *opr_stringlist_read - (const struct sieve_runtime_env *renv, sieve_size_t *address); + (const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address); +static int opr_stringlist_read + (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, struct sieve_stringlist **strlist_r); const struct sieve_opr_stringlist_interface stringlist_interface = { opr_stringlist_dump, @@ -337,12 +343,12 @@ const struct sieve_operand_def stringlist_operand = { /* Catenated String */ -static bool opr_catenated_string_read - (const struct sieve_runtime_env *renv, const struct sieve_operand *operand, - sieve_size_t *address, string_t **str); static bool opr_catenated_string_dump (const struct sieve_dumptime_env *denv, const struct sieve_operand *operand, - sieve_size_t *address, const char *field_name); + sieve_size_t *address); +static int opr_catenated_string_read + (const struct sieve_runtime_env *renv, const struct sieve_operand *operand, + sieve_size_t *address, string_t **str); const struct sieve_opr_string_interface catenated_string_interface = { opr_catenated_string_dump, @@ -377,20 +383,22 @@ void sieve_opr_number_emit } bool sieve_opr_number_dump_data -(const struct sieve_dumptime_env *denv, const struct sieve_operand *opr, +(const struct sieve_dumptime_env *denv, struct sieve_operand *oprnd, sieve_size_t *address, const char *field_name) { const struct sieve_opr_number_interface *intf; - if ( !sieve_operand_is_number(opr) ) + oprnd->field_name = field_name; + + if ( !sieve_operand_is_number(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->dump == NULL ) return FALSE; - return intf->dump(denv, address, field_name); + return intf->dump(denv, oprnd, address); } bool sieve_opr_number_dump @@ -401,60 +409,61 @@ bool sieve_opr_number_dump sieve_code_mark(denv); - if ( !sieve_operand_read(denv->sblock, address, &operand) ) + if ( !sieve_operand_read(denv->sblock, address, field_name, &operand) ) return FALSE; return sieve_opr_number_dump_data(denv, &operand, address, field_name); } -bool sieve_opr_number_read_data -(const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, +int sieve_opr_number_read_data +(const struct sieve_runtime_env *renv, struct sieve_operand *oprnd, sieve_size_t *address, const char *field_name, sieve_number_t *number_r) { const struct sieve_opr_number_interface *intf; + oprnd->field_name = field_name; + if ( !sieve_operand_is_number(oprnd) ) { - sieve_runtime_trace_operand_error(renv, oprnd, field_name, + sieve_runtime_trace_operand_error(renv, oprnd, "expected number operand but found %s", sieve_operand_name(oprnd)); - return FALSE; + return SIEVE_EXEC_BIN_CORRUPT; } intf = (const struct sieve_opr_number_interface *) oprnd->def->interface; - if ( intf->read == NULL ) - return FALSE; - - if ( !intf->read(renv, address, number_r) ) { - sieve_runtime_trace_operand_error(renv, oprnd, field_name, - "invalid number operand"); - return FALSE; + if ( intf->read == NULL ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "number operand not implemented"); + return SIEVE_EXEC_FAILURE; } - return TRUE; + return intf->read(renv, oprnd, address, number_r); } -bool sieve_opr_number_read +int sieve_opr_number_read (const struct sieve_runtime_env *renv, sieve_size_t *address, const char *field_name, sieve_number_t *number_r) { struct sieve_operand operand; + int ret; - if ( !sieve_operand_runtime_read(renv, address, field_name, &operand) ) - return FALSE; + if ( (ret=sieve_operand_runtime_read(renv, address, field_name, &operand)) + <= 0) + return ret; return sieve_opr_number_read_data (renv, &operand, address, field_name, number_r); } static bool opr_number_dump -(const struct sieve_dumptime_env *denv, sieve_size_t *address, - const char *field_name) +(const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address) { sieve_number_t number = 0; if (sieve_binary_read_integer(denv->sblock, address, &number) ) { - if ( field_name != NULL ) - sieve_code_dumpf(denv, "%s: NUM %llu", field_name, + if ( oprnd->field_name != NULL ) + sieve_code_dumpf(denv, "%s: NUM %llu", oprnd->field_name, (unsigned long long) number); else sieve_code_dumpf(denv, "NUM %llu", (unsigned long long) number); @@ -465,11 +474,16 @@ static bool opr_number_dump return FALSE; } -static bool opr_number_read -(const struct sieve_runtime_env *renv, sieve_size_t *address, - sieve_number_t *number_r) +static int opr_number_read +(const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, sieve_number_t *number_r) { - return sieve_binary_read_integer(renv->sblock, address, number_r); + if ( !sieve_binary_read_integer(renv->sblock, address, number_r) ) { + sieve_runtime_trace_operand_error(renv, oprnd, "invalid number operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + return SIEVE_EXEC_OK; } /* String */ @@ -481,25 +495,27 @@ void sieve_opr_string_emit(struct sieve_binary_block *sblock, string_t *str) } bool sieve_opr_string_dump_data -(const struct sieve_dumptime_env *denv, const struct sieve_operand *opr, +(const struct sieve_dumptime_env *denv, struct sieve_operand *oprnd, sieve_size_t *address, const char *field_name) { const struct sieve_opr_string_interface *intf; - if ( !sieve_operand_is_string(opr) ) { + oprnd->field_name = field_name; + + if ( !sieve_operand_is_string(oprnd) ) { sieve_code_dumpf(denv, "ERROR: INVALID STRING OPERAND %s", - sieve_operand_name(opr)); + 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->dump == NULL ) { sieve_code_dumpf(denv, "ERROR: DUMP STRING OPERAND"); return FALSE; } - return intf->dump(denv, opr, address, field_name); + return intf->dump(denv, oprnd, address); } bool sieve_opr_string_dump @@ -510,7 +526,7 @@ bool sieve_opr_string_dump sieve_code_mark(denv); - if ( !sieve_operand_read(denv->sblock, address, &operand) ) { + if ( !sieve_operand_read(denv->sblock, address, field_name, &operand) ) { sieve_code_dumpf(denv, "ERROR: INVALID OPERAND"); return FALSE; } @@ -525,7 +541,7 @@ bool sieve_opr_string_dump_ex struct sieve_operand operand; sieve_code_mark(denv); - if ( !sieve_operand_read(denv->sblock, address, &operand) ) { + if ( !sieve_operand_read(denv->sblock, address, field_name, &operand) ) { sieve_code_dumpf(denv, "ERROR: INVALID OPERAND"); return FALSE; } @@ -535,49 +551,55 @@ bool sieve_opr_string_dump_ex return sieve_opr_string_dump_data(denv, &operand, address, field_name); } -bool sieve_opr_string_read_data -(const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, +int sieve_opr_string_read_data +(const struct sieve_runtime_env *renv, struct sieve_operand *oprnd, sieve_size_t *address, const char *field_name, string_t **str_r) { const struct sieve_opr_string_interface *intf; + + oprnd->field_name = field_name; if ( !sieve_operand_is_string(oprnd) ) { - sieve_runtime_trace_operand_error(renv, oprnd, field_name, + sieve_runtime_trace_operand_error(renv, oprnd, "expected string operand but found %s", sieve_operand_name(oprnd)); - return FALSE; + return SIEVE_EXEC_BIN_CORRUPT; } intf = (const struct sieve_opr_string_interface *) oprnd->def->interface; if ( intf->read == NULL ) { - sieve_runtime_trace_operand_error(renv, oprnd, field_name, - "invalid string operand"); - return FALSE; + sieve_runtime_trace_operand_error(renv, oprnd, + "string operand not implemented"); + return SIEVE_EXEC_FAILURE; } return intf->read(renv, oprnd, address, str_r); } -bool sieve_opr_string_read +int sieve_opr_string_read (const struct sieve_runtime_env *renv, sieve_size_t *address, const char *field_name, string_t **str_r) { struct sieve_operand operand; + int ret; - if ( !sieve_operand_runtime_read(renv, address, field_name, &operand) ) - return FALSE; + if ( (ret=sieve_operand_runtime_read(renv, address, field_name, &operand)) + <= 0 ) + return ret; return sieve_opr_string_read_data(renv, &operand, address, field_name, str_r); } -bool sieve_opr_string_read_ex +int sieve_opr_string_read_ex (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; + int ret; - if ( !sieve_operand_runtime_read(renv, address, field_name, &operand) ) - return FALSE; + if ( (ret=sieve_operand_runtime_read(renv, address, field_name, &operand)) + <= 0 ) + return ret; *literal_r = sieve_operand_is(&operand, string_operand); @@ -606,14 +628,13 @@ static void _dump_string } bool opr_string_dump -(const struct sieve_dumptime_env *denv, - const struct sieve_operand *opr ATTR_UNUSED, sieve_size_t *address, - const char *field_name) +(const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address) { string_t *str; if ( sieve_binary_read_string(denv->sblock, address, &str) ) { - _dump_string(denv, str, field_name); + _dump_string(denv, str, oprnd->field_name); return TRUE; } @@ -621,12 +642,17 @@ bool opr_string_dump return FALSE; } -static bool opr_string_read -(const struct sieve_runtime_env *renv, - const struct sieve_operand *opr ATTR_UNUSED, sieve_size_t *address, - string_t **str_r) +static int opr_string_read +(const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, string_t **str_r) { - return sieve_binary_read_string(renv->sblock, address, str_r); + if ( !sieve_binary_read_string(renv->sblock, address, str_r) ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "invalid string operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + return SIEVE_EXEC_OK; } /* String list */ @@ -662,28 +688,30 @@ void sieve_opr_stringlist_emit_end } bool sieve_opr_stringlist_dump_data -(const struct sieve_dumptime_env *denv, const struct sieve_operand *opr, +(const struct sieve_dumptime_env *denv, 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 FALSE; - if ( opr->def->class == &stringlist_class ) { + oprnd->field_name = field_name; + + 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; if ( intf->dump == NULL ) return FALSE; - return intf->dump(denv, address, field_name); - } else if ( opr->def->class == &string_class ) { + return intf->dump(denv, oprnd, address); + } else if ( oprnd->def->class == &string_class ) { 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->dump == NULL ) return FALSE; - return intf->dump(denv, opr, address, field_name); + return intf->dump(denv, oprnd, address); } return FALSE; @@ -697,70 +725,83 @@ bool sieve_opr_stringlist_dump sieve_code_mark(denv); - if ( !sieve_operand_read(denv->sblock, address, &operand) ) { + if ( !sieve_operand_read(denv->sblock, address, field_name, &operand) ) { return FALSE; } return sieve_opr_stringlist_dump_data(denv, &operand, address, field_name); } -struct sieve_stringlist *sieve_opr_stringlist_read_data -(const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, - sieve_size_t *address, const char *field_name) +int sieve_opr_stringlist_read_data +(const struct sieve_runtime_env *renv, struct sieve_operand *oprnd, + sieve_size_t *address, const char *field_name, + struct sieve_stringlist **strlist_r) { if ( oprnd == NULL || oprnd->def == NULL ) - return NULL; + return SIEVE_EXEC_FAILURE; + + oprnd->field_name = field_name; if ( oprnd->def->class == &stringlist_class ) { const struct sieve_opr_stringlist_interface *intf = (const struct sieve_opr_stringlist_interface *) oprnd->def->interface; - struct sieve_stringlist *strlist; + int ret; - if ( intf->read == NULL ) - return NULL; - - if ( (strlist=intf->read(renv, address)) == NULL ) { - sieve_runtime_trace_operand_error(renv, oprnd, field_name, - "invalid stringlist operand"); - return NULL; + if ( intf->read == NULL ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "stringlist operand not implemented"); + return SIEVE_EXEC_FAILURE; } - return strlist; + if ( (ret=intf->read(renv, oprnd, address, strlist_r)) <= 0 ) + return ret; + + return SIEVE_EXEC_OK; } 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 *) oprnd->def->interface; + int ret; - 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; + if ( intf->read == NULL ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "stringlist string operand not implemented"); + return SIEVE_EXEC_FAILURE; } - - return sieve_code_stringlist_create(renv, oprnd->address, 1, *address); + + if ( (ret=intf->read(renv, oprnd, address, NULL)) <= 0 ) + return ret; + + if ( strlist_r != NULL ) + *strlist_r = sieve_code_stringlist_create + (renv, oprnd->address, 1, *address); + return SIEVE_EXEC_OK; } - sieve_runtime_trace_operand_error(renv, oprnd, field_name, + sieve_runtime_trace_operand_error(renv, oprnd, "expected stringlist or string operand but found %s", sieve_operand_name(oprnd)); - return NULL; + return SIEVE_EXEC_BIN_CORRUPT; } -struct sieve_stringlist *sieve_opr_stringlist_read +int sieve_opr_stringlist_read (const struct sieve_runtime_env *renv, sieve_size_t *address, - const char *field_name) + const char *field_name, struct sieve_stringlist **strlist_r) { struct sieve_operand operand; + int ret; - if ( !sieve_operand_runtime_read(renv, address, field_name, &operand) ) - return NULL; + if ( (ret=sieve_operand_runtime_read(renv, address, field_name, &operand)) + <= 0 ) + return ret; - return sieve_opr_stringlist_read_data(renv, &operand, address, field_name); + return sieve_opr_stringlist_read_data + (renv, &operand, address, field_name, strlist_r); } static bool opr_stringlist_dump -(const struct sieve_dumptime_env *denv, sieve_size_t *address, - const char *field_name) +(const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address) { sieve_size_t pc = *address; sieve_size_t end; @@ -775,33 +816,41 @@ static bool opr_stringlist_dump if ( !sieve_binary_read_unsigned(denv->sblock, address, &length) ) return FALSE; - return sieve_code_stringlist_dump(denv, address, length, end, field_name); + return sieve_code_stringlist_dump + (denv, address, length, end, oprnd->field_name); } -static struct sieve_stringlist *opr_stringlist_read -(const struct sieve_runtime_env *renv, sieve_size_t *address ) +static int opr_stringlist_read +(const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, struct sieve_stringlist **strlist_r) { - struct sieve_stringlist *strlist; sieve_size_t pc = *address; sieve_size_t end; unsigned int length = 0; sieve_offset_t end_offset; - if ( !sieve_binary_read_offset(renv->sblock, address, &end_offset) ) - return NULL; + if ( !sieve_binary_read_offset(renv->sblock, address, &end_offset) ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "stringlist corrupt: invalid end offset"); + return SIEVE_EXEC_BIN_CORRUPT; + } end = pc + end_offset; - if ( !sieve_binary_read_unsigned(renv->sblock, address, &length) ) - return NULL; - - strlist = sieve_code_stringlist_create - (renv, *address, (unsigned int) length, end); + if ( !sieve_binary_read_unsigned(renv->sblock, address, &length) ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "stringlist corrupt: invalid length data"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if ( strlist_r != NULL ) + *strlist_r = sieve_code_stringlist_create + (renv, *address, (unsigned int) length, end); /* Skip over the string list for now */ *address = end; - return strlist; + return SIEVE_EXEC_OK; } /* Catenated String */ @@ -814,19 +863,18 @@ void sieve_opr_catenated_string_emit } static bool opr_catenated_string_dump -(const struct sieve_dumptime_env *denv, - const struct sieve_operand *operand ATTR_UNUSED, sieve_size_t *address, - const char *field_name) +(const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address) { unsigned int elements = 0; unsigned int i; - if (!sieve_binary_read_unsigned(denv->sblock, address, &elements) ) + if ( !sieve_binary_read_unsigned(denv->sblock, address, &elements) ) return FALSE; - if ( field_name != NULL ) + if ( oprnd->field_name != NULL ) sieve_code_dumpf(denv, "%s: CAT-STR [%ld]:", - field_name, (long) elements); + oprnd->field_name, (long) elements); else sieve_code_dumpf(denv, "CAT-STR [%ld]:", (long) elements); @@ -840,24 +888,27 @@ static bool opr_catenated_string_dump return TRUE; } -static bool opr_catenated_string_read -(const struct sieve_runtime_env *renv, - const struct sieve_operand *operand ATTR_UNUSED, sieve_size_t *address, - string_t **str) +static int opr_catenated_string_read +(const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, string_t **str) { unsigned int elements = 0; unsigned int i; + int ret; - if ( !sieve_binary_read_unsigned(renv->sblock, address, &elements) ) - return FALSE; + if ( !sieve_binary_read_unsigned(renv->sblock, address, &elements) ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "catenated string corrupt: invalid element count data"); + return SIEVE_EXEC_BIN_CORRUPT; + } /* Parameter str can be NULL if we are requested to only skip and not * actually read the argument. */ if ( str == NULL ) { for ( i = 0; i < (unsigned int) elements; i++ ) { - if ( !sieve_opr_string_read(renv, address, NULL, NULL) ) - return FALSE; + if ( (ret=sieve_opr_string_read(renv, address, NULL, NULL)) <= 0 ) + return ret; } } else { string_t *strelm; @@ -866,8 +917,8 @@ 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, NULL, elm) ) - return FALSE; + if ( (ret=sieve_opr_string_read(renv, address, NULL, elm)) <= 0 ) + return ret; if ( elm != NULL ) { str_append_str(*str, strelm); @@ -880,7 +931,7 @@ static bool opr_catenated_string_read } } - return TRUE; + return SIEVE_EXEC_OK; } /* diff --git a/src/lib-sieve/sieve-code.h b/src/lib-sieve/sieve-code.h index 7f8ce700e..302baa5fc 100644 --- a/src/lib-sieve/sieve-code.h +++ b/src/lib-sieve/sieve-code.h @@ -36,6 +36,7 @@ struct sieve_operand { const struct sieve_operand_def *def; const struct sieve_extension *ext; sieve_size_t address; + const char *field_name; }; #define sieve_operand_name(opr) \ @@ -48,19 +49,18 @@ sieve_size_t sieve_operand_emit const struct sieve_operand_def *oprnd); bool sieve_operand_read (struct sieve_binary_block *sblock, sieve_size_t *address, - struct sieve_operand *oprnd); + const char *field_name, struct sieve_operand *oprnd); -static inline bool sieve_operand_runtime_read +static inline int 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; + if ( !sieve_operand_read(renv->sblock, address, field_name, operand) ) { + sieve_runtime_trace_operand_error(renv, operand, "invalid operand"); + return SIEVE_EXEC_BIN_CORRUPT; } - return TRUE; + return SIEVE_EXEC_OK; } /* @@ -137,28 +137,29 @@ extern const unsigned int sieve_operand_count; struct sieve_opr_number_interface { bool (*dump) - (const struct sieve_dumptime_env *denv, sieve_size_t *address, - const char *field_name); - bool (*read) - (const struct sieve_runtime_env *renv, sieve_size_t *address, - sieve_number_t *number_r); + (const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address); + int (*read) + (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, sieve_number_t *number_r); }; struct sieve_opr_string_interface { bool (*dump) - (const struct sieve_dumptime_env *denv, const struct sieve_operand *operand, - sieve_size_t *address, const char *field_name); - bool (*read) - (const struct sieve_runtime_env *renv, const struct sieve_operand *operand, + (const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address); + int (*read) + (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, sieve_size_t *address, string_t **str_r); }; struct sieve_opr_stringlist_interface { bool (*dump) - (const struct sieve_dumptime_env *denv, sieve_size_t *address, - const char *field_name); - struct sieve_stringlist *(*read) - (const struct sieve_runtime_env *renv, sieve_size_t *address); + (const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address); + int (*read) + (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + sieve_size_t *address, struct sieve_stringlist **strlist_r); }; /* @@ -181,15 +182,15 @@ static inline bool sieve_operand_is_omitted void sieve_opr_number_emit (struct sieve_binary_block *sblock, sieve_number_t number); bool sieve_opr_number_dump_data - (const struct sieve_dumptime_env *denv, const struct sieve_operand *operand, + (const struct sieve_dumptime_env *denv, struct sieve_operand *operand, sieve_size_t *address, const char *field_name); bool sieve_opr_number_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address, const char *field_name); -bool sieve_opr_number_read_data - (const struct sieve_runtime_env *renv, const struct sieve_operand *operand, +int sieve_opr_number_read_data + (const struct sieve_runtime_env *renv, struct sieve_operand *operand, sieve_size_t *address, const char *field_name, sieve_number_t *number_r); -bool sieve_opr_number_read +int sieve_opr_number_read (const struct sieve_runtime_env *renv, sieve_size_t *address, const char *field_name, sieve_number_t *number_r); @@ -205,7 +206,7 @@ static inline bool sieve_operand_is_number void sieve_opr_string_emit (struct sieve_binary_block *sblock, string_t *str); bool sieve_opr_string_dump_data - (const struct sieve_dumptime_env *denv, const struct sieve_operand *operand, + (const struct sieve_dumptime_env *denv, struct sieve_operand *operand, sieve_size_t *address, const char *field_name); bool sieve_opr_string_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address, @@ -213,13 +214,13 @@ bool sieve_opr_string_dump bool sieve_opr_string_dump_ex (const struct sieve_dumptime_env *denv, sieve_size_t *address, const char *field_name, bool *literal_r); -bool sieve_opr_string_read_data - (const struct sieve_runtime_env *renv, const struct sieve_operand *operand, +int sieve_opr_string_read_data + (const struct sieve_runtime_env *renv, struct sieve_operand *operand, sieve_size_t *address, const char *field_name, string_t **str_r); -bool sieve_opr_string_read +int sieve_opr_string_read (const struct sieve_runtime_env *renv, sieve_size_t *address, const char *field_name, string_t **str_r); -bool sieve_opr_string_read_ex +int sieve_opr_string_read_ex (const struct sieve_runtime_env *renv, sieve_size_t *address, const char *field_name, string_t **str_r, bool *literal_r); @@ -240,17 +241,18 @@ void sieve_opr_stringlist_emit_item void sieve_opr_stringlist_emit_end (struct sieve_binary_block *sblock, void *context); bool sieve_opr_stringlist_dump_data - (const struct sieve_dumptime_env *denv, const struct sieve_operand *operand, + (const struct sieve_dumptime_env *denv, struct sieve_operand *operand, sieve_size_t *address, const char *field_name); bool sieve_opr_stringlist_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address, const char *field_name); -struct sieve_stringlist *sieve_opr_stringlist_read_data - (const struct sieve_runtime_env *renv, const struct sieve_operand *operand, - sieve_size_t *address, const char *field_name); -struct sieve_stringlist *sieve_opr_stringlist_read +int sieve_opr_stringlist_read_data + (const struct sieve_runtime_env *renv, struct sieve_operand *operand, + sieve_size_t *address, const char *field_name, + struct sieve_stringlist **strlist_r); +int sieve_opr_stringlist_read (const struct sieve_runtime_env *renv, sieve_size_t *address, - const char *field_name); + const char *field_name, struct sieve_stringlist **strlist_r); static inline bool sieve_operand_is_stringlist (const struct sieve_operand *operand) diff --git a/src/lib-sieve/sieve-comparators.h b/src/lib-sieve/sieve-comparators.h index 512c072fc..d0058425d 100644 --- a/src/lib-sieve/sieve-comparators.h +++ b/src/lib-sieve/sieve-comparators.h @@ -126,24 +126,23 @@ static inline void sieve_opr_comparator_emit { sieve_opr_object_emit(sblock, cmp->object.ext, cmp->object.def); } +static inline bool sieve_opr_comparator_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + return sieve_opr_object_dump + (denv, &sieve_comparator_operand_class, address, NULL); +} -static inline bool sieve_opr_comparator_read +static inline int sieve_opr_comparator_read (const struct sieve_runtime_env *renv, sieve_size_t *address, struct sieve_comparator *cmp) { if ( !sieve_opr_object_read (renv, &sieve_comparator_operand_class, address, &cmp->object) ) - return FALSE; + return SIEVE_EXEC_BIN_CORRUPT; cmp->def = (const struct sieve_comparator_def *) cmp->object.def; - return TRUE; -} - -static inline bool sieve_opr_comparator_dump -(const struct sieve_dumptime_env *denv, sieve_size_t *address) -{ - return sieve_opr_object_dump - (denv, &sieve_comparator_operand_class, address, NULL); + return SIEVE_EXEC_OK; } /* diff --git a/src/lib-sieve/sieve-match-types.h b/src/lib-sieve/sieve-match-types.h index 2a0e68f3c..79d633c00 100644 --- a/src/lib-sieve/sieve-match-types.h +++ b/src/lib-sieve/sieve-match-types.h @@ -204,23 +204,23 @@ static inline void sieve_opr_match_type_emit sieve_opr_object_emit(sblock, mcht->object.ext, mcht->object.def); } -static inline bool sieve_opr_match_type_read +static inline bool sieve_opr_match_type_dump +(const struct sieve_dumptime_env *denv, sieve_size_t *address) +{ + return sieve_opr_object_dump + (denv, &sieve_match_type_operand_class, address, NULL); +} + +static inline int sieve_opr_match_type_read (const struct sieve_runtime_env *renv, sieve_size_t *address, struct sieve_match_type *mcht) { if ( !sieve_opr_object_read (renv, &sieve_match_type_operand_class, address, &mcht->object) ) - return FALSE; + return SIEVE_EXEC_BIN_CORRUPT; mcht->def = (const struct sieve_match_type_def *) mcht->object.def; - return TRUE; -} - -static inline bool sieve_opr_match_type_dump -(const struct sieve_dumptime_env *denv, sieve_size_t *address) -{ - return sieve_opr_object_dump - (denv, &sieve_match_type_operand_class, address, NULL); + return SIEVE_EXEC_OK; } /* Common validation implementation */ diff --git a/src/lib-sieve/sieve-match.c b/src/lib-sieve/sieve-match.c index 19c0a2e36..9cf437751 100644 --- a/src/lib-sieve/sieve-match.c +++ b/src/lib-sieve/sieve-match.c @@ -46,6 +46,7 @@ struct sieve_match_context *sieve_match_begin mctx->runenv = renv; mctx->match_type = mcht; mctx->comparator = cmp; + mctx->exec_status = SIEVE_EXEC_OK; mctx->trace = sieve_runtime_trace_active(renv, SIEVE_TRLVL_MATCHING); /* Trace */ @@ -70,7 +71,7 @@ int sieve_match_value { const struct sieve_match_type *mcht = mctx->match_type; const struct sieve_runtime_env *renv = mctx->runenv; - int result = 0; + int match, ret; if ( mctx->trace ) { sieve_runtime_trace(renv, 0, @@ -88,55 +89,62 @@ int sieve_match_value if ( mcht->def->match_keys != NULL ) { /* Call match-type's own key match handler */ - result = mcht->def->match_keys(mctx, value, value_size, key_list); + match = mcht->def->match_keys(mctx, value, value_size, key_list); } else { string_t *key_item = NULL; - int ret; /* Default key match loop */ - while ( result == 0 && + match = 0; + while ( match == 0 && (ret=sieve_stringlist_next_item(key_list, &key_item)) > 0 ) { T_BEGIN { - result = mcht->def->match_key + match = mcht->def->match_key (mctx, value, value_size, str_c(key_item), str_len(key_item)); if ( mctx->trace ) { sieve_runtime_trace(renv, 0, "with key `%s' => %d", str_sanitize(str_c(key_item), 80), - result); + match); } } T_END; } - if ( ret < 0 ) result = -1; + if ( ret < 0 ) { + mctx->exec_status = key_list->exec_status; + match = -1; + } } sieve_runtime_trace_ascend(renv); - if ( mctx->status < 0 || result < 0 ) - mctx->status = -1; + if ( mctx->match_status < 0 || match < 0 ) + mctx->match_status = -1; else - mctx->status = ( mctx->status > result ? mctx->status : result ); - return result; + mctx->match_status = + ( mctx->match_status > match ? mctx->match_status : match ); + return match; } -int sieve_match_end(struct sieve_match_context **mctx) +int sieve_match_end(struct sieve_match_context **mctx, int *exec_status) { const struct sieve_match_type *mcht = (*mctx)->match_type; const struct sieve_runtime_env *renv = (*mctx)->runenv; - int result = (*mctx)->status; + int match = (*mctx)->match_status; if ( mcht->def != NULL && mcht->def->match_deinit != NULL ) mcht->def->match_deinit(*mctx); + if ( exec_status != NULL ) + *exec_status = (*mctx)->exec_status; + pool_unref(&(*mctx)->pool); sieve_runtime_trace(renv, SIEVE_TRLVL_MATCHING, "finishing match with result: %s", - ( result > 0 ? "matched" : ( result < 0 ? "error" : "not matched" ) )); + ( match > 0 ? "matched" : ( match < 0 ? "error" : "not matched" ) )); sieve_runtime_trace_ascend(renv); - return result; + return match; } int sieve_match @@ -144,11 +152,12 @@ int sieve_match const struct sieve_match_type *mcht, const struct sieve_comparator *cmp, struct sieve_stringlist *value_list, - struct sieve_stringlist *key_list) + struct sieve_stringlist *key_list, + int *exec_status) { struct sieve_match_context *mctx; string_t *value_item = NULL; - int result, ret; + int match, ret; if ( (mctx=sieve_match_begin(renv, mcht, cmp)) == NULL ) return 0; @@ -162,24 +171,28 @@ int sieve_match if ( mcht->def->match != NULL ) { /* Call match-type's match handler */ - result = mctx->status = mcht->def->match(mctx, value_list, key_list); + match = mctx->match_status = + mcht->def->match(mctx, value_list, key_list); } else { /* Default value match loop */ - result = 0; - while ( result == 0 && + match = 0; + while ( match == 0 && (ret=sieve_stringlist_next_item(value_list, &value_item)) > 0 ) { - result = sieve_match_value + match = sieve_match_value (mctx, str_c(value_item), str_len(value_item), key_list); } - if ( ret < 0 ) result = -1; + if ( ret < 0 ) { + mctx->exec_status = value_list->exec_status; + match = -1; + } } - (void)sieve_match_end(&mctx); - return result; + (void)sieve_match_end(&mctx, exec_status); + return match; } /* @@ -189,13 +202,19 @@ int sieve_match int sieve_match_opr_optional_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address, int *opt_code) { - bool opok = TRUE; + int _opt_code = 0; + bool final = FALSE, opok = TRUE; + + if ( opt_code == NULL ) { + opt_code = &_opt_code; + final = TRUE; + } while ( opok ) { - int ret; + int opt; - if ( (ret=sieve_opr_optional_dump(denv, address, opt_code)) <= 0 ) - return ret; + if ( (opt=sieve_opr_optional_dump(denv, address, opt_code)) <= 0 ) + return opt; switch ( *opt_code ) { case SIEVE_MATCH_OPT_COMPARATOR: @@ -205,7 +224,7 @@ int sieve_match_opr_optional_dump opok = sieve_opr_match_type_dump(denv, address); break; default: - return 1; + return ( final ? -1 : 1 ); } } @@ -214,28 +233,49 @@ int sieve_match_opr_optional_dump 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) + int *exec_status, struct sieve_comparator *cmp, struct sieve_match_type *mcht) { - bool opok = TRUE; + int _opt_code = 0; + bool final = FALSE; + int status = SIEVE_EXEC_OK; - while ( opok ) { - int ret; + if ( opt_code == NULL ) { + opt_code = &_opt_code; + final = TRUE; + } - if ( (ret=sieve_opr_optional_read(renv, address, opt_code)) <= 0 ) - return ret; + if ( exec_status != NULL ) + *exec_status = SIEVE_EXEC_OK; + + while ( status == SIEVE_EXEC_OK ) { + int opt; + + if ( (opt=sieve_opr_optional_read(renv, address, opt_code)) <= 0 ){ + if ( opt < 0 && exec_status != NULL ) + *exec_status = SIEVE_EXEC_BIN_CORRUPT; + return opt; + } switch ( *opt_code ) { case SIEVE_MATCH_OPT_COMPARATOR: - opok = sieve_opr_comparator_read(renv, address, cmp); + status = sieve_opr_comparator_read(renv, address, cmp); break; case SIEVE_MATCH_OPT_MATCH_TYPE: - opok = sieve_opr_match_type_read(renv, address, mcht); + status = sieve_opr_match_type_read(renv, address, mcht); break; default: + if ( final ) { + sieve_runtime_trace_error(renv, "invalid optional operand"); + if ( exec_status != NULL ) + *exec_status = SIEVE_EXEC_BIN_CORRUPT; + return -1; + } return 1; } } + if ( exec_status != NULL ) + *exec_status = status; return -1; } diff --git a/src/lib-sieve/sieve-match.h b/src/lib-sieve/sieve-match.h index e32bae1eb..804d72acd 100644 --- a/src/lib-sieve/sieve-match.h +++ b/src/lib-sieve/sieve-match.h @@ -20,7 +20,9 @@ struct sieve_match_context { void *data; - int status; + int match_status; + int exec_status; + unsigned int trace:1; }; @@ -36,7 +38,7 @@ struct sieve_match_context *sieve_match_begin int sieve_match_value (struct sieve_match_context *mctx, const char *value, size_t value_size, struct sieve_stringlist *key_list); -int sieve_match_end(struct sieve_match_context **mctx); +int sieve_match_end(struct sieve_match_context **mctx, int *exec_status); /* Default matching operation */ int sieve_match @@ -44,7 +46,8 @@ int sieve_match const struct sieve_match_type *mcht, const struct sieve_comparator *cmp, struct sieve_stringlist *value_list, - struct sieve_stringlist *key_list); + struct sieve_stringlist *key_list, + int *exec_status); /* * Read matching operands @@ -62,6 +65,7 @@ int sieve_match_opr_optional_dump 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); + int *exec_status, struct sieve_comparator *cmp, + struct sieve_match_type *mcht); #endif /* __SIEVE_MATCH_H */ diff --git a/src/lib-sieve/sieve-message.c b/src/lib-sieve/sieve-message.c index 30b747269..ba346be20 100644 --- a/src/lib-sieve/sieve-message.c +++ b/src/lib-sieve/sieve-message.c @@ -226,6 +226,7 @@ struct sieve_stringlist *sieve_message_header_stringlist_create strlist = t_new(struct sieve_message_header_stringlist, 1); strlist->strlist.runenv = renv; + strlist->strlist.exec_status = SIEVE_EXEC_OK; strlist->strlist.next_item = sieve_message_header_stringlist_next_item; strlist->strlist.reset = sieve_message_header_stringlist_reset; strlist->field_names = field_names; diff --git a/src/lib-sieve/sieve-objects.c b/src/lib-sieve/sieve-objects.c index 614dd1b5e..bfbe1d542 100644 --- a/src/lib-sieve/sieve-objects.c +++ b/src/lib-sieve/sieve-objects.c @@ -69,7 +69,7 @@ bool sieve_opr_object_read { struct sieve_operand operand; - if ( !sieve_operand_read(renv->sblock, address, &operand) ) { + if ( !sieve_operand_read(renv->sblock, address, NULL, &operand) ) { return FALSE; } @@ -91,7 +91,7 @@ bool sieve_opr_object_dump sieve_code_mark(denv); - if ( !sieve_operand_read(denv->sblock, address, &operand) ) { + if ( !sieve_operand_read(denv->sblock, address, NULL, &operand) ) { return FALSE; } diff --git a/src/lib-sieve/sieve-runtime-trace.c b/src/lib-sieve/sieve-runtime-trace.c index 07e7a4746..49d606276 100644 --- a/src/lib-sieve/sieve-runtime-trace.c +++ b/src/lib-sieve/sieve-runtime-trace.c @@ -61,15 +61,15 @@ void _sieve_runtime_trace_error 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) + const char *fmt, va_list args) { string_t *trline = _trace_line_new(renv, 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); + if ( oprnd->field_name != NULL ) + str_printfa(trline, "%s: ", oprnd->field_name); str_vprintfa(trline, fmt, args); diff --git a/src/lib-sieve/sieve-runtime-trace.h b/src/lib-sieve/sieve-runtime-trace.h index a22088eff..9f1dbd0ae 100644 --- a/src/lib-sieve/sieve-runtime-trace.h +++ b/src/lib-sieve/sieve-runtime-trace.h @@ -55,7 +55,7 @@ void _sieve_runtime_trace_error 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); + const char *fmt, va_list args); static inline void sieve_runtime_trace_error (const struct sieve_runtime_env *renv, const char *fmt, ...) @@ -63,7 +63,7 @@ static inline void sieve_runtime_trace_error 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); + const char *fmt, ...) ATTR_FORMAT(3, 4); static inline void sieve_runtime_trace_error (const struct sieve_runtime_env *renv, const char *fmt, ...) @@ -78,13 +78,13 @@ static inline void sieve_runtime_trace_error 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, ...) + const char *fmt, ...) { va_list args; va_start(args, fmt); if ( renv->trace != NULL ) - _sieve_runtime_trace_operand_error(renv, oprnd, field_name, fmt, args); + _sieve_runtime_trace_operand_error(renv, oprnd, fmt, args); va_end(args); } diff --git a/src/lib-sieve/sieve-stringlist.c b/src/lib-sieve/sieve-stringlist.c index d3f7bc38f..caed0f341 100644 --- a/src/lib-sieve/sieve-stringlist.c +++ b/src/lib-sieve/sieve-stringlist.c @@ -9,7 +9,7 @@ * Default implementation */ -bool sieve_stringlist_read_all +int sieve_stringlist_read_all (struct sieve_stringlist *strlist, pool_t pool, const char * const **list_r) { @@ -32,7 +32,7 @@ bool sieve_stringlist_read_all (void)array_append_space(&items); *list_r = array_idx(&items, 0); - return ( ret >= 0 ); + return ( ret < 0 ? -1 : 1 ); } return strlist->read_all(strlist, pool, list_r); @@ -85,6 +85,7 @@ struct sieve_stringlist *sieve_single_stringlist_create strlist = t_new(struct sieve_single_stringlist, 1); strlist->strlist.runenv = renv; + strlist->strlist.exec_status = SIEVE_EXEC_OK; strlist->strlist.next_item = sieve_single_stringlist_next_item; strlist->strlist.reset = sieve_single_stringlist_reset; strlist->strlist.get_length = sieve_single_stringlist_get_length; diff --git a/src/lib-sieve/sieve-stringlist.h b/src/lib-sieve/sieve-stringlist.h index f5446a089..cf37f5a78 100644 --- a/src/lib-sieve/sieve-stringlist.h +++ b/src/lib-sieve/sieve-stringlist.h @@ -13,7 +13,7 @@ struct sieve_stringlist { int (*get_length) (struct sieve_stringlist *strlist); - bool (*read_all) + int (*read_all) (struct sieve_stringlist *strlist, pool_t pool, const char * const **list_r); @@ -21,6 +21,8 @@ struct sieve_stringlist { (struct sieve_stringlist *strlist, bool trace); const struct sieve_runtime_env *runenv; + int exec_status; + unsigned int trace:1; }; @@ -48,7 +50,7 @@ static inline void sieve_stringlist_reset int sieve_stringlist_get_length (struct sieve_stringlist *strlist); -bool sieve_stringlist_read_all +int sieve_stringlist_read_all (struct sieve_stringlist *strlist, pool_t pool, const char * const **list_r); diff --git a/src/lib-sieve/tst-address.c b/src/lib-sieve/tst-address.c index 1e6567ce1..ec2fee9c7 100644 --- a/src/lib-sieve/tst-address.c +++ b/src/lib-sieve/tst-address.c @@ -234,22 +234,22 @@ static int tst_address_operation_execute SIEVE_ADDRESS_PART_DEFAULT(all_address_part); struct sieve_stringlist *hdr_list, *hdr_value_list, *value_list, *key_list; struct sieve_address_list *addr_list; - int ret; + int match, ret; /* Read optional operands */ - if ( (ret=sieve_addrmatch_opr_optional_read - (renv, address, NULL, &addrp, &mcht, &cmp)) < 0 ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( sieve_addrmatch_opr_optional_read + (renv, address, NULL, &ret, &addrp, &mcht, &cmp) < 0 ) + return ret; /* Read header-list */ - if ( (hdr_list=sieve_opr_stringlist_read(renv, address, "header-list")) - == NULL ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_stringlist_read(renv, address, "header-list", &hdr_list)) + <= 0 ) + return ret; /* Read key-list */ - if ( (key_list=sieve_opr_stringlist_read(renv, address, "key-list")) - == NULL ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_stringlist_read(renv, address, "key-list", &key_list)) + <= 0 ) + return ret; sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "address test"); @@ -259,14 +259,10 @@ static int tst_address_operation_execute value_list = sieve_address_part_stringlist_create(renv, &addrp, addr_list); /* Perform match */ - ret = sieve_match(renv, &mcht, &cmp, value_list, key_list); - - /* Set test result for subsequent conditional jump */ - if ( ret >= 0 ) { - sieve_interpreter_set_test_result(renv->interp, ret > 0); - return SIEVE_EXEC_OK; - } + if ( (match=sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret)) < 0 ) + return ret; - sieve_runtime_trace_error(renv, "invalid string-list item"); - return SIEVE_EXEC_BIN_CORRUPT; + /* Set test result for subsequent conditional jump */ + sieve_interpreter_set_test_result(renv->interp, match > 0); + return SIEVE_EXEC_OK; } diff --git a/src/lib-sieve/tst-exists.c b/src/lib-sieve/tst-exists.c index 4aa6c55aa..c35e2eac1 100644 --- a/src/lib-sieve/tst-exists.c +++ b/src/lib-sieve/tst-exists.c @@ -106,19 +106,19 @@ static bool tst_exists_operation_dump static int tst_exists_operation_execute (const struct sieve_runtime_env *renv, sieve_size_t *address) { - int ret; struct sieve_stringlist *hdr_list; string_t *hdr_item; bool matched; + int ret; /* * Read operands */ /* Read header-list */ - if ( (hdr_list=sieve_opr_stringlist_read(renv, address, "header-list")) - == NULL ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_stringlist_read(renv, address, "header-list", &hdr_list)) + <= 0 ) + return ret; /* * Perfrom test diff --git a/src/lib-sieve/tst-header.c b/src/lib-sieve/tst-header.c index 9f1b85f8c..7e2fedfcf 100644 --- a/src/lib-sieve/tst-header.c +++ b/src/lib-sieve/tst-header.c @@ -134,13 +134,11 @@ static bool tst_header_generate static bool tst_header_operation_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address) { - int opt_code = 0; - sieve_code_dumpf(denv, "HEADER"); sieve_code_descend(denv); /* Optional operands */ - if ( sieve_match_opr_optional_dump(denv, address, &opt_code) != 0 ) + if ( sieve_match_opr_optional_dump(denv, address, NULL) != 0 ) return FALSE; return @@ -155,38 +153,31 @@ static bool tst_header_operation_dump static int tst_header_operation_execute (const struct sieve_runtime_env *renv, sieve_size_t *address) { - int opt_code = 0; struct sieve_comparator cmp = SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator); struct sieve_match_type mcht = SIEVE_COMPARATOR_DEFAULT(is_match_type); struct sieve_stringlist *hdr_list, *key_list, *value_list; - int ret; + int match, ret; /* * Read operands */ /* Handle match-type and comparator operands */ - 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; - } + if ( sieve_match_opr_optional_read(renv, address, NULL, &ret, &cmp, &mcht) + < 0 ) + return ret; /* Read header-list */ - if ( (hdr_list=sieve_opr_stringlist_read(renv, address, "header-list")) - == NULL ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_stringlist_read(renv, address, "header-list", &hdr_list)) + <= 0 ) + return ret; /* Read key-list */ - if ( (key_list=sieve_opr_stringlist_read(renv, address, "key-list")) - == NULL ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_stringlist_read(renv, address, "key-list", &key_list)) + <= 0 ) + return ret; /* * Perform test @@ -198,14 +189,10 @@ static int tst_header_operation_execute value_list = sieve_message_header_stringlist_create(renv, hdr_list); /* Perform match */ - ret = sieve_match(renv, &mcht, &cmp, value_list, key_list); - - /* Set test result for subsequent conditional jump */ - if ( ret >= 0 ) { - sieve_interpreter_set_test_result(renv->interp, ret > 0); - return SIEVE_EXEC_OK; - } + if ( (match=sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret)) < 0 ) + return ret; - sieve_runtime_trace_error(renv, "invalid string-list item"); - return SIEVE_EXEC_BIN_CORRUPT; + /* Set test result for subsequent conditional jump */ + sieve_interpreter_set_test_result(renv->interp, match > 0); + return SIEVE_EXEC_OK; } diff --git a/src/lib-sieve/tst-size.c b/src/lib-sieve/tst-size.c index f10238d12..536025455 100644 --- a/src/lib-sieve/tst-size.c +++ b/src/lib-sieve/tst-size.c @@ -246,14 +246,15 @@ static int tst_size_operation_execute (const struct sieve_runtime_env *renv, sieve_size_t *address) { sieve_number_t mail_size, limit; + int ret; /* * Read operands */ /* Read size limit */ - if ( !sieve_opr_number_read(renv, address, "limit", &limit) ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_number_read(renv, address, "limit", &limit)) <= 0 ) + return ret; /* * Perform test diff --git a/src/managesieve/cmd-putscript.c b/src/managesieve/cmd-putscript.c index 844860676..724b57040 100644 --- a/src/managesieve/cmd-putscript.c +++ b/src/managesieve/cmd-putscript.c @@ -348,7 +348,7 @@ static bool cmd_putscript_continue_script(struct client_command_context *cmd) break; } if (ret == -1 || ret == 0) - break; + break; } } diff --git a/src/sieve-tools/debug/cmd-debug-print.c b/src/sieve-tools/debug/cmd-debug-print.c index 2fb27867e..04f464e82 100644 --- a/src/sieve-tools/debug/cmd-debug-print.c +++ b/src/sieve-tools/debug/cmd-debug-print.c @@ -103,7 +103,7 @@ static int cmd_debug_print_operation_execute (const struct sieve_runtime_env *renv, sieve_size_t *address) { string_t *message; - int ret = SIEVE_EXEC_OK; + int ret; /* * Read operands @@ -111,8 +111,8 @@ static int cmd_debug_print_operation_execute /* Read message */ - if ( sieve_opr_string_read(renv, address, "message", &message) < 0 ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_string_read(renv, address, "message", &message)) <= 0 ) + return ret; /* * Perform operation @@ -123,5 +123,5 @@ static int cmd_debug_print_operation_execute /* FIXME: give this proper source location */ sieve_runtime_log(renv, "DEBUG", "%s", str_c(message)); - return ret; + return SIEVE_EXEC_OK; } diff --git a/src/testsuite/cmd-test-binary.c b/src/testsuite/cmd-test-binary.c index a8aef7327..0b8b6619f 100644 --- a/src/testsuite/cmd-test-binary.c +++ b/src/testsuite/cmd-test-binary.c @@ -222,6 +222,7 @@ static int cmd_test_binary_operation_execute { const struct sieve_operation *oprtn = renv->oprtn; string_t *binary_name = NULL; + int ret; /* * Read operands @@ -229,8 +230,9 @@ static int cmd_test_binary_operation_execute /* Binary Name */ - if ( !sieve_opr_string_read(renv, address, "binary-name", &binary_name) ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_string_read(renv, address, "binary-name", &binary_name)) + <= 0 ) + return ret; /* * Perform operation diff --git a/src/testsuite/cmd-test-config.c b/src/testsuite/cmd-test-config.c index 91d2ca61e..92cc7630d 100644 --- a/src/testsuite/cmd-test-config.c +++ b/src/testsuite/cmd-test-config.c @@ -318,18 +318,19 @@ static int cmd_test_config_set_operation_execute { string_t *setting; string_t *value; + int ret; /* * Read operands */ /* Setting */ - if ( !sieve_opr_string_read(renv, address, "setting", &setting) ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_string_read(renv, address, "setting", &setting)) <= 0 ) + return ret; /* Value */ - if ( !sieve_opr_string_read(renv, address, "value", &value) ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_string_read(renv, address, "value", &value)) <= 0 ) + return ret; /* * Perform operation @@ -352,14 +353,15 @@ static int cmd_test_config_unset_operation_execute (const struct sieve_runtime_env *renv, sieve_size_t *address) { string_t *setting; + int ret; /* * Read operands */ /* Setting */ - if ( !sieve_opr_string_read(renv, address, "setting", &setting) ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_string_read(renv, address, "setting", &setting)) <= 0 ) + return ret; /* * Perform operation @@ -382,14 +384,16 @@ static int cmd_test_config_reload_operation_execute { const struct sieve_extension *ext; string_t *extension; + int ret; /* * Read operands */ /* Extension */ - if ( !sieve_opr_string_read(renv, address, "extension", &extension) ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_string_read(renv, address, "extension", &extension)) + <= 0 ) + return ret; /* * Perform operation diff --git a/src/testsuite/cmd-test-fail.c b/src/testsuite/cmd-test-fail.c index 238acc053..b504de77d 100644 --- a/src/testsuite/cmd-test-fail.c +++ b/src/testsuite/cmd-test-fail.c @@ -131,9 +131,10 @@ static int cmd_test_fail_operation_execute (const struct sieve_runtime_env *renv, sieve_size_t *address) { string_t *reason; + int ret; - if ( !sieve_opr_string_read(renv, address, "reason", &reason) ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_string_read(renv, address, "reason", &reason)) <= 0 ) + return ret; sieve_runtime_trace(renv, SIEVE_TRLVL_COMMANDS, "testsuite: test_fail command; FAIL current test"); diff --git a/src/testsuite/cmd-test-mailbox.c b/src/testsuite/cmd-test-mailbox.c index 8ab5cc345..7a508b545 100644 --- a/src/testsuite/cmd-test-mailbox.c +++ b/src/testsuite/cmd-test-mailbox.c @@ -223,6 +223,7 @@ static int cmd_test_mailbox_operation_execute { const struct sieve_operation *oprtn = renv->oprtn; string_t *mailbox = NULL; + int ret; /* * Read operands @@ -230,8 +231,8 @@ static int cmd_test_mailbox_operation_execute /* Index */ - if ( !sieve_opr_string_read(renv, address, "mailbox", &mailbox) ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_string_read(renv, address, "mailbox", &mailbox)) <= 0 ) + return ret; /* * Perform operation diff --git a/src/testsuite/cmd-test-message.c b/src/testsuite/cmd-test-message.c index 2623e4e35..7c5d2c911 100644 --- a/src/testsuite/cmd-test-message.c +++ b/src/testsuite/cmd-test-message.c @@ -301,6 +301,7 @@ static int cmd_test_message_smtp_operation_execute sieve_number_t msg_index; unsigned int is_test = -1; bool result; + int ret; /* * Read operands @@ -315,8 +316,8 @@ static int cmd_test_message_smtp_operation_execute /* Index */ - if ( !sieve_opr_number_read(renv, address, "index", &msg_index) ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_number_read(renv, address, "index", &msg_index)) <= 0 ) + return ret; /* * Perform operation @@ -360,6 +361,7 @@ static int cmd_test_message_mailbox_operation_execute sieve_number_t msg_index; unsigned int is_test = -1; bool result; + int ret; /* * Read operands @@ -372,12 +374,12 @@ static int cmd_test_message_mailbox_operation_execute } /* Folder */ - if ( !sieve_opr_string_read(renv, address, "folder", &folder) ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_string_read(renv, address, "folder", &folder)) <= 0 ) + return ret; /* Index */ - if ( !sieve_opr_number_read(renv, address, "index", &msg_index) ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_number_read(renv, address, "index", &msg_index)) <= 0 ) + return ret; /* * Perform operation diff --git a/src/testsuite/cmd-test-set.c b/src/testsuite/cmd-test-set.c index 32077d6c8..527bc0d21 100644 --- a/src/testsuite/cmd-test-set.c +++ b/src/testsuite/cmd-test-set.c @@ -128,6 +128,7 @@ static int cmd_test_set_operation_execute struct testsuite_object tobj; string_t *value; int member_id; + int ret; if ( !testsuite_object_read_member (renv->sblock, address, &tobj, &member_id) ) { @@ -135,8 +136,8 @@ static int cmd_test_set_operation_execute return SIEVE_EXEC_BIN_CORRUPT; } - if ( !sieve_opr_string_read(renv, address, "string", &value) ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_string_read(renv, address, "string", &value)) <= 0 ) + return ret; if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS) ) { sieve_runtime_trace(renv, 0, "testsuite: test_set command"); diff --git a/src/testsuite/cmd-test.c b/src/testsuite/cmd-test.c index 40fb7f5c9..123be9ee1 100644 --- a/src/testsuite/cmd-test.c +++ b/src/testsuite/cmd-test.c @@ -151,9 +151,11 @@ static int cmd_test_operation_execute (const struct sieve_runtime_env *renv, sieve_size_t *address) { string_t *test_name; + int ret; - if ( !sieve_opr_string_read(renv, address, "test name", &test_name) ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_string_read(renv, address, "test name", &test_name)) + <= 0 ) + return ret; sieve_runtime_trace_sep(renv); sieve_runtime_trace(renv, SIEVE_TRLVL_NONE, diff --git a/src/testsuite/testsuite-log.c b/src/testsuite/testsuite-log.c index 97b54a194..039d9d934 100644 --- a/src/testsuite/testsuite-log.c +++ b/src/testsuite/testsuite-log.c @@ -204,6 +204,7 @@ struct sieve_stringlist *testsuite_log_stringlist_create strlist = t_new(struct testsuite_log_stringlist, 1); strlist->strlist.runenv = renv; + strlist->strlist.exec_status = SIEVE_EXEC_OK; strlist->strlist.next_item = testsuite_log_stringlist_next_item; strlist->strlist.reset = testsuite_log_stringlist_reset; diff --git a/src/testsuite/testsuite-objects.c b/src/testsuite/testsuite-objects.c index 9c0c11c1e..c02626403 100644 --- a/src/testsuite/testsuite-objects.c +++ b/src/testsuite/testsuite-objects.c @@ -124,13 +124,13 @@ bool testsuite_object_read (struct sieve_binary_block *sblock, sieve_size_t *address, struct testsuite_object *tobj) { - struct sieve_operand operand; + struct sieve_operand oprnd; - if ( !sieve_operand_read(sblock, address, &operand) ) + if ( !sieve_operand_read(sblock, address, NULL, &oprnd) ) return FALSE; if ( !sieve_opr_object_read_data - (sblock, &operand, &sieve_testsuite_object_operand_class, address, + (sblock, &oprnd, &sieve_testsuite_object_operand_class, address, &tobj->object) ) return FALSE; diff --git a/src/testsuite/testsuite-result.c b/src/testsuite/testsuite-result.c index e73d31244..f7340397b 100644 --- a/src/testsuite/testsuite-result.c +++ b/src/testsuite/testsuite-result.c @@ -121,6 +121,7 @@ struct sieve_stringlist *testsuite_result_stringlist_create strlist = t_new(struct testsuite_result_stringlist, 1); strlist->strlist.runenv = renv; + strlist->strlist.exec_status = SIEVE_EXEC_OK; strlist->strlist.next_item = testsuite_result_stringlist_next_item; strlist->strlist.reset = testsuite_result_stringlist_reset; diff --git a/src/testsuite/testsuite-substitutions.c b/src/testsuite/testsuite-substitutions.c index bb6d79c4d..d36f3e9a3 100644 --- a/src/testsuite/testsuite-substitutions.c +++ b/src/testsuite/testsuite-substitutions.c @@ -136,10 +136,10 @@ static bool arg_testsuite_substitution_generate */ static bool opr_substitution_dump - (const struct sieve_dumptime_env *denv, const struct sieve_operand *opr, - sieve_size_t *address, const char *field_name); -static bool opr_substitution_read_value - (const struct sieve_runtime_env *renv, const struct sieve_operand *opr, + (const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address); +static int opr_substitution_read_value + (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, sieve_size_t *address, string_t **str); const struct sieve_opr_string_interface testsuite_substitution_interface = { @@ -167,9 +167,8 @@ void testsuite_opr_substitution_emit } static bool opr_substitution_dump -(const struct sieve_dumptime_env *denv, - const struct sieve_operand *opr ATTR_UNUSED, sieve_size_t *address, - const char *field_name) +(const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, + sieve_size_t *address) { unsigned int code = 0; const struct testsuite_substitution_def *tsub; @@ -185,41 +184,48 @@ static bool opr_substitution_dump if ( !sieve_binary_read_string(denv->sblock, address, ¶m) ) return FALSE; - if ( field_name != NULL ) + if ( oprnd->field_name != NULL ) sieve_code_dumpf(denv, "%s: TEST_SUBS %%{%s:%s}", - field_name, tsub->obj_def.identifier, str_c(param)); + oprnd->field_name, tsub->obj_def.identifier, str_c(param)); else sieve_code_dumpf(denv, "TEST_SUBS %%{%s:%s}", tsub->obj_def.identifier, str_c(param)); return TRUE; } -static bool opr_substitution_read_value +static int opr_substitution_read_value (const struct sieve_runtime_env *renv, - const struct sieve_operand *opr ATTR_UNUSED, sieve_size_t *address, - string_t **str) + const struct sieve_operand *oprnd ATTR_UNUSED, sieve_size_t *address, + string_t **str_r) { const struct testsuite_substitution_def *tsub; unsigned int code = 0; string_t *param; if ( !sieve_binary_read_unsigned(renv->sblock, address, &code) ) - return FALSE; + return SIEVE_EXEC_BIN_CORRUPT; tsub = testsuite_substitution_get(code); if ( tsub == NULL ) - return FALSE; + return SIEVE_EXEC_FAILURE; /* Parameter str can be NULL if we are requested to only skip and not * actually read the argument. */ - if ( str == NULL ) - return sieve_binary_read_string(renv->sblock, address, NULL); + if ( str_r == NULL ) { + if ( !sieve_binary_read_string(renv->sblock, address, NULL) ) + return SIEVE_EXEC_BIN_CORRUPT; + + return SIEVE_EXEC_OK; + } if ( !sieve_binary_read_string(renv->sblock, address, ¶m) ) - return FALSE; + return SIEVE_EXEC_BIN_CORRUPT; - return tsub->get_value(str_c(param), str); + if ( !tsub->get_value(str_c(param), str_r) ) + return SIEVE_EXEC_FAILURE; + + return SIEVE_EXEC_OK; } /* diff --git a/src/testsuite/tst-test-error.c b/src/testsuite/tst-test-error.c index 9d7f1e58a..925ae5525 100644 --- a/src/testsuite/tst-test-error.c +++ b/src/testsuite/tst-test-error.c @@ -183,13 +183,13 @@ static bool tst_test_error_operation_dump /* Handle any optional arguments */ for (;;) { - int ret; + int opt; - if ( (ret=sieve_match_opr_optional_dump(denv, address, &opt_code)) + if ( (opt=sieve_match_opr_optional_dump(denv, address, &opt_code)) < 0 ) return FALSE; - if ( ret == 0 ) break; + if ( opt == 0 ) break; if ( opt_code == OPT_INDEX ) { if ( !sieve_opr_number_dump(denv, address, "index") ) @@ -214,7 +214,7 @@ static int tst_test_error_operation_execute struct sieve_match_type mcht = SIEVE_COMPARATOR_DEFAULT(is_match_type); struct sieve_stringlist *value_list, *key_list; int index = -1; - int ret; + int match, ret; /* * Read operands @@ -223,17 +223,17 @@ static int tst_test_error_operation_execute /* Read optional operands */ for (;;) { sieve_number_t number; - int ret; + int opt; - if ( (ret=sieve_match_opr_optional_read - (renv, address, &opt_code, &cmp, &mcht)) < 0 ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (opt=sieve_match_opr_optional_read + (renv, address, &opt_code, &ret, &cmp, &mcht)) < 0 ) + return ret; - if ( ret == 0 ) break; + if ( opt == 0 ) break; if ( opt_code == OPT_INDEX ) { - if ( !sieve_opr_number_read(renv, address, "index", &number) ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_number_read(renv, address, "index", &number)) <= 0 ) + return ret; index = (int) number; } else { sieve_runtime_trace_error(renv, "invalid optional operand"); @@ -242,8 +242,9 @@ static int tst_test_error_operation_execute } /* Read key-list */ - if ( (key_list=sieve_opr_stringlist_read(renv, address, "key_list")) == NULL ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_stringlist_read(renv, address, "key_list", &key_list)) + <= 0 ) + return ret; /* * Perform operation @@ -260,16 +261,12 @@ static int tst_test_error_operation_execute value_list = testsuite_log_stringlist_create(renv, index); /* Perform match */ - ret = sieve_match(renv, &mcht, &cmp, value_list, key_list); + if ( (match=sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret)) < 0 ) + return ret; /* Set test result for subsequent conditional jump */ - if ( ret >= 0 ) { - sieve_interpreter_set_test_result(renv->interp, ret > 0); - return SIEVE_EXEC_OK; - } - - sieve_runtime_trace_error(renv, "invalid string-list item"); - return SIEVE_EXEC_BIN_CORRUPT; + sieve_interpreter_set_test_result(renv->interp, match > 0); + return SIEVE_EXEC_OK; } diff --git a/src/testsuite/tst-test-multiscript.c b/src/testsuite/tst-test-multiscript.c index 156bf434a..fab25e3f0 100644 --- a/src/testsuite/tst-test-multiscript.c +++ b/src/testsuite/tst-test-multiscript.c @@ -118,9 +118,9 @@ static int tst_test_multiscript_operation_execute * Read operands */ - if ( (scripts_list=sieve_opr_stringlist_read(renv, address, "scripts")) - == NULL ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_stringlist_read(renv, address, "scripts", &scripts_list)) + <= 0 ) + return ret; /* * Perform operation diff --git a/src/testsuite/tst-test-result.c b/src/testsuite/tst-test-result.c index 9a9889bd9..178a8648c 100644 --- a/src/testsuite/tst-test-result.c +++ b/src/testsuite/tst-test-result.c @@ -188,13 +188,13 @@ static bool tst_test_result_operation_dump /* Handle any optional arguments */ for (;;) { - int ret; + int opt; - if ( (ret=sieve_match_opr_optional_dump(denv, address, &opt_code)) + if ( (opt=sieve_match_opr_optional_dump(denv, address, &opt_code)) < 0 ) return FALSE; - if ( ret == 0 ) break; + if ( opt == 0 ) break; if ( opt_code == OPT_INDEX ) { if ( !sieve_opr_number_dump(denv, address, "index") ) @@ -219,7 +219,7 @@ static int tst_test_result_operation_execute struct sieve_match_type mcht = SIEVE_MATCH_TYPE_DEFAULT(is_match_type); struct sieve_stringlist *value_list, *key_list; int index = 0; - int ret; + int match, ret; /* * Read operands @@ -228,17 +228,17 @@ static int tst_test_result_operation_execute /* Read optional operands */ for (;;) { sieve_number_t number; - int ret; + int opt; - if ( (ret=sieve_match_opr_optional_read - (renv, address, &opt_code, &cmp, &mcht)) < 0 ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (opt=sieve_match_opr_optional_read + (renv, address, &opt_code, &ret, &cmp, &mcht)) < 0 ) + return ret; - if ( ret == 0 ) break; + if ( opt == 0 ) break; if ( opt_code == OPT_INDEX ) { - if ( !sieve_opr_number_read(renv, address, "index", &number) ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_number_read(renv, address, "index", &number)) <= 0 ) + return ret; index = (int) number; } else { sieve_runtime_trace_error(renv, "invalid optional operand"); @@ -247,8 +247,9 @@ static int tst_test_result_operation_execute } /* Read key-list */ - if ( (key_list=sieve_opr_stringlist_read(renv, address, "key-list")) == NULL ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_stringlist_read(renv, address, "key-list", &key_list)) + <= 0 ) + return ret; /* * Perform operation @@ -261,16 +262,12 @@ static int tst_test_result_operation_execute value_list = testsuite_result_stringlist_create(renv, index); /* Perform match */ - ret = sieve_match(renv, &mcht, &cmp, value_list, key_list); + if ( (match=sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret)) < 0 ) + return ret; /* Set test result for subsequent conditional jump */ - if ( ret >= 0 ) { - sieve_interpreter_set_test_result(renv->interp, ret > 0); - return SIEVE_EXEC_OK; - } - - sieve_runtime_trace_error(renv, "invalid string-list item"); - return SIEVE_EXEC_BIN_CORRUPT; + sieve_interpreter_set_test_result(renv->interp, match > 0); + return SIEVE_EXEC_OK; } diff --git a/src/testsuite/tst-test-script-compile.c b/src/testsuite/tst-test-script-compile.c index 58ec3f413..4d4760118 100644 --- a/src/testsuite/tst-test-script-compile.c +++ b/src/testsuite/tst-test-script-compile.c @@ -109,13 +109,15 @@ static int tst_test_script_compile_operation_execute { string_t *script_name; bool result = TRUE; + int ret; /* * Read operands */ - if ( !sieve_opr_string_read(renv, address, "script-name", &script_name) ) - return SIEVE_EXEC_BIN_CORRUPT; + if ( (ret=sieve_opr_string_read(renv, address, "script-name", &script_name)) + <= 0 ) + return ret; /* * Perform operation diff --git a/src/testsuite/tst-test-script-run.c b/src/testsuite/tst-test-script-run.c index c59d91013..aaf9d471e 100644 --- a/src/testsuite/tst-test-script-run.c +++ b/src/testsuite/tst-test-script-run.c @@ -111,12 +111,12 @@ static bool tst_test_script_run_operation_dump /* Dump optional operands */ for (;;) { - int ret; + int opt; - if ( (ret=sieve_opr_optional_dump(denv, address, &opt_code)) < 0 ) + if ( (opt=sieve_opr_optional_dump(denv, address, &opt_code)) < 0 ) return FALSE; - if ( ret == 0 ) break; + if ( opt == 0 ) break; switch ( opt_code ) { case OPT_APPEND_RESULT: @@ -148,12 +148,12 @@ static int tst_test_script_run_operation_execute /* Optional operands */ for (;;) { - int ret; + int opt; - if ( (ret=sieve_opr_optional_read(renv, address, &opt_code)) < 0 ) + if ( (opt=sieve_opr_optional_read(renv, address, &opt_code)) < 0 ) return SIEVE_EXEC_BIN_CORRUPT; - if ( ret == 0 ) break; + if ( opt == 0 ) break; switch ( opt_code ) { case OPT_APPEND_RESULT: -- GitLab