From f6e23af1c5994363f8bb3bfd901f31c1cc6709ef Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Sun, 7 Sep 2008 15:41:59 +0200
Subject: [PATCH] Variables: made sure broken/malicious binary cannot allocate
 variable storage of arbitrary size.

---
 TODO                                          |  1 -
 .../plugins/include/ext-include-common.c      |  2 +-
 .../plugins/variables/ext-variables-common.c  | 33 ++++++++-----------
 .../variables/ext-variables-operands.c        |  4 +--
 .../plugins/variables/sieve-ext-variables.h   |  5 ++-
 5 files changed, 19 insertions(+), 26 deletions(-)

diff --git a/TODO b/TODO
index 7dbf0bd30..1756bdf69 100644
--- a/TODO
+++ b/TODO
@@ -5,7 +5,6 @@ Next (in order of descending priority/precedence):
 * Fix security issues:
 	- Impose limitations on the imapflags extension regarding the number of
 	  set flags and the length of each flag name.
-	- Malicious/Broken binary can allocate large variable storage
 * Finish the test suite for the base functionality
 * Improve debugging and error handling:
 	- Improve byte code dumping and trace functionality to be a little more 
diff --git a/src/lib-sieve/plugins/include/ext-include-common.c b/src/lib-sieve/plugins/include/ext-include-common.c
index a35b31ead..c9224c0ef 100644
--- a/src/lib-sieve/plugins/include/ext-include-common.c
+++ b/src/lib-sieve/plugins/include/ext-include-common.c
@@ -233,7 +233,7 @@ static void ext_include_runtime_init
 
 	if ( ctx->parent == NULL ) {
 		ctx->global_variables = sieve_variable_storage_create
-			(ctx->pool, ext_include_binary_get_global_scope(renv->sbin));
+			(ctx->pool, ext_include_binary_get_global_scope(renv->sbin), 0);
 	} else {
 		ctx->global_variables = ctx->parent->global_variables;
 	}
diff --git a/src/lib-sieve/plugins/variables/ext-variables-common.c b/src/lib-sieve/plugins/variables/ext-variables-common.c
index b6b22e4f6..9343f417a 100644
--- a/src/lib-sieve/plugins/variables/ext-variables-common.c
+++ b/src/lib-sieve/plugins/variables/ext-variables-common.c
@@ -198,17 +198,23 @@ struct sieve_variable * const *sieve_variable_scope_get_variables
 struct sieve_variable_storage {
 	pool_t pool;
 	struct sieve_variable_scope *scope;
+	unsigned int max_size;
 	ARRAY_DEFINE(var_values, string_t *); 
 };
 
 struct sieve_variable_storage *sieve_variable_storage_create
-(pool_t pool, struct sieve_variable_scope *scope)
+(pool_t pool, struct sieve_variable_scope *scope, unsigned int max_size)
 {
 	struct sieve_variable_storage *storage;
 	
 	storage = p_new(pool, struct sieve_variable_storage, 1);
 	storage->pool = pool;
 	storage->scope = scope;
+	
+	if ( scope != NULL )
+		storage->max_size = sieve_variable_scope_size(scope);
+	else
+		storage->max_size = max_size;
 		
 	p_array_init(&storage->var_values, pool, 4);
 
@@ -220,7 +226,7 @@ static inline bool sieve_variable_valid
 {
 	if ( storage->scope == NULL ) return TRUE;
 
-	return ( index < array_count(&storage->scope->variable_index) );
+	return ( index < storage->max_size );
 }
 
 bool sieve_variable_get_identifier
@@ -469,13 +475,14 @@ struct ext_variables_interpreter_context {
 };
 
 static struct ext_variables_interpreter_context *
-ext_variables_interpreter_context_create(struct sieve_interpreter *interp)
+ext_variables_interpreter_context_create
+(struct sieve_interpreter *interp, unsigned int max_size)
 {		
 	pool_t pool = sieve_interpreter_pool(interp);
 	struct ext_variables_interpreter_context *ctx;
 	
 	ctx = p_new(pool, struct ext_variables_interpreter_context, 1);
-	ctx->local_storage = sieve_variable_storage_create(pool, NULL);
+	ctx->local_storage = sieve_variable_storage_create(pool, NULL, max_size);
 	p_array_init(&ctx->ext_storages, pool, sieve_extensions_get_count());
 
 	sieve_interpreter_extension_set_context
@@ -512,7 +519,7 @@ bool ext_variables_interpreter_load
 	*address = pc + end_offset;
 	
 	/* Create our context */
-	ctx = ext_variables_interpreter_context_create(renv->interp);
+	ctx = ext_variables_interpreter_context_create(renv->interp, scope_size);
 
 	/* Enable support for match values */
 	(void) sieve_match_values_set_enabled(renv->interp, TRUE);
@@ -528,8 +535,7 @@ ext_variables_interpreter_context_get(struct sieve_interpreter *interp)
 }
 
 struct sieve_variable_storage *sieve_ext_variables_get_storage
-(struct sieve_interpreter *interp, const struct sieve_extension *ext, 
-	bool create)
+(struct sieve_interpreter *interp, const struct sieve_extension *ext)
 {
 	struct ext_variables_interpreter_context *ctx = 
 		ext_variables_interpreter_context_get(interp);
@@ -546,19 +552,8 @@ struct sieve_variable_storage *sieve_ext_variables_get_storage
 		storage = array_idx(&ctx->ext_storages, ext_id);
 	}
 	
-	if ( storage == NULL || *storage == NULL ) {
-		if ( create ) {
-			pool_t pool = sieve_interpreter_pool(interp);
-			struct sieve_variable_storage *strg = 
-				sieve_variable_storage_create(pool, NULL);
-		
-			array_idx_set(&ctx->ext_storages, (unsigned int) ext_id, &strg);
-		
-			return strg;		
-		}
-
+	if ( storage == NULL || *storage == NULL ) 
 		return NULL;
-	}
 	
 	return *storage;
 }
diff --git a/src/lib-sieve/plugins/variables/ext-variables-operands.c b/src/lib-sieve/plugins/variables/ext-variables-operands.c
index 4799523b6..2a123a90e 100644
--- a/src/lib-sieve/plugins/variables/ext-variables-operands.c
+++ b/src/lib-sieve/plugins/variables/ext-variables-operands.c
@@ -91,7 +91,7 @@ static bool opr_variable_read_value
 	if ( !sieve_binary_read_extension(renv->sbin, address, &code, &ext) )
 		return FALSE;
 
-	storage = sieve_ext_variables_get_storage(renv->interp, ext, FALSE);
+	storage = sieve_ext_variables_get_storage(renv->interp, ext);
 	if ( storage == NULL ) 
 		return FALSE;
 	
@@ -127,7 +127,7 @@ bool sieve_variable_operand_read_data
 	if ( !sieve_binary_read_extension(renv->sbin, address, &code, &ext) )
         return FALSE;
 		
-	*storage = sieve_ext_variables_get_storage(renv->interp, ext, FALSE);
+	*storage = sieve_ext_variables_get_storage(renv->interp, ext);
 	if ( *storage == NULL )	
 		return FALSE;
 	
diff --git a/src/lib-sieve/plugins/variables/sieve-ext-variables.h b/src/lib-sieve/plugins/variables/sieve-ext-variables.h
index f46f697de..b85b21056 100644
--- a/src/lib-sieve/plugins/variables/sieve-ext-variables.h
+++ b/src/lib-sieve/plugins/variables/sieve-ext-variables.h
@@ -74,7 +74,7 @@ struct sieve_variable * const *sieve_variable_scope_get_variables
 struct sieve_variable_storage;
 
 struct sieve_variable_storage *sieve_variable_storage_create
-	(pool_t pool, struct sieve_variable_scope *scope);
+	(pool_t pool, struct sieve_variable_scope *scope, unsigned int max_size);
 bool sieve_variable_get
 	(struct sieve_variable_storage *storage, unsigned int index, 
 		string_t **value);
@@ -98,8 +98,7 @@ struct sieve_variable_scope *sieve_ext_variables_get_main_scope
 	(struct sieve_validator *validator);
 	
 struct sieve_variable_storage *sieve_ext_variables_get_storage
-	(struct sieve_interpreter *interp, const struct sieve_extension *ext,
-		bool create);
+	(struct sieve_interpreter *interp, const struct sieve_extension *ext);
 void sieve_ext_variables_set_storage
 	(struct sieve_interpreter *interp, struct sieve_variable_storage *storage,
 		const struct sieve_extension *ext);	
-- 
GitLab