From d3d9775297186292668da722a6b5e6b0ea8b4119 Mon Sep 17 00:00:00 2001 From: Stephan Bosch <stephan@rename-it.nl> Date: Fri, 25 Jul 2008 19:17:20 +0200 Subject: [PATCH] Implemented graceful handling of corrupt binaries by the sieve lda plugin. --- src/lib-sieve/sieve-binary.c | 14 +++++++ src/lib-sieve/sieve-interpreter.c | 4 +- src/plugins/lda-sieve/lda-sieve-plugin.c | 49 ++++++++++++++++++++++-- src/sieve-bin/sieve-exec.c | 11 ++++-- src/sieve-bin/sieve-test.c | 10 ++++- 5 files changed, 78 insertions(+), 10 deletions(-) diff --git a/src/lib-sieve/sieve-binary.c b/src/lib-sieve/sieve-binary.c index 9236beb41..cf7cf4658 100644 --- a/src/lib-sieve/sieve-binary.c +++ b/src/lib-sieve/sieve-binary.c @@ -604,6 +604,16 @@ bool sieve_binary_save struct ostream *stream; int fd; + /* Use default path if none is specified */ + if ( path == NULL ) { + if ( sbin->script == NULL ) { + sieve_sys_error("cannot determine default binary save path " + "with missing script object"); + return FALSE; + } + path = sieve_script_binpath(sbin->script); + } + /* Open it as temp file first, as not to overwrite an existing just yet */ temp_path = t_strconcat(path, ".tmp", NULL); fd = open(temp_path, O_CREAT | O_TRUNC | O_WRONLY, 0600); @@ -629,6 +639,10 @@ bool sieve_binary_save if ( !result ) { /* Get rid of temp output (if any) */ (void) unlink(temp_path); + } else { + if ( sbin->path == NULL || strcmp(sbin->path, path) != 0 ) { + sbin->path = p_strdup(sbin->pool, path); + } } return result; diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c index bbe112d38..edb5adc6d 100644 --- a/src/lib-sieve/sieve-interpreter.c +++ b/src/lib-sieve/sieve-interpreter.c @@ -199,10 +199,10 @@ void _sieve_runtime_trace_error va_list args; va_start(args, fmt); - str_printfa(outbuf, "%08x: %s: ", runenv->interp->pc + str_printfa(outbuf, "%08x: [[ERROR: %s: ", runenv->interp->pc , runenv->interp->current_op->mnemonic); str_vprintfa(outbuf, fmt, args); - str_append_c(outbuf, '\n'); + str_append(outbuf, "]]\n"); va_end(args); o_stream_send(runenv->trace_stream, str_data(outbuf), str_len(outbuf)); diff --git a/src/plugins/lda-sieve/lda-sieve-plugin.c b/src/plugins/lda-sieve/lda-sieve-plugin.c index 6b8be27f4..98587a77d 100644 --- a/src/plugins/lda-sieve/lda-sieve-plugin.c +++ b/src/plugins/lda-sieve/lda-sieve-plugin.c @@ -136,12 +136,55 @@ static int lda_sieve_run /* Execute the script */ if ( debug ) - sieve_sys_info("executing (in-memory) script %s", script_path); + sieve_sys_info("executing compiled script %s", script_path); ret = sieve_execute(sbin, &msgdata, &scriptenv, ehandler, NULL); - if ( ret < 0 ) - sieve_sys_error("failed to execute script %s", script_path); + if ( ret == SIEVE_EXEC_BIN_CORRUPT ) { + sieve_sys_warning("encountered corrupt binary: recompiling script %s", + script_path); + + /* + * Try again; possibly author forgot to increase binary version number + */ + + /* Close corrupt script */ + sieve_close(&sbin); + + /* Recompile */ + + sieve_error_handler_copy_masterlog(ehandler, FALSE); + + if ( (sbin=sieve_compile(script_path, ehandler)) == NULL ) { + sieve_sys_error("failed to compile script %s; " + "log should be available as %s", script_path, scriptlog); + + sieve_error_handler_unref(&ehandler); + return -1; + } + + sieve_error_handler_copy_masterlog(ehandler, TRUE); + + /* Execute again */ + + ret = sieve_execute(sbin, &msgdata, &scriptenv, ehandler, NULL); + } + + switch ( ret ) { + case SIEVE_EXEC_FAILURE: + sieve_sys_error("execution of script %s failed, but implicit keep was successful", + script_path); + break; + case SIEVE_EXEC_BIN_CORRUPT: + sieve_sys_error("!!BUG!!: binary compiled from %s is still corrupt; bailing out", + script_path); + break; + case SIEVE_EXEC_KEEP_FAILED: + sieve_sys_error("script %s failed with unsuccessful implicit keep", script_path); + break; + default: + break; + } /* Clean up */ sieve_close(&sbin); diff --git a/src/sieve-bin/sieve-exec.c b/src/sieve-bin/sieve-exec.c index 9c0bcf5b8..3eebaa6c0 100644 --- a/src/sieve-bin/sieve-exec.c +++ b/src/sieve-bin/sieve-exec.c @@ -10,6 +10,7 @@ #include "mail-raw.h" #include "namespaces.h" #include "sieve.h" +#include "sieve-binary.h" #include <stdio.h> #include <stdlib.h> @@ -191,17 +192,19 @@ int main(int argc, char **argv) /* Run */ switch ( sieve_execute(sbin, &msgdata, &scriptenv, ehandler, NULL) ) { case SIEVE_EXEC_OK: - i_info("Final result: success\n"); + i_info("Final result: success"); break; case SIEVE_EXEC_FAILURE: - i_info("Final result: failed; resolved with successful implicit keep\n"); + i_info("Final result: failed; resolved with successful implicit keep"); break; case SIEVE_EXEC_BIN_CORRUPT: + i_info("Corrupt binary deleted."); + (void) unlink(sieve_binary_path(sbin)); case SIEVE_EXEC_KEEP_FAILED: - i_info("Final result: utter failure (caller please handle implicit keep!)\n"); + i_info("Final result: utter failure (caller please handle implicit keep!)"); break; default: - i_info("Final result: unrecognized return value?!\n"); + i_info("Final result: unrecognized return value?!"); } sieve_close(&sbin); diff --git a/src/sieve-bin/sieve-test.c b/src/sieve-bin/sieve-test.c index dd5bec3b2..d5b2be8d2 100644 --- a/src/sieve-bin/sieve-test.c +++ b/src/sieve-bin/sieve-test.c @@ -8,6 +8,7 @@ #include "mail-raw.h" #include "namespaces.h" #include "sieve.h" +#include "sieve-binary.h" #include <stdio.h> #include <stdlib.h> @@ -45,6 +46,7 @@ int main(int argc, char **argv) struct sieve_error_handler *ehandler; struct ostream *teststream; bool force_compile = FALSE; + int ret; #ifdef SIEVE_RUNTIME_TRACE bool trace = FALSE; @@ -114,6 +116,7 @@ int main(int argc, char **argv) /* Compile sieve script */ if ( force_compile ) { sbin = bin_compile_sieve_script(scriptfile); + (void) sieve_save(sbin, NULL); } else { sbin = bin_open_sieve_script(scriptfile); } @@ -156,9 +159,14 @@ int main(int argc, char **argv) #endif /* Run the test */ - (void) sieve_test + ret = sieve_test (sbin, &msgdata, &scriptenv, teststream, ehandler, trace_stream); + if ( ret == SIEVE_EXEC_BIN_CORRUPT ) { + i_info("Corrupt binary deleted."); + (void) unlink(sieve_binary_path(sbin)); + } + o_stream_destroy(&teststream); sieve_close(&sbin); -- GitLab