From 8b9f5e2ed8df09b099c8dda57702a220e7487052 Mon Sep 17 00:00:00 2001 From: Stephan Bosch <stephan.bosch@dovecot.fi> Date: Thu, 4 Jan 2018 00:39:38 +0100 Subject: [PATCH] lib-sieve: imap4flags extension: Fix binary corruption occurring when setflag/addflag/removeflag flag-list is a variable. The original implementation checked the first operand for being a variable. Obviously, when the assigned flag string is just a variable, this doesn't work. This causes the flag list to be recognized erroneously as a variable flags string. Fixed the problem by explicitly emitting an omitted operand when there is no second argument for a setflag/addflag/removeflag. Because the new byte code format is incompatible, the extension version is bumped to 1. --- src/lib-sieve/plugins/imap4flags/cmd-flag.c | 40 +++++++++++-------- .../plugins/imap4flags/ext-imap4flags.c | 1 + 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/lib-sieve/plugins/imap4flags/cmd-flag.c b/src/lib-sieve/plugins/imap4flags/cmd-flag.c index 6e550d9b1..26456691b 100644 --- a/src/lib-sieve/plugins/imap4flags/cmd-flag.c +++ b/src/lib-sieve/plugins/imap4flags/cmd-flag.c @@ -122,6 +122,8 @@ const struct sieve_operation_def removeflag_operation = { static bool cmd_flag_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) { + struct sieve_ast_argument *arg1, *arg2; + /* Emit operation */ if ( sieve_command_is(cmd, cmd_setflag) ) sieve_operation_emit(cgenv->sblock, cmd->ext, &setflag_operation); @@ -130,10 +132,21 @@ static bool cmd_flag_generate else if ( sieve_command_is(cmd, cmd_removeflag) ) sieve_operation_emit(cgenv->sblock, cmd->ext, &removeflag_operation); - /* Generate arguments */ - if ( !sieve_generate_arguments(cgenv, cmd, NULL) ) - return FALSE; + arg1 = cmd->first_positional; + arg2 = sieve_ast_argument_next(arg1); + if ( arg2 == NULL ) { + /* No variable */ + sieve_opr_omitted_emit(cgenv->sblock); + if ( !sieve_generate_argument(cgenv, arg1, cmd) ) + return FALSE; + } else { + /* Full command */ + if ( !sieve_generate_argument(cgenv, arg1, cmd) ) + return FALSE; + if ( !sieve_generate_argument(cgenv, arg2, cmd) ) + return FALSE; + } return TRUE; } @@ -155,14 +168,14 @@ bool cmd_flag_operation_dump return FALSE; } - if ( sieve_operand_is_variable(&oprnd) ) { + if ( !sieve_operand_is_omitted(&oprnd) ) { return 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, &oprnd, address, "list of flags"); + sieve_opr_stringlist_dump(denv, address, "list of flags"); } /* @@ -190,10 +203,10 @@ static int cmd_flag_operation_execute return ret; /* Variable operand (optional) */ - if ( sieve_operand_is_variable(&oprnd) ) { + if ( !sieve_operand_is_omitted(&oprnd) ) { /* Read the variable operand */ if ( (ret=sieve_variable_operand_read_data - (renv, &oprnd, address, "variable", &storage, &var_index)) <= 0 ) + (renv, &oprnd, address, "variable", &storage, &var_index)) <= 0 ) return ret; /* Read flag list */ @@ -202,21 +215,14 @@ static int cmd_flag_operation_execute return ret; /* Flag-list operand */ - } else if ( sieve_operand_is_stringlist(&oprnd) ) { + } else { storage = NULL; var_index = 0; /* Read flag list */ - if ( (ret=sieve_opr_stringlist_read_data - (renv, &oprnd, address, "flag-list", &flag_list)) <= 0 ) + if ( (ret=sieve_opr_stringlist_read(renv, address, + "flag-list", &flag_list)) <= 0 ) return ret; - - /* Invalid */ - } else { - 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.c b/src/lib-sieve/plugins/imap4flags/ext-imap4flags.c index 3b908c0d5..23230c110 100644 --- a/src/lib-sieve/plugins/imap4flags/ext-imap4flags.c +++ b/src/lib-sieve/plugins/imap4flags/ext-imap4flags.c @@ -50,6 +50,7 @@ static bool ext_imap4flags_interpreter_load const struct sieve_extension_def imap4flags_extension = { .name = "imap4flags", + .version = 1, .validator_load = ext_imap4flags_validator_load, .interpreter_load = ext_imap4flags_interpreter_load, SIEVE_EXT_DEFINE_OPERATIONS(imap4flags_operations), -- GitLab