From 5c0c25fd56188b1ec09315c05dcd4770b00606ba Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan.bosch@open-xchange.com>
Date: Thu, 11 Jun 2020 20:53:24 +0200
Subject: [PATCH] lib-sieve: plugins: special-use: tst-specialuse-exists -
 Check mailbox name validity.

Fixes assert failure occurring either at compiletime or at runtime (depending on
whether the value originates from variable).
---
 .../special-use/tst-specialuse-exists.c       | 24 +++++++++++++++++++
 tests/extensions/special-use/errors.svtest    | 20 +++++++++++++++-
 .../errors/specialuse_exists-bad-utf8.sieve   |  9 +++++++
 .../special-use/errors/syntax.sieve           |  6 +++++
 4 files changed, 58 insertions(+), 1 deletion(-)
 create mode 100644 tests/extensions/special-use/errors/specialuse_exists-bad-utf8.sieve

diff --git a/src/lib-sieve/plugins/special-use/tst-specialuse-exists.c b/src/lib-sieve/plugins/special-use/tst-specialuse-exists.c
index 8231e4d77..4123e1a08 100644
--- a/src/lib-sieve/plugins/special-use/tst-specialuse-exists.c
+++ b/src/lib-sieve/plugins/special-use/tst-specialuse-exists.c
@@ -141,6 +141,20 @@ tst_specialuse_exists_validate(struct sieve_validator *valdtr,
 		if (!sieve_validator_argument_activate(valdtr, tst, arg, FALSE))
 			return FALSE;
 
+		/* Check name validity when mailbox argument is not a variable */
+		if (sieve_argument_is_string_literal(arg)) {
+			const char *mailbox = sieve_ast_argument_strc(arg);
+			const char *error;
+
+			if (!sieve_mailbox_check_name(mailbox, &error)) {
+				sieve_argument_validate_warning(
+					valdtr, arg, "%s test: "
+					"invalid mailbox name `%s' specified: %s",
+					sieve_command_identifier(tst),
+					str_sanitize(mailbox, 256), error);
+			}
+		}
+
 		if (sieve_ast_argument_type(arg2) != SAAT_STRING &&
 		    sieve_ast_argument_type(arg2) != SAAT_STRING_LIST) {
 			sieve_argument_validate_error(
@@ -389,6 +403,7 @@ tst_specialuse_exists_operation_execute(const struct sieve_runtime_env *renv,
 	struct sieve_stringlist *special_use_flags;
 	string_t *mailbox, *special_use_flag;
 	struct mailbox *box = NULL;
+	const char *error;
 	bool trace = FALSE, all_exist = TRUE;
 	int ret;
 
@@ -439,6 +454,15 @@ tst_specialuse_exists_operation_execute(const struct sieve_runtime_env *renv,
 	}
 
 	if (mailbox != NULL) {
+		if (!sieve_mailbox_check_name(str_c(mailbox), &error)) {
+			sieve_runtime_warning(
+				renv, NULL, "specialuse_exists test: "
+				"invalid mailbox name `%s' specified: %s",
+				str_sanitize(str_c(mailbox), 256), error);
+			sieve_interpreter_set_test_result(renv->interp, FALSE);
+			return SIEVE_EXEC_OK;
+		}
+
 		if (tst_specialuse_find_mailbox(renv, str_c(mailbox), &box) < 0)
 			return SIEVE_EXEC_TEMP_FAILURE;
 	}
diff --git a/tests/extensions/special-use/errors.svtest b/tests/extensions/special-use/errors.svtest
index a0148a0ce..49b187264 100644
--- a/tests/extensions/special-use/errors.svtest
+++ b/tests/extensions/special-use/errors.svtest
@@ -12,9 +12,27 @@ test "Invalid Syntax" {
                 test_fail "compile should have failed";
         }
 
-        if not test_error :count "eq" :comparator "i;ascii-numeric" "14" {
+	# FIXME: check warnings
+        if not test_error :count "eq" :comparator "i;ascii-numeric" "15" {
                 test_fail "wrong number of errors reported";
         }
 }
 
+/*
+ * Specialuse_exists - bad UTF-8 in mailbox name
+ */
+
+test "Specialuse_exists - bad UTF-8 in mailbox name" {
+	if not test_script_compile "errors/specialuse_exists-bad-utf8.sieve" {
+		test_fail "compile failed";
+	}
 
+	if not test_script_run {
+		test_fail "execution failed";
+	}
+
+	# FIXME: check warnings
+	if not test_error :count "eq" :comparator "i;ascii-numeric" "0" {
+		test_fail "wrong number of runtime errors reported";
+	}
+}
diff --git a/tests/extensions/special-use/errors/specialuse_exists-bad-utf8.sieve b/tests/extensions/special-use/errors/specialuse_exists-bad-utf8.sieve
new file mode 100644
index 000000000..9710fb30b
--- /dev/null
+++ b/tests/extensions/special-use/errors/specialuse_exists-bad-utf8.sieve
@@ -0,0 +1,9 @@
+require "special-use";
+require "variables";
+require "encoded-character";
+
+set "mailbox" "${hex:ff}rop";
+if specialuse_exists "${mailbox}" "\\Sent" {
+	keep;
+}
+
diff --git a/tests/extensions/special-use/errors/syntax.sieve b/tests/extensions/special-use/errors/syntax.sieve
index fc2801009..cb8bc4f0e 100644
--- a/tests/extensions/special-use/errors/syntax.sieve
+++ b/tests/extensions/special-use/errors/syntax.sieve
@@ -1,5 +1,6 @@
 require "special-use";
 require "fileinto";
+require "encoded-character";
 
 # 1
 if specialuse_exists {}
@@ -19,6 +20,9 @@ if specialuse_exists "frop" {}
 # 8
 if specialuse_exists "frop" ["frop"] {}
 
+# W:1
+if specialuse_exists "${hex:ff}rop" "\\Sent" {}
+
 # 9
 fileinto :specialuse "\\frop";
 # 10
@@ -30,3 +34,5 @@ fileinto :specialuse "\\frop" 234234;
 
 # 13
 fileinto :specialuse "frop" "frop";
+# 14
+fileinto :specialuse "\\Sent" "${hex:ff}rop";
-- 
GitLab