From a16a9b8bbbbb9c1ba75a79e3b543f5bfee8677d1 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Mon, 20 Jun 2016 22:20:32 +0200
Subject: [PATCH] lib-sieve: variables extension: Changed declaration of new
 variables to avoid useless memory allocation.

Also prevents assert failures with new hash_table_insert() assertion against existing entries.
This changes the API for the variables extension.
---
 .../plugins/include/ext-include-variables.c   |  6 +-
 .../variables/ext-variables-arguments.c       |  2 +-
 .../plugins/variables/ext-variables-common.c  | 55 ++++++++++---------
 .../plugins/variables/ext-variables-common.h  |  5 +-
 .../plugins/variables/sieve-ext-variables.h   |  2 +-
 5 files changed, 39 insertions(+), 31 deletions(-)

diff --git a/src/lib-sieve/plugins/include/ext-include-variables.c b/src/lib-sieve/plugins/include/ext-include-variables.c
index cadd378dc..e84eab1ed 100644
--- a/src/lib-sieve/plugins/include/ext-include-variables.c
+++ b/src/lib-sieve/plugins/include/ext-include-variables.c
@@ -48,7 +48,7 @@ struct sieve_variable *ext_include_variable_import_global
 	}
 
 	/* Get/Declare the variable in the global scope */
-	global_var = sieve_variable_scope_get_variable(global_scope, variable, TRUE);
+	global_var = sieve_variable_scope_declare(global_scope, variable);
 
 	/* Check whether scope is over its size limit */
 	if ( global_var == NULL ) {
@@ -62,7 +62,7 @@ struct sieve_variable *ext_include_variable_import_global
 	/* Import the global variable into the local script scope */
 	local_scope = sieve_ext_variables_get_local_scope(ectx->var_ext, valdtr);
 
-	local_var = sieve_variable_scope_get_variable(local_scope, variable, FALSE);
+	local_var = sieve_variable_scope_get_variable(local_scope, variable);
 	if ( local_var != NULL && local_var->ext != this_ext ) {
 		/* FIXME: indicate location of conflicting set statement */
 		sieve_command_validate_error(valdtr, cmd,
@@ -206,7 +206,7 @@ bool vnspc_global_variables_validate
 
 	/* Get/Declare the variable in the global scope */
 
-	var = sieve_variable_scope_get_variable(ctx->global_vars, variable, TRUE);
+	var = sieve_variable_scope_declare(ctx->global_vars, variable);
 
 	if ( var == NULL ) {
 		sieve_argument_validate_error(valdtr, arg,
diff --git a/src/lib-sieve/plugins/variables/ext-variables-arguments.c b/src/lib-sieve/plugins/variables/ext-variables-arguments.c
index 7bd4c183b..6212212c0 100644
--- a/src/lib-sieve/plugins/variables/ext-variables-arguments.c
+++ b/src/lib-sieve/plugins/variables/ext-variables-arguments.c
@@ -41,7 +41,7 @@ static bool ext_variables_variable_argument_activate
 	struct sieve_ast *ast = arg->ast;
 	struct sieve_variable *var;
 
-	var = ext_variables_validator_get_variable(this_ext, valdtr, variable, TRUE);
+	var = ext_variables_validator_declare_variable(this_ext, valdtr, variable);
 
 	if ( var == NULL ) {
 		sieve_argument_validate_error(valdtr, arg,
diff --git a/src/lib-sieve/plugins/variables/ext-variables-common.c b/src/lib-sieve/plugins/variables/ext-variables-common.c
index c523ac493..63c6523a7 100644
--- a/src/lib-sieve/plugins/variables/ext-variables-common.c
+++ b/src/lib-sieve/plugins/variables/ext-variables-common.c
@@ -112,44 +112,39 @@ pool_t sieve_variable_scope_pool(struct sieve_variable_scope *scope)
 struct sieve_variable *sieve_variable_scope_declare
 (struct sieve_variable_scope *scope, const char *identifier)
 {
-	struct sieve_variable *new_var;
+	struct sieve_variable *var;
 
-	new_var = p_new(scope->pool, struct sieve_variable, 1);
-	new_var->ext = scope->ext;
+	var = hash_table_lookup(scope->variables, identifier);
+	if (var != NULL)
+		return var;
 
 	if ( array_count(&scope->variable_index) >= EXT_VARIABLES_MAX_SCOPE_SIZE ) {
 		if ( scope->error_var == NULL ) {
-			new_var->identifier = "@ERROR@";
-			new_var->index = 0;
+			var = p_new(scope->pool, struct sieve_variable, 1);
+			var->identifier = "@ERROR@";
+			var->index = 0;
 
-			scope->error_var = new_var;
+			scope->error_var = var;
 			return NULL;
 		}
 
 		return scope->error_var;
 	}
 
-	new_var->identifier = p_strdup(scope->pool, identifier);
-	new_var->index = array_count(&scope->variable_index);
+	var = p_new(scope->pool, struct sieve_variable, 1);
+	var->ext = scope->ext;
+	var->identifier = p_strdup(scope->pool, identifier);
+	var->index = array_count(&scope->variable_index);
 
-	hash_table_insert(scope->variables, new_var->identifier, new_var);
-	array_append(&scope->variable_index, &new_var, 1);
-
-	return new_var;
+	hash_table_insert(scope->variables, var->identifier, var);
+	array_append(&scope->variable_index, &var, 1);
+	return var;
 }
 
 struct sieve_variable *sieve_variable_scope_get_variable
-(struct sieve_variable_scope *scope, const char *identifier, bool declare)
+(struct sieve_variable_scope *scope, const char *identifier)
 {
-	struct sieve_variable *var;
-
-	var = hash_table_lookup(scope->variables, identifier);
-
-	if ( var == NULL && declare ) {
-		var = sieve_variable_scope_declare(scope, identifier);
-	}
-
-	return var;
+	return hash_table_lookup(scope->variables, identifier);
 }
 
 struct sieve_variable *sieve_variable_scope_import
@@ -158,7 +153,7 @@ struct sieve_variable *sieve_variable_scope_import
 	struct sieve_variable *old_var, *new_var;
 
 	old_var = sieve_variable_scope_get_variable
-		(scope, var->identifier, FALSE);
+		(scope, var->identifier);
 	if (old_var != NULL) {
 		i_assert(memcmp(old_var, var, sizeof(*var)) == 0);
 		return old_var;
@@ -643,12 +638,22 @@ void ext_variables_validator_initialize
 
 struct sieve_variable *ext_variables_validator_get_variable
 (const struct sieve_extension *this_ext, struct sieve_validator *validator,
-	const char *variable, bool declare)
+	const char *variable)
+{
+	struct ext_variables_validator_context *ctx =
+		ext_variables_validator_context_get(this_ext, validator);
+
+	return sieve_variable_scope_get_variable(ctx->local_scope, variable);
+}
+
+struct sieve_variable *ext_variables_validator_declare_variable
+(const struct sieve_extension *this_ext, struct sieve_validator *validator,
+	const char *variable)
 {
 	struct ext_variables_validator_context *ctx =
 		ext_variables_validator_context_get(this_ext, validator);
 
-	return sieve_variable_scope_get_variable(ctx->local_scope, variable, declare);
+	return sieve_variable_scope_declare(ctx->local_scope, variable);
 }
 
 struct sieve_variable_scope *sieve_ext_variables_get_local_scope
diff --git a/src/lib-sieve/plugins/variables/ext-variables-common.h b/src/lib-sieve/plugins/variables/ext-variables-common.h
index 7a7449f1a..1e1ae4c7b 100644
--- a/src/lib-sieve/plugins/variables/ext-variables-common.h
+++ b/src/lib-sieve/plugins/variables/ext-variables-common.h
@@ -66,7 +66,10 @@ struct ext_variables_validator_context *ext_variables_validator_context_get
 
 struct sieve_variable *ext_variables_validator_get_variable
 	(const struct sieve_extension *this_ext, struct sieve_validator *validator,
-		const char *variable, bool declare);
+		const char *variable);
+struct sieve_variable *ext_variables_validator_declare_variable
+	(const struct sieve_extension *this_ext, struct sieve_validator *validator,
+		const char *variable);
 
 /*
  * Code generation
diff --git a/src/lib-sieve/plugins/variables/sieve-ext-variables.h b/src/lib-sieve/plugins/variables/sieve-ext-variables.h
index 130142576..d1809152d 100644
--- a/src/lib-sieve/plugins/variables/sieve-ext-variables.h
+++ b/src/lib-sieve/plugins/variables/sieve-ext-variables.h
@@ -76,7 +76,7 @@ struct sieve_variable *sieve_variable_scope_declare
 struct sieve_variable *sieve_variable_scope_import
 	(struct sieve_variable_scope *scope, struct sieve_variable *var);
 struct sieve_variable *sieve_variable_scope_get_variable
-	(struct sieve_variable_scope *scope, const char *identifier, bool create);
+	(struct sieve_variable_scope *scope, const char *identifier);
 struct sieve_variable *sieve_variable_scope_get_indexed
 	(struct sieve_variable_scope *scope, unsigned int index);
 
-- 
GitLab