diff --git a/src/lib-sieve/sieve-address-parts.c b/src/lib-sieve/sieve-address-parts.c
index 1ecfa9f75680fdc68952dc1dafad3ded8544f1ff..79e6a40242e06c64031d83519f61f204d31a7bfd 100644
--- a/src/lib-sieve/sieve-address-parts.c
+++ b/src/lib-sieve/sieve-address-parts.c
@@ -27,9 +27,10 @@
  */
  
 static void opr_address_part_emit
-	(struct sieve_binary *sbin, struct sieve_address_part *addrp);
+	(struct sieve_binary *sbin, const struct sieve_address_part *addrp);
 static void opr_address_part_emit_ext
-	(struct sieve_binary *sbin, struct sieve_address_part *addrp, int ext_id);
+	(struct sieve_binary *sbin, const struct sieve_address_part *addrp, 
+		int ext_id);
 
 /* 
  * Address-part 'extension' 
@@ -193,43 +194,39 @@ struct sieve_operand address_part_operand =
  */
   
 static bool tag_address_part_is_instance_of
-	(struct sieve_validator *validator, const char *tag)
+(struct sieve_validator *validator, struct sieve_command_context *cmd,
+	struct sieve_ast_argument *arg)
 {
-	return sieve_address_part_find(validator, tag, NULL) != NULL;
+	int ext_id;
+	struct sieve_address_part_context *adpctx;
+	const struct sieve_address_part *addrp = sieve_address_part_find
+		(validator, sieve_ast_argument_tag(arg), &ext_id);
+
+	if ( addrp == NULL ) return FALSE;
+
+	adpctx = p_new(sieve_command_pool(cmd), struct sieve_address_part_context, 1);
+	adpctx->command_ctx = cmd;
+	adpctx->address_part = addrp;
+	adpctx->ext_id = ext_id;
+
+	/* Store address-part in context */
+	arg->context = (void *) adpctx;
+
+	return TRUE;
 }
  
 static bool tag_address_part_validate
-	(struct sieve_validator *validator, 
-	struct sieve_ast_argument **arg, 
-	struct sieve_command_context *cmd)
+(struct sieve_validator *validator ATTR_UNUSED, struct sieve_ast_argument **arg, 
+	struct sieve_command_context *cmd ATTR_UNUSED)
 {
-	int ext_id;
-	const struct sieve_address_part *addrp;
-
+	/* FIXME: Currenly trivial, but might need to allow for further validation for
+	 * future extensions.
+	 */
+	 
 	/* Syntax:   
 	 *   ":localpart" / ":domain" / ":all" (subject to extension)
    */
 	
-	/* Get address_part from registry */
-	addrp = sieve_address_part_find
-		(validator, sieve_ast_argument_tag(*arg), &ext_id);
-	
-	/* In theory, addrp can never be NULL, because we must have found it earlier
-	 * to get here.
-	 */
-	if ( addrp == NULL ) {
-		sieve_command_validate_error(validator, cmd, 
-			"unknown address-part modifier '%s' "
-			"(this error should not occur and is probably a bug)", 
-			sieve_ast_argument_strc(*arg));
-
-		return FALSE;
-	}
-
-	/* Store address-part in context */
-	(*arg)->context = (void *) addrp;
-	(*arg)->ext_id = ext_id;
-	
 	/* Skip tag */
 	*arg = sieve_ast_argument_next(*arg);
 
@@ -239,14 +236,14 @@ static bool tag_address_part_validate
 /* Code generation */
 
 static void opr_address_part_emit
-	(struct sieve_binary *sbin, struct sieve_address_part *addrp)
+(struct sieve_binary *sbin, const struct sieve_address_part *addrp)
 { 
 	(void) sieve_operand_emit_code(sbin, SIEVE_OPERAND_ADDRESS_PART);
 	(void) sieve_binary_emit_byte(sbin, addrp->code);
 }
 
 static void opr_address_part_emit_ext
-	(struct sieve_binary *sbin, struct sieve_address_part *addrp, int ext_id)
+(struct sieve_binary *sbin, const struct sieve_address_part *addrp, int ext_id)
 { 
 	unsigned char addrp_code = SIEVE_ADDRESS_PART_CUSTOM + 
 		sieve_binary_extension_get_index(sbin, ext_id);
@@ -321,8 +318,9 @@ static bool tag_address_part_generate
 	struct sieve_command_context *cmd ATTR_UNUSED)
 {
 	struct sieve_binary *sbin = sieve_generator_get_binary(generator);
-	struct sieve_address_part *addrp =
-		(struct sieve_address_part *) arg->context;
+	struct sieve_address_part_context *adpctx =
+		(struct sieve_address_part_context *) arg->context;
+	const struct sieve_address_part *addrp = adpctx->address_part;	
 	
 	if ( addrp->extension == NULL ) {
 		if ( addrp->code < SIEVE_ADDRESS_PART_CUSTOM )
@@ -330,7 +328,7 @@ static bool tag_address_part_generate
 		else
 			return FALSE;
 	} else {
-		opr_address_part_emit_ext(sbin, addrp, arg->ext_id);
+		opr_address_part_emit_ext(sbin, addrp, adpctx->ext_id);
 	} 
 		
 	return TRUE;
diff --git a/src/lib-sieve/sieve-address-parts.h b/src/lib-sieve/sieve-address-parts.h
index 1049e608c62902d0db28b1bee19f847ab4eb0ea2..12368faf324439242f8563958e4b67613f9a4fd7 100644
--- a/src/lib-sieve/sieve-address-parts.h
+++ b/src/lib-sieve/sieve-address-parts.h
@@ -36,6 +36,13 @@ struct sieve_address_part_extension {
 		(unsigned int code);
 };
 
+struct sieve_address_part_context {
+	struct sieve_command_context *command_ctx;
+	const struct sieve_address_part *address_part;
+	
+	int ext_id;
+};
+
 void sieve_address_parts_link_tags
 	(struct sieve_validator *validator, 
 		struct sieve_command_registration *cmd_reg, int id_code);
diff --git a/src/lib-sieve/sieve-ast.h b/src/lib-sieve/sieve-ast.h
index 101c9d6f9b9f15ebdb074a66a14f1c5f0171bfe5..1cbfcbefd2595024c92172bd6ccffcc2c5df2455 100644
--- a/src/lib-sieve/sieve-ast.h
+++ b/src/lib-sieve/sieve-ast.h
@@ -89,9 +89,6 @@ struct sieve_ast_argument {
 	
 	/* Context data associated with this ast element */
 	void *context;
-	
-	/* Indicates whether this argument is part of which extension */
-	int ext_id;
 };
 
 struct sieve_ast_list {
diff --git a/src/lib-sieve/sieve-commands.c b/src/lib-sieve/sieve-commands.c
index 675557c5fc561acde48e4d029f612337f08cf35d..0ab71477d0561a77f243218619bda5ba43987612 100644
--- a/src/lib-sieve/sieve-commands.c
+++ b/src/lib-sieve/sieve-commands.c
@@ -195,7 +195,8 @@ inline struct sieve_command_context *sieve_command_parent_context
 }
 
 struct sieve_command_context *sieve_command_context_create
-	(struct sieve_ast_node *cmd_node, const struct sieve_command *command)
+	(struct sieve_ast_node *cmd_node, const struct sieve_command *command,
+		struct sieve_command_registration *reg)
 {
 	struct sieve_command_context *cmd;
 	
@@ -203,6 +204,7 @@ struct sieve_command_context *sieve_command_context_create
 	
 	cmd->ast_node = cmd_node;	
 	cmd->command = command;
+	cmd->cmd_reg = reg;
 	
 	cmd->block_exit_command = NULL;
 	
diff --git a/src/lib-sieve/sieve-commands.h b/src/lib-sieve/sieve-commands.h
index bd86026b3f9e9bb44f6868b8e9323fc1d24969d8..36ce0b0ac569930052e3ae2b9171ad46795e8fbb 100644
--- a/src/lib-sieve/sieve-commands.h
+++ b/src/lib-sieve/sieve-commands.h
@@ -11,17 +11,20 @@
 struct sieve_argument {
 	const char *identifier;
 	
-	bool (*is_instance_of)(struct sieve_validator *validator, const char *tag);
+	bool (*is_instance_of)
+		(struct sieve_validator *validator, struct sieve_command_context *cmdctx,
+			struct sieve_ast_argument *arg);
 	
 	bool (*validate)
-	(struct sieve_validator *validator, struct sieve_ast_argument **arg, 
-		struct sieve_command_context *context);
+		(struct sieve_validator *validator, struct sieve_ast_argument **arg, 
+			struct sieve_command_context *context);
 	bool (*validate_context)
-	(struct sieve_validator *validator, struct sieve_ast_argument *arg, 
-		struct sieve_command_context *context);
+		(struct sieve_validator *validator, struct sieve_ast_argument *arg, 
+			struct sieve_command_context *context);
 		
-	bool (*generate)(struct sieve_generator *generator, struct sieve_ast_argument *arg, 
-		struct sieve_command_context *context);
+	bool (*generate)
+		(struct sieve_generator *generator, struct sieve_ast_argument *arg, 
+			struct sieve_command_context *context);
 };
 
 extern const struct sieve_argument number_argument;
@@ -62,7 +65,7 @@ struct sieve_command {
 struct sieve_command_context {
 	const struct sieve_command *command;
 	
-	/* The registration of this command in the validator */
+	/* The registration of this command in the validator (sieve-validator.h) */
 	struct sieve_command_registration *cmd_reg;
 
 	/* The ast node of this command */
@@ -79,7 +82,8 @@ struct sieve_command_context {
 };
 
 struct sieve_command_context *sieve_command_context_create
-	(struct sieve_ast_node *cmd_node, const struct sieve_command *command);
+	(struct sieve_ast_node *cmd_node, const struct sieve_command *command,
+		struct sieve_command_registration *reg);
 		
 const char *sieve_command_type_name(const struct sieve_command *command);		
 		
diff --git a/src/lib-sieve/sieve-comparators.c b/src/lib-sieve/sieve-comparators.c
index 234d0916ad65ed655dc2d66580a2b45504b7c050..341196ac8e3dda3590ada78838edf0628b96e05c 100644
--- a/src/lib-sieve/sieve-comparators.c
+++ b/src/lib-sieve/sieve-comparators.c
@@ -26,9 +26,9 @@ extern const struct sieve_comparator *sieve_core_comparators[];
 extern const unsigned int sieve_core_comparators_count;
 
 static void opr_comparator_emit
-	(struct sieve_binary *sbin, struct sieve_comparator *cmp);
+	(struct sieve_binary *sbin, const struct sieve_comparator *cmp);
 static void opr_comparator_emit_ext
-	(struct sieve_binary *sbin, struct sieve_comparator *cmp, int ext_id);
+	(struct sieve_binary *sbin, const struct sieve_comparator *cmp, int ext_id);
 
 static int cmp_i_octet_compare
 	(const struct sieve_comparator *cmp,
@@ -217,6 +217,7 @@ static bool tag_comparator_validate
 	struct sieve_command_context *cmd)
 {
 	int ext_id;
+	struct sieve_comparator_context *cmpctx;
 	struct sieve_ast_argument *tag = *arg;
 	const struct sieve_comparator *cmp;
 	
@@ -244,12 +245,19 @@ static bool tag_comparator_validate
 		return FALSE;
 	}
 	
-	/* String argument not needed during code generation, so detach it from argument list */
+	/* String argument not needed during code generation, so detach it from 
+	 * argument list 
+	 */
 	*arg = sieve_ast_arguments_detach(*arg, 1);
 
+	/* Create context */
+	cmpctx = p_new(sieve_command_pool(cmd), struct sieve_comparator_context, 1);
+	cmpctx->command_ctx = cmd;
+	cmpctx->comparator = cmp;
+	cmpctx->ext_id = ext_id;
+
 	/* Store comparator in context */
-	tag->context = (void *) cmp;
-	tag->ext_id = ext_id;
+	tag->context = (void *) cmpctx;
 	
 	return TRUE;
 }
@@ -280,14 +288,14 @@ inline const struct sieve_comparator *sieve_comparator_tag_get
 /* Code generation */
 
 static void opr_comparator_emit
-	(struct sieve_binary *sbin, struct sieve_comparator *cmp)
+	(struct sieve_binary *sbin, const struct sieve_comparator *cmp)
 { 
 	(void) sieve_operand_emit_code(sbin, SIEVE_OPERAND_COMPARATOR);
 	(void) sieve_binary_emit_byte(sbin, cmp->code);
 }
 
 static void opr_comparator_emit_ext
-	(struct sieve_binary *sbin, struct sieve_comparator *cmp, int ext_id)
+	(struct sieve_binary *sbin, const struct sieve_comparator *cmp, int ext_id)
 { 
 	unsigned char cmp_code = SIEVE_COMPARATOR_CUSTOM + 
 		sieve_binary_extension_get_index(sbin, ext_id);
@@ -361,7 +369,9 @@ static bool tag_comparator_generate
 	struct sieve_command_context *cmd ATTR_UNUSED)
 {
 	struct sieve_binary *sbin = sieve_generator_get_binary(generator);
-	struct sieve_comparator *cmp = (struct sieve_comparator *) arg->context;
+	struct sieve_comparator_context *cmpctx = 
+		(struct sieve_comparator_context *) arg->context;
+	const struct sieve_comparator *cmp = cmpctx->comparator;
 	
 	if ( cmp->extension == NULL ) {
 		if ( cmp->code < SIEVE_COMPARATOR_CUSTOM )
@@ -369,7 +379,7 @@ static bool tag_comparator_generate
 		else
 			return FALSE;
 	} else {
-		opr_comparator_emit_ext(sbin, cmp, arg->ext_id);
+		opr_comparator_emit_ext(sbin, cmp, cmpctx->ext_id);
 	} 
 		
 	return TRUE;
diff --git a/src/lib-sieve/sieve-comparators.h b/src/lib-sieve/sieve-comparators.h
index 340fc50cd197238f82ec00ea8593b1f288bf803a..61016ded7799299404edbd9865b7dae93fc63300 100644
--- a/src/lib-sieve/sieve-comparators.h
+++ b/src/lib-sieve/sieve-comparators.h
@@ -51,6 +51,13 @@ struct sieve_comparator_extension {
 		(unsigned int code);
 };
 
+struct sieve_comparator_context {
+	struct sieve_command_context *command_ctx;
+	const struct sieve_comparator *comparator;
+	
+	int ext_id;
+};
+
 extern const struct sieve_argument comparator_tag;
 
 void sieve_comparators_link_tag
diff --git a/src/lib-sieve/sieve-match-types.c b/src/lib-sieve/sieve-match-types.c
index b2e013c43dd5410f1b64fb7fc393cca3342b14b7..967948309b66a0c499ce83abbc4215fb403d5f01 100644
--- a/src/lib-sieve/sieve-match-types.c
+++ b/src/lib-sieve/sieve-match-types.c
@@ -191,48 +191,39 @@ struct sieve_operand match_type_operand =
  */
   
 static bool tag_match_type_is_instance_of
-	(struct sieve_validator *validator, const char *tag)
-{
-	return sieve_match_type_find(validator, tag, NULL) != NULL;
-}
- 
-static bool tag_match_type_validate
-	(struct sieve_validator *validator, 
-	struct sieve_ast_argument **arg, 
-	struct sieve_command_context *cmd)
+(struct sieve_validator *validator, struct sieve_command_context *cmd, 
+	struct sieve_ast_argument *arg)
 {
 	int ext_id;
 	struct sieve_match_type_context *mtctx;
-	const struct sieve_match_type *mtch;
-
-	/* Syntax:   
-	 *   ":is" / ":contains" / ":matches" (subject to extension)
-   	 */
-	
-	/* Get match_type from registry */
-	mtch = sieve_match_type_find
-		(validator, sieve_ast_argument_tag(*arg), &ext_id);
-	
-	/* In theory, mtch can never be NULL, because we must have found it earlier
-	 * to get here.
-	 */
-	if ( mtch == NULL ) {
-		sieve_command_validate_error(validator, cmd, 
-			"unknown match-type modifier '%s' "
-			"(this error should not occur and is probably a bug)", 
-			sieve_ast_argument_strc(*arg));
-
-		return FALSE;	
-	}
-
+	const struct sieve_match_type *mtch = 
+		sieve_match_type_find(validator, sieve_ast_argument_tag(arg), &ext_id);
+		
+	if ( mtch == NULL ) return FALSE;	
+		
 	/* Create context */
 	mtctx = p_new(sieve_command_pool(cmd), struct sieve_match_type_context, 1);
 	mtctx->match_type = mtch;
+	mtctx->ext_id = ext_id;
 	mtctx->command_ctx = cmd;
 	
-	(*arg)->context = (void *) mtctx;
-	(*arg)->ext_id = ext_id;
+	arg->context = (void *) mtctx;
 	
+	return TRUE;
+}
+ 
+static bool tag_match_type_validate
+(struct sieve_validator *validator, struct sieve_ast_argument **arg, 
+	struct sieve_command_context *cmd ATTR_UNUSED)
+{
+	struct sieve_match_type_context *mtctx = 
+		(struct sieve_match_type_context *) (*arg)->context;
+	const struct sieve_match_type *mtch = mtctx->match_type;
+
+	/* Syntax:   
+	 *   ":is" / ":contains" / ":matches" (subject to extension)
+	 */
+		
 	/* Skip tag */
 	*arg = sieve_ast_argument_next(*arg);
 	
@@ -378,7 +369,7 @@ static bool tag_match_type_generate
 		else
 			return FALSE;
 	} else {
-		opr_match_type_emit_ext(sbin, mtctx->match_type, arg->ext_id);
+		opr_match_type_emit_ext(sbin, mtctx->match_type, mtctx->ext_id);
 	} 
 			
 	return TRUE;
diff --git a/src/lib-sieve/sieve-match-types.h b/src/lib-sieve/sieve-match-types.h
index df976a090c0b6b20e5563529c75e2fab5d9b45b7..810992897e137bdb316b3221cc8a22d6b0b4639e 100644
--- a/src/lib-sieve/sieve-match-types.h
+++ b/src/lib-sieve/sieve-match-types.h
@@ -64,6 +64,8 @@ struct sieve_match_type_context {
 	struct sieve_command_context *command_ctx;
 	const struct sieve_match_type *match_type;
 	
+	int ext_id;
+	
 	/* Context data could be used in the future to pass data between validator and
 	 * generator in match types that use extra parameters. Currently not 
 	 * necessary, not even for the relational extension.
diff --git a/src/lib-sieve/sieve-validator.c b/src/lib-sieve/sieve-validator.c
index f73e590a951400bbf5f8633b13279a342a5c0fa1..6c70f2a90f509fabdeb9b95c1b2b1180b86a11b5 100644
--- a/src/lib-sieve/sieve-validator.c
+++ b/src/lib-sieve/sieve-validator.c
@@ -246,8 +246,8 @@ static void sieve_validator_register_unknown_command
 	(void)_sieve_validator_register_command(validator, &unknown_command, command);		
 }
 
-static const struct sieve_command *
-	sieve_validator_find_command(struct sieve_validator *validator, const char *command) 
+const struct sieve_command *sieve_validator_find_command
+(struct sieve_validator *validator, const char *command) 
 {
   struct sieve_command_registration *record = 
   	sieve_validator_find_command_registration(validator, command);
@@ -328,19 +328,22 @@ void sieve_validator_register_tag
 }
 
 static void sieve_validator_register_unknown_tag
-	(struct sieve_validator *validator, struct sieve_command_registration *cmd_reg, 
+(struct sieve_validator *validator, struct sieve_command_registration *cmd_reg, 
 	const char *tag) 
 {
 	_sieve_validator_register_tag(validator, cmd_reg, &_unknown_tag, tag, 0);
 }
 
 static const struct sieve_argument *sieve_validator_find_tag
-	(struct sieve_validator *validator, 
-		struct sieve_command_registration *cmd_reg, 
-		const char *tag, unsigned int *id_code) 
+(struct sieve_validator *validator, struct sieve_command_context *cmd, 
+	struct sieve_ast_argument *arg, unsigned int *id_code) 
 {
+	const char *tag;
 	unsigned int i;
+	struct sieve_command_registration *cmd_reg = cmd->cmd_reg;
 	const struct sieve_tag_registration *reg;
+		
+	tag = sieve_ast_argument_tag(arg);
 	
 	*id_code = 0;
 	
@@ -360,7 +363,9 @@ static const struct sieve_argument *sieve_validator_find_tag
 	  	struct sieve_tag_registration * const *reg = 
 	  		array_idx(&cmd_reg->instanced_tags, i);
   	
-	  	if ( (*reg)->tag != NULL && (*reg)->tag->is_instance_of(validator, tag) ) {
+	  	if ( (*reg)->tag != NULL && 
+	  		(*reg)->tag->is_instance_of(validator, cmd, arg) ) 
+	  	{
 	  		*id_code = (*reg)->id_code;
 	  		return (*reg)->tag;
 	  	}
@@ -540,39 +545,19 @@ static bool sieve_validate_command_arguments
 	int arg_count = cmd->command->positional_arguments;
 	int real_count = 0;
 	struct sieve_ast_argument *arg;
-	struct sieve_command_registration *cmd_reg = NULL;
+	struct sieve_command_registration *cmd_reg = cmd->cmd_reg;
 	
-	/* Validate any tags that might be present */\
+	/* Validate any tags that might be present */
 	
 	arg = sieve_ast_argument_first(cmd->ast_node);
-	
-	/* Get the command registration to get access to its tag registry */
-	if ( sieve_ast_argument_type(arg) == SAAT_TAG ) {
-		cmd_reg = sieve_validator_find_command_registration(validator, cmd->command->identifier);
 		
-		if ( cmd_reg == NULL ) {
-			sieve_command_validate_error(
-				validator, cmd, 
-				"!!BUG!!: the '%s' %s seemed to be known before, "
-				"but somehow its registration got lost",
-				cmd->command->identifier, sieve_command_type_name(cmd->command)
-			);
-			i_error("BUG: the '%s' %s seemed to be known before, "
-				"but somehow its registration got lost",
-				cmd->command->identifier, sieve_command_type_name(cmd->command)
-			);
-			return FALSE; 
-		}
-	}
-	
-	/* Parse tagged and optional arguments */
+	/* Visit tagged and optional arguments */
 	while ( sieve_ast_argument_type(arg) == SAAT_TAG ) {
 		unsigned int id_code;
 		struct sieve_ast_argument *tag_arg = arg;
 		struct sieve_ast_argument *parg; 
 		const struct sieve_argument *tag = 
-			sieve_validator_find_tag
-				(validator, cmd_reg, sieve_ast_argument_tag(arg), &id_code);
+			sieve_validator_find_tag(validator, cmd, arg, &id_code);
 		
 		if ( tag == NULL ) {
 			sieve_command_validate_error(validator, cmd, 
@@ -765,13 +750,16 @@ static bool sieve_validate_command
 {
 	enum sieve_ast_type ast_type = sieve_ast_node_type(cmd_node);
 	bool result = TRUE;
+	struct sieve_command_registration *cmd_reg;
 	const struct sieve_command *command;
 	
 	i_assert( ast_type == SAT_TEST || ast_type == SAT_COMMAND );
 	
 	/* Verify the command specified by this node */
 	
-	command = sieve_validator_find_command(validator, cmd_node->identifier);
+	cmd_reg = sieve_validator_find_command_registration
+		(validator, cmd_node->identifier);
+	command = cmd_reg->command;
 	
 	if ( command != NULL ) {
 		/* Identifier = "" when the command was previously marked as unknown */
@@ -788,7 +776,7 @@ static bool sieve_validate_command
 			} 
 			 
 			struct sieve_command_context *ctx = 
-				sieve_command_context_create(cmd_node, command); 
+				sieve_command_context_create(cmd_node, command, cmd_reg); 
 			cmd_node->context = ctx;
 		
 			/* If pre-validation fails, don't bother to validate further 
diff --git a/src/lib-sieve/sieve-validator.h b/src/lib-sieve/sieve-validator.h
index fcf96d13ebaf34b482204a77862e357deb661265..c3f7d2f61e8df19aaa91ee402b6aac9af3fa2656 100644
--- a/src/lib-sieve/sieve-validator.h
+++ b/src/lib-sieve/sieve-validator.h
@@ -47,6 +47,9 @@ void sieve_validator_critical
 /* Command/Test registration */
 void sieve_validator_register_command
 	(struct sieve_validator *validator, const struct sieve_command *command);
+const struct sieve_command *sieve_validator_find_command
+	(struct sieve_validator *validator, const char *command);	
+	
 void sieve_validator_register_external_tag
 	(struct sieve_validator *validator, const struct sieve_argument *tag, 
 		const char *command, int id_code);