diff --git a/src/lib-sieve/sieve-code.c b/src/lib-sieve/sieve-code.c
index 276d1a8381495d168c784597b52f7245a79c7ac9..af0e1cae0b54da54dfd82de16cbc30a5d1b95d6a 100644
--- a/src/lib-sieve/sieve-code.c
+++ b/src/lib-sieve/sieve-code.c
@@ -216,7 +216,10 @@ static struct sieve_extension_obj_registry oprd_default_reg =
 
 sieve_size_t sieve_operand_emit_code
 	(struct sieve_binary *sbin, const struct sieve_operand *opr, int ext_id)
-{	
+{
+	/* A sanity check on the emitted operand */
+	i_assert( !((opr->extension != NULL) && (ext_id < 0)) );
+	
 	return sieve_extension_emit_obj
 		(sbin, &oprd_default_reg, opr, operands, ext_id);
 }
@@ -758,7 +761,10 @@ static struct sieve_extension_obj_registry oprt_default_reg =
 
 sieve_size_t sieve_operation_emit_code
 	(struct sieve_binary *sbin, const struct sieve_operation *op, int ext_id)
-{	
+{
+	/* A sanity check on the emitted operation */
+	i_assert( !((op->extension != NULL) && (ext_id < 0)) );
+		
 	return sieve_extension_emit_obj
 		(sbin, &oprt_default_reg, op, operations, ext_id);
 }
diff --git a/src/lib-sieve/sieve-objects.c b/src/lib-sieve/sieve-objects.c
index ca4bb74b33079c8e6f20b0c58a4f604bc70ee42c..1358a577e4b5d6580933337bc5a125787d44a732 100644
--- a/src/lib-sieve/sieve-objects.c
+++ b/src/lib-sieve/sieve-objects.c
@@ -27,7 +27,7 @@ const struct sieve_object *sieve_opr_object_read_data
 	const struct sieve_extension_obj_registry *reg;
 	unsigned int obj_code; 
 
-	if ( operand->class != opclass )
+	if ( operand == NULL || operand->class != opclass )
 		return NULL;
 	
 	reg = (struct sieve_extension_obj_registry *) operand->interface;
diff --git a/src/testsuite/testsuite-common.c b/src/testsuite/testsuite-common.c
index e61a35e3b7c124eb18c27b61607483db8f2ebcad..5a613850a48a8b649263f8e84ff64e1aca8a9c58 100644
--- a/src/testsuite/testsuite-common.c
+++ b/src/testsuite/testsuite-common.c
@@ -134,16 +134,21 @@ bool testsuite_validator_context_initialize(struct sieve_validator *valdtr)
 		p_new(pool, struct testsuite_validator_context, 1);
 	
 	/* Setup object registry */
-	ctx->object_registrations = hash_create
-		(pool, pool, 0, str_hash, (hash_cmp_callback_t *) strcmp);
-
-	testsuite_register_core_objects(pool, ctx);
+	ctx->object_registrations = sieve_validator_object_registry_create(valdtr);
+	testsuite_register_core_objects(ctx);
 	
 	sieve_validator_extension_set_context(valdtr, ext_testsuite_my_id, ctx);
 
 	return TRUE;
 }
 
+struct testsuite_validator_context *testsuite_validator_context_get
+(struct sieve_validator *valdtr)
+{
+	return (struct testsuite_validator_context *)
+		sieve_validator_extension_get_context(valdtr, ext_testsuite_my_id);
+}
+
 /* 
  * Generator context 
  */
diff --git a/src/testsuite/testsuite-common.h b/src/testsuite/testsuite-common.h
index 2edbea9f2ce61923f9803bd0a914129d374825f6..cdf9c3092a1730c63b999c7c9c6ae6faf51d42a9 100644
--- a/src/testsuite/testsuite-common.h
+++ b/src/testsuite/testsuite-common.h
@@ -21,10 +21,12 @@ void testsuite_envelope_set_auth_user(const char *value);
 /* Testsuite validator context */
 
 struct testsuite_validator_context {
-	struct hash_table *object_registrations;
+	struct sieve_validator_object_registry *object_registrations;
 };
 
 bool testsuite_validator_context_initialize(struct sieve_validator *valdtr);
+struct testsuite_validator_context *testsuite_validator_context_get
+	(struct sieve_validator *valdtr);
 
 /* Testsuite generator context */
 
diff --git a/src/testsuite/testsuite-objects.c b/src/testsuite/testsuite-objects.c
index c990fe2518d73a35aa244393cefedced6f71a808..3f2420f15654c8ed505c806779dacf4755ea31e9 100644
--- a/src/testsuite/testsuite-objects.c
+++ b/src/testsuite/testsuite-objects.c
@@ -16,15 +16,6 @@
 
 #include "testsuite-common.h"
 #include "testsuite-objects.h"
-
-/* 
- * Types
- */
- 
-struct testsuite_object_registration {
-	int ext_id;
-	const struct testsuite_object *object;
-};
  
 /* 
  * Testsuite core objects
@@ -42,72 +33,43 @@ const struct testsuite_object *testsuite_core_objects[] = {
 const unsigned int testsuite_core_objects_count =
 	N_ELEMENTS(testsuite_core_objects);
 
-/* 
- * Forward declarations
- */
- 
-static void _testsuite_object_register
-	(pool_t pool, struct testsuite_validator_context *ctx, 
-		const struct testsuite_object *obj, int ext_id);
-
 /* 
  * Testsuite object registry
  */
  
-static inline struct testsuite_validator_context *
-	_get_validator_context(struct sieve_validator *valdtr)
-{
-	return (struct testsuite_validator_context *) 
-		sieve_validator_extension_get_context(valdtr, ext_testsuite_my_id);
-}
- 
-static void _testsuite_object_register
-(pool_t pool, struct testsuite_validator_context *ctx, 
-	const struct testsuite_object *obj, int ext_id) 
-{	
-	struct testsuite_object_registration *reg;
-	
-	reg = p_new(pool, struct testsuite_object_registration, 1);
-	reg->object = obj;
-	reg->ext_id = ext_id;
-
-	hash_insert(ctx->object_registrations, (void *) obj->identifier, (void *) reg);
-}
- 
 void testsuite_object_register
-(struct sieve_validator *valdtr, const struct testsuite_object *obj, int ext_id) 
+(struct sieve_validator *valdtr, const struct testsuite_object *tobj, 
+	int ext_id) 
 {
-	pool_t pool = sieve_validator_pool(valdtr);
-	struct testsuite_validator_context *ctx = _get_validator_context(valdtr);
-
-	_testsuite_object_register(pool, ctx, obj, ext_id);
+	struct testsuite_validator_context *ctx = testsuite_validator_context_get
+		(valdtr);
+	
+	sieve_validator_object_registry_add
+		(ctx->object_registrations, &tobj->object, ext_id);
 }
 
 const struct testsuite_object *testsuite_object_find
 (struct sieve_validator *valdtr, const char *identifier, int *ext_id) 
 {
-	struct testsuite_validator_context *ctx = _get_validator_context(valdtr);		
-	struct testsuite_object_registration *reg =
-		(struct testsuite_object_registration *) 
-			hash_lookup(ctx->object_registrations, identifier);
-			
-	if ( reg == NULL ) return NULL;
-
-	if ( ext_id != NULL ) *ext_id = reg->ext_id;
+	struct testsuite_validator_context *ctx = testsuite_validator_context_get
+		(valdtr);
+	const struct sieve_object *object = 
+		sieve_validator_object_registry_find
+			(ctx->object_registrations, identifier, ext_id);
 
-  return reg->object;
+  return (const struct testsuite_object *) object;
 }
 
 void testsuite_register_core_objects
-	(pool_t pool, struct testsuite_validator_context *ctx)
+	(struct testsuite_validator_context *ctx)
 {
 	unsigned int i;
 	
 	/* Register core testsuite objects */
 	for ( i = 0; i < testsuite_core_objects_count; i++ ) {
-		const struct testsuite_object *object = testsuite_core_objects[i];
-		
-		_testsuite_object_register(pool, ctx, object, ext_testsuite_my_id);
+		sieve_validator_object_registry_add
+			(ctx->object_registrations, &(testsuite_core_objects[i]->object), 
+				ext_testsuite_my_id);
 	}
 }
  
@@ -115,27 +77,25 @@ void testsuite_register_core_objects
  * Testsuite object code
  */ 
  
-const struct sieve_operand_class testsuite_object_oprclass = 
-	{ "testsuite-object" };
+const struct sieve_operand_class sieve_testsuite_object_operand_class = 
+	{ "TESTSUITE-OBJECT" };
 
-const struct testsuite_object_operand_interface testsuite_object_oprint = {
-	SIEVE_EXT_DEFINE_OBJECTS(testsuite_core_objects)
-};
+static const struct sieve_extension_obj_registry core_testsuite_objects =
+	SIEVE_EXT_DEFINE_OBJECTS(testsuite_core_objects);
 
 const struct sieve_operand testsuite_object_operand = { 
 	"testsuite-object",
 	&testsuite_extension, 
 	TESTSUITE_OPERAND_OBJECT, 
-	&testsuite_object_oprclass,
-	&testsuite_object_oprint
+	&sieve_testsuite_object_operand_class,
+	&core_testsuite_objects
 };
 
 static void testsuite_object_emit
 (struct sieve_binary *sbin, const struct testsuite_object *obj, int ext_id,
 	int member_id)
 { 
-	(void) sieve_operand_emit_code(sbin, obj->operand, ext_id);	
-	(void) sieve_binary_emit_byte(sbin, obj->code);
+	sieve_opr_object_emit(sbin, &obj->object, ext_id);
 	
 	if ( obj->get_member_id != NULL ) {
 		(void) sieve_binary_emit_byte(sbin, (unsigned char) member_id);
@@ -145,23 +105,10 @@ static void testsuite_object_emit
 const struct testsuite_object *testsuite_object_read
 (struct sieve_binary *sbin, sieve_size_t *address)
 {
-	const struct sieve_operand *operand;
-	const struct testsuite_object_operand_interface *intf;	
-	unsigned int obj_code; 
-
-	operand = sieve_operand_read(sbin, address);
-	if ( operand == NULL || operand->class != &testsuite_object_oprclass ) 
-		return NULL;
+	const struct sieve_operand *operand = sieve_operand_read(sbin, address);
 	
-	intf = operand->interface;
-	if ( intf == NULL ) 
-		return NULL;
-			
-	if ( !sieve_binary_read_byte(sbin, address, &obj_code) ) 
-		return NULL;
-
-	return sieve_extension_get_object
-		(struct testsuite_object, intf->testsuite_objects, obj_code);
+	return (const struct testsuite_object *) sieve_opr_object_read_data
+		(sbin, operand, &sieve_testsuite_object_operand_class, address);
 }
 
 const struct testsuite_object *testsuite_object_read_member
@@ -190,12 +137,12 @@ const char *testsuite_object_member_name
 		if ( object->get_member_name != NULL )
 			member = object->get_member_name(member_id);
 	} else 
-		return object->identifier;
+		return object->object.identifier;
 		
 	if ( member == NULL )	
-		return t_strdup_printf("%s.%d", object->identifier, member_id);
+		return t_strdup_printf("%s.%d", object->object.identifier, member_id);
 	
-	return t_strdup_printf("%s.%s", object->identifier, member);
+	return t_strdup_printf("%s.%s", object->object.identifier, member);
 }
 
 bool testsuite_object_dump
@@ -210,7 +157,8 @@ bool testsuite_object_dump
 		== NULL )
 		return FALSE;
 	
-	sieve_code_dumpf(denv, "TESTSUITE_OBJECT: %s", 
+	sieve_code_dumpf(denv, "%s: %s",
+		sieve_testsuite_object_operand_class.name, 
 		testsuite_object_member_name(object, member_id));
 	
 	return TRUE;
@@ -311,18 +259,14 @@ static const char *tsto_envelope_get_member_name(int id);
 static bool tsto_envelope_set_member(int id, string_t *value);
 
 const struct testsuite_object message_testsuite_object = { 
-	"message",
-	TESTSUITE_OBJECT_MESSAGE,
-	&testsuite_object_operand,
+	SIEVE_OBJECT("message",	&testsuite_object_operand, TESTSUITE_OBJECT_MESSAGE),
 	NULL, NULL, 
 	tsto_message_set_member, 
 	NULL
 };
 
 const struct testsuite_object envelope_testsuite_object = { 
-	"envelope",
-	TESTSUITE_OBJECT_ENVELOPE,
-	&testsuite_object_operand,
+	SIEVE_OBJECT("envelope", &testsuite_object_operand, TESTSUITE_OBJECT_ENVELOPE),
 	tsto_envelope_get_member_id, 
 	tsto_envelope_get_member_name,
 	tsto_envelope_set_member, 
diff --git a/src/testsuite/testsuite-objects.h b/src/testsuite/testsuite-objects.h
index 6719afd18dcceb620113c40dc338b48bfe7044be..b86fcf5c1993f2da9d31b2ee9dc73a1ecb1041a3 100644
--- a/src/testsuite/testsuite-objects.h
+++ b/src/testsuite/testsuite-objects.h
@@ -1,6 +1,9 @@
 #ifndef __TESTSUITE_OBJECTS_H
 #define __TESTSUITE_OBJECTS_H
 
+#include "sieve-common.h"
+#include "sieve-objects.h"
+
 #include "testsuite-common.h"
 
 /* Testsuite object operand */
@@ -14,9 +17,7 @@ extern const struct sieve_operand_class testsuite_object_oprclass;
 /* Testsuite object access */
 
 struct testsuite_object {
-	const char *identifier;
-	unsigned int code;
-	const struct sieve_operand *operand;
+	struct sieve_object object;
 	
 	int (*get_member_id)(const char *identifier);
 	const char *(*get_member_name)(int id);
@@ -29,10 +30,10 @@ struct testsuite_object {
 const struct testsuite_object *testsuite_object_find
 	(struct sieve_validator *valdtr, const char *identifier, int *ext_id);
 void testsuite_object_register
-	(struct sieve_validator *valdtr, const struct testsuite_object *obj, 
+	(struct sieve_validator *valdtr, const struct testsuite_object *tobj, 
 		int ext_id);		
 void testsuite_register_core_objects
-	(pool_t pool, struct testsuite_validator_context *ctx);
+	(struct testsuite_validator_context *ctx);
 		
 /* Testsuite object argument */