diff --git a/src/lib-sieve/plugins/include/cmd-include.c b/src/lib-sieve/plugins/include/cmd-include.c
index d6331a599f39f18b7af18dc23799ce4292bad932..a76477b571f164ef84e4cea8e8c991b25cc9b96b 100644
--- a/src/lib-sieve/plugins/include/cmd-include.c
+++ b/src/lib-sieve/plugins/include/cmd-include.c
@@ -12,6 +12,7 @@
 #include "sieve-dump.h"
 
 #include "ext-include-common.h"
+#include "ext-include-binary.h"
 
 /* 
  * Include command 
@@ -213,17 +214,17 @@ static bool cmd_include_generate
 {
 	struct cmd_include_context_data *ctx_data = 
 		(struct cmd_include_context_data *) cmd->data;
-	unsigned int block_id;
+	const struct ext_include_script_info *included;
 
 	/* Compile (if necessary) and include the script into the binary.
 	 * This yields the id of the binary block containing the compiled byte code.  
 	 */
 	if ( !ext_include_generate_include
-		(cgenv, cmd, ctx_data->location, ctx_data->script, &block_id) )
+		(cgenv, cmd, ctx_data->location, ctx_data->script, &included) )
  		return FALSE;
  		
  	sieve_operation_emit_code(cgenv->sbin, &include_operation);
-	sieve_binary_emit_offset(cgenv->sbin, block_id); 
+	sieve_binary_emit_offset(cgenv->sbin, included->id); 
  	 		
 	return TRUE;
 }
@@ -236,12 +237,18 @@ static bool opc_include_dump
 (const struct sieve_operation *op ATTR_UNUSED,
 	const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
-	int block;
+	const struct ext_include_script_info *included;
+	int include_id;
 	
-	if ( !sieve_binary_read_offset(denv->sbin, address, &block) )
+	if ( !sieve_binary_read_offset(denv->sbin, address, &include_id) )
+		return FALSE;
+
+	included = ext_include_binary_script_get_included(denv->sbin, include_id);
+	if ( included == NULL )
 		return FALSE;
 		
-	sieve_code_dumpf(denv, "INCLUDE [BLOCK: %d]", block);
+	sieve_code_dumpf(denv, "INCLUDE %s [ID: %d, BLOCK: %d]", 
+		sieve_script_name(included->script), include_id, included->block_id);
 	 
 	return TRUE;
 }
@@ -254,16 +261,14 @@ static int opc_include_execute
 (const struct sieve_operation *op ATTR_UNUSED,
 	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
-	int block;
+	int include_id;
 		
-	if ( !sieve_binary_read_offset(renv->sbin, address, &block) ) {
-		sieve_runtime_trace_error(renv, "invalid block operand");
+	if ( !sieve_binary_read_offset(renv->sbin, address, &include_id) ) {
+		sieve_runtime_trace_error(renv, "invalid include-id operand");
 		return SIEVE_EXEC_BIN_CORRUPT;
 	}
 	
-	sieve_runtime_trace(renv, "INCLUDE command (BLOCK: %d)", block);
-	
-	return ext_include_execute_include(renv, (unsigned int) block);
+	return ext_include_execute_include(renv, (unsigned int) include_id);
 }
 
 
diff --git a/src/lib-sieve/plugins/include/ext-include-binary.c b/src/lib-sieve/plugins/include/ext-include-binary.c
index 202bdc209ee560bd62dbbc6937bc3d9d80b2de57..9ce2770405ba547d195c2a3da59eecff05f54083 100644
--- a/src/lib-sieve/plugins/include/ext-include-binary.c
+++ b/src/lib-sieve/plugins/include/ext-include-binary.c
@@ -19,18 +19,13 @@
  * Types
  */
  
-struct _included_script {
-	struct sieve_script *script;
-	enum ext_include_script_location location;
-	
-	unsigned int block_id;
-};
- 
 struct ext_include_binary_context {
 	struct sieve_binary *binary;
 	unsigned int dependency_block;
 	
 	struct hash_table *included_scripts;
+	ARRAY_DEFINE(include_index, struct ext_include_script_info *);
+
 	struct sieve_variable_scope *global_vars;
 };
 
@@ -71,6 +66,7 @@ static struct ext_include_binary_context *ext_include_binary_create_context
 	ctx->included_scripts = hash_create(default_pool, pool, 0, 
 		(hash_callback_t *) sieve_script_hash, 
 		(hash_cmp_callback_t *) sieve_script_cmp);
+	p_array_init(&ctx->include_index, pool, 128);
 	
 	return ctx;
 }
@@ -116,14 +112,19 @@ struct ext_include_binary_context *ext_include_binary_init
 	return ctx;
 }
 
-void ext_include_binary_script_include
+/*
+ * Script inclusion
+ */
+
+const struct ext_include_script_info *ext_include_binary_script_include
 (struct ext_include_binary_context *binctx, struct sieve_script *script,
 	enum ext_include_script_location location, unsigned int block_id)
 {
 	pool_t pool = sieve_binary_pool(binctx->binary);
-	struct _included_script *incscript;
+	struct ext_include_script_info *incscript;
 	
-	incscript = p_new(pool, struct _included_script, 1);
+	incscript = p_new(pool, struct ext_include_script_info, 1);
+	incscript->id = array_count(&binctx->include_index);
 	incscript->script = script;
 	incscript->location = location;
 	incscript->block_id = block_id;
@@ -132,39 +133,64 @@ void ext_include_binary_script_include
 	sieve_script_ref(script);
 	
 	hash_insert(binctx->included_scripts, (void *) script, (void *) incscript);
+	array_append(&binctx->include_index, &incscript, 1);
+
+	return incscript;
 }
 
 bool ext_include_binary_script_is_included
 (struct ext_include_binary_context *binctx, struct sieve_script *script,
-	unsigned int *block_id)
+	const struct ext_include_script_info **script_info_r)
 {
-	struct _included_script *incscript = (struct _included_script *)
+	struct ext_include_script_info *incscript = (struct ext_include_script_info *)
 		hash_lookup(binctx->included_scripts, script);
 		
 	if ( incscript == 0 )
 		return FALSE;
 				
-	*block_id = incscript->block_id;
+	*script_info_r = incscript;
 	return TRUE;
 }
 
+const struct ext_include_script_info *ext_include_binary_script_get_included
+(struct sieve_binary *sbin, unsigned int include_id)
+{
+	struct ext_include_binary_context *binctx = 
+		ext_include_binary_get_context(sbin);
+		
+	if ( include_id < array_count(&binctx->include_index) ) {
+		struct ext_include_script_info *const *sinfo =
+			array_idx(&binctx->include_index, include_id);
+
+		return *sinfo;
+	}
+
+	return NULL;
+}
+
+/*
+ * Binary extension
+ */
+
 static bool ext_include_binary_save(struct sieve_binary *sbin)
 {
 	struct ext_include_binary_context *binctx = 
 		ext_include_binary_get_context(sbin);
-	struct hash_iterate_context *hctx = 
-		hash_iterate_init(binctx->included_scripts);
-	void *key, *value;
+	struct ext_include_script_info *const *scripts;
+	unsigned int script_count, i;
 	unsigned int prvblk;
 	bool result = TRUE;
 	
 	sieve_binary_block_clear(sbin, binctx->dependency_block);
 	if ( !sieve_binary_block_set_active(sbin, binctx->dependency_block, &prvblk) )	
 		return FALSE;
-			
-	sieve_binary_emit_integer(sbin, hash_count(binctx->included_scripts));	
-	while ( hash_iterate(hctx, &key, &value) ) {
-		struct _included_script *incscript = (struct _included_script *) value;
+
+	scripts = array_get(&binctx->include_index, &script_count);
+
+	sieve_binary_emit_integer(sbin, script_count);
+
+	for ( i = 0; i < script_count; i++ ) {
+		struct ext_include_script_info *incscript = scripts[i];
 
 		sieve_binary_emit_integer(sbin, incscript->block_id);
 		sieve_binary_emit_byte(sbin, incscript->location);
@@ -175,8 +201,6 @@ static bool ext_include_binary_save(struct sieve_binary *sbin)
 	
 	(void) sieve_binary_block_set_active(sbin, prvblk, NULL);
 
-	hash_iterate_deinit(&hctx);
-	
 	return result;
 }
 
@@ -236,7 +260,7 @@ static bool ext_include_binary_open(struct sieve_binary *sbin)
 			return FALSE;
 		}
 		
-		ext_include_binary_script_include(binctx, script, location, block_id);
+		(void)ext_include_binary_script_include(binctx, script, location, block_id);
 				
 		sieve_script_unref(&script);
 	}
@@ -260,7 +284,7 @@ static bool ext_include_binary_up_to_date(struct sieve_binary *sbin)
 	/* Release references to all included script objects */
 	hctx = hash_iterate_init(binctx->included_scripts);
 	while ( hash_iterate(hctx, &key, &value) ) {
-		struct _included_script *incscript = (struct _included_script *) value;
+		struct ext_include_script_info *incscript = (struct ext_include_script_info *) value;
 		
 		/* Is the binary newer than this dependency? */
 		if ( !sieve_binary_script_older(sbin, incscript->script) ) {
@@ -283,7 +307,7 @@ static void ext_include_binary_free(struct sieve_binary *sbin)
 	/* Release references to all included script objects */
 	hctx = hash_iterate_init(binctx->included_scripts);
 	while ( hash_iterate(hctx, &key, &value) ) {
-		struct _included_script *incscript = (struct _included_script *) value;
+		struct ext_include_script_info *incscript = (struct ext_include_script_info *) value;
 		
 		sieve_script_unref(&incscript->script);
 	}
@@ -325,7 +349,7 @@ bool ext_include_binary_dump(struct sieve_dumptime_env *denv)
 
 	hctx = hash_iterate_init(binctx->included_scripts);		
 	while ( hash_iterate(hctx, &key, &value) ) {
-		struct _included_script *incscript = (struct _included_script *) value;
+		struct ext_include_script_info *incscript = (struct ext_include_script_info *) value;
 
 		sieve_binary_dump_sectionf(denv, "Included %s script '%s' (block: %d)", 
 			_script_location(incscript->location), 
diff --git a/src/lib-sieve/plugins/include/ext-include-binary.h b/src/lib-sieve/plugins/include/ext-include-binary.h
index 36c27306c9e1a43e4b8901e0c2358a7e2a49c33c..06c7bbcb84a9daacd4abbc5f22a98274bab613cf 100644
--- a/src/lib-sieve/plugins/include/ext-include-binary.h
+++ b/src/lib-sieve/plugins/include/ext-include-binary.h
@@ -8,12 +8,27 @@ struct ext_include_binary_context;
 struct ext_include_binary_context *ext_include_binary_init
 	(struct sieve_binary *sbin, struct sieve_ast *ast);
 
-void ext_include_binary_script_include
+/*
+ * Including scripts
+ */
+
+struct ext_include_script_info {
+    unsigned int id;
+
+    struct sieve_script *script;
+    enum ext_include_script_location location;
+
+    unsigned int block_id;
+};
+
+const struct ext_include_script_info *ext_include_binary_script_include
 	(struct ext_include_binary_context *binctx, struct sieve_script *script,
 		enum ext_include_script_location location, unsigned int block_id);
 bool ext_include_binary_script_is_included
 	(struct ext_include_binary_context *binctx, struct sieve_script *script,
-		unsigned int *block_id);
+		const struct ext_include_script_info **script_info_r);
+const struct ext_include_script_info *ext_include_binary_script_get_included
+	(struct sieve_binary *sbin, unsigned int include_id);
 		
 bool ext_include_binary_dump(struct sieve_dumptime_env *denv);
 		
diff --git a/src/lib-sieve/plugins/include/ext-include-common.c b/src/lib-sieve/plugins/include/ext-include-common.c
index 86a676652137dd0485dff763ad2b1961837bafa3..184d3907d3eff8accf7f28b083baf8fdaaa4d81b 100644
--- a/src/lib-sieve/plugins/include/ext-include-common.c
+++ b/src/lib-sieve/plugins/include/ext-include-common.c
@@ -284,7 +284,7 @@ void ext_include_interpreter_context_init
 bool ext_include_generate_include
 (const struct sieve_codegen_env *cgenv, struct sieve_command_context *cmd,
 	enum ext_include_script_location location, struct sieve_script *script, 
-	unsigned *blk_id_r)
+	const struct ext_include_script_info **included_r)
 {
 	bool result = TRUE;
 	struct sieve_ast *ast;
@@ -296,9 +296,9 @@ bool ext_include_generate_include
 		ext_include_get_generator_context(gentr);
 	struct ext_include_generator_context *pctx;
 	struct sieve_error_handler *ehandler = sieve_generator_error_handler(gentr);
-	unsigned this_block_id, inc_block_id; 
+	const struct ext_include_script_info *included;
 		
-	*blk_id_r = 0;
+	*included_r = NULL;
 
 	/* Just to be sure: do not include more scripts when errors have occured 
 	 * already. 
@@ -330,14 +330,16 @@ bool ext_include_generate_include
 	binctx = ext_include_binary_init(sbin, cgenv->ast);
 
 	/* Is the script already compiled into the current binary? */
-	if ( !ext_include_binary_script_is_included(binctx, script, &inc_block_id) )	
+	if ( !ext_include_binary_script_is_included(binctx, script, &included) )	
 	{	
+		unsigned int inc_block_id, this_block_id;
 		const char *script_name = sieve_script_name(script);
 		
 		/* No, allocate a new block in the binary and mark the script as included.
 		 */
 		inc_block_id = sieve_binary_block_create(sbin);
-		ext_include_binary_script_include(binctx, script, location, inc_block_id);
+		included = ext_include_binary_script_include
+			(binctx, script, location, inc_block_id);
 		
 		/* Parse */
 		if ( (ast = sieve_parse(script, ehandler)) == NULL ) {
@@ -381,7 +383,7 @@ bool ext_include_generate_include
 		sieve_ast_unref(&ast);		
 	} 
 
-	if ( result ) *blk_id_r = inc_block_id;
+	if ( result ) *included_r = included;
 	
 	return result;
 }
@@ -391,11 +393,25 @@ bool ext_include_generate_include
  */
 
 bool ext_include_execute_include
-	(const struct sieve_runtime_env *renv, unsigned int block_id)
+	(const struct sieve_runtime_env *renv, unsigned int include_id)
 {
 	int result = TRUE;
-	struct ext_include_interpreter_context *ctx =
-		ext_include_get_interpreter_context(renv->interp);
+	struct ext_include_interpreter_context *ctx;
+	const struct ext_include_script_info *included;
+	unsigned int block_id;
+
+	/* Check for invalid include id (== corrupt binary) */
+	included = ext_include_binary_script_get_included(renv->sbin, include_id);
+	if ( included == NULL ) {
+		sieve_runtime_trace_error(renv, "invalid include id: %d", include_id);
+        return SIEVE_EXEC_BIN_CORRUPT;
+	}
+
+	ctx = ext_include_get_interpreter_context(renv->interp);
+	block_id = included->block_id;
+
+	sieve_runtime_trace(renv, "INCLUDE command (id: %d, script: %s, block: %d)", 
+		include_id, sieve_script_name(included->script), block_id);
 
 	if ( ctx->parent == NULL ) {
 		struct ext_include_interpreter_context *curctx;
@@ -424,15 +440,17 @@ bool ext_include_execute_include
 			result = ( sieve_interpreter_start
 				(subinterp, renv->msgdata, renv->scriptenv, renv->msgctx, renv->result, 
 					&interrupted) == 1 );
-		else
-			result = FALSE;
+		else {
+			sieve_runtime_trace_error(renv, "invalid block id: %d", block_id);
+			result = SIEVE_EXEC_BIN_CORRUPT;
+		}
 		
 		/* Included scripts can have includes of their own. This is not implemented
 		 * recursively. Rather, the sub-interpreter interrupts and defers the 
 		 * include to the top-level interpreter, which is here.
 		 */
-		if ( result && interrupted && !curctx->returned ) {
-			while ( result ) {
+		if ( result > 0 && interrupted && !curctx->returned ) {
+			while ( result > 0 ) {
 				if ( ( (interrupted && curctx->returned) || (!interrupted) ) && 
 					curctx->parent != NULL ) {
 					
@@ -477,8 +495,10 @@ bool ext_include_execute_include
 							result = ( sieve_interpreter_start
 								(subinterp, renv->msgdata, renv->scriptenv, renv->msgctx,
 									renv->result, &interrupted) == 1 );		 	
-						} else 
-							result = FALSE;
+						} else {
+							sieve_runtime_trace_error(renv, "invalid block id: %d", curctx->block_id);
+					        result = SIEVE_EXEC_BIN_CORRUPT;
+						}
 					} else {
 						/* Sub-interpreter was interrupted outside this extension, probably
 						 * stop command was executed. Generate an interrupt ourselves, 
diff --git a/src/lib-sieve/plugins/include/ext-include-common.h b/src/lib-sieve/plugins/include/ext-include-common.h
index fa005e49fad5982650e1d22b386623cebf3dff3c..91666d6efb28a2e2376ae4c517b30c98e64649bc 100644
--- a/src/lib-sieve/plugins/include/ext-include-common.h
+++ b/src/lib-sieve/plugins/include/ext-include-common.h
@@ -10,6 +10,12 @@
 
 #define EXT_INCLUDE_MAX_NESTING_LEVEL 10
 
+/* 
+ * Forward declarations
+ */
+
+struct ext_include_script_info;
+
 /* Extension */
 
 extern int ext_include_my_id;
@@ -74,7 +80,7 @@ void ext_include_register_generator_context
 bool ext_include_generate_include
 	(const struct sieve_codegen_env *cgenv, struct sieve_command_context *cmd,
 		enum ext_include_script_location location, struct sieve_script *script, 
-		unsigned *blk_id_r);
+		const struct ext_include_script_info **included_r);
 
 /* 
  * Interpreter context