dovecot-1.2-sieve: Fixed bugs in parser recovery and added corre...

pigeonhole at rename-it.nl pigeonhole at rename-it.nl
Sat Jan 23 01:37:33 EET 2010


details:   http://hg.rename-it.nl/dovecot-1.2-sieve/rev/0ceabefd8360
changeset: 1220:0ceabefd8360
user:      Stephan Bosch <stephan at rename-it.nl>
date:      Sat Jan 23 00:37:21 2010 +0100
description:
Fixed bugs in parser recovery and added corresponding tests in the test suite.

diffstat:

 Makefile.am                                    |   1 +
 src/lib-sieve/sieve-parser.c                   |  64 ++++++++++++++++++++-----------
 tests/compile/recover.svtest                   |  50 +++++++++++++++++++++++++
 tests/compile/recover/commands-endblock.sieve  |  24 ++++++++++++
 tests/compile/recover/commands-semicolon.sieve |   7 +++
 tests/compile/recover/tests-endcomma.sieve     |  10 +++++
 6 files changed, 133 insertions(+), 23 deletions(-)

diffs (252 lines):

diff -r 84a8e1a7ed6a -r 0ceabefd8360 Makefile.am
--- a/Makefile.am	Fri Jan 22 15:28:07 2010 +0100
+++ b/Makefile.am	Sat Jan 23 00:37:21 2010 +0100
@@ -56,6 +56,7 @@
 	tests/compile/compile.svtest \
 	tests/compile/errors.svtest \
 	tests/compile/warnings.svtest \
+	tests/compile/recover.svtest \
 	tests/execute/errors.svtest \
 	tests/execute/actions.svtest \
 	tests/execute/smtp.svtest \
diff -r 84a8e1a7ed6a -r 0ceabefd8360 src/lib-sieve/sieve-parser.c
--- a/src/lib-sieve/sieve-parser.c	Fri Jan 22 15:28:07 2010 +0100
+++ b/src/lib-sieve/sieve-parser.c	Sat Jan 23 00:37:21 2010 +0100
@@ -157,9 +157,13 @@
 	                       necessarily error-free state */
 
 	/* Parse arguments */
-	while ( arg_present && result > 0 && 
-		(parser->valid || sieve_errors_more_allowed(parser->ehandler)) ) {
+	while ( arg_present && result > 0 ) {
 		struct sieve_ast_argument *arg;
+
+		if ( !parser->valid && !sieve_errors_more_allowed(parser->ehandler) ) {
+			result = 0;
+			break;
+		}
 		
 		switch ( sieve_lexer_current_token(lexer) ) {
 		
@@ -184,10 +188,14 @@
 				
 				sieve_lexer_skip_token(lexer);
 				 
-				while ( !add_failed && sieve_lexer_current_token(lexer) == STT_COMMA &&
-					(parser->valid || sieve_errors_more_allowed(parser->ehandler)) ) {
-			
+				while ( !add_failed && sieve_lexer_current_token(lexer) == STT_COMMA ) {
 					sieve_lexer_skip_token(lexer);
+
+					/* Check parser status */
+					if ( !parser->valid && !sieve_errors_more_allowed(parser->ehandler) ) {
+						result = sieve_parser_recover(parser, STT_RSQUARE);
+						break;						
+					}
 				
 					if ( sieve_lexer_current_token(lexer) == STT_STRING ) {
 						/* Add the string to the list */
@@ -339,10 +347,15 @@
 			if ( (result=sieve_parse_arguments(parser, test, depth+1)) > 0 ) {
 			
 				/* More tests ? */
-				while ( sieve_lexer_current_token(lexer) == STT_COMMA && 
-					(parser->valid && sieve_errors_more_allowed(parser->ehandler)) ) {
+				while ( sieve_lexer_current_token(lexer) == STT_COMMA ) { 
 					sieve_lexer_skip_token(lexer);
-					
+
+					/* Check parser status */
+					if ( !parser->valid && !sieve_errors_more_allowed(parser->ehandler) ) {
+						result = sieve_parser_recover(parser, STT_RBRACKET);
+						break;
+					}
+
 					/* Test starts with identifier */
 					if ( sieve_lexer_current_token(lexer) == STT_IDENTIFIER ) {
 						test = sieve_ast_test_create
@@ -355,7 +368,6 @@
 						/* Parse test arguments, which may include more tests (recurse) */
 						if ( (result=sieve_parse_arguments(parser, test, depth+1)) <= 0 ) {
 							if ( result < 0 ) return result;
-
 							result = sieve_parser_recover(parser, STT_RBRACKET);
 							break;
 						}
@@ -430,12 +442,20 @@
 	int result = TRUE;
 
 	while ( result > 0 && 
-		sieve_lexer_current_token(lexer) == STT_IDENTIFIER && 
-		(parser->valid || sieve_errors_more_allowed(parser->ehandler)) ) {
-		struct sieve_ast_node *command = 
-			sieve_ast_command_create
-				(block, sieve_lexer_token_ident(lexer), 
-					sieve_lexer_current_line(parser->lexer));
+		sieve_lexer_current_token(lexer) == STT_IDENTIFIER ) {
+		struct sieve_ast_node *command;
+
+		/* Check parser status */
+		if ( !parser->valid && !sieve_errors_more_allowed(parser->ehandler) ) {
+			result = sieve_parser_recover(parser, STT_SEMICOLON);
+			break;
+		}
+
+		/* Create command node */
+		command = sieve_ast_command_create
+			(block, sieve_lexer_token_ident(lexer), 
+				sieve_lexer_current_line(parser->lexer));
+		sieve_lexer_skip_token(lexer);
 	
 		if ( command == NULL ) {
 			sieve_parser_error(parser, 
@@ -444,11 +464,6 @@
 			return -1;
 		}
 
-		/* Defined state */
-		result = TRUE;		
-		
-		sieve_lexer_skip_token(lexer);
-		
 		result = sieve_parse_arguments(parser, command, 1);
 
 		/* Check whether the command is properly terminated 
@@ -471,7 +486,9 @@
 		}
 
 		/* Don't bother to continue if we are not in a defined state */
-		if ( result <= 0 ) return result;
+		if ( result <= 0 ) {
+			return result;
+		}
 			
 		switch ( sieve_lexer_current_token(lexer) ) {
 		
@@ -510,7 +527,7 @@
 			} else {
 				if ( result < 0 ) return result;
 
-				if ( (result=sieve_parser_recover(parser, STT_RCURLY)) == 0 ) 
+				if ( (result=sieve_parser_recover(parser, STT_RCURLY)) > 0 ) 
 					sieve_lexer_skip_token(lexer);
 			}
 
@@ -643,8 +660,9 @@
 	
 	/* Special case: COMMAND */
 	if (end_token == STT_SEMICOLON && 
-		sieve_lexer_current_token(lexer) == STT_LCURLY)
+		sieve_lexer_current_token(lexer) == STT_LCURLY) {
 		return TRUE;
+	}
 	
 	/* End not found before eof or end of surrounding grammatical structure 
 	 */
diff -r 84a8e1a7ed6a -r 0ceabefd8360 tests/compile/recover.svtest
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/compile/recover.svtest	Sat Jan 23 00:37:21 2010 +0100
@@ -0,0 +1,50 @@
+require "vnd.dovecot.testsuite";
+
+require "relational";
+require "comparator-i;ascii-numeric";
+
+/*
+ * Test parser's recover capability
+ */
+
+/*
+ * Commands 
+ */
+
+/* Missing semicolon */
+
+test "Missing semicolons" {
+    if test_script_compile "recover/commands-semicolon.sieve" {
+        test_fail "compile should have failed.";
+    }
+
+    if not test_error :count "eq" :comparator "i;ascii-numeric" "3" {
+        test_fail "wrong number of errors reported";
+    }
+}
+
+/* End of block recovery*/
+
+test "Missing semicolon at end of block" {
+    if test_script_compile "recover/commands-endblock.sieve" {
+        test_fail "compile should have failed.";
+    }
+
+    if not test_error :count "eq" :comparator "i;ascii-numeric" "4" {
+        test_fail "wrong number of errors reported";
+    }
+}
+
+/*
+ * Tests
+ */
+
+test "Spurious comma at end of test list" {
+    if test_script_compile "recover/tests-endcomma.sieve" {
+        test_fail "compile should have failed.";
+    }
+
+    if not test_error :count "eq" :comparator "i;ascii-numeric" "3" {
+        test_fail "wrong number of errors reported";
+    }
+}
diff -r 84a8e1a7ed6a -r 0ceabefd8360 tests/compile/recover/commands-endblock.sieve
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/compile/recover/commands-endblock.sieve	Sat Jan 23 00:37:21 2010 +0100
@@ -0,0 +1,24 @@
+if true {
+	if true {
+		keep
+	}
+}
+
+if true {
+	keep,
+	keep
+}
+
+if true {
+	if anyof(true,true,false) {
+		keep;
+	}
+}
+
+if true {
+	if anyof(true,true,false) {
+		keep;
+		discard
+	}
+}
+
diff -r 84a8e1a7ed6a -r 0ceabefd8360 tests/compile/recover/commands-semicolon.sieve
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/compile/recover/commands-semicolon.sieve	Sat Jan 23 00:37:21 2010 +0100
@@ -0,0 +1,7 @@
+keep;
+discard;
+keep
+redirect "frop at frop.nl";
+discard;
+keep
+redirect "frml at frop.nl";
diff -r 84a8e1a7ed6a -r 0ceabefd8360 tests/compile/recover/tests-endcomma.sieve
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/compile/recover/tests-endcomma.sieve	Sat Jan 23 00:37:21 2010 +0100
@@ -0,0 +1,10 @@
+if true {
+if true {
+if anyof(true,true,true,) {
+}}}
+
+if true {
+if anyof(true,true) {
+if anyof(true,true,true,) {
+if anyof(true,true,true) {
+}}}}


More information about the dovecot-cvs mailing list