diff --git a/TODO b/TODO
index 150d2e69b698d85148ecb6f128224a86696aa1d8..f27a1091dd90ee56e3ce96b0dc017977f8b88abc 100644
--- a/TODO
+++ b/TODO
@@ -11,10 +11,10 @@ Next (in order of descending priority/precedence):
       of the ADDRESS-PART argument specified.
     - Header test does not strip trailing whitespace
 * Code cleanup 
-* Make sure cmusieve can be replaced seamlessly with the new plugin.
 * Full security review. Enforce limits on number of created objects, script 
   size, execution time, etc...
-* Make simple test suite for the base functionality
+* Finish the test suite for the base functionality
+* Make sure cmusieve can be replaced seamlessly with the new plugin.
 
 * ## MAKE A FIRST RELEASE ##
 
diff --git a/src/lib-sieve/cmd-keep.c b/src/lib-sieve/cmd-keep.c
index d7881b59da2dcedc150b138868dea0562455924a..333578947dfb6bda57fe430f6d7cf516085e7905 100644
--- a/src/lib-sieve/cmd-keep.c
+++ b/src/lib-sieve/cmd-keep.c
@@ -107,10 +107,9 @@ static int cmd_keep_operation_execute
 	}
 	
 	/* Optional operands (side effects only) */
-	if ( !sieve_interpreter_handle_optional_operands(renv, address, &slist) ) {
-		sieve_runtime_trace_error(renv, "invalid optional operands");
-		return SIEVE_EXEC_BIN_CORRUPT;
-	}
+	if ( (ret=sieve_interpreter_handle_optional_operands
+		(renv, address, &slist)) <= 0 ) 
+		return ret;
 
 	sieve_runtime_trace(renv, "KEEP action");
 	
diff --git a/src/lib-sieve/cmd-redirect.c b/src/lib-sieve/cmd-redirect.c
index 5b2e4a68858df5378d29276006d39b6e97cfca73..08a882c721bf1ee59ef558a2a4589f031cf39e5a 100644
--- a/src/lib-sieve/cmd-redirect.c
+++ b/src/lib-sieve/cmd-redirect.c
@@ -204,10 +204,9 @@ static int cmd_redirect_operation_execute
 	}
 
 	/* Optional operands (side effects) */
-	if ( !sieve_interpreter_handle_optional_operands(renv, address, &slist) ) {
-		sieve_runtime_trace_error(renv, "invalid optional operands");
-		return SIEVE_EXEC_BIN_CORRUPT;
-	}
+	if ( (ret=sieve_interpreter_handle_optional_operands
+		(renv, address, &slist)) <= 0 )
+		return ret;
 
 	/* Read the address */
 	if ( !sieve_opr_string_read(renv, address, &redirect) ) {
diff --git a/src/lib-sieve/ext-fileinto.c b/src/lib-sieve/ext-fileinto.c
index d5ff69726e18ff3ca1684a4408170506aca4b904..9e26739c4c748b8c82e39b27321be899e5c01b5f 100644
--- a/src/lib-sieve/ext-fileinto.c
+++ b/src/lib-sieve/ext-fileinto.c
@@ -153,13 +153,10 @@ static bool ext_fileinto_operation_dump
         return FALSE;
 
 	if ( !sieve_code_dumper_print_optional_operands(denv, address) ) {
-		sieve_binary_corrupt(denv->sbin, 
-			"FILEINTO: failed to dump optional operands");
 		return FALSE;
 	}
 
 	if ( !sieve_opr_string_dump(denv, address) ) {
-		sieve_binary_corrupt(denv->sbin, "FILEINTO: failed to dump string operand");
 		return FALSE;
 	}
 	
@@ -180,14 +177,16 @@ static int ext_fileinto_operation_execute
 	int ret = 0;
 
 	/* Source line */
-    if ( !sieve_code_source_line_read(renv, address, &source_line) )
+    if ( !sieve_code_source_line_read(renv, address, &source_line) ) {
+		sieve_runtime_trace_error(renv, "invalid source line");
         return SIEVE_EXEC_BIN_CORRUPT;
+	}
 	
-	if ( !sieve_interpreter_handle_optional_operands(renv, address, &slist) )
-		return SIEVE_EXEC_BIN_CORRUPT;
+	if ( (ret=sieve_interpreter_handle_optional_operands(renv, address, &slist)) <= 0 )
+		return ret;
 
 	if ( !sieve_opr_string_read(renv, address, &folder) ) {
-		sieve_binary_corrupt(renv->sbin, "FILEINTO: failed to read string operand");
+		sieve_runtime_trace_error(renv, "invalid folder operand");
 		return SIEVE_EXEC_BIN_CORRUPT;
 	}
 
diff --git a/src/lib-sieve/ext-reject.c b/src/lib-sieve/ext-reject.c
index 8511e59f6c33ce8cf00378c5d5687ce10cf6d8da..6b7f31ae8cd956adbd3a457afa9dc66b64a8ecb8 100644
--- a/src/lib-sieve/ext-reject.c
+++ b/src/lib-sieve/ext-reject.c
@@ -217,16 +217,21 @@ static int ext_reject_operation_execute
 	int ret;
 
 	/* Source line */
-    if ( !sieve_code_source_line_read(renv, address, &source_line) )
+    if ( !sieve_code_source_line_read(renv, address, &source_line) ) {
+		sieve_runtime_trace_error(renv, "invalid source line");
         return SIEVE_EXEC_BIN_CORRUPT;
+	}
 	
 	/* Optional operands (side effects) */
-	if ( !sieve_interpreter_handle_optional_operands(renv, address, &slist) )
-		return SIEVE_EXEC_BIN_CORRUPT;
+	if ( (ret=sieve_interpreter_handle_optional_operands
+		(renv, address, &slist)) <= 0 )
+		return ret;
 
 	/* Read rejection reason */
-	if ( !sieve_opr_string_read(renv, address, &reason) )
+	if ( !sieve_opr_string_read(renv, address, &reason) ) {
+		sieve_runtime_trace_error(renv, "invalid reason operand");
 		return SIEVE_EXEC_BIN_CORRUPT;
+	}
 
 	sieve_runtime_trace(renv, "REJECT action (\"%s\")", str_c(reason));
 
diff --git a/src/lib-sieve/sieve-actions.c b/src/lib-sieve/sieve-actions.c
index 3f5d20084bf2487b4fbcc134ae968abeaea04eae..f1139461c0b84e97c80fcef144c61358da2d461e 100644
--- a/src/lib-sieve/sieve-actions.c
+++ b/src/lib-sieve/sieve-actions.c
@@ -48,7 +48,6 @@ bool sieve_opr_side_effect_dump
 	if ( seffect->dump_context != NULL ) {
 		sieve_code_descend(denv);
 		if ( !seffect->dump_context(seffect, denv, address) ) {
-			sieve_binary_corrupt(denv->sbin, "failed to read side effect context");
 			return FALSE;	
 		}
 		sieve_code_ascend(denv);
diff --git a/src/lib-sieve/sieve-binary.c b/src/lib-sieve/sieve-binary.c
index cf7cf4658179445f62bbbf5f73b9c5bd83da0d7f..2dc8166448814e599358052ed2c5836a81b18a7e 100644
--- a/src/lib-sieve/sieve-binary.c
+++ b/src/lib-sieve/sieve-binary.c
@@ -274,15 +274,6 @@ bool sieve_binary_script_older
 	return ( sieve_script_older(script, sbin->file->st.st_mtime) );
 }
 
-void sieve_binary_corrupt(struct sieve_binary *sbin, const char *fmt, ...)
-{
-	va_list args;
-	
-	va_start(args, fmt);
-	printf("BINARY CORRUPT: %s.\n", t_strdup_vprintf(fmt, args));
-	va_end(args);
-}
-
 /* 
  * Block management 
  */
diff --git a/src/lib-sieve/sieve-binary.h b/src/lib-sieve/sieve-binary.h
index a278d4900817db5cc7bcd862268d57a3978224bd..4ccc26aa66467c84f6678454a28cecf9383bdd93 100644
--- a/src/lib-sieve/sieve-binary.h
+++ b/src/lib-sieve/sieve-binary.h
@@ -18,8 +18,6 @@ const char *sieve_binary_path(struct sieve_binary *sbin);
 bool sieve_binary_script_older
 	(struct sieve_binary *sbin, struct sieve_script *script);
 
-void sieve_binary_corrupt(struct sieve_binary *sbin, const char *fmt, ...);
-
 void sieve_binary_activate(struct sieve_binary *sbin);
 
 bool sieve_binary_save
diff --git a/src/lib-sieve/sieve-code-dumper.c b/src/lib-sieve/sieve-code-dumper.c
index 619a0f7342d1d82a45ecf9329a5fc95c2aeb04b5..8f1b55a613a729eabadfcf4f67f2e13026c9347e 100644
--- a/src/lib-sieve/sieve-code-dumper.c
+++ b/src/lib-sieve/sieve-code-dumper.c
@@ -117,7 +117,6 @@ bool sieve_code_dumper_print_optional_operands
 		
 		while ( opt_code != 0 ) {			
 			if ( !sieve_operand_optional_read(denv->sbin, address, &opt_code) ) {
-				sieve_binary_corrupt(denv->sbin, "failed to read optional operand");
 				return FALSE;
 			}
 
diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c
index edb5adc6d0b875573d8f61ab1f022b12a09339ee..73e2b518312fb1e44e9812d4fb464b6583e2392a 100644
--- a/src/lib-sieve/sieve-interpreter.c
+++ b/src/lib-sieve/sieve-interpreter.c
@@ -293,7 +293,7 @@ bool sieve_interpreter_get_test_result
 
 /* Operations and operands */
 
-bool sieve_interpreter_handle_optional_operands
+int sieve_interpreter_handle_optional_operands
 	(const struct sieve_runtime_env *renv, sieve_size_t *address,
 		struct sieve_side_effects_list **list)
 {
@@ -301,8 +301,10 @@ bool sieve_interpreter_handle_optional_operands
 	
 	if ( sieve_operand_optional_present(renv->sbin, address) ) {
 		while ( opt_code != 0 ) {
-			if ( !sieve_operand_optional_read(renv->sbin, address, &opt_code) )
-				return FALSE;
+			if ( !sieve_operand_optional_read(renv->sbin, address, &opt_code) ) {
+				sieve_runtime_trace_error(renv, "invalid optional operand");
+				return SIEVE_EXEC_BIN_CORRUPT;
+			}
 
 			if ( opt_code == SIEVE_OPT_SIDE_EFFECT ) {
 				void *context = NULL;
@@ -313,12 +315,17 @@ bool sieve_interpreter_handle_optional_operands
 				const struct sieve_side_effect *seffect = 
 					sieve_opr_side_effect_read(renv, address);
 
-				if ( seffect == NULL ) return FALSE;
+				if ( seffect == NULL ) {
+					sieve_runtime_trace_error(renv, "invalid side effect operand");
+					return SIEVE_EXEC_BIN_CORRUPT;
+				}
 			
 				if ( list != NULL ) {
 					if ( seffect->read_context != NULL && !seffect->read_context
-						(seffect, renv, address, &context) )
-						return FALSE;
+						(seffect, renv, address, &context) ) {
+						sieve_runtime_trace_error(renv, "invalid side effect context");
+						return SIEVE_EXEC_BIN_CORRUPT;
+					}
 				
 					sieve_side_effects_list_add(*list, seffect, context);
 				}
diff --git a/src/lib-sieve/sieve-interpreter.h b/src/lib-sieve/sieve-interpreter.h
index f8c5d8b028b704f95484c386603e605b0093d027..86ab5d446aada0a29ece50f4f0f413acae32fffd 100644
--- a/src/lib-sieve/sieve-interpreter.h
+++ b/src/lib-sieve/sieve-interpreter.h
@@ -105,7 +105,7 @@ const void *sieve_interpreter_extension_get_context
 
 /* Opcodes and operands */
 	
-bool sieve_interpreter_handle_optional_operands
+int sieve_interpreter_handle_optional_operands
 	(const struct sieve_runtime_env *renv, sieve_size_t *address,
 		struct sieve_side_effects_list **list);