dovecot-2.0-pigeonhole: Fixed bugs in parser recovery and added ...
pigeonhole at rename-it.nl
pigeonhole at rename-it.nl
Sat Jan 23 01:47:48 EET 2010
details: http://hg.rename-it.nl/dovecot-2.0-pigeonhole/rev/3da0be0bcb4d
changeset: 1216:3da0be0bcb4d
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 50c429139d63 -r 3da0be0bcb4d Makefile.am
--- a/Makefile.am Fri Jan 22 15:28:07 2010 +0100
+++ b/Makefile.am Sat Jan 23 00:37:21 2010 +0100
@@ -39,6 +39,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 50c429139d63 -r 3da0be0bcb4d 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 50c429139d63 -r 3da0be0bcb4d 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 50c429139d63 -r 3da0be0bcb4d 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 50c429139d63 -r 3da0be0bcb4d 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 50c429139d63 -r 3da0be0bcb4d 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