From fec57037421e74f3173ef3ebab26a6dff00293b8 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Sun, 29 Nov 2015 21:47:14 +0100
Subject: [PATCH] lib-sieve: variables extension: Fixed handling of empty
 string by the `:length' set modifier. An empty string yielded an empty string
 rather than "0".

---
 .../plugins/enotify/vmodf-encodeurl.c         |  5 +++
 src/lib-sieve/plugins/variables/cmd-set.c     | 36 +++++++++----------
 .../variables/ext-variables-modifiers.c       | 25 +++++++++++++
 tests/extensions/variables/modifiers.svtest   | 10 +++++-
 4 files changed, 56 insertions(+), 20 deletions(-)

diff --git a/src/lib-sieve/plugins/enotify/vmodf-encodeurl.c b/src/lib-sieve/plugins/enotify/vmodf-encodeurl.c
index a82e81dfb..fe5477c39 100644
--- a/src/lib-sieve/plugins/enotify/vmodf-encodeurl.c
+++ b/src/lib-sieve/plugins/enotify/vmodf-encodeurl.c
@@ -67,6 +67,11 @@ bool mod_encodeurl_modify(string_t *in, string_t **result)
 	unsigned int i;
 	const unsigned char *c;
 
+	if ( str_len(in) == 0 ) {
+		*result = in;
+		return TRUE;
+	}
+
 	*result = t_str_new(2*str_len(in));
 	c = str_data(in);
 
diff --git a/src/lib-sieve/plugins/variables/cmd-set.c b/src/lib-sieve/plugins/variables/cmd-set.c
index ca30b56e3..43997fa36 100644
--- a/src/lib-sieve/plugins/variables/cmd-set.c
+++ b/src/lib-sieve/plugins/variables/cmd-set.c
@@ -326,26 +326,24 @@ static int cmd_set_operation_execute
 			break;
 		}
 
-		if ( str_len(value) > 0 ) {
-			if ( modf.def != NULL && modf.def->modify != NULL ) {
-				if ( !modf.def->modify(value, &new_value) ) {
-					value = NULL;
-					ret = SIEVE_EXEC_FAILURE;
-					break;
-				}
-
-				sieve_runtime_trace_here
-					(renv, SIEVE_TRLVL_COMMANDS, "modify :%s \"%s\" => \"%s\"",
-						sieve_variables_modifier_name(&modf), str_c(value), str_c(new_value));
-
-				value = new_value;
-				if ( value == NULL )
-					break;
-
-				/* Hold value within limits */
-				if ( str_len(value) > EXT_VARIABLES_MAX_VARIABLE_SIZE )
-					str_truncate(value, EXT_VARIABLES_MAX_VARIABLE_SIZE);
+		if ( modf.def != NULL && modf.def->modify != NULL ) {
+			if ( !modf.def->modify(value, &new_value) ) {
+				value = NULL;
+				ret = SIEVE_EXEC_FAILURE;
+				break;
 			}
+
+			sieve_runtime_trace_here
+				(renv, SIEVE_TRLVL_COMMANDS, "modify :%s \"%s\" => \"%s\"",
+					sieve_variables_modifier_name(&modf), str_c(value), str_c(new_value));
+
+			value = new_value;
+			if ( value == NULL )
+				break;
+
+			/* Hold value within limits */
+			if ( str_len(value) > EXT_VARIABLES_MAX_VARIABLE_SIZE )
+				str_truncate(value, EXT_VARIABLES_MAX_VARIABLE_SIZE);
 		}
 	}
 
diff --git a/src/lib-sieve/plugins/variables/ext-variables-modifiers.c b/src/lib-sieve/plugins/variables/ext-variables-modifiers.c
index e6e9d9408..5c1790a90 100644
--- a/src/lib-sieve/plugins/variables/ext-variables-modifiers.c
+++ b/src/lib-sieve/plugins/variables/ext-variables-modifiers.c
@@ -190,6 +190,11 @@ bool mod_upperfirst_modify(string_t *in, string_t **result)
 {
 	char *content;
 
+	if ( str_len(in) == 0 ) {
+		*result = in;
+		return TRUE;
+	}
+
 	*result = t_str_new(str_len(in));
 	str_append_str(*result, in);
 
@@ -203,6 +208,11 @@ bool mod_lowerfirst_modify(string_t *in, string_t **result)
 {
 	char *content;
 
+	if ( str_len(in) == 0 ) {
+		*result = in;
+		return TRUE;
+	}
+
 	*result = t_str_new(str_len(in));
 	str_append_str(*result, in);
 
@@ -216,6 +226,11 @@ bool mod_upper_modify(string_t *in, string_t **result)
 {
 	char *content;
 
+	if ( str_len(in) == 0 ) {
+		*result = in;
+		return TRUE;
+	}
+
 	*result = t_str_new(str_len(in));
 	str_append_str(*result, in);
 
@@ -229,6 +244,11 @@ bool mod_lower_modify(string_t *in, string_t **result)
 {
 	char *content;
 
+	if ( str_len(in) == 0 ) {
+		*result = in;
+		return TRUE;
+	}
+
 	*result = t_str_new(str_len(in));
 	str_append_str(*result, in);
 
@@ -251,6 +271,11 @@ bool mod_quotewildcard_modify(string_t *in, string_t **result)
 	unsigned int i;
 	const char *content;
 
+	if ( str_len(in) == 0 ) {
+		*result = in;
+		return TRUE;
+	}
+
 	*result = t_str_new(str_len(in) * 2);
 	content = (const char *) str_data(in);
 
diff --git a/tests/extensions/variables/modifiers.svtest b/tests/extensions/variables/modifiers.svtest
index 60b174fa5..37068b63d 100644
--- a/tests/extensions/variables/modifiers.svtest
+++ b/tests/extensions/variables/modifiers.svtest
@@ -70,7 +70,15 @@ test "Modifiers :lowerfirst :upper" {
 	}
 }
 
-test "Modifier :length" {
+test "Modifier :length (empty)" {
+	set :length "test" "";
+
+	if not string :is "${test}" "0" {
+		test_fail "modified variable assignment failed";
+	}
+}
+
+test "Modifier :length (simple)" {
 	set :length "test" "VaLuE";
 
 	if not string :is "${test}" "5" {
-- 
GitLab