dovecot-2.2-pigeonhole: lib-sieve: mime/foreverypart: Implemente...

pigeonhole at rename-it.nl pigeonhole at rename-it.nl
Sun Nov 29 12:00:43 UTC 2015


details:   http://hg.rename-it.nl/dovecot-2.2-pigeonhole/rev/5607f866fd94
changeset: 2144:5607f866fd94
user:      Stephan Bosch <stephan at rename-it.nl>
date:      Sun Nov 29 13:00:38 2015 +0100
description:
lib-sieve: mime/foreverypart: Implemented loop nesting limit.

diffstat:

 src/lib-sieve/plugins/mime/cmd-foreverypart.c |  43 +++++++++++++++++++++++---
 src/lib-sieve/sieve-interpreter.c             |  20 ++++++++++--
 src/lib-sieve/sieve-interpreter.h             |   5 +-
 src/lib-sieve/sieve-limits.h                  |   2 +
 tests/extensions/mime/errors.svtest           |  10 ++++++
 tests/extensions/mime/errors/limits.sieve     |  13 ++++++++
 6 files changed, 82 insertions(+), 11 deletions(-)

diffs (202 lines):

diff -r 146ca83393c6 -r 5607f866fd94 src/lib-sieve/plugins/mime/cmd-foreverypart.c
--- a/src/lib-sieve/plugins/mime/cmd-foreverypart.c	Sun Nov 29 12:17:32 2015 +0100
+++ b/src/lib-sieve/plugins/mime/cmd-foreverypart.c	Sun Nov 29 13:00:38 2015 +0100
@@ -2,6 +2,7 @@
  */
 
 #include "sieve-common.h"
+#include "sieve-limits.h"
 #include "sieve-code.h"
 #include "sieve-extensions.h"
 #include "sieve-commands.h"
@@ -28,6 +29,8 @@
 		struct sieve_command_registration *cmd_reg);
 static bool cmd_foreverypart_pre_validate
 	(struct sieve_validator *valdtr, struct sieve_command *cmd);
+static bool cmd_foreverypart_validate
+	(struct sieve_validator *valdtr, struct sieve_command *cmd);
 static bool cmd_foreverypart_generate
 	(const struct sieve_codegen_env *cgenv,
 		struct sieve_command *ctx);
@@ -38,7 +41,8 @@
 	0, 0, TRUE, TRUE,
 	cmd_foreverypart_registered,
 	cmd_foreverypart_pre_validate,
-	NULL, NULL,
+	cmd_foreverypart_validate,
+	NULL,
 	cmd_foreverypart_generate,
 	NULL,
 };
@@ -149,6 +153,36 @@
 	return TRUE;
 }
 
+static bool cmd_foreverypart_validate
+(struct sieve_validator *valdtr, struct sieve_command *cmd)
+{
+	struct sieve_ast_node *node = cmd->ast_node;
+	unsigned int nesting = 0;
+
+	/* Determine nesting depth of foreverypart commands at this point. */
+	i_assert(node != NULL);
+	node = sieve_ast_node_parent(node);
+	while ( node != NULL && node->command != NULL ) {
+		if ( sieve_command_is(node->command, cmd_foreverypart) )
+			nesting++;
+		node = sieve_ast_node_parent(node);
+	}
+
+	/* Enforce nesting limit
+	   NOTE: this only recognizes the foreverypart command as a loop; if
+	   new loop commands are introduced in the future, these must be 
+	   recognized somehow. */
+	if ( nesting + 1 > SIEVE_MAX_LOOP_DEPTH ) {
+		sieve_command_validate_error(valdtr, cmd,
+			"the nested foreverypart loop exceeds "
+			"the nesting limit (<= %u levels)",
+			SIEVE_MAX_LOOP_DEPTH);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
 /*
  * Code generation
  */
@@ -262,10 +296,9 @@
 
 	sfploop = ext_foreverypart_runtime_loop_get_current(renv);
 
-	loop = sieve_interpreter_loop_start
-		(renv->interp, loop_end, &foreverypart_extension);
-	if ( loop == NULL )
-		return SIEVE_EXEC_BIN_CORRUPT;
+	if ( (ret=sieve_interpreter_loop_start(renv->interp,
+		loop_end, &foreverypart_extension, &loop)) <= 0 )
+		return ret;
 
 	pool = sieve_interpreter_loop_get_pool(loop);
 	fploop = p_new(pool, struct ext_foreverypart_runtime_loop, 1);
diff -r 146ca83393c6 -r 5607f866fd94 src/lib-sieve/sieve-interpreter.c
--- a/src/lib-sieve/sieve-interpreter.c	Sun Nov 29 12:17:32 2015 +0100
+++ b/src/lib-sieve/sieve-interpreter.c	Sun Nov 29 13:00:38 2015 +0100
@@ -9,6 +9,7 @@
 #include "mail-storage.h"
 
 #include "sieve-common.h"
+#include "sieve-limits.h"
 #include "sieve-script.h"
 #include "sieve-error.h"
 #include "sieve-extensions.h"
@@ -482,9 +483,10 @@
  * Loop handling
  */
 
-struct sieve_interpreter_loop *sieve_interpreter_loop_start
+int sieve_interpreter_loop_start
 (struct sieve_interpreter *interp, sieve_size_t loop_end,
-	const struct sieve_extension_def *ext_def)
+	const struct sieve_extension_def *ext_def,
+	struct sieve_interpreter_loop **loop_r)
 {
 	const struct sieve_runtime_env *renv = &interp->runenv;
 	struct sieve_interpreter_loop *loop;
@@ -494,7 +496,7 @@
 	if ( loop_end > sieve_binary_block_get_size(renv->sblock) ) {
 		sieve_runtime_trace_error(renv,
 			"loop end offset out of range");
-		return NULL;
+		return SIEVE_EXEC_BIN_CORRUPT;
 	}
 
 	if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS) ) {
@@ -511,6 +513,15 @@
 
 	if ( !array_is_created(&interp->loop_stack) )
 		p_array_init(&interp->loop_stack, interp->pool, 8);
+	else if ( array_count(&interp->loop_stack)
+		>= SIEVE_MAX_LOOP_DEPTH ) {
+		/* Should normally be caught at compile time */
+		sieve_runtime_error(renv, NULL,
+			"new program loop exceeds "
+			"the nesting limit (<= %u levels)",
+			SIEVE_MAX_LOOP_DEPTH);
+		return SIEVE_EXEC_FAILURE;
+	}
 
 	loop = array_append_space(&interp->loop_stack);
 	loop->level = array_count(&interp->loop_stack)-1;
@@ -519,7 +530,8 @@
 	loop->end = loop_end;
 	loop->pool =  pool_alloconly_create("sieve_interpreter", 128);
 	
-	return loop;
+	*loop_r = loop;
+	return SIEVE_EXEC_OK;
 }
 
 struct sieve_interpreter_loop *sieve_interpreter_loop_get
diff -r 146ca83393c6 -r 5607f866fd94 src/lib-sieve/sieve-interpreter.h
--- a/src/lib-sieve/sieve-interpreter.h	Sun Nov 29 12:17:32 2015 +0100
+++ b/src/lib-sieve/sieve-interpreter.h	Sun Nov 29 13:00:38 2015 +0100
@@ -51,9 +51,10 @@
 
 struct sieve_interpreter_loop;
 
-struct sieve_interpreter_loop *sieve_interpreter_loop_start
+int sieve_interpreter_loop_start
 	(struct sieve_interpreter *interp, sieve_size_t loop_end,
-		const struct sieve_extension_def *ext_def);
+		const struct sieve_extension_def *ext_def,
+		struct sieve_interpreter_loop **loop_r);
 struct sieve_interpreter_loop *sieve_interpreter_loop_get
 	(struct sieve_interpreter *interp, sieve_size_t loop_end,
 		const struct sieve_extension_def *ext_def);
diff -r 146ca83393c6 -r 5607f866fd94 src/lib-sieve/sieve-limits.h
--- a/src/lib-sieve/sieve-limits.h	Sun Nov 29 12:17:32 2015 +0100
+++ b/src/lib-sieve/sieve-limits.h	Sun Nov 29 13:00:38 2015 +0100
@@ -12,6 +12,8 @@
 
 #define SIEVE_DEFAULT_MAX_SCRIPT_SIZE  (1 << 20)
 
+#define SIEVE_MAX_LOOP_DEPTH           4
+
 /*
  * Lexer
  */
diff -r 146ca83393c6 -r 5607f866fd94 tests/extensions/mime/errors.svtest
--- a/tests/extensions/mime/errors.svtest	Sun Nov 29 12:17:32 2015 +0100
+++ b/tests/extensions/mime/errors.svtest	Sun Nov 29 13:00:38 2015 +0100
@@ -52,3 +52,13 @@
 		test_fail "incorrect number of compile errors reported";
 	}
 }
+
+test "Limits" {
+	if test_script_compile "errors/limits.sieve" {
+		test_fail "compile should have failed";
+	}
+
+	if test_error :count "ne" :comparator "i;ascii-numeric" "2" {
+		test_fail "incorrect number of compile errors reported";
+	}
+}
diff -r 146ca83393c6 -r 5607f866fd94 tests/extensions/mime/errors/limits.sieve
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/extensions/mime/errors/limits.sieve	Sun Nov 29 13:00:38 2015 +0100
@@ -0,0 +1,13 @@
+require "foreverypart";
+
+foreverypart :name "frop" {
+	foreverypart :name "friep" {
+		foreverypart :name "frml" {
+			foreverypart {
+				foreverypart {
+					break;
+				}
+			}
+		}
+	}
+}


More information about the dovecot-cvs mailing list