From b01bd7c9eb6f06dbe91d2a32d4fcd7b784267e21 Mon Sep 17 00:00:00 2001 From: Stephan Bosch <stephan@rename-it.nl> Date: Sat, 8 Dec 2007 13:13:26 +0100 Subject: [PATCH] Properly implemented circular include detection for the include extension. --- src/lib-sieve/plugins/include/cmd-include.c | 10 +---- .../plugins/include/ext-include-common.c | 21 +++++++--- .../plugins/include/ext-include-common.h | 4 +- src/lib-sieve/plugins/include/included3.sieve | 5 ++- src/lib-sieve/sieve-lexer.c | 2 +- src/lib-sieve/sieve-script.c | 42 ++++++++++++++----- src/lib-sieve/sieve-script.h | 6 +-- src/lib-sieve/sieve.c | 3 +- 8 files changed, 61 insertions(+), 32 deletions(-) diff --git a/src/lib-sieve/plugins/include/cmd-include.c b/src/lib-sieve/plugins/include/cmd-include.c index cffd608dc..40ae8c8ed 100644 --- a/src/lib-sieve/plugins/include/cmd-include.c +++ b/src/lib-sieve/plugins/include/cmd-include.c @@ -162,7 +162,6 @@ static bool cmd_include_validate(struct sieve_validator *validator, struct cmd_include_context_data *ctx_data = (struct cmd_include_context_data *) cmd->data; const char *script_name, *script_path; - struct sieve_script *script; struct sieve_ast *ast; if ( !sieve_validate_positional_argument @@ -185,17 +184,12 @@ static bool cmd_include_validate(struct sieve_validator *validator, else return FALSE; - script = sieve_script_create(script_path, script_name); - /* Validate */ if ( !ext_include_validate_include - (validator, cmd, script, &ast) ) { - sieve_script_unref(&script); + (validator, cmd, script_path, script_name, &ast) ) { return FALSE; } - - sieve_script_unref(&script); - + ctx_data->ast = ast; sieve_validator_argument_activate(validator, arg); diff --git a/src/lib-sieve/plugins/include/ext-include-common.c b/src/lib-sieve/plugins/include/ext-include-common.c index 4e6394ffa..f9bfda0b6 100644 --- a/src/lib-sieve/plugins/include/ext-include-common.c +++ b/src/lib-sieve/plugins/include/ext-include-common.c @@ -70,9 +70,10 @@ void ext_include_register_validator_context bool ext_include_validate_include (struct sieve_validator *validator, struct sieve_command_context *cmd, - struct sieve_script *script, struct sieve_ast **ast_r) + const char *script_path, const char *script_name, struct sieve_ast **ast_r) { bool result = TRUE; + struct sieve_script *script; struct sieve_validator *subvalid; struct ext_include_validator_context *parent = ext_include_get_validator_context(validator); @@ -80,6 +81,11 @@ bool ext_include_validate_include struct sieve_error_handler *ehandler = sieve_validator_get_error_handler(validator); + /* Create script object */ + if ( (script = sieve_script_create(script_path, script_name, ehandler)) + == NULL ) + return FALSE; + *ast_r = NULL; /* Check for circular include */ @@ -89,21 +95,26 @@ bool ext_include_validate_include if ( sieve_script_equals(ctx->script, script) ) { sieve_command_validate_error (validator, cmd, "circular include"); + + sieve_script_unref(&script); return FALSE; } ctx = ctx->parent; - } + } /* Parse script */ if ( (*ast_r = sieve_parse(script, ehandler)) == NULL ) { sieve_command_validate_error - (validator, cmd, "parse failed for included script '%s'", - sieve_script_name(script)); + (validator, cmd, "parse failed for included script '%s'", script_name); + sieve_script_unref(&script); return FALSE; } + /* AST now holds a reference, so we can drop it already */ + sieve_script_unref(&script); + /* Validate script */ subvalid = sieve_validator_create(*ast_r, ehandler); @@ -113,7 +124,7 @@ bool ext_include_validate_include if ( !sieve_validator_run(subvalid) || sieve_get_errors(ehandler) > 0 ) { sieve_command_validate_error (validator, cmd, "validation failed for included script '%s'", - sieve_script_name(script)); + script_name); sieve_ast_unref(ast_r); result = FALSE; } diff --git a/src/lib-sieve/plugins/include/ext-include-common.h b/src/lib-sieve/plugins/include/ext-include-common.h index f7e89a3fa..b4f1d51c2 100644 --- a/src/lib-sieve/plugins/include/ext-include-common.h +++ b/src/lib-sieve/plugins/include/ext-include-common.h @@ -29,7 +29,7 @@ void ext_include_register_validator_context (struct sieve_validator *validator, struct sieve_script *script); bool ext_include_validate_include -(struct sieve_validator *validator, struct sieve_command_context *cmd, - struct sieve_script *script, struct sieve_ast **ast_r); + (struct sieve_validator *validator, struct sieve_command_context *cmd, + const char *script_path, const char *script_name, struct sieve_ast **ast_r); #endif /* __EXT_INCLUDE_COMMON_H */ diff --git a/src/lib-sieve/plugins/include/included3.sieve b/src/lib-sieve/plugins/include/included3.sieve index 08a6621ed..720364ed5 100644 --- a/src/lib-sieve/plugins/include/included3.sieve +++ b/src/lib-sieve/plugins/include/included3.sieve @@ -1 +1,4 @@ -discard +require "include"; + +include "include"; +discard; diff --git a/src/lib-sieve/sieve-lexer.c b/src/lib-sieve/sieve-lexer.c index f6e87ac23..db4285073 100644 --- a/src/lib-sieve/sieve-lexer.c +++ b/src/lib-sieve/sieve-lexer.c @@ -80,7 +80,7 @@ struct sieve_lexer *sieve_lexer_create struct sieve_lexer *lexer; struct istream *stream; - stream = sieve_script_open(script, ehandler); + stream = sieve_script_open(script); if ( stream == NULL ) return NULL; diff --git a/src/lib-sieve/sieve-script.c b/src/lib-sieve/sieve-script.c index 55ba5fa39..3c472e939 100644 --- a/src/lib-sieve/sieve-script.c +++ b/src/lib-sieve/sieve-script.c @@ -13,6 +13,10 @@ struct sieve_script { pool_t pool; unsigned int refcount; + struct stat st; + + struct sieve_error_handler *ehandler; + /* Parameters */ const char *name; const char *path; @@ -25,17 +29,32 @@ struct sieve_script { /* Script object */ struct sieve_script *sieve_script_create - (const char *path, const char *name) + (const char *path, const char *name, struct sieve_error_handler *ehandler) { pool_t pool; + struct stat st; struct sieve_script *script; + /* First obtain stat data from the system */ + + if ( stat(path, &st) < 0 ) { + if ( errno == ENOENT ) + sieve_error(ehandler, name, "sieve script does not exist"); + else + sieve_critical(ehandler, path, "failed to stat sieve script: %m"); + return NULL; + } + + /* Only create object if it stat()s without problems */ + pool = pool_alloconly_create("sieve_script", 1024); script = p_new(pool, struct sieve_script, 1); script->pool = pool; script->refcount = 1; + script->ehandler = ehandler; - script->path = p_strdup(pool, path); + memcpy((void *) &script->st, (void *) &st, sizeof(st)); + script->path = p_strdup(pool, path); if ( name == NULL || *name == '\0' ) { const char *filename, *ext; @@ -84,17 +103,18 @@ void sieve_script_unref(struct sieve_script **script) /* Stream manageement */ -struct istream *sieve_script_open(struct sieve_script *script, - struct sieve_error_handler *ehandler) +struct istream *sieve_script_open(struct sieve_script *script) { int fd; if ( (fd=open(script->path, O_RDONLY)) < 0 ) { - if ( errno == ENOENT ) - sieve_error(ehandler, script->path, "sieve script '%s' does not exist", - script->name); - else - sieve_critical(ehandler, script->path, "failed to open sieve script: %m"); + if ( errno == ENOENT ) + /* Not supposed to occur, create() does stat already */ + sieve_error(script->ehandler, script->name, + "sieve script '%s' does not exist", script->name); + else + sieve_critical(script->ehandler, script->path, + "failed to open sieve script: %m"); return NULL; } @@ -112,8 +132,8 @@ void sieve_script_close(struct sieve_script *script) bool sieve_script_equals (struct sieve_script *script1, struct sieve_script *script2) -{ - return ( strcmp(script1->path, script2->path) == 0 ); +{ + return ( script1->st.st_ino == script2->st.st_ino ); } /* Inline accessors */ diff --git a/src/lib-sieve/sieve-script.h b/src/lib-sieve/sieve-script.h index 1266d1757..44ffb8ca4 100644 --- a/src/lib-sieve/sieve-script.h +++ b/src/lib-sieve/sieve-script.h @@ -7,15 +7,15 @@ struct sieve_script; -struct sieve_script *sieve_script_create(const char *path, const char *name); +struct sieve_script *sieve_script_create + (const char *path, const char *name, struct sieve_error_handler *ehandler); void sieve_script_ref(struct sieve_script *script); void sieve_script_unref(struct sieve_script **script); /* Stream manageement */ -struct istream *sieve_script_open(struct sieve_script *script, - struct sieve_error_handler *ehandler); +struct istream *sieve_script_open(struct sieve_script *script); void sieve_script_close(struct sieve_script *script); bool sieve_script_equals diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c index ebbbd89d0..42cd6fee4 100644 --- a/src/lib-sieve/sieve.c +++ b/src/lib-sieve/sieve.c @@ -125,7 +125,8 @@ struct sieve_binary *sieve_compile struct sieve_script *script; struct sieve_binary *sbin; - script = sieve_script_create(script_path, NULL); + if ( (script = sieve_script_create(script_path, NULL, ehandler)) == NULL ) + return NULL; sbin = sieve_compile_script(script, ehandler); -- GitLab