diff --git a/TODO b/TODO
index f4c28665a32c1a27422156a569a993955cabef01..da882720d27c553c5a812c45667d0828e39f25e5 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 089cbc59f491812349a4fe1c9fa55e1c10cf8026..0fcece096d739658271490763af9e6b2bbfb3931 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 27f3782c98a0f03f783e8a103a91f2bfc4ec0990..7f56149306cbd7cc7b6e390acfe1fddfdae0a850 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 4d439b4a1e1dc4c93da8280f82955a5a72502c40..dcf991647718aa1e270bb4e16aa592f0c1b19fac 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 f50698ba5ae79dafdb0b595eecc14ecacc66bc13..2de4996200e70f208f95d92c6478b91fb5e674ff 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 da5607a7c9ef8a7026138622ba8a76d127bea3f6..80b4b8b9eeceb69dd6af389979605e86732d767e 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 5ca7ed783a9fcac865b5667446eda42a6720f9b0..8663da25cf80cdd17d849760fd149707412513f6 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 f3033bc87a5af181305a285055b5b15e1c3a9947..36b4a6cf843ea7cf62594062264d89b9266f4ee4 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 7891b17e5c1977661fb60a3a31de693ce516b1d5..ce69112500f436e98295975354be8284e24c4ef0 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 90b62c3b5eaf07be99a10edf7efbd00a6b83659b..201cf404717ca1db7c9042796fad6ddad28a7dbd 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 69a4f0530627c26b6a1769cebf018019800b9668..b331e76aca5ffe23ebd49462df1df4dd0a7ffe3a 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 8ee7fb53fb500a3efacdddc8a1f4983ed23f5022..73c982929720fb9609001e30e6f2b3cbc70cf274 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", &notify_uri) )
-		return SIEVE_EXEC_BIN_CORRUPT;
+	if ( (ret=sieve_opr_string_read(renv, address, "notify-uri", &notify_uri))
+		<= 0 )
+		return ret;
 	
 	/* Read notify capability */
-	if ( !sieve_opr_string_read
-		(renv, address, "notify-capability", &notify_capability) )
-		return SIEVE_EXEC_BIN_CORRUPT;
+	if ( (ret=sieve_opr_string_read
+		(renv, address, "notify-capability", &notify_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 493bc3dc81e5dfbb97c912dd98e655866bd00281..1774de2cc880bcf354709da2495b3e1cd98cb8f2 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", &notify_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 5f9496d0f19f2eef23f79a431e1a9bd6b3367ecf..b25ac49cb123a77f7873f0ed2fc6282baee9db56 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 71471d352f708fee0695010f27dfe1569eab9508..59564da886a9c44040e255103cbefaef66d41aa8 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 51ba9602defe2dd7a33c7c05ecacfac2311f2b35..63003e25a1e910a39cdef2684a98e7aa4031118c 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 2cf116e61fbf238133c4cbd3ece9ec5215ddc514..fc7e708344462c578dbccdf9b07148abfa4b8d1e 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 b6ea02ed51ef11b86d09fd57053a20beb2eb0f7e..a3e6837a1649b91a13fdd250f4000969828ae0ae 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 972e987d7c5159b9542d659ba74b17dfbbbb3349..4c50b3f1962636eae687729f95c90f2aed36e1fc 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 0a920006ddec43ae4032d0a84c6d77385bafeb9f..5c68d9de330c6d25691bb97730c0fb8a3711ed21 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 e0e03ba76b7eee27b80dfb8fab9d9d4cd687bbf5..b50620b08ab178b58c3bb27b8fa19d88bc857310 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 dd98841c9ae721752ebe5b3c8c52fd6c10b601bd..ea70c23dea2b310b08df90362b1c4abd565f17bf 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 98b417319c76f54b577737d08681a4eb41e626e0..e4c45809a289646ea2260f5645a2c9ec4bf3771c 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 cda0a3e3a33b44f6c4cdca0334ed42340834d8d7..8a977724405913480b1d84400e330d64970c2c99 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 ec2d452f8ffdb77a58ebcf8cd4a77630a2bfe6f2..45736768e03400db214edd25a8537a57f589e0e8 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 aafcb523e134436502cae8621c3ae379205c59cb..d2ec4cb486dfee874d2c9abe84c44790662121d8 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 2f8897de9922a67f1a765d1fe56c9addb7fccdeb..9ee1aec0a147240a7992db7927fe771d5ceb8383 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 11ef017317fb658d08d794958a9141ef0adc1147..0e294d8e5ce19a8f36fda436f34260b29bbf464f 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 5ef1e9f1d51d5ba50e629d48b46bb2cbd3854aaa..6d1f74ecc9cf16fb2701d47fdc3c892b710aaaef 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 b4184f1ec005d6b9c66849392de01e70783bb1eb..5d7f0bdd6f5d506120182b4347049c8e0ae414a0 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 4aa3f59901d9c4ec13488d0d25f60b021be5b346..a2e8a439b04ddcf04b401e698cfd92cf6ea40160 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 c858580e62dfda837d504bfb31fdf547284eb376..9ab035209314238380822d12d63f858c3102fea5 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 5971dbf76b2fc663d2ae024f36b80960bef2057d..13b696a5469b00ada026f2b0120df950d587d7d8 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 8c8797e01d379339d746b57a20a3907b0b08a052..3e7a09524d06f5fbba6e450fe28e3e5ba845e5fa 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 e89b40a5e824eb27c527a2e1ae85d20992043616..0d983b750929a10467d193f05bb6f88d4e8da3e4 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 d64f77d4b98a7ebf1d914c39cb9f2b4b240181ca..1c237a9de5b5138ad61cae3bb0dff4f75a22b44e 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 7f8ce700e84879b20082acb6b89a2d31a681f936..302baa5fc39e15e180e2ada2caf03935dae363a6 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 512c072fc3a80cfd04c5630850207ce836a14ed0..d0058425d64fdd739d26243be0c99d6c1a1d07d1 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 2a0e68f3c4a588d7a50da6a55b3f47170b6d4d3a..79d633c001f0306b0b6e92e7b61c2f14e523a5ad 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 19c0a2e36739fce0f6a9b5d6c5dcf954e3045b4e..9cf43775149944d9eec35832bcac354bc515f6e1 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 e32bae1eb45135d7aebc4c539f3d13878841f1bc..804d72acde204e911b90177ba46f7e34ee2dbaf9 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 30b7472695e99ba3724febdba5d4a0d368c195ad..ba346be20b50b155b545017f8f8cbf4e86a8aca2 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 614dd1b5efc6a1125942ae6ca5506a640a3cb5cc..bfbe1d54253bbebab1156f3d002bf36ce51f1977 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 07e7a4746900b25167dc70a9cea9ff163a6398e1..49d60627682379e443e89975957396c6f2a33c64 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 a22088eff0396ccafc805425269d03f65f91bd11..9f1dbd0ae731fadffd2965ec576883cf6dfe9a8d 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 d3f7bc38f84401ca374badca7af154bfcc0a444a..caed0f341cb95774efad12c47be461992d3530d9 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 f5446a0891718069a69f47a82d32e06a26bdd14f..cf37f5a78a9fd655edc94ec3c0a9eb5ba0a986b1 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 1e6567ce19719a35c9aacebef4027278373f8d05..ec2fee9c70d911a0f276f14bf94028a72088a175 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 4aa6c55aaa10913f3257d6dd601646b50734977f..c35e2eac1cfc8b17ae9f1854a0684119a8495cc8 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 9f1b85f8c761f66a02750964012de96756e0aa51..7e2fedfcf899d5222ba4b9b8e560b6f2f1a7184e 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 f10238d12af64bbf43d334b8eb2d1407ac571abd..53602545548b2bd56894d68001a9c35d7856e3b8 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 8448606765dc081d11204e99fbfc03f6cb44a7f9..724b57040f08cd1d037c8eb47648c480a1062ba1 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 2fb27867ef5a18e7803fcfa24a72695764f9b13c..04f464e82e9e28611707c1d74e1b35e39018c060 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 a8aef73278275c241406c38f799ca419612bce92..0b8b6619f358ff517fdc4022867573b3c697221d 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 91d2ca61e2a31f66e0999992feb5c1db4d16c93c..92cc7630dd29714947c0cff54260d3ca4033288e 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 238acc05315cab80989161f521e181a77ebc5630..b504de77d60760fe82e27d7570093881cc24980b 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 8ab5cc345855e627c14c0aba455dbe6ac5124409..7a508b54525c8e490035347a9b21193329e5e5b7 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 2623e4e35e0094d72aab7d6e5df8d49f738090fe..7c5d2c911568373b61ab8f8f1dbd79489f342411 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 32077d6c80f4c582b90bd9fecee5fa8184edfa09..527bc0d21e89b5437975719e097aa6c38c929cb4 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 40fb7f5c958c4dc074be57ac2b187d2ed0d4622d..123be9ee169495c98a922090314042d6713e53bc 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 97b54a19434bd0a01de3aa7cca65942236c1ca11..039d9d934a908dfbda1112d650fd224986ee46c0 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 9c0c11c1ef8773691efdbb063a2df599fdc5b51e..c02626403e75414537ff312ccf7d5ff986cf0eaa 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 e73d31244d05304187ac9cb105c680d298be5b1d..f7340397b64fcfe4432ee02f48678ed44a9d3dab 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 bb6d79c4d32ee7163ada870bbc17b91794c105f3..d36f3e9a313c1242e34623a0a2adb13e48122af7 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, &param) )
 		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, &param) )
-		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 9d7f1e58afd34066e912487b1c0d51436d70e823..925ae552540559f712e86d2f77cba971d1a1d128 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 156bf434ac6a4a5cb02793f6fbaad1f26c19ce1a..fab25e3f04f29af72b072d7842bd030896a21d24 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 9a9889bd9c70524712da11c188567c18d2d9dd99..178a8648c7f058219ec76cfc00fdbdab6c8a273e 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 58ec3f413bd611a7f1d83918339bbe6bfc532f02..4d476011869de63d4625f8ff2c9409e2cb9289b5 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 c59d91013e53e0ab953d5979a009f168d339c2e0..aaf9d471e685b4622654f8ecdd8b940ebe9c7709 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: