From 691db805aca90bbc53c3d02424fc040b8639f6df Mon Sep 17 00:00:00 2001 From: Stephan Bosch <stephan@rename-it.nl> Date: Fri, 14 May 2010 13:08:14 +0200 Subject: [PATCH] Restructured binary implementation and added lineinfo debug blocks to the binary. --- src/lib-sieve-tool/sieve-tool.c | 2 +- src/lib-sieve/Makefile.am | 4 + src/lib-sieve/cmd-discard.c | 4 +- src/lib-sieve/cmd-if.c | 16 +- src/lib-sieve/cmd-keep.c | 4 +- src/lib-sieve/cmd-redirect.c | 4 +- src/lib-sieve/cmd-stop.c | 2 +- src/lib-sieve/ext-envelope.c | 2 +- src/lib-sieve/ext-fileinto.c | 4 +- src/lib-sieve/ext-reject.c | 6 +- src/lib-sieve/plugins/body/tst-body.c | 8 +- src/lib-sieve/plugins/copy/ext-copy.c | 2 +- src/lib-sieve/plugins/date/tst-date.c | 10 +- src/lib-sieve/plugins/enotify/cmd-notify.c | 12 +- .../enotify/tst-notify-method-capability.c | 2 +- .../plugins/enotify/tst-valid-notify-method.c | 2 +- .../plugins/environment/tst-environment.c | 2 +- src/lib-sieve/plugins/imap4flags/cmd-flag.c | 10 +- src/lib-sieve/plugins/imap4flags/tag-flags.c | 8 +- .../plugins/imap4flags/tst-hasflag.c | 2 +- src/lib-sieve/plugins/include/cmd-global.c | 19 +- src/lib-sieve/plugins/include/cmd-include.c | 16 +- src/lib-sieve/plugins/include/cmd-return.c | 2 +- .../plugins/include/ext-include-binary.c | 97 +- .../plugins/include/ext-include-binary.h | 5 +- .../plugins/include/ext-include-common.c | 78 +- .../plugins/include/ext-include-variables.c | 28 +- .../plugins/include/ext-include-variables.h | 7 +- .../plugins/mailbox/tag-mailbox-create.c | 2 +- .../plugins/mailbox/tst-mailboxexists.c | 2 +- src/lib-sieve/plugins/notify/cmd-denotify.c | 12 +- src/lib-sieve/plugins/notify/cmd-notify.c | 12 +- .../plugins/spamvirustest/tst-spamvirustest.c | 4 +- src/lib-sieve/plugins/vacation/cmd-vacation.c | 14 +- src/lib-sieve/plugins/variables/cmd-set.c | 12 +- .../variables/ext-variables-arguments.c | 4 +- .../plugins/variables/ext-variables-common.c | 12 +- .../plugins/variables/ext-variables-dump.c | 6 +- .../variables/ext-variables-modifiers.h | 4 +- .../variables/ext-variables-namespaces.c | 11 +- .../variables/ext-variables-namespaces.h | 5 - .../variables/ext-variables-operands.c | 38 +- .../plugins/variables/sieve-ext-variables.h | 6 +- src/lib-sieve/plugins/variables/tst-string.c | 2 +- src/lib-sieve/sieve-actions.h | 4 +- src/lib-sieve/sieve-address-parts.c | 10 +- src/lib-sieve/sieve-address-parts.h | 4 +- src/lib-sieve/sieve-binary-code.c | 386 ++++ src/lib-sieve/sieve-binary-debug.c | 256 +++ src/lib-sieve/sieve-binary-dumper.c | 46 +- src/lib-sieve/sieve-binary-dumper.h | 2 +- src/lib-sieve/sieve-binary-file.c | 839 +++++++++ src/lib-sieve/sieve-binary-private.h | 208 ++ src/lib-sieve/sieve-binary.c | 1666 ++--------------- src/lib-sieve/sieve-binary.h | 127 +- src/lib-sieve/sieve-code-dumper.c | 74 +- src/lib-sieve/sieve-code.c | 135 +- src/lib-sieve/sieve-code.h | 33 +- src/lib-sieve/sieve-commands.c | 11 +- src/lib-sieve/sieve-common.h | 3 + src/lib-sieve/sieve-comparators.c | 2 +- src/lib-sieve/sieve-comparators.h | 4 +- src/lib-sieve/sieve-dump.h | 1 + src/lib-sieve/sieve-generator.c | 157 +- src/lib-sieve/sieve-generator.h | 14 +- src/lib-sieve/sieve-interpreter.c | 59 +- src/lib-sieve/sieve-interpreter.h | 3 + src/lib-sieve/sieve-match-types.c | 2 +- src/lib-sieve/sieve-match-types.h | 4 +- src/lib-sieve/sieve-match.c | 8 +- src/lib-sieve/sieve-objects.c | 18 +- src/lib-sieve/sieve-objects.h | 4 +- src/lib-sieve/sieve.c | 6 +- src/lib-sieve/sieve.h | 2 +- src/lib-sieve/tst-address.c | 2 +- src/lib-sieve/tst-allof.c | 8 +- src/lib-sieve/tst-anyof.c | 8 +- src/lib-sieve/tst-exists.c | 2 +- src/lib-sieve/tst-header.c | 2 +- src/lib-sieve/tst-size.c | 4 +- src/lib-sieve/tst-truefalse.c | 8 +- src/sieve-tools/debug/cmd-debug-print.c | 2 +- src/testsuite/cmd-test-binary.c | 4 +- src/testsuite/cmd-test-config.c | 2 +- src/testsuite/cmd-test-fail.c | 6 +- src/testsuite/cmd-test-mailbox.c | 2 +- src/testsuite/cmd-test-message.c | 12 +- src/testsuite/cmd-test-result-print.c | 2 +- src/testsuite/cmd-test-result-reset.c | 2 +- src/testsuite/cmd-test-set.c | 4 +- src/testsuite/cmd-test.c | 4 +- src/testsuite/testsuite-common.c | 4 +- src/testsuite/testsuite-objects.c | 24 +- src/testsuite/testsuite-objects.h | 4 +- src/testsuite/testsuite-substitutions.c | 22 +- src/testsuite/tst-test-error.c | 2 +- src/testsuite/tst-test-multiscript.c | 2 +- src/testsuite/tst-test-result-execute.c | 2 +- src/testsuite/tst-test-result.c | 2 +- src/testsuite/tst-test-script-compile.c | 2 +- src/testsuite/tst-test-script-run.c | 10 +- 101 files changed, 2642 insertions(+), 2098 deletions(-) create mode 100644 src/lib-sieve/sieve-binary-code.c create mode 100644 src/lib-sieve/sieve-binary-debug.c create mode 100644 src/lib-sieve/sieve-binary-file.c create mode 100644 src/lib-sieve/sieve-binary-private.h diff --git a/src/lib-sieve-tool/sieve-tool.c b/src/lib-sieve-tool/sieve-tool.c index 6b69ec7f7..edb3e40f0 100644 --- a/src/lib-sieve-tool/sieve-tool.c +++ b/src/lib-sieve-tool/sieve-tool.c @@ -244,7 +244,7 @@ void sieve_tool_dump_binary_to(struct sieve_binary *sbin, const char *filename) } if ( dumpstream != NULL ) { - (void) sieve_dump(sbin, dumpstream); + (void) sieve_dump(sbin, dumpstream, FALSE); o_stream_destroy(&dumpstream); } else { i_fatal("Failed to create stream for sieve code dump."); diff --git a/src/lib-sieve/Makefile.am b/src/lib-sieve/Makefile.am index e29cb36fc..9ad44e736 100644 --- a/src/lib-sieve/Makefile.am +++ b/src/lib-sieve/Makefile.am @@ -76,6 +76,9 @@ libdovecot_sieve_la_SOURCES = \ sieve-script.c \ sieve-ast.c \ sieve-binary.c \ + sieve-binary-file.c \ + sieve-binary-code.c \ + sieve-binary-debug.c \ sieve-parser.c \ sieve-address.c \ sieve-validator.c \ @@ -116,6 +119,7 @@ headers = \ sieve-script-private.h \ sieve-ast.h \ sieve-binary.h \ + sieve-binary-private.h \ sieve-parser.h \ sieve-address.h \ sieve-validator.h \ diff --git a/src/lib-sieve/cmd-discard.c b/src/lib-sieve/cmd-discard.c index 340c437ba..f62fd0f4e 100644 --- a/src/lib-sieve/cmd-discard.c +++ b/src/lib-sieve/cmd-discard.c @@ -79,10 +79,10 @@ const struct sieve_action_def act_discard = { static bool cmd_discard_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) { - sieve_operation_emit(cgenv->sbin, NULL, &cmd_discard_operation); + sieve_operation_emit(cgenv->sblock, NULL, &cmd_discard_operation); /* Emit line number */ - sieve_code_source_line_emit(cgenv->sbin, sieve_command_source_line(cmd)); + sieve_code_source_line_emit(cgenv->sblock, sieve_command_source_line(cmd)); return TRUE; } diff --git a/src/lib-sieve/cmd-if.c b/src/lib-sieve/cmd-if.c index 9e6343f66..2d2aaae61 100644 --- a/src/lib-sieve/cmd-if.c +++ b/src/lib-sieve/cmd-if.c @@ -149,7 +149,7 @@ static bool cmd_elsif_validate */ static void cmd_if_resolve_exit_jumps -(struct sieve_binary *sbin, struct cmd_if_context_data *cmd_data) +(struct sieve_binary_block *sblock, struct cmd_if_context_data *cmd_data) { struct cmd_if_context_data *if_ctx = cmd_data->previous; @@ -158,7 +158,7 @@ static void cmd_if_resolve_exit_jumps */ while ( if_ctx != NULL ) { if ( if_ctx->jump_generated ) - sieve_binary_resolve_offset(sbin, if_ctx->exit_jump); + sieve_binary_resolve_offset(sblock, if_ctx->exit_jump); if_ctx = if_ctx->previous; } } @@ -166,14 +166,14 @@ static void cmd_if_resolve_exit_jumps static bool cmd_if_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) { - struct sieve_binary *sbin = cgenv->sbin; + struct sieve_binary_block *sblock = cgenv->sblock; struct cmd_if_context_data *cmd_data = (struct cmd_if_context_data *) cmd->data; struct sieve_ast_node *test; struct sieve_jumplist jmplist; /* Prepare jumplist */ - sieve_jumplist_init_temp(&jmplist, sbin); + sieve_jumplist_init_temp(&jmplist, sblock); /* Generate test condition */ test = sieve_ast_test_first(cmd->ast_node); @@ -192,13 +192,13 @@ static bool cmd_if_generate * anyway. */ if ( !sieve_command_block_exits_unconditionally(cmd) ) { - sieve_operation_emit(sbin, NULL, &sieve_jmp_operation); - cmd_data->exit_jump = sieve_binary_emit_offset(sbin, 0); + sieve_operation_emit(sblock, NULL, &sieve_jmp_operation); + cmd_data->exit_jump = sieve_binary_emit_offset(sblock, 0); cmd_data->jump_generated = TRUE; } } else { /* Yes, Resolve previous exit jumps to this point */ - cmd_if_resolve_exit_jumps(sbin, cmd_data); + cmd_if_resolve_exit_jumps(sblock, cmd_data); } /* Case false ... (subsequent elsif/else commands might generate more) */ @@ -218,7 +218,7 @@ static bool cmd_else_generate return FALSE; /* } End: resolve all exit blocks */ - cmd_if_resolve_exit_jumps(cgenv->sbin, cmd_data); + cmd_if_resolve_exit_jumps(cgenv->sblock, cmd_data); return TRUE; } diff --git a/src/lib-sieve/cmd-keep.c b/src/lib-sieve/cmd-keep.c index 60cba5fb3..c228a2943 100644 --- a/src/lib-sieve/cmd-keep.c +++ b/src/lib-sieve/cmd-keep.c @@ -57,10 +57,10 @@ static bool cmd_keep_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) { /* Emit opcode */ - sieve_operation_emit(cgenv->sbin, NULL, &cmd_keep_operation); + sieve_operation_emit(cgenv->sblock, NULL, &cmd_keep_operation); /* Emit line number */ - sieve_code_source_line_emit(cgenv->sbin, sieve_command_source_line(cmd)); + sieve_code_source_line_emit(cgenv->sblock, sieve_command_source_line(cmd)); /* Generate arguments */ return sieve_generate_arguments(cgenv, cmd, NULL); diff --git a/src/lib-sieve/cmd-redirect.c b/src/lib-sieve/cmd-redirect.c index 1c2b39146..0be56bffe 100644 --- a/src/lib-sieve/cmd-redirect.c +++ b/src/lib-sieve/cmd-redirect.c @@ -160,10 +160,10 @@ static bool cmd_redirect_validate static bool cmd_redirect_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) { - sieve_operation_emit(cgenv->sbin, NULL, &cmd_redirect_operation); + sieve_operation_emit(cgenv->sblock, NULL, &cmd_redirect_operation); /* Emit line number */ - sieve_code_source_line_emit(cgenv->sbin, sieve_command_source_line(cmd)); + sieve_code_source_line_emit(cgenv->sblock, sieve_command_source_line(cmd)); /* Generate arguments */ return sieve_generate_arguments(cgenv, cmd, NULL); diff --git a/src/lib-sieve/cmd-stop.c b/src/lib-sieve/cmd-stop.c index 054a11552..eaae8affe 100644 --- a/src/lib-sieve/cmd-stop.c +++ b/src/lib-sieve/cmd-stop.c @@ -65,7 +65,7 @@ static bool cmd_stop_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd ATTR_UNUSED) { - sieve_operation_emit(cgenv->sbin, NULL, &cmd_stop_operation); + sieve_operation_emit(cgenv->sblock, NULL, &cmd_stop_operation); return TRUE; } diff --git a/src/lib-sieve/ext-envelope.c b/src/lib-sieve/ext-envelope.c index aa0ed7fa3..2c294226b 100644 --- a/src/lib-sieve/ext-envelope.c +++ b/src/lib-sieve/ext-envelope.c @@ -288,7 +288,7 @@ static bool tst_envelope_validate static bool tst_envelope_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) { - (void)sieve_operation_emit(cgenv->sbin, cmd->ext, &envelope_operation); + (void)sieve_operation_emit(cgenv->sblock, cmd->ext, &envelope_operation); /* Generate arguments */ if ( !sieve_generate_arguments(cgenv, cmd, NULL) ) diff --git a/src/lib-sieve/ext-fileinto.c b/src/lib-sieve/ext-fileinto.c index 6bbc126a7..1d963ab13 100644 --- a/src/lib-sieve/ext-fileinto.c +++ b/src/lib-sieve/ext-fileinto.c @@ -123,10 +123,10 @@ static bool cmd_fileinto_validate static bool cmd_fileinto_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) { - sieve_operation_emit(cgenv->sbin, cmd->ext, &fileinto_operation); + sieve_operation_emit(cgenv->sblock, cmd->ext, &fileinto_operation); /* Emit line number */ - sieve_code_source_line_emit(cgenv->sbin, sieve_command_source_line(cmd)); + sieve_code_source_line_emit(cgenv->sblock, sieve_command_source_line(cmd)); /* Generate arguments */ return sieve_generate_arguments(cgenv, cmd, NULL); diff --git a/src/lib-sieve/ext-reject.c b/src/lib-sieve/ext-reject.c index 2486acd7b..3b8f70f02 100644 --- a/src/lib-sieve/ext-reject.c +++ b/src/lib-sieve/ext-reject.c @@ -231,12 +231,12 @@ static bool cmd_reject_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) { if ( sieve_command_is(cmd, reject_command) ) - sieve_operation_emit(cgenv->sbin, cmd->ext, &reject_operation); + sieve_operation_emit(cgenv->sblock, cmd->ext, &reject_operation); else - sieve_operation_emit(cgenv->sbin, cmd->ext, &ereject_operation); + sieve_operation_emit(cgenv->sblock, cmd->ext, &ereject_operation); /* Emit line number */ - sieve_code_source_line_emit(cgenv->sbin, sieve_command_source_line(cmd)); + sieve_code_source_line_emit(cgenv->sblock, sieve_command_source_line(cmd)); /* Generate arguments */ return sieve_generate_arguments(cgenv, cmd, NULL); diff --git a/src/lib-sieve/plugins/body/tst-body.c b/src/lib-sieve/plugins/body/tst-body.c index 3a9e058c6..91f4ba386 100644 --- a/src/lib-sieve/plugins/body/tst-body.c +++ b/src/lib-sieve/plugins/body/tst-body.c @@ -230,7 +230,7 @@ static bool tst_body_validate static bool tst_body_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) { - (void)sieve_operation_emit(cgenv->sbin, cmd->ext, &body_operation); + (void)sieve_operation_emit(cgenv->sblock, cmd->ext, &body_operation); /* Generate arguments */ return sieve_generate_arguments(cgenv, cmd, NULL); @@ -243,7 +243,7 @@ static bool tag_body_transform_generate enum tst_body_transform transform = (enum tst_body_transform) arg->argument->data; - sieve_binary_emit_byte(cgenv->sbin, transform); + sieve_binary_emit_byte(cgenv->sblock, transform); sieve_generate_argument_parameters(cgenv, cmd, arg); return TRUE; @@ -272,7 +272,7 @@ static bool ext_body_operation_dump case SIEVE_MATCH_OPT_END: break; case OPT_BODY_TRANSFORM: - if ( !sieve_binary_read_byte(denv->sbin, address, &transform) ) + if ( !sieve_binary_read_byte(denv->sblock, address, &transform) ) return FALSE; switch ( transform ) { @@ -339,7 +339,7 @@ static int ext_body_operation_execute case SIEVE_MATCH_OPT_END: break; case OPT_BODY_TRANSFORM: - if ( !sieve_binary_read_byte(renv->sbin, address, &transform) || + if ( !sieve_binary_read_byte(renv->sblock, address, &transform) || transform > TST_BODY_TRANSFORM_TEXT ) { sieve_runtime_trace_error(renv, "invalid body transform type"); return SIEVE_EXEC_BIN_CORRUPT; diff --git a/src/lib-sieve/plugins/copy/ext-copy.c b/src/lib-sieve/plugins/copy/ext-copy.c index 33d5422b3..510f63441 100644 --- a/src/lib-sieve/plugins/copy/ext-copy.c +++ b/src/lib-sieve/plugins/copy/ext-copy.c @@ -144,7 +144,7 @@ static bool tag_copy_generate } sieve_opr_side_effect_emit - (cgenv->sbin, sieve_argument_ext(arg), ©_side_effect); + (cgenv->sblock, sieve_argument_ext(arg), ©_side_effect); return TRUE; } diff --git a/src/lib-sieve/plugins/date/tst-date.c b/src/lib-sieve/plugins/date/tst-date.c index 30d519034..53e6d67e7 100644 --- a/src/lib-sieve/plugins/date/tst-date.c +++ b/src/lib-sieve/plugins/date/tst-date.c @@ -298,9 +298,9 @@ static bool tst_date_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *tst) { if ( sieve_command_is(tst, date_test) ) - sieve_operation_emit(cgenv->sbin, tst->ext, &date_operation); + sieve_operation_emit(cgenv->sblock, tst->ext, &date_operation); else if ( sieve_command_is(tst, currentdate_test) ) - sieve_operation_emit(cgenv->sbin, tst->ext, ¤tdate_operation); + sieve_operation_emit(cgenv->sblock, tst->ext, ¤tdate_operation); else i_unreached(); @@ -313,7 +313,7 @@ static bool tag_zone_generate struct sieve_command *cmd) { if ( arg->parameters == NULL ) { - sieve_opr_omitted_emit(cgenv->sbin); + sieve_opr_omitted_emit(cgenv->sblock); return TRUE; } @@ -343,7 +343,7 @@ static bool tst_date_operation_dump case SIEVE_MATCH_OPT_END: break; case OPT_DATE_ZONE: - if ( !sieve_operand_read(denv->sbin, address, &operand) ) { + if ( !sieve_operand_read(denv->sblock, address, &operand) ) { sieve_code_dumpf(denv, "ERROR: INVALID OPERAND"); return FALSE; } @@ -405,7 +405,7 @@ static int tst_date_operation_execute case SIEVE_MATCH_OPT_END: break; case OPT_DATE_ZONE: - if ( !sieve_operand_read(renv->sbin, address, &operand) ) { + if ( !sieve_operand_read(renv->sblock, address, &operand) ) { sieve_runtime_trace_error(renv, "invalid operand"); return SIEVE_EXEC_BIN_CORRUPT; } diff --git a/src/lib-sieve/plugins/enotify/cmd-notify.c b/src/lib-sieve/plugins/enotify/cmd-notify.c index 9bddb87ab..4e9500e68 100644 --- a/src/lib-sieve/plugins/enotify/cmd-notify.c +++ b/src/lib-sieve/plugins/enotify/cmd-notify.c @@ -334,10 +334,10 @@ static bool cmd_notify_validate static bool cmd_notify_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) { - sieve_operation_emit(cgenv->sbin, cmd->ext, ¬ify_operation); + sieve_operation_emit(cgenv->sblock, cmd->ext, ¬ify_operation); /* Emit source line */ - sieve_code_source_line_emit(cgenv->sbin, sieve_command_source_line(cmd)); + sieve_code_source_line_emit(cgenv->sblock, sieve_command_source_line(cmd)); /* Generate arguments */ return sieve_generate_arguments(cgenv, cmd, NULL); @@ -360,11 +360,11 @@ static bool cmd_notify_operation_dump return FALSE; /* Dump optional operands */ - if ( sieve_operand_optional_present(denv->sbin, address) ) { + if ( sieve_operand_optional_present(denv->sblock, address) ) { while ( opt_code != 0 ) { sieve_code_mark(denv); - if ( !sieve_operand_optional_read(denv->sbin, address, &opt_code) ) + if ( !sieve_operand_optional_read(denv->sblock, address, &opt_code) ) return FALSE; switch ( opt_code ) { @@ -427,9 +427,9 @@ static int cmd_notify_operation_execute } /* Optional operands */ - if ( sieve_operand_optional_present(renv->sbin, address) ) { + if ( sieve_operand_optional_present(renv->sblock, address) ) { while ( opt_code != 0 ) { - if ( !sieve_operand_optional_read(renv->sbin, address, &opt_code) ) { + if ( !sieve_operand_optional_read(renv->sblock, address, &opt_code) ) { sieve_runtime_trace_error(renv, "invalid optional operand"); return SIEVE_EXEC_BIN_CORRUPT; } diff --git a/src/lib-sieve/plugins/enotify/tst-notify-method-capability.c b/src/lib-sieve/plugins/enotify/tst-notify-method-capability.c index 751dc6b4f..7d87b017b 100644 --- a/src/lib-sieve/plugins/enotify/tst-notify-method-capability.c +++ b/src/lib-sieve/plugins/enotify/tst-notify-method-capability.c @@ -141,7 +141,7 @@ static bool tst_notifymc_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) { sieve_operation_emit - (cgenv->sbin, cmd->ext, ¬ify_method_capability_operation); + (cgenv->sblock, cmd->ext, ¬ify_method_capability_operation); /* Generate arguments */ return sieve_generate_arguments(cgenv, cmd, NULL); diff --git a/src/lib-sieve/plugins/enotify/tst-valid-notify-method.c b/src/lib-sieve/plugins/enotify/tst-valid-notify-method.c index 2595d86dc..db45c68f3 100644 --- a/src/lib-sieve/plugins/enotify/tst-valid-notify-method.c +++ b/src/lib-sieve/plugins/enotify/tst-valid-notify-method.c @@ -77,7 +77,7 @@ static bool tst_vnotifym_validate static bool tst_vnotifym_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) { - sieve_operation_emit(cgenv->sbin, cmd->ext, &valid_notify_method_operation); + sieve_operation_emit(cgenv->sblock, cmd->ext, &valid_notify_method_operation); /* Generate arguments */ return sieve_generate_arguments(cgenv, cmd, NULL); diff --git a/src/lib-sieve/plugins/environment/tst-environment.c b/src/lib-sieve/plugins/environment/tst-environment.c index 80a4d1d0d..110f053e1 100644 --- a/src/lib-sieve/plugins/environment/tst-environment.c +++ b/src/lib-sieve/plugins/environment/tst-environment.c @@ -116,7 +116,7 @@ static bool tst_environment_validate static bool tst_environment_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) { - sieve_operation_emit(cgenv->sbin, cmd->ext, &tst_environment_operation); + sieve_operation_emit(cgenv->sblock, cmd->ext, &tst_environment_operation); /* Generate arguments */ if ( !sieve_generate_arguments(cgenv, cmd, NULL) ) diff --git a/src/lib-sieve/plugins/imap4flags/cmd-flag.c b/src/lib-sieve/plugins/imap4flags/cmd-flag.c index a1c6fd964..8cc194a0d 100644 --- a/src/lib-sieve/plugins/imap4flags/cmd-flag.c +++ b/src/lib-sieve/plugins/imap4flags/cmd-flag.c @@ -123,11 +123,11 @@ static bool cmd_flag_generate { /* Emit operation */ if ( sieve_command_is(cmd, cmd_setflag) ) - sieve_operation_emit(cgenv->sbin, cmd->ext, &setflag_operation); + sieve_operation_emit(cgenv->sblock, cmd->ext, &setflag_operation); else if ( sieve_command_is(cmd, cmd_addflag) ) - sieve_operation_emit(cgenv->sbin, cmd->ext, &addflag_operation); + sieve_operation_emit(cgenv->sblock, cmd->ext, &addflag_operation); else if ( sieve_command_is(cmd, cmd_removeflag) ) - sieve_operation_emit(cgenv->sbin, cmd->ext, &removeflag_operation); + sieve_operation_emit(cgenv->sblock, cmd->ext, &removeflag_operation); /* Generate arguments */ if ( !sieve_generate_arguments(cgenv, cmd, NULL) ) @@ -149,7 +149,7 @@ bool cmd_flag_operation_dump sieve_code_descend(denv); sieve_code_mark(denv); - if ( !sieve_operand_read(denv->sbin, address, &operand) ) { + if ( !sieve_operand_read(denv->sblock, address, &operand) ) { sieve_code_dumpf(denv, "ERROR: INVALID OPERAND"); return FALSE; } @@ -188,7 +188,7 @@ static int cmd_flag_operation_execute * Read operands */ - if ( !sieve_operand_read(renv->sbin, address, &operand) ) { + if ( !sieve_operand_read(renv->sblock, address, &operand) ) { sieve_runtime_trace_error(renv, "invalid operand"); return SIEVE_EXEC_BIN_CORRUPT; } diff --git a/src/lib-sieve/plugins/imap4flags/tag-flags.c b/src/lib-sieve/plugins/imap4flags/tag-flags.c index 026faf0b6..1645a0871 100644 --- a/src/lib-sieve/plugins/imap4flags/tag-flags.c +++ b/src/lib-sieve/plugins/imap4flags/tag-flags.c @@ -155,7 +155,7 @@ static bool tag_flags_generate } sieve_opr_side_effect_emit - (cgenv->sbin, arg->argument->ext, &flags_side_effect); + (cgenv->sblock, arg->argument->ext, &flags_side_effect); if ( sieve_argument_is(arg, tag_flags) ) { /* Explicit :flags tag */ @@ -169,7 +169,7 @@ static bool tag_flags_generate } else if ( sieve_argument_is(arg, tag_flags_implicit) ) { /* Implicit flags */ - sieve_opr_omitted_emit(cgenv->sbin); + sieve_opr_omitted_emit(cgenv->sblock); } else { /* Something else?! */ @@ -198,7 +198,7 @@ static bool seff_flags_dump_context { struct sieve_operand operand; - if ( !sieve_operand_read(denv->sbin, address, &operand) ) { + if ( !sieve_operand_read(denv->sblock, address, &operand) ) { sieve_code_dumpf(denv, "ERROR: INVALID OPERAND"); return FALSE; } @@ -269,7 +269,7 @@ static bool seff_flags_read_context t_push(); /* Check whether explicit flag list operand is present */ - if ( !sieve_operand_read(renv->sbin, address, &operand) ) { + if ( !sieve_operand_read(renv->sblock, address, &operand) ) { sieve_runtime_trace_error(renv, "invalid operand"); t_pop(); return FALSE; diff --git a/src/lib-sieve/plugins/imap4flags/tst-hasflag.c b/src/lib-sieve/plugins/imap4flags/tst-hasflag.c index 01f03191a..cbcec03de 100644 --- a/src/lib-sieve/plugins/imap4flags/tst-hasflag.c +++ b/src/lib-sieve/plugins/imap4flags/tst-hasflag.c @@ -119,7 +119,7 @@ static bool tst_hasflag_validate static bool tst_hasflag_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) { - sieve_operation_emit(cgenv->sbin, cmd->ext, &hasflag_operation); + sieve_operation_emit(cgenv->sblock, cmd->ext, &hasflag_operation); /* Generate arguments */ if ( !sieve_generate_arguments(cgenv, cmd, NULL) ) diff --git a/src/lib-sieve/plugins/include/cmd-global.c b/src/lib-sieve/plugins/include/cmd-global.c index 06afdb3fe..1c50483bc 100644 --- a/src/lib-sieve/plugins/include/cmd-global.c +++ b/src/lib-sieve/plugins/include/cmd-global.c @@ -201,26 +201,27 @@ static bool cmd_global_generate { struct sieve_ast_argument *arg = cmd->first_positional; - sieve_operation_emit(cgenv->sbin, cmd->ext, &global_operation); + sieve_operation_emit(cgenv->sblock, cmd->ext, &global_operation); if ( sieve_ast_argument_type(arg) == SAAT_STRING ) { /* Single string */ struct sieve_variable *var = (struct sieve_variable *) arg->argument->data; - (void)sieve_binary_emit_unsigned(cgenv->sbin, 1); - (void)sieve_binary_emit_unsigned(cgenv->sbin, var->index); + (void)sieve_binary_emit_unsigned(cgenv->sblock, 1); + (void)sieve_binary_emit_unsigned(cgenv->sblock, var->index); } else if ( sieve_ast_argument_type(arg) == SAAT_STRING_LIST ) { /* String list */ struct sieve_ast_argument *stritem = sieve_ast_strlist_first(arg); - (void)sieve_binary_emit_unsigned(cgenv->sbin, sieve_ast_strlist_count(arg)); + (void)sieve_binary_emit_unsigned + (cgenv->sblock, sieve_ast_strlist_count(arg)); while ( stritem != NULL ) { struct sieve_variable *var = (struct sieve_variable *) stritem->argument->data; - (void)sieve_binary_emit_unsigned(cgenv->sbin, var->index); + (void)sieve_binary_emit_unsigned(cgenv->sblock, var->index); stritem = sieve_ast_strlist_next(stritem); } @@ -243,7 +244,7 @@ static bool opc_global_dump struct sieve_variable_scope *scope; struct sieve_variable * const *vars; - if ( !sieve_binary_read_unsigned(denv->sbin, address, &count) ) + if ( !sieve_binary_read_unsigned(denv->sblock, address, &count) ) return FALSE; sieve_code_dumpf(denv, "GLOBAL (count: %u):", count); @@ -257,7 +258,7 @@ static bool opc_global_dump unsigned int index; sieve_code_mark(denv); - if ( !sieve_binary_read_unsigned(denv->sbin, address, &index) || + if ( !sieve_binary_read_unsigned(denv->sblock, address, &index) || index >= var_count ) return FALSE; @@ -280,7 +281,7 @@ static int opc_global_execute struct sieve_variable * const *vars; unsigned int var_count, count, i; - if ( !sieve_binary_read_unsigned(renv->sbin, address, &count) ) { + if ( !sieve_binary_read_unsigned(renv->sblock, address, &count) ) { sieve_runtime_trace_error(renv, "invalid count operand"); return SIEVE_EXEC_BIN_CORRUPT; } @@ -293,7 +294,7 @@ static int opc_global_execute for ( i = 0; i < count; i++ ) { unsigned int index; - if ( !sieve_binary_read_unsigned(renv->sbin, address, &index) ) { + if ( !sieve_binary_read_unsigned(renv->sblock, address, &index) ) { sieve_runtime_trace_error(renv, "invalid global variable operand"); return SIEVE_EXEC_BIN_CORRUPT; } diff --git a/src/lib-sieve/plugins/include/cmd-include.c b/src/lib-sieve/plugins/include/cmd-include.c index ce25fbcd8..2be54eee2 100644 --- a/src/lib-sieve/plugins/include/cmd-include.c +++ b/src/lib-sieve/plugins/include/cmd-include.c @@ -287,9 +287,9 @@ static bool cmd_include_generate ctx_data->include_once) ) return FALSE; - (void)sieve_operation_emit(cgenv->sbin, cmd->ext, &include_operation); - (void)sieve_binary_emit_unsigned(cgenv->sbin, included->id); - (void)sieve_binary_emit_byte(cgenv->sbin, flags); + (void)sieve_operation_emit(cgenv->sblock, cmd->ext, &include_operation); + (void)sieve_binary_emit_unsigned(cgenv->sblock, included->id); + (void)sieve_binary_emit_byte(cgenv->sblock, flags); return TRUE; } @@ -308,10 +308,10 @@ static bool opc_include_dump sieve_code_dumpf(denv, "INCLUDE:"); sieve_code_mark(denv); - if ( !sieve_binary_read_unsigned(denv->sbin, address, &include_id) ) + if ( !sieve_binary_read_unsigned(denv->sblock, address, &include_id) ) return FALSE; - if ( !sieve_binary_read_byte(denv->sbin, address, &flags) ) + if ( !sieve_binary_read_byte(denv->sblock, address, &flags) ) return FALSE; binctx = ext_include_binary_get_context(denv->oprtn.ext, denv->sbin); @@ -322,7 +322,7 @@ static bool opc_include_dump sieve_code_descend(denv); sieve_code_dumpf(denv, "script: %s %s[ID: %d, BLOCK: %d]", sieve_script_filename(included->script), (flags & 0x01 ? "(once) " : ""), - include_id, included->block_id); + include_id, sieve_binary_block_get_id(included->block)); return TRUE; } @@ -336,12 +336,12 @@ static int opc_include_execute { unsigned int include_id, flags; - if ( !sieve_binary_read_unsigned(renv->sbin, address, &include_id) ) { + if ( !sieve_binary_read_unsigned(renv->sblock, address, &include_id) ) { sieve_runtime_trace_error(renv, "invalid include-id operand"); return SIEVE_EXEC_BIN_CORRUPT; } - if ( !sieve_binary_read_unsigned(renv->sbin, address, &flags) ) { + if ( !sieve_binary_read_unsigned(renv->sblock, address, &flags) ) { sieve_runtime_trace_error(renv, "invalid flags operand"); return SIEVE_EXEC_BIN_CORRUPT; } diff --git a/src/lib-sieve/plugins/include/cmd-return.c b/src/lib-sieve/plugins/include/cmd-return.c index f3dec7877..37625400b 100644 --- a/src/lib-sieve/plugins/include/cmd-return.c +++ b/src/lib-sieve/plugins/include/cmd-return.c @@ -52,7 +52,7 @@ const struct sieve_operation_def return_operation = { static bool cmd_return_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) { - sieve_operation_emit(cgenv->sbin, cmd->ext, &return_operation); + sieve_operation_emit(cgenv->sblock, cmd->ext, &return_operation); return TRUE; } diff --git a/src/lib-sieve/plugins/include/ext-include-binary.c b/src/lib-sieve/plugins/include/ext-include-binary.c index eb661a41c..802ee5805 100644 --- a/src/lib-sieve/plugins/include/ext-include-binary.c +++ b/src/lib-sieve/plugins/include/ext-include-binary.c @@ -50,7 +50,7 @@ const struct sieve_binary_extension include_binary_ext = { struct ext_include_binary_context { struct sieve_binary *binary; - unsigned int dependency_block; + struct sieve_binary_block *dependency_block; struct hash_table *included_scripts; ARRAY_DEFINE(include_index, struct ext_include_script_info *); @@ -120,7 +120,7 @@ struct ext_include_binary_context *ext_include_binary_init const struct ext_include_script_info *ext_include_binary_script_include (struct ext_include_binary_context *binctx, struct sieve_script *script, - enum ext_include_script_location location, unsigned int block_id) + enum ext_include_script_location location, struct sieve_binary_block *inc_block) { pool_t pool = sieve_binary_pool(binctx->binary); struct ext_include_script_info *incscript; @@ -129,7 +129,7 @@ const struct ext_include_script_info *ext_include_binary_script_include incscript->id = array_count(&binctx->include_index)+1; incscript->script = script; incscript->location = location; - incscript->block_id = block_id; + incscript->block = inc_block; /* Unreferenced on binary_free */ sieve_script_ref(script); @@ -200,36 +200,32 @@ struct sieve_variable_scope *ext_include_binary_get_global_scope */ static bool ext_include_binary_save -(const struct sieve_extension *ext ATTR_UNUSED, struct sieve_binary *sbin, - void *context) +(const struct sieve_extension *ext ATTR_UNUSED, + struct sieve_binary *sbin ATTR_UNUSED, void *context) { struct ext_include_binary_context *binctx = (struct ext_include_binary_context *) context; struct ext_include_script_info *const *scripts; + struct sieve_binary_block *sblock = binctx->dependency_block; unsigned int script_count, i; - unsigned int prvblk; bool result = TRUE; - sieve_binary_block_clear(sbin, binctx->dependency_block); - if ( !sieve_binary_block_set_active(sbin, binctx->dependency_block, &prvblk) ) - return FALSE; + sieve_binary_block_clear(sblock); scripts = array_get(&binctx->include_index, &script_count); - sieve_binary_emit_unsigned(sbin, script_count); + sieve_binary_emit_unsigned(sblock, script_count); for ( i = 0; i < script_count; i++ ) { struct ext_include_script_info *incscript = scripts[i]; - sieve_binary_emit_unsigned(sbin, incscript->block_id); - sieve_binary_emit_byte(sbin, incscript->location); - sieve_binary_emit_cstring(sbin, sieve_script_name(incscript->script)); + sieve_binary_emit_unsigned(sblock, sieve_binary_block_get_id(incscript->block)); + sieve_binary_emit_byte(sblock, incscript->location); + sieve_binary_emit_cstring(sblock, sieve_script_name(incscript->script)); } - result = ext_include_variables_save(sbin, binctx->global_vars); + result = ext_include_variables_save(sblock, binctx->global_vars); - (void) sieve_binary_block_set_active(sbin, prvblk, NULL); - return result; } @@ -238,19 +234,20 @@ static bool ext_include_binary_open { struct ext_include_binary_context *binctx = (struct ext_include_binary_context *) context; - unsigned int block, prvblk, depcount, i; + struct sieve_binary_block *sblock; + unsigned int depcount, i, block_id; sieve_size_t offset; - block = sieve_binary_extension_get_block(sbin, ext); - - if ( !sieve_binary_block_set_active(sbin, block, &prvblk) ) - return FALSE; - + sblock = sieve_binary_extension_get_block(sbin, ext); + block_id = sieve_binary_block_get_id(sblock); + offset = 0; - if ( !sieve_binary_read_unsigned(sbin, &offset, &depcount) ) { + if ( !sieve_binary_read_unsigned(sblock, &offset, &depcount) ) { sieve_sys_error("include: failed to read include count " - "for dependency block %d of binary %s", block, sieve_binary_path(sbin)); + "for dependency block %d of binary %s", block_id, + sieve_binary_path(sbin)); + printf("BLOCK: %ld\n", sieve_binary_block_get_size(sblock)); return FALSE; } @@ -263,19 +260,29 @@ static bool ext_include_binary_open /* Read dependencies */ for ( i = 0; i < depcount; i++ ) { - unsigned int block_id; + unsigned int inc_block_id; + struct sieve_binary_block *inc_block; enum ext_include_script_location location; string_t *script_name; const char *script_dir; struct sieve_script *script; if ( - !sieve_binary_read_unsigned(sbin, &offset, &block_id) || - !sieve_binary_read_byte(sbin, &offset, &location) || - !sieve_binary_read_string(sbin, &offset, &script_name) ) { + !sieve_binary_read_unsigned(sblock, &offset, &inc_block_id) || + !sieve_binary_read_byte(sblock, &offset, &location) || + !sieve_binary_read_string(sblock, &offset, &script_name) ) { /* Binary is corrupt, recompile */ sieve_sys_error("include: failed to read included script " - "from dependency block %d of binary %s", block, sieve_binary_path(sbin)); + "from dependency block %d of binary %s", block_id, + sieve_binary_path(sbin)); + return FALSE; + } + + if ( (inc_block=sieve_binary_block_get(sbin, inc_block_id)) == NULL ) { + sieve_sys_error("include: failed to find block %d for included script " + "from dependency block %d of binary %s", inc_block_id, block_id, + sieve_binary_path(sbin)); + return FALSE; } @@ -283,7 +290,7 @@ static bool ext_include_binary_open /* Binary is corrupt, recompile */ sieve_sys_error("include: dependency block %d of binary %s " "reports invalid script location (id %d)", - block, sieve_binary_path(sbin), location); + block_id, sieve_binary_path(sbin), location); return FALSE; } @@ -297,18 +304,16 @@ static bool ext_include_binary_open return FALSE; } - (void)ext_include_binary_script_include(binctx, script, location, block_id); + (void)ext_include_binary_script_include + (binctx, script, location, inc_block); sieve_script_unref(&script); } if ( !ext_include_variables_load - (ext, sbin, &offset, block, &binctx->global_vars) ) + (ext, sblock, &offset, &binctx->global_vars) ) return FALSE; - /* Restore previously active block */ - (void)sieve_binary_block_set_active(sbin, prvblk, NULL); - return TRUE; } @@ -375,7 +380,6 @@ bool ext_include_binary_dump ext_include_binary_get_context(ext, sbin); struct hash_iterate_context *hctx; void *key, *value; - unsigned int prvblk = 0; if ( !ext_include_variables_dump(denv, binctx->global_vars) ) return FALSE; @@ -384,19 +388,13 @@ bool ext_include_binary_dump while ( hash_table_iterate(hctx, &key, &value) ) { struct ext_include_script_info *incscript = (struct ext_include_script_info *) value; - + unsigned int block_id = sieve_binary_block_get_id(incscript->block); + sieve_binary_dump_sectionf(denv, "Included %s script '%s' (block: %d)", ext_include_script_location_name(incscript->location), - sieve_script_name(incscript->script), incscript->block_id); - - if ( prvblk == 0 ) { - if ( !sieve_binary_block_set_active(sbin, incscript->block_id, &prvblk) ) - return FALSE; - } else { - if ( !sieve_binary_block_set_active(sbin, incscript->block_id, NULL) ) - return FALSE; - } - + sieve_script_name(incscript->script), block_id); + + denv->sblock = incscript->block; denv->cdumper = sieve_code_dumper_create(denv); if ( denv->cdumper == NULL ) @@ -405,10 +403,7 @@ bool ext_include_binary_dump sieve_code_dumper_run(denv->cdumper); sieve_code_dumper_free(&(denv->cdumper)); } - - if ( !sieve_binary_block_set_active(sbin, prvblk, NULL) ) - return FALSE; - + hash_table_iterate_deinit(&hctx); return TRUE; diff --git a/src/lib-sieve/plugins/include/ext-include-binary.h b/src/lib-sieve/plugins/include/ext-include-binary.h index 68f3344db..dfc63a487 100644 --- a/src/lib-sieve/plugins/include/ext-include-binary.h +++ b/src/lib-sieve/plugins/include/ext-include-binary.h @@ -35,12 +35,13 @@ struct ext_include_script_info { struct sieve_script *script; enum ext_include_script_location location; - unsigned int block_id; + struct sieve_binary_block *block; }; const struct ext_include_script_info *ext_include_binary_script_include (struct ext_include_binary_context *binctx, struct sieve_script *script, - enum ext_include_script_location location, unsigned int block_id); + enum ext_include_script_location location, + struct sieve_binary_block *block); bool ext_include_binary_script_is_included (struct ext_include_binary_context *binctx, struct sieve_script *script, const struct ext_include_script_info **script_info_r); diff --git a/src/lib-sieve/plugins/include/ext-include-common.c b/src/lib-sieve/plugins/include/ext-include-common.c index 436c6e47a..6a3289030 100644 --- a/src/lib-sieve/plugins/include/ext-include-common.c +++ b/src/lib-sieve/plugins/include/ext-include-common.c @@ -433,7 +433,7 @@ bool ext_include_generate_include /* Is the script already compiled into the current binary? */ if ( !ext_include_binary_script_is_included(binctx, script, &included) ) { - unsigned int inc_block_id, this_block_id; + struct sieve_binary_block *inc_block; const char *script_name = sieve_script_name(script); /* Check whether include limit is exceeded */ @@ -447,9 +447,9 @@ bool ext_include_generate_include /* No, allocate a new block in the binary and mark the script as included. */ - inc_block_id = sieve_binary_block_create(sbin); + inc_block = sieve_binary_block_create(sbin); included = ext_include_binary_script_include - (binctx, script, location, inc_block_id); + (binctx, script, location, inc_block); /* Parse */ if ( (ast = sieve_parse(script, ehandler)) == NULL ) { @@ -475,28 +475,18 @@ bool ext_include_generate_include * FIXME: It might not be a good idea to recurse code generation for * included scripts. */ - if ( sieve_binary_block_set_active(sbin, inc_block_id, &this_block_id) ) { - subgentr = sieve_generator_create(ast, ehandler); - ext_include_initialize_generator_context(cmd->ext, subgentr, ctx, script); - - if ( !sieve_generator_run(subgentr, &sbin) ) { - sieve_command_generate_error(gentr, cmd, - "failed to generate code for included script '%s'", - str_sanitize(script_name, 80)); - result = FALSE; - } + subgentr = sieve_generator_create(ast, ehandler); + ext_include_initialize_generator_context(cmd->ext, subgentr, ctx, script); - if ( sbin != NULL ) - (void) sieve_binary_block_set_active(sbin, this_block_id, NULL); - - sieve_generator_free(&subgentr); - - } else { - sieve_sys_error("include: failed to activate binary block %d for " - "generating code for the included script", inc_block_id); - result = FALSE; + if ( sieve_generator_run(subgentr, &inc_block) == NULL ) { + sieve_command_generate_error(gentr, cmd, + "failed to generate code for included script '%s'", + str_sanitize(script_name, 80)); + result = FALSE; } + sieve_generator_free(&subgentr); + /* Cleanup */ sieve_ast_unref(&ast); } @@ -537,6 +527,7 @@ static bool ext_include_runtime_include_mark includes = array_get(&ctx->global->included_scripts, &count); for ( i = 0; i < count; i++ ) { + if ( sieve_script_equals(include->script, includes[i]) ) return ( !once ); } @@ -555,6 +546,7 @@ int ext_include_execute_include const struct ext_include_script_info *included; struct ext_include_binary_context *binctx = ext_include_binary_get_context(this_ext, renv->sbin); + unsigned int block_id; /* Check for invalid include id (== corrupt binary) */ included = ext_include_binary_script_get_included(binctx, include_id); @@ -565,16 +557,18 @@ int ext_include_execute_include ctx = ext_include_get_interpreter_context(this_ext, renv->interp); + block_id = sieve_binary_block_get_id(included->block); + sieve_runtime_trace(renv, "INCLUDE command (script: %s, id: %d block: %d) START::", - sieve_script_name(included->script), include_id, included->block_id); + sieve_script_name(included->script), include_id, block_id); /* If :once modifier is specified, check for duplicate include */ if ( !ext_include_runtime_include_mark(ctx, included, once) ) { /* skip */ sieve_runtime_trace(renv, - "INCLUDE command (block: %d) SKIPPED ::", included->block_id); + "INCLUDE command (block: %d) SKIPPED ::", block_id); return result; } @@ -584,7 +578,7 @@ int ext_include_execute_include if ( ext_include_runtime_check_circular(ctx, included) ) { sieve_runtime_trace_error(renv, "circular include for script: %s [%d]", - sieve_script_name(included->script), included->block_id); + sieve_script_name(included->script), block_id); /* Situation has no valid way to emerge at runtime */ return SIEVE_EXEC_BIN_CORRUPT; @@ -595,24 +589,16 @@ int ext_include_execute_include struct sieve_error_handler *ehandler = sieve_interpreter_get_error_handler(renv->interp); struct sieve_interpreter *subinterp; - unsigned int this_block_id; bool interrupted = FALSE; /* We are the top-level interpreter instance */ - /* Activate block for included script */ - if ( !sieve_binary_block_set_active - (renv->sbin, included->block_id, &this_block_id) ) { - sieve_runtime_trace_error(renv, "invalid block id: %d", - included->block_id); - result = SIEVE_EXEC_BIN_CORRUPT; - } - if ( result == SIEVE_EXEC_OK ) { /* Create interpreter for top-level included script * (first sub-interpreter) */ - subinterp = sieve_interpreter_create(renv->sbin, ehandler); + subinterp = sieve_interpreter_create_for_block + (included->block, ehandler); if ( subinterp != NULL ) { curctx = ext_include_interpreter_context_init_child @@ -639,7 +625,7 @@ int ext_include_execute_include /* Sub-interpreter ended or executed return */ sieve_runtime_trace(renv, "INCLUDE command (block: %d) END ::", - curctx->script_info->block_id); + sieve_binary_block_get_id(curctx->script_info->block)); /* Ascend interpreter stack */ curctx = curctx->parent; @@ -648,9 +634,6 @@ int ext_include_execute_include /* This is the top-most sub-interpreter, bail out */ if ( curctx->parent == NULL ) break; - /* Reactivate parent */ - (void) sieve_binary_block_set_active - (renv->sbin, curctx->script_info->block_id, NULL); subinterp = curctx->interp; /* Continue parent */ @@ -662,18 +645,11 @@ int ext_include_execute_include if ( curctx->include != NULL ) { /* Sub-include requested */ - - /* Activate the sub-include's block */ - if ( !sieve_binary_block_set_active - (renv->sbin, curctx->include->block_id, NULL) ) { - sieve_runtime_trace_error(renv, "invalid block id: %d", - curctx->include->block_id); - result = SIEVE_EXEC_BIN_CORRUPT; - } - + if ( result == SIEVE_EXEC_OK ) { /* Create sub-interpreter */ - subinterp = sieve_interpreter_create(renv->sbin, ehandler); + subinterp = sieve_interpreter_create_for_block + (curctx->include->block, ehandler); if ( subinterp != NULL ) { curctx = ext_include_interpreter_context_init_child @@ -701,7 +677,7 @@ int ext_include_execute_include } } else sieve_runtime_trace(renv, "INCLUDE command (block: %d) END ::", - curctx->script_info->block_id); + sieve_binary_block_get_id(curctx->script_info->block)); /* Free any sub-interpreters that might still be active */ while ( curctx != NULL && curctx->parent != NULL ) { @@ -715,8 +691,6 @@ int ext_include_execute_include curctx = nextctx; } - /* Return to our own block */ - (void) sieve_binary_block_set_active(renv->sbin, this_block_id, NULL); } else { /* We are an included script already, defer inclusion to main interpreter */ diff --git a/src/lib-sieve/plugins/include/ext-include-variables.c b/src/lib-sieve/plugins/include/ext-include-variables.c index 4ef36dae5..16b175cac 100644 --- a/src/lib-sieve/plugins/include/ext-include-variables.c +++ b/src/lib-sieve/plugins/include/ext-include-variables.c @@ -70,11 +70,11 @@ struct sieve_variable *ext_include_variable_import_global */ bool ext_include_variables_save -(struct sieve_binary *sbin, struct sieve_variable_scope *global_vars) +(struct sieve_binary_block *sblock, struct sieve_variable_scope *global_vars) { unsigned int count = sieve_variable_scope_size(global_vars); - sieve_binary_emit_unsigned(sbin, count); + sieve_binary_emit_unsigned(sblock, count); if ( count > 0 ) { unsigned int size, i; @@ -82,7 +82,7 @@ bool ext_include_variables_save sieve_variable_scope_get_variables(global_vars, &size); for ( i = 0; i < size; i++ ) { - sieve_binary_emit_cstring(sbin, vars[i]->identifier); + sieve_binary_emit_cstring(sblock, vars[i]->identifier); } } @@ -90,20 +90,21 @@ bool ext_include_variables_save } bool ext_include_variables_load -(const struct sieve_extension *this_ext, struct sieve_binary *sbin, - sieve_size_t *offset, unsigned int block, - struct sieve_variable_scope **global_vars_r) +(const struct sieve_extension *this_ext, struct sieve_binary_block *sblock, + sieve_size_t *offset, struct sieve_variable_scope **global_vars_r) { - unsigned int count = 0; - unsigned int i; + struct sieve_binary *sbin = sieve_binary_block_get_binary(sblock); + unsigned int block_id = sieve_binary_block_get_id(sblock); + unsigned int i, count = 0; pool_t pool; /* Sanity assert */ i_assert( *global_vars_r == NULL ); - if ( !sieve_binary_read_unsigned(sbin, offset, &count) ) { + if ( !sieve_binary_read_unsigned(sblock, offset, &count) ) { sieve_sys_error("include: failed to read global variables count " - "from dependency block %d of binary %s", block, sieve_binary_path(sbin)); + "from dependency block %d of binary %s", block_id, + sieve_binary_path(sbin)); return FALSE; } @@ -122,10 +123,11 @@ bool ext_include_variables_load struct sieve_variable *var; string_t *identifier; - if ( !sieve_binary_read_string(sbin, offset, &identifier) ) { + if ( !sieve_binary_read_string(sblock, offset, &identifier) ) { /* Binary is corrupt, recompile */ sieve_sys_error("include: failed to read global variable specification " - "from dependency block %d of binary %s", block, sieve_binary_path(sbin)); + "from dependency block %d of binary %s", block_id, + sieve_binary_path(sbin)); return FALSE; } @@ -248,7 +250,7 @@ bool vnspc_global_variables_generate struct sieve_variable *var = (struct sieve_variable *) var_data; - sieve_variables_opr_variable_emit(cgenv->sbin, ectx->var_ext, var); + sieve_variables_opr_variable_emit(cgenv->sblock, ectx->var_ext, var); return TRUE; } diff --git a/src/lib-sieve/plugins/include/ext-include-variables.h b/src/lib-sieve/plugins/include/ext-include-variables.h index 036136895..9d494165d 100644 --- a/src/lib-sieve/plugins/include/ext-include-variables.h +++ b/src/lib-sieve/plugins/include/ext-include-variables.h @@ -23,11 +23,10 @@ struct sieve_variable *ext_include_variable_import_global */ bool ext_include_variables_save - (struct sieve_binary *sbin, struct sieve_variable_scope *global_vars); + (struct sieve_binary_block *sblock, struct sieve_variable_scope *global_vars); bool ext_include_variables_load - (const struct sieve_extension *this_ext, struct sieve_binary *sbin, - sieve_size_t *offset, unsigned int block, - struct sieve_variable_scope **global_vars_r); + (const struct sieve_extension *this_ext, struct sieve_binary_block *sblock, + sieve_size_t *offset, struct sieve_variable_scope **global_vars_r); bool ext_include_variables_dump (struct sieve_dumptime_env *denv, struct sieve_variable_scope *global_vars); diff --git a/src/lib-sieve/plugins/mailbox/tag-mailbox-create.c b/src/lib-sieve/plugins/mailbox/tag-mailbox-create.c index d67d9a277..f78142f4f 100644 --- a/src/lib-sieve/plugins/mailbox/tag-mailbox-create.c +++ b/src/lib-sieve/plugins/mailbox/tag-mailbox-create.c @@ -96,7 +96,7 @@ static bool tag_mailbox_create_generate } sieve_opr_side_effect_emit - (cgenv->sbin, arg->argument->ext, &mailbox_create_side_effect); + (cgenv->sblock, arg->argument->ext, &mailbox_create_side_effect); return TRUE; } diff --git a/src/lib-sieve/plugins/mailbox/tst-mailboxexists.c b/src/lib-sieve/plugins/mailbox/tst-mailboxexists.c index 5a07cffc3..ac9044e64 100644 --- a/src/lib-sieve/plugins/mailbox/tst-mailboxexists.c +++ b/src/lib-sieve/plugins/mailbox/tst-mailboxexists.c @@ -78,7 +78,7 @@ static bool tst_mailboxexists_validate static bool tst_mailboxexists_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *tst) { - sieve_operation_emit(cgenv->sbin, tst->ext, &mailboxexists_operation); + sieve_operation_emit(cgenv->sblock, tst->ext, &mailboxexists_operation); /* Generate arguments */ return sieve_generate_arguments(cgenv, tst, NULL); diff --git a/src/lib-sieve/plugins/notify/cmd-denotify.c b/src/lib-sieve/plugins/notify/cmd-denotify.c index 4b1919193..f1512e56c 100644 --- a/src/lib-sieve/plugins/notify/cmd-denotify.c +++ b/src/lib-sieve/plugins/notify/cmd-denotify.c @@ -218,10 +218,10 @@ static bool cmd_denotify_validate static bool cmd_denotify_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) { - sieve_operation_emit(cgenv->sbin, cmd->ext, &denotify_operation); + sieve_operation_emit(cgenv->sblock, cmd->ext, &denotify_operation); /* Emit source line */ - sieve_code_source_line_emit(cgenv->sbin, sieve_command_source_line(cmd)); + sieve_code_source_line_emit(cgenv->sblock, sieve_command_source_line(cmd)); /* Generate arguments */ return sieve_generate_arguments(cgenv, cmd, NULL); @@ -245,11 +245,11 @@ static bool cmd_denotify_operation_dump return FALSE; /* Dump optional operands */ - if ( sieve_operand_optional_present(denv->sbin, address) ) { + if ( sieve_operand_optional_present(denv->sblock, address) ) { while ( opt_code != 0 ) { sieve_code_mark(denv); - if ( !sieve_operand_optional_read(denv->sbin, address, &opt_code) ) + if ( !sieve_operand_optional_read(denv->sblock, address, &opt_code) ) return FALSE; switch ( opt_code ) { @@ -308,9 +308,9 @@ static int cmd_denotify_operation_execute } /* Optional operands */ - if ( sieve_operand_optional_present(renv->sbin, address) ) { + if ( sieve_operand_optional_present(renv->sblock, address) ) { while ( opt_code != 0 ) { - if ( !sieve_operand_optional_read(renv->sbin, address, &opt_code) ) { + if ( !sieve_operand_optional_read(renv->sblock, address, &opt_code) ) { sieve_runtime_trace_error(renv, "invalid optional operand"); return SIEVE_EXEC_BIN_CORRUPT; } diff --git a/src/lib-sieve/plugins/notify/cmd-notify.c b/src/lib-sieve/plugins/notify/cmd-notify.c index d7d31742f..69586a240 100644 --- a/src/lib-sieve/plugins/notify/cmd-notify.c +++ b/src/lib-sieve/plugins/notify/cmd-notify.c @@ -353,10 +353,10 @@ static bool cmd_notify_validate static bool cmd_notify_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) { - sieve_operation_emit(cgenv->sbin, cmd->ext, ¬ify_old_operation); + sieve_operation_emit(cgenv->sblock, cmd->ext, ¬ify_old_operation); /* Emit source line */ - sieve_code_source_line_emit(cgenv->sbin, sieve_command_source_line(cmd)); + sieve_code_source_line_emit(cgenv->sblock, sieve_command_source_line(cmd)); /* Generate arguments */ return sieve_generate_arguments(cgenv, cmd, NULL); @@ -379,11 +379,11 @@ static bool cmd_notify_operation_dump return FALSE; /* Dump optional operands */ - if ( sieve_operand_optional_present(denv->sbin, address) ) { + if ( sieve_operand_optional_present(denv->sblock, address) ) { while ( opt_code != 0 ) { sieve_code_mark(denv); - if ( !sieve_operand_optional_read(denv->sbin, address, &opt_code) ) + if ( !sieve_operand_optional_read(denv->sblock, address, &opt_code) ) return FALSE; switch ( opt_code ) { @@ -442,9 +442,9 @@ static int cmd_notify_operation_execute } /* Optional operands */ - if ( sieve_operand_optional_present(renv->sbin, address) ) { + if ( sieve_operand_optional_present(renv->sblock, address) ) { while ( opt_code != 0 ) { - if ( !sieve_operand_optional_read(renv->sbin, address, &opt_code) ) { + if ( !sieve_operand_optional_read(renv->sblock, address, &opt_code) ) { sieve_runtime_trace_error(renv, "invalid optional operand"); return SIEVE_EXEC_BIN_CORRUPT; } diff --git a/src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c b/src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c index ef9b1bade..3f1103d8a 100644 --- a/src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c +++ b/src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c @@ -187,9 +187,9 @@ static bool tst_spamvirustest_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *tst) { if ( sieve_command_is(tst, spamtest_test) ) - sieve_operation_emit(cgenv->sbin, tst->ext, &spamtest_operation); + sieve_operation_emit(cgenv->sblock, tst->ext, &spamtest_operation); else if ( sieve_command_is(tst, virustest_test) ) - sieve_operation_emit(cgenv->sbin, tst->ext, &virustest_operation); + sieve_operation_emit(cgenv->sblock, tst->ext, &virustest_operation); else i_unreached(); diff --git a/src/lib-sieve/plugins/vacation/cmd-vacation.c b/src/lib-sieve/plugins/vacation/cmd-vacation.c index c5e632349..52dfe4702 100644 --- a/src/lib-sieve/plugins/vacation/cmd-vacation.c +++ b/src/lib-sieve/plugins/vacation/cmd-vacation.c @@ -463,17 +463,17 @@ static bool cmd_vacation_generate struct cmd_vacation_context_data *ctx_data = (struct cmd_vacation_context_data *) cmd->data; - sieve_operation_emit(cgenv->sbin, cmd->ext, &vacation_operation); + sieve_operation_emit(cgenv->sblock, cmd->ext, &vacation_operation); /* Emit source line */ - sieve_code_source_line_emit(cgenv->sbin, sieve_command_source_line(cmd)); + sieve_code_source_line_emit(cgenv->sblock, sieve_command_source_line(cmd)); /* Generate arguments */ if ( !sieve_generate_arguments(cgenv, cmd, NULL) ) return FALSE; /* FIXME: this will not allow the handle to be a variable */ - sieve_opr_string_emit(cgenv->sbin, ctx_data->handle); + sieve_opr_string_emit(cgenv->sblock, ctx_data->handle); return TRUE; } @@ -495,11 +495,11 @@ static bool ext_vacation_operation_dump return FALSE; /* Dump optional operands */ - if ( sieve_operand_optional_present(denv->sbin, address) ) { + if ( sieve_operand_optional_present(denv->sblock, address) ) { while ( opt_code != 0 ) { sieve_code_mark(denv); - if ( !sieve_operand_optional_read(denv->sbin, address, &opt_code) ) + if ( !sieve_operand_optional_read(denv->sblock, address, &opt_code) ) return FALSE; switch ( opt_code ) { @@ -567,9 +567,9 @@ static int ext_vacation_operation_execute } /* Optional operands */ - if ( sieve_operand_optional_present(renv->sbin, address) ) { + if ( sieve_operand_optional_present(renv->sblock, address) ) { while ( opt_code != 0 ) { - if ( !sieve_operand_optional_read(renv->sbin, address, &opt_code) ) { + if ( !sieve_operand_optional_read(renv->sblock, address, &opt_code) ) { sieve_runtime_trace_error(renv, "invalid optional operand"); return SIEVE_EXEC_BIN_CORRUPT; } diff --git a/src/lib-sieve/plugins/variables/cmd-set.c b/src/lib-sieve/plugins/variables/cmd-set.c index 5476be283..1870a07aa 100644 --- a/src/lib-sieve/plugins/variables/cmd-set.c +++ b/src/lib-sieve/plugins/variables/cmd-set.c @@ -223,23 +223,23 @@ static bool cmd_set_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) { const struct sieve_extension *this_ext = cmd->ext; - struct sieve_binary *sbin = cgenv->sbin; + struct sieve_binary_block *sblock = cgenv->sblock; struct cmd_set_context *sctx = (struct cmd_set_context *) cmd->data; const struct sieve_variables_modifier *const *modfs; unsigned int i, modf_count; - sieve_operation_emit(sbin, this_ext, &cmd_set_operation); + sieve_operation_emit(sblock, this_ext, &cmd_set_operation); /* Generate arguments */ if ( !sieve_generate_arguments(cgenv, cmd, NULL) ) return FALSE; /* Generate modifiers (already sorted during validation) */ - sieve_binary_emit_byte(sbin, array_count(&sctx->modifiers)); + sieve_binary_emit_byte(sblock, array_count(&sctx->modifiers)); modfs = array_get(&sctx->modifiers, &modf_count); for ( i = 0; i < modf_count; i++ ) { - ext_variables_opr_modifier_emit(sbin, modfs[i]->object.ext, modfs[i]->def); + ext_variables_opr_modifier_emit(sblock, modfs[i]->object.ext, modfs[i]->def); } return TRUE; @@ -263,7 +263,7 @@ static bool cmd_set_operation_dump return FALSE; /* Read the number of applied modifiers we need to read */ - if ( !sieve_binary_read_byte(denv->sbin, address, &mdfs) ) + if ( !sieve_binary_read_byte(denv->sblock, address, &mdfs) ) return FALSE; /* Print all modifiers (sorted during code generation already) */ @@ -305,7 +305,7 @@ static int cmd_set_operation_execute } /* Read the number of modifiers used */ - if ( !sieve_binary_read_byte(renv->sbin, address, &mdfs) ) { + if ( !sieve_binary_read_byte(renv->sblock, address, &mdfs) ) { sieve_runtime_trace_error(renv, "invalid modifier count"); return SIEVE_EXEC_BIN_CORRUPT; } diff --git a/src/lib-sieve/plugins/variables/ext-variables-arguments.c b/src/lib-sieve/plugins/variables/ext-variables-arguments.c index 70f91eac0..d0874c68e 100644 --- a/src/lib-sieve/plugins/variables/ext-variables-arguments.c +++ b/src/lib-sieve/plugins/variables/ext-variables-arguments.c @@ -82,7 +82,7 @@ static bool arg_variable_generate struct sieve_argument *argument = arg->argument; struct sieve_variable *var = (struct sieve_variable *) argument->data; - sieve_variables_opr_variable_emit(cgenv->sbin, argument->ext, var); + sieve_variables_opr_variable_emit(cgenv->sblock, argument->ext, var); return TRUE; } @@ -152,7 +152,7 @@ static bool arg_match_value_generate struct sieve_argument *argument = arg->argument; unsigned int index = POINTER_CAST_TO(argument->data, unsigned int); - sieve_variables_opr_match_value_emit(cgenv->sbin, argument->ext, index); + sieve_variables_opr_match_value_emit(cgenv->sblock, argument->ext, index); return TRUE; } diff --git a/src/lib-sieve/plugins/variables/ext-variables-common.c b/src/lib-sieve/plugins/variables/ext-variables-common.c index 051612c98..4d28541a6 100644 --- a/src/lib-sieve/plugins/variables/ext-variables-common.c +++ b/src/lib-sieve/plugins/variables/ext-variables-common.c @@ -459,9 +459,9 @@ bool ext_variables_generator_load unsigned int count = sieve_variable_scope_size(main_scope); sieve_size_t jump; - sieve_binary_emit_unsigned(cgenv->sbin, count); + sieve_binary_emit_unsigned(cgenv->sblock, count); - jump = sieve_binary_emit_offset(cgenv->sbin, 0); + jump = sieve_binary_emit_offset(cgenv->sblock, 0); if ( count > 0 ) { unsigned int size, i; @@ -469,11 +469,11 @@ bool ext_variables_generator_load sieve_variable_scope_get_variables(main_scope, &size); for ( i = 0; i < size; i++ ) { - sieve_binary_emit_cstring(cgenv->sbin, vars[i]->identifier); + sieve_binary_emit_cstring(cgenv->sblock, vars[i]->identifier); } } - sieve_binary_resolve_offset(cgenv->sbin, jump); + sieve_binary_resolve_offset(cgenv->sblock, jump); return TRUE; } @@ -515,7 +515,7 @@ bool ext_variables_interpreter_load sieve_size_t pc; int end_offset; - if ( !sieve_binary_read_unsigned(renv->sbin, address, &scope_size) ) { + if ( !sieve_binary_read_unsigned(renv->sblock, address, &scope_size) ) { sieve_sys_error("variables: failed to read main scope size"); return FALSE; } @@ -527,7 +527,7 @@ bool ext_variables_interpreter_load } pc = *address; - if ( !sieve_binary_read_offset(renv->sbin, address, &end_offset) ) + if ( !sieve_binary_read_offset(renv->sblock, address, &end_offset) ) return NULL; *address = pc + end_offset; diff --git a/src/lib-sieve/plugins/variables/ext-variables-dump.c b/src/lib-sieve/plugins/variables/ext-variables-dump.c index 93d7572c6..a9e60ada6 100644 --- a/src/lib-sieve/plugins/variables/ext-variables-dump.c +++ b/src/lib-sieve/plugins/variables/ext-variables-dump.c @@ -77,11 +77,11 @@ bool ext_variables_code_dump int end_offset; sieve_code_mark(denv); - if ( !sieve_binary_read_unsigned(denv->sbin, address, &scope_size) ) + if ( !sieve_binary_read_unsigned(denv->sblock, address, &scope_size) ) return FALSE; pc = *address; - if ( !sieve_binary_read_offset(denv->sbin, address, &end_offset) ) + if ( !sieve_binary_read_offset(denv->sblock, address, &end_offset) ) return FALSE; main_scope = sieve_variable_scope_create(NULL); @@ -95,7 +95,7 @@ bool ext_variables_code_dump string_t *identifier; sieve_code_mark(denv); - if (!sieve_binary_read_string(denv->sbin, address, &identifier) ) { + if (!sieve_binary_read_string(denv->sblock, address, &identifier) ) { return FALSE; } diff --git a/src/lib-sieve/plugins/variables/ext-variables-modifiers.h b/src/lib-sieve/plugins/variables/ext-variables-modifiers.h index 4462f54ca..92ee6cceb 100644 --- a/src/lib-sieve/plugins/variables/ext-variables-modifiers.h +++ b/src/lib-sieve/plugins/variables/ext-variables-modifiers.h @@ -34,10 +34,10 @@ void ext_variables_register_core_modifiers extern const struct sieve_operand_def modifier_operand; static inline void ext_variables_opr_modifier_emit -(struct sieve_binary *sbin, const struct sieve_extension *ext, +(struct sieve_binary_block *sblock, const struct sieve_extension *ext, const struct sieve_variables_modifier_def *modf_def) { - sieve_opr_object_emit(sbin, ext, &modf_def->obj_def); + sieve_opr_object_emit(sblock, ext, &modf_def->obj_def); } static inline bool ext_variables_opr_modifier_read diff --git a/src/lib-sieve/plugins/variables/ext-variables-namespaces.c b/src/lib-sieve/plugins/variables/ext-variables-namespaces.c index 69b2cf5d4..2f8897de9 100644 --- a/src/lib-sieve/plugins/variables/ext-variables-namespaces.c +++ b/src/lib-sieve/plugins/variables/ext-variables-namespaces.c @@ -178,12 +178,12 @@ const struct sieve_operand_def namespace_variable_operand = { }; void sieve_variables_opr_namespace_variable_emit -(struct sieve_binary *sbin, const struct sieve_extension *var_ext, +(struct sieve_binary_block *sblock, const struct sieve_extension *var_ext, const struct sieve_extension *ext, const struct sieve_variables_namespace_def *nspc_def) { - sieve_operand_emit(sbin, var_ext, &namespace_variable_operand); - sieve_opr_object_emit(sbin, ext, &nspc_def->obj_def); + sieve_operand_emit(sblock, var_ext, &namespace_variable_operand); + sieve_opr_object_emit(sblock, ext, &nspc_def->obj_def); } static bool opr_namespace_variable_read @@ -202,7 +202,6 @@ static bool opr_namespace_variable_read if ( nspc.def == NULL || nspc.def->read_variable == NULL ) return FALSE; - return nspc.def->read_variable(renv, &nspc, address, str); } @@ -214,12 +213,12 @@ static bool opr_namespace_variable_dump struct sieve_variables_namespace nspc; struct sieve_operand oprnd; - if ( !sieve_operand_read(denv->sbin, address, &oprnd) ) { + if ( !sieve_operand_read(denv->sblock, address, &oprnd) ) { return FALSE; } if ( !sieve_opr_object_read_data - (denv->sbin, &oprnd, &sieve_variables_namespace_operand_class, address, + (denv->sblock, &oprnd, &sieve_variables_namespace_operand_class, address, &nspc.object) ) { return FALSE; } diff --git a/src/lib-sieve/plugins/variables/ext-variables-namespaces.h b/src/lib-sieve/plugins/variables/ext-variables-namespaces.h index 184d14ae6..2e7030101 100644 --- a/src/lib-sieve/plugins/variables/ext-variables-namespaces.h +++ b/src/lib-sieve/plugins/variables/ext-variables-namespaces.h @@ -43,9 +43,4 @@ bool ext_variables_namespace_argument_activate extern const struct sieve_operand_def namespace_variable_operand; -void ext_variables_opr_namespace_variable_emit - (struct sieve_binary *sbin, const struct sieve_extension *var_ext, - const struct sieve_extension *ext, - const struct sieve_variables_namespace_def *nspc_def); - #endif /* __EXT_VARIABLES_NAMESPACES_H */ diff --git a/src/lib-sieve/plugins/variables/ext-variables-operands.c b/src/lib-sieve/plugins/variables/ext-variables-operands.c index a3f790414..fccfd673f 100644 --- a/src/lib-sieve/plugins/variables/ext-variables-operands.c +++ b/src/lib-sieve/plugins/variables/ext-variables-operands.c @@ -49,20 +49,20 @@ const struct sieve_operand_def variable_operand = { }; void sieve_variables_opr_variable_emit -(struct sieve_binary *sbin, const struct sieve_extension *var_ext, +(struct sieve_binary_block *sblock, const struct sieve_extension *var_ext, struct sieve_variable *var) { if ( var->ext == NULL ) { /* Default variable storage */ - (void) sieve_operand_emit(sbin, var_ext, &variable_operand); - (void) sieve_binary_emit_byte(sbin, 0); /* Default */ - (void) sieve_binary_emit_unsigned(sbin, var->index); + (void) sieve_operand_emit(sblock, var_ext, &variable_operand); + (void) sieve_binary_emit_byte(sblock, 0); /* Default */ + (void) sieve_binary_emit_unsigned(sblock, var->index); return; } - (void) sieve_operand_emit(sbin, var_ext, &variable_operand); - (void) sieve_binary_emit_extension(sbin, var->ext, 1); /* Extension */ - (void) sieve_binary_emit_unsigned(sbin, var->index); + (void) sieve_operand_emit(sblock, var_ext, &variable_operand); + (void) sieve_binary_emit_extension(sblock, var->ext, 1); /* Extension */ + (void) sieve_binary_emit_unsigned(sblock, var->index); } static bool opr_variable_dump @@ -75,10 +75,10 @@ static bool opr_variable_dump unsigned int code = 1; /* Initially set to offset value */ const char *identifier; - if ( !sieve_binary_read_extension(denv->sbin, address, &code, &ext) ) + if ( !sieve_binary_read_extension(denv->sblock, address, &code, &ext) ) return FALSE; - if ( !sieve_binary_read_unsigned(denv->sbin, address, &index) ) + if ( !sieve_binary_read_unsigned(denv->sblock, address, &index) ) return FALSE; identifier = ext_variables_dump_get_identifier(this_ext, denv, ext, index); @@ -112,14 +112,14 @@ static bool opr_variable_read_value struct sieve_variable_storage *storage; unsigned int index = 0; - if ( !sieve_binary_read_extension(renv->sbin, address, &code, &ext) ) + if ( !sieve_binary_read_extension(renv->sblock, address, &code, &ext) ) return FALSE; storage = sieve_ext_variables_get_storage(this_ext, renv->interp, ext); if ( storage == NULL ) return FALSE; - if (sieve_binary_read_unsigned(renv->sbin, address, &index) ) { + if (sieve_binary_read_unsigned(renv->sblock, address, &index) ) { /* Parameter str can be NULL if we are requested to only skip and not * actually read the argument. */ @@ -148,14 +148,14 @@ bool sieve_variable_operand_read_data return FALSE; } - if ( !sieve_binary_read_extension(renv->sbin, address, &code, &ext) ) + if ( !sieve_binary_read_extension(renv->sblock, address, &code, &ext) ) return FALSE; *storage = sieve_ext_variables_get_storage(operand->ext, renv->interp, ext); if ( *storage == NULL ) return FALSE; - if ( !sieve_binary_read_unsigned(renv->sbin, address, &idx) ) + if ( !sieve_binary_read_unsigned(renv->sblock, address, &idx) ) return FALSE; *var_index = idx; @@ -168,7 +168,7 @@ bool sieve_variable_operand_read { struct sieve_operand operand; - if ( !sieve_operand_read(renv->sbin, address, &operand) ) + if ( !sieve_operand_read(renv->sblock, address, &operand) ) return FALSE; return sieve_variable_operand_read_data @@ -200,11 +200,11 @@ const struct sieve_operand_def match_value_operand = { }; void sieve_variables_opr_match_value_emit -(struct sieve_binary *sbin, const struct sieve_extension *var_ext, +(struct sieve_binary_block *sblock, const struct sieve_extension *var_ext, unsigned int index) { - (void) sieve_operand_emit(sbin, var_ext, &match_value_operand); - (void) sieve_binary_emit_unsigned(sbin, index); + (void) sieve_operand_emit(sblock, var_ext, &match_value_operand); + (void) sieve_binary_emit_unsigned(sblock, index); } static bool opr_match_value_dump @@ -214,7 +214,7 @@ static bool opr_match_value_dump { unsigned int index = 0; - if (sieve_binary_read_unsigned(denv->sbin, address, &index) ) { + if (sieve_binary_read_unsigned(denv->sblock, address, &index) ) { if ( field_name != NULL ) sieve_code_dumpf (denv, "%s: MATCHVAL %lu", field_name, (unsigned long) index); @@ -234,7 +234,7 @@ static bool opr_match_value_read { unsigned int index = 0; - if (sieve_binary_read_unsigned(renv->sbin, address, &index) ) { + if (sieve_binary_read_unsigned(renv->sblock, address, &index) ) { /* Parameter str can be NULL if we are requested to only skip and not * actually read the argument. */ diff --git a/src/lib-sieve/plugins/variables/sieve-ext-variables.h b/src/lib-sieve/plugins/variables/sieve-ext-variables.h index 1fefc202c..3a6aa7208 100644 --- a/src/lib-sieve/plugins/variables/sieve-ext-variables.h +++ b/src/lib-sieve/plugins/variables/sieve-ext-variables.h @@ -124,7 +124,7 @@ void sieve_variables_namespace_register extern const struct sieve_operand_class sieve_variables_namespace_operand_class; void sieve_variables_opr_namespace_variable_emit -(struct sieve_binary *sbin, const struct sieve_extension *var_ext, + (struct sieve_binary_block *sblock, const struct sieve_extension *var_ext, const struct sieve_extension *ext, const struct sieve_variables_namespace_def *nspc_def); @@ -204,10 +204,10 @@ bool sieve_variable_argument_activate extern const struct sieve_operand_def variable_operand; void sieve_variables_opr_variable_emit - (struct sieve_binary *sbin, const struct sieve_extension *var_ext, + (struct sieve_binary_block *sblock, const struct sieve_extension *var_ext, struct sieve_variable *var); void sieve_variables_opr_match_value_emit - (struct sieve_binary *sbin, const struct sieve_extension *var_ext, + (struct sieve_binary_block *sblock, const struct sieve_extension *var_ext, unsigned int index); bool sieve_variable_operand_read_data diff --git a/src/lib-sieve/plugins/variables/tst-string.c b/src/lib-sieve/plugins/variables/tst-string.c index fbbeb5c48..7ca25ab36 100644 --- a/src/lib-sieve/plugins/variables/tst-string.c +++ b/src/lib-sieve/plugins/variables/tst-string.c @@ -126,7 +126,7 @@ static bool tst_string_validate static bool tst_string_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) { - sieve_operation_emit(cgenv->sbin, cmd->ext, &tst_string_operation); + sieve_operation_emit(cgenv->sblock, cmd->ext, &tst_string_operation); /* Generate arguments */ if ( !sieve_generate_arguments(cgenv, cmd, NULL) ) diff --git a/src/lib-sieve/sieve-actions.h b/src/lib-sieve/sieve-actions.h index 060e88ce1..211f5606e 100644 --- a/src/lib-sieve/sieve-actions.h +++ b/src/lib-sieve/sieve-actions.h @@ -170,10 +170,10 @@ struct sieve_side_effect { extern const struct sieve_operand_class sieve_side_effect_operand_class; static inline void sieve_opr_side_effect_emit -(struct sieve_binary *sbin, const struct sieve_extension *ext, +(struct sieve_binary_block *sblock, const struct sieve_extension *ext, const struct sieve_side_effect_def *seff) { - sieve_opr_object_emit(sbin, ext, &seff->obj_def); + sieve_opr_object_emit(sblock, ext, &seff->obj_def); } bool sieve_opr_side_effect_read diff --git a/src/lib-sieve/sieve-address-parts.c b/src/lib-sieve/sieve-address-parts.c index 297b23bd2..247848aa5 100644 --- a/src/lib-sieve/sieve-address-parts.c +++ b/src/lib-sieve/sieve-address-parts.c @@ -204,7 +204,7 @@ static bool tag_address_part_generate struct sieve_address_part *addrp = (struct sieve_address_part *) arg->argument->data; - sieve_opr_address_part_emit(cgenv->sbin, addrp); + sieve_opr_address_part_emit(cgenv->sblock, addrp); return TRUE; } @@ -295,9 +295,9 @@ bool sieve_addrmatch_default_dump_optionals { int opt_code = 1; - if ( sieve_operand_optional_present(denv->sbin, address) ) { + if ( sieve_operand_optional_present(denv->sblock, address) ) { while ( opt_code != 0 ) { - if ( !sieve_operand_optional_read(denv->sbin, address, &opt_code) ) + if ( !sieve_operand_optional_read(denv->sblock, address, &opt_code) ) return FALSE; switch ( opt_code ) { @@ -331,9 +331,9 @@ bool sieve_addrmatch_default_get_optionals { int opt_code = 1; - if ( sieve_operand_optional_present(renv->sbin, address) ) { + if ( sieve_operand_optional_present(renv->sblock, address) ) { while ( opt_code != 0 ) { - if ( !sieve_operand_optional_read(renv->sbin, address, &opt_code) ) + if ( !sieve_operand_optional_read(renv->sblock, address, &opt_code) ) return FALSE; switch ( opt_code ) { diff --git a/src/lib-sieve/sieve-address-parts.h b/src/lib-sieve/sieve-address-parts.h index f50971602..699bf2398 100644 --- a/src/lib-sieve/sieve-address-parts.h +++ b/src/lib-sieve/sieve-address-parts.h @@ -82,9 +82,9 @@ extern const struct sieve_operand_class sieve_address_part_operand_class; #define SIEVE_EXT_DEFINE_ADDRESS_PARTS(OPS) SIEVE_EXT_DEFINE_OBJECTS(OPS) static inline void sieve_opr_address_part_emit -(struct sieve_binary *sbin, const struct sieve_address_part *addrp) +(struct sieve_binary_block *sblock, const struct sieve_address_part *addrp) { - sieve_opr_object_emit(sbin, addrp->object.ext, addrp->object.def); + sieve_opr_object_emit(sblock, addrp->object.ext, addrp->object.def); } static inline bool sieve_opr_address_part_read diff --git a/src/lib-sieve/sieve-binary-code.c b/src/lib-sieve/sieve-binary-code.c new file mode 100644 index 000000000..1f1052a46 --- /dev/null +++ b/src/lib-sieve/sieve-binary-code.c @@ -0,0 +1,386 @@ +/* Copyright (c) 2002-2010 Dovecot Sieve authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "str-sanitize.h" +#include "mempool.h" +#include "buffer.h" +#include "hash.h" +#include "array.h" +#include "ostream.h" + +#include "sieve-common.h" +#include "sieve-error.h" +#include "sieve-extensions.h" +#include "sieve-code.h" +#include "sieve-script.h" + +#include "sieve-binary-private.h" + +/* + * Forward declarations + */ + +static inline sieve_size_t sieve_binary_emit_dynamic_data + (struct sieve_binary_block *sblock, const void *data, size_t size); + +/* + * Emission functions + */ + +/* Low-level emission functions */ + +static inline void _sieve_binary_emit_data +(struct sieve_binary_block *sblock, const void *data, sieve_size_t size) +{ + buffer_append(sblock->data, data, size); +} + +static inline void _sieve_binary_emit_byte +(struct sieve_binary_block *sblock, unsigned char byte) +{ + _sieve_binary_emit_data(sblock, &byte, 1); +} + +static inline void _sieve_binary_update_data +(struct sieve_binary_block *sblock, sieve_size_t address, const void *data, + sieve_size_t size) +{ + buffer_write(sblock->data, address, data, size); +} + +sieve_size_t sieve_binary_emit_data +(struct sieve_binary_block *sblock, const void *data, sieve_size_t size) +{ + sieve_size_t address = _sieve_binary_block_get_size(sblock); + + _sieve_binary_emit_data(sblock, data, size); + + return address; +} + +sieve_size_t sieve_binary_emit_byte +(struct sieve_binary_block *sblock, unsigned char byte) +{ + sieve_size_t address = _sieve_binary_block_get_size(sblock); + + _sieve_binary_emit_data(sblock, &byte, 1); + + return address; +} + +void sieve_binary_update_data +(struct sieve_binary_block *sblock, sieve_size_t address, const void *data, + sieve_size_t size) +{ + _sieve_binary_update_data(sblock, address, data, size); +} + +/* Offset emission functions */ + +sieve_size_t sieve_binary_emit_offset +(struct sieve_binary_block *sblock, int offset) +{ + int i; + sieve_size_t address = _sieve_binary_block_get_size(sblock); + + for ( i = 3; i >= 0; i-- ) { + char c = (char) (offset >> (i * 8)); + _sieve_binary_emit_data(sblock, &c, 1); + } + + return address; +} + +void sieve_binary_resolve_offset +(struct sieve_binary_block *sblock, sieve_size_t address) +{ + int i; + int offset = _sieve_binary_block_get_size(sblock) - address; + + for ( i = 3; i >= 0; i-- ) { + char c = (char) (offset >> (i * 8)); + _sieve_binary_update_data(sblock, address + 3 - i, &c, 1); + } +} + +/* Literal emission */ + +sieve_size_t sieve_binary_emit_integer +(struct sieve_binary_block *sblock, sieve_number_t integer) +{ + sieve_size_t address = _sieve_binary_block_get_size(sblock); + int i; + char buffer[sizeof(sieve_number_t) + 1]; + int bufpos = sizeof(buffer) - 1; + + buffer[bufpos] = integer & 0x7F; + bufpos--; + integer >>= 7; + while ( integer > 0 ) { + buffer[bufpos] = integer & 0x7F; + bufpos--; + integer >>= 7; + } + + bufpos++; + if ( (sizeof(buffer) - bufpos) > 1 ) { + for ( i = bufpos; i < ((int) sizeof(buffer) - 1); i++) { + buffer[i] |= 0x80; + } + } + + _sieve_binary_emit_data + (sblock, buffer + bufpos, sizeof(buffer) - bufpos); + + return address; +} + +static inline sieve_size_t sieve_binary_emit_dynamic_data +(struct sieve_binary_block *sblock, const void *data, sieve_size_t size) +{ + sieve_size_t address = sieve_binary_emit_integer + (sblock, (sieve_number_t) size); + + _sieve_binary_emit_data(sblock, data, size); + + return address; +} + +sieve_size_t sieve_binary_emit_cstring +(struct sieve_binary_block *sblock, const char *str) +{ + sieve_size_t address = sieve_binary_emit_dynamic_data + (sblock, (void *) str, (sieve_size_t) strlen(str)); + _sieve_binary_emit_byte(sblock, 0); + + return address; +} + +sieve_size_t sieve_binary_emit_string +(struct sieve_binary_block *sblock, const string_t *str) +{ + sieve_size_t address = sieve_binary_emit_dynamic_data + (sblock, (void *) str_data(str), (sieve_size_t) str_len(str)); + _sieve_binary_emit_byte(sblock, 0); + + return address; +} + +/* + * Extension emission + */ + +sieve_size_t sieve_binary_emit_extension +(struct sieve_binary_block *sblock, const struct sieve_extension *ext, + unsigned int offset) +{ + sieve_size_t address = _sieve_binary_block_get_size(sblock); + struct sieve_binary_extension_reg *ereg = NULL; + + (void)sieve_binary_extension_register(sblock->sbin, ext, &ereg); + + i_assert(ereg != NULL); + + _sieve_binary_emit_byte(sblock, offset + ereg->index); + return address; +} + +void sieve_binary_emit_extension_object +(struct sieve_binary_block *sblock, const struct sieve_extension_objects *objs, + unsigned int code) +{ + if ( objs->count > 1 ) + _sieve_binary_emit_byte(sblock, code); +} + +/* + * Code retrieval + */ + +#define ADDR_CODE_READ(block) \ + size_t _code_size; \ + const signed char *_code = buffer_get_data((block)->data, &_code_size) + +#define ADDR_CODE_AT(address) \ + ((signed char) (_code[*address])) +#define ADDR_DATA_AT(address) \ + ((unsigned char) (_code[*address])) +#define ADDR_POINTER(address) \ + ((const char *) (&_code[*address])) + +#define ADDR_BYTES_LEFT(address) \ + ((_code_size) - (*address)) +#define ADDR_JUMP(address, offset) \ + (*address) += offset + +/* Literals */ + +bool sieve_binary_read_byte +(struct sieve_binary_block *sblock, sieve_size_t *address, unsigned int *byte_r) +{ + ADDR_CODE_READ(sblock); + + if ( ADDR_BYTES_LEFT(address) >= 1 ) { + if ( byte_r != NULL ) + *byte_r = ADDR_DATA_AT(address); + ADDR_JUMP(address, 1); + + return TRUE; + } + + *byte_r = 0; + return FALSE; +} + +bool sieve_binary_read_code +(struct sieve_binary_block *sblock, sieve_size_t *address, signed int *code_r) +{ + ADDR_CODE_READ(sblock); + + if ( ADDR_BYTES_LEFT(address) >= 1 ) { + if ( code_r != NULL ) + *code_r = ADDR_CODE_AT(address); + ADDR_JUMP(address, 1); + + return TRUE; + } + + *code_r = 0; + return FALSE; +} + + +bool sieve_binary_read_offset +(struct sieve_binary_block *sblock, sieve_size_t *address, int *offset_r) +{ + uint32_t offs = 0; + ADDR_CODE_READ(sblock); + + if ( ADDR_BYTES_LEFT(address) >= 4 ) { + int i; + + for ( i = 0; i < 4; i++ ) { + offs = (offs << 8) + ADDR_DATA_AT(address); + ADDR_JUMP(address, 1); + } + + if ( offset_r != NULL ) + *offset_r = (int) offs; + + return TRUE; + } + + return FALSE; +} + +/* FIXME: might need negative numbers in the future */ +bool sieve_binary_read_integer +(struct sieve_binary_block *sblock, sieve_size_t *address, sieve_number_t *int_r) +{ + int bits = sizeof(sieve_number_t) * 8; + *int_r = 0; + + ADDR_CODE_READ(sblock); + + if ( ADDR_BYTES_LEFT(address) == 0 ) + return FALSE; + + while ( (ADDR_DATA_AT(address) & 0x80) > 0 ) { + if ( ADDR_BYTES_LEFT(address) > 0 && bits > 0) { + *int_r |= ADDR_DATA_AT(address) & 0x7F; + ADDR_JUMP(address, 1); + + *int_r <<= 7; + bits -= 7; + } else { + /* This is an error */ + return FALSE; + } + } + + *int_r |= ADDR_DATA_AT(address) & 0x7F; + ADDR_JUMP(address, 1); + + return TRUE; +} + +bool sieve_binary_read_string +(struct sieve_binary_block *sblock, sieve_size_t *address, string_t **str_r) +{ + unsigned int strlen = 0; + + ADDR_CODE_READ(sblock); + + if ( !sieve_binary_read_unsigned(sblock, address, &strlen) ) + return FALSE; + + if ( strlen > ADDR_BYTES_LEFT(address) ) + return FALSE; + + if ( str_r != NULL ) + *str_r = t_str_new_const(ADDR_POINTER(address), strlen); + ADDR_JUMP(address, strlen); + + if ( ADDR_CODE_AT(address) != 0 ) + return FALSE; + + ADDR_JUMP(address, 1); + + return TRUE; +} + +bool sieve_binary_read_extension +(struct sieve_binary_block *sblock, sieve_size_t *address, + unsigned int *offset_r, const struct sieve_extension **ext_r) +{ + unsigned int code; + unsigned int offset = *offset_r; + const struct sieve_extension *ext = NULL; + + ADDR_CODE_READ(sblock); + + if ( ADDR_BYTES_LEFT(address) <= 0 ) + return FALSE; + + (*offset_r) = code = ADDR_DATA_AT(address); + ADDR_JUMP(address, 1); + + if ( code >= offset ) { + ext = sieve_binary_extension_get_by_index(sblock->sbin, code - offset); + + if ( ext == NULL ) + return FALSE; + } + + (*ext_r) = ext; + + return TRUE; +} + +const void *sieve_binary_read_extension_object +(struct sieve_binary_block *sblock, sieve_size_t *address, + const struct sieve_extension_objects *objs) +{ + unsigned int code; + + ADDR_CODE_READ(sblock); + + if ( objs->count == 0 ) + return NULL; + + if ( objs->count == 1 ) + return objs->objects; + + if ( ADDR_BYTES_LEFT(address) <= 0 ) + return NULL; + + code = ADDR_DATA_AT(address); + ADDR_JUMP(address, 1); + + if ( code >= objs->count ) + return NULL; + + return ((const void *const *) objs->objects)[code]; +} diff --git a/src/lib-sieve/sieve-binary-debug.c b/src/lib-sieve/sieve-binary-debug.c new file mode 100644 index 000000000..af71c6d24 --- /dev/null +++ b/src/lib-sieve/sieve-binary-debug.c @@ -0,0 +1,256 @@ +/* Copyright (c) 2002-2010 Dovecot Sieve authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" + +#include "sieve-common.h" +#include "sieve-error.h" +#include "sieve-code.h" + +#include "sieve-binary-private.h" + +/* Quick 'n dirty debug */ +#if 0 +#define debug_printf(...) printf ("lineinfo: " __VA_ARGS__) +#else +#define debug_printf(...) +#endif + +/* + * Opcodes + */ + +enum { + LINPROG_OP_COPY, + LINPROG_OP_ADVANCE_PC, + LINPROG_OP_ADVANCE_LINE, + LINPROG_OP_SET_COLUMN, + LINPROG_OP_SPECIAL_BASE +}; + +#define LINPROG_LINE_BASE 0 +#define LINPROG_LINE_RANGE 4 + +/* + * Lineinfo writer + */ + +struct sieve_binary_debug_writer { + struct sieve_binary_block *sblock; + + sieve_size_t address; + unsigned long int line; + unsigned long int column; +}; + +struct sieve_binary_debug_writer *sieve_binary_debug_writer_init +(struct sieve_binary_block *sblock) +{ + struct sieve_binary_debug_writer *dwriter; + + dwriter = i_new(struct sieve_binary_debug_writer, 1); + dwriter->sblock = sblock; + + return dwriter; +} + +void sieve_binary_debug_writer_deinit +(struct sieve_binary_debug_writer **dwriter) +{ + i_free(*dwriter); + *dwriter = NULL; +} + +void sieve_binary_debug_emit +(struct sieve_binary_debug_writer *dwriter, sieve_size_t code_address, + unsigned int code_line, unsigned int code_column) +{ + struct sieve_binary_block *sblock = dwriter->sblock; + sieve_size_t address_inc = code_address - dwriter->address; + unsigned int line_inc = code_line - dwriter->line; + unsigned int sp_opcode = 0; + + /* Check for applicability of special opcode */ + if ( (LINPROG_LINE_BASE + LINPROG_LINE_RANGE - 1) >= line_inc ) { + sp_opcode = LINPROG_OP_SPECIAL_BASE + (line_inc - LINPROG_LINE_BASE) + + (LINPROG_LINE_RANGE * address_inc); + + if ( sp_opcode > 255 ) + sp_opcode = 0; + } + + /* Update line and address */ + if ( sp_opcode == 0 ) { + if ( line_inc > 0 ) { + (void)sieve_binary_emit_byte(sblock, LINPROG_OP_ADVANCE_LINE); + (void)sieve_binary_emit_unsigned(sblock, line_inc); + } + + if ( address_inc > 0 ) { + (void)sieve_binary_emit_byte(sblock, LINPROG_OP_ADVANCE_PC); + (void)sieve_binary_emit_unsigned(sblock, address_inc); + } + } else { + (void)sieve_binary_emit_byte(sblock, sp_opcode); + } + + /* Set column */ + if ( dwriter->column != code_column ) { + (void)sieve_binary_emit_byte(sblock, LINPROG_OP_SET_COLUMN); + (void)sieve_binary_emit_unsigned(sblock, code_column); + } + + /* Generate matrix row */ + (void)sieve_binary_emit_byte(sblock, LINPROG_OP_COPY); + + dwriter->address = code_address; + dwriter->line = code_line; + dwriter->column = code_column; +} + +/* + * Debug reader + */ + +struct sieve_binary_debug_reader { + struct sieve_binary_block *sblock; + + sieve_size_t address, last_address; + unsigned long int line, last_line; + + unsigned long int column; + + sieve_size_t state; +}; + +struct sieve_binary_debug_reader *sieve_binary_debug_reader_init +(struct sieve_binary_block *sblock) +{ + struct sieve_binary_debug_reader *dreader; + + dreader = i_new(struct sieve_binary_debug_reader, 1); + dreader->sblock = sblock; + + return dreader; +} + +void sieve_binary_debug_reader_deinit +(struct sieve_binary_debug_reader **dreader) +{ + i_free(*dreader); + *dreader = NULL; +} + +void sieve_binary_debug_reader_reset +(struct sieve_binary_debug_reader *dreader) +{ + dreader->address = 0; + dreader->line = 0; + dreader->column = 0; + dreader->state = 0; +} + +unsigned int sieve_binary_debug_read_line +(struct sieve_binary_debug_reader *dreader, sieve_size_t code_address) +{ + size_t linprog_size; + sieve_size_t address; + unsigned long int line; + + if ( code_address < dreader->last_address ) + sieve_binary_debug_reader_reset(dreader); + + if ( code_address >= dreader->last_address && + code_address < dreader->address ) { + debug_printf("%08llx: NOOP [%08llx]\n", + (unsigned long long) dreader->state, (unsigned long long) code_address); + return dreader->last_line; + } + + address = dreader->address; + line = dreader->line; + + debug_printf("%08llx: READ [%08llx]\n", + (unsigned long long) dreader->state, (unsigned long long) code_address); + + linprog_size = sieve_binary_block_get_size(dreader->sblock); + while ( dreader->state < linprog_size ) { + unsigned int opcode; + unsigned int value; + + if ( sieve_binary_read_byte(dreader->sblock, &dreader->state, &opcode) ) { + switch ( opcode ) { + + case LINPROG_OP_COPY: + debug_printf("%08llx: COPY ==> %08llx: %ld\n", + (unsigned long long) dreader->state, (unsigned long long) address, + line); + + dreader->last_address = dreader->address; + dreader->last_line = dreader->line; + + dreader->address = address; + dreader->line = line; + + if ( code_address < address ) { + return dreader->last_line; + } else if ( code_address == address ) { + return dreader->line; + } + break; + + case LINPROG_OP_ADVANCE_PC: + debug_printf("%08llx: ADV_PC\n", (unsigned long long) dreader->state); + if ( !sieve_binary_read_unsigned + (dreader->sblock, &dreader->state, &value) ) { + sieve_binary_debug_reader_reset(dreader); + return 0; + } + debug_printf(" : + %d\n", value); + address += value; + break; + + case LINPROG_OP_ADVANCE_LINE: + debug_printf("%08llx: ADV_LINE\n", (unsigned long long) dreader->state); + if ( !sieve_binary_read_unsigned + (dreader->sblock, &dreader->state, &value) ) { + sieve_binary_debug_reader_reset(dreader); + return 0; + } + debug_printf(" : + %d\n", value); + line += value; + break; + + case LINPROG_OP_SET_COLUMN: + debug_printf("%08llx: SET_COL\n", (unsigned long long) dreader->state); + if ( !sieve_binary_read_unsigned + (dreader->sblock, &dreader->state, &value) ) { + sieve_binary_debug_reader_reset(dreader); + return 0; + } + debug_printf(" : = %d\n", value); + dreader->column = value; + break; + + default: + opcode -= LINPROG_OP_SPECIAL_BASE; + + address += (opcode / LINPROG_LINE_RANGE); + line += LINPROG_LINE_BASE + (opcode % LINPROG_LINE_RANGE); + + debug_printf("%08llx: SPECIAL\n", (unsigned long long) dreader->state); + debug_printf(" : +A %d +L %d\n", (opcode / LINPROG_LINE_RANGE), + LINPROG_LINE_BASE + (opcode % LINPROG_LINE_RANGE)); + break; + } + } else { + debug_printf("OPCODE READ FAILED\n"); + sieve_binary_debug_reader_reset(dreader); + return 0; + } + } + + return dreader->line; +} + diff --git a/src/lib-sieve/sieve-binary-dumper.c b/src/lib-sieve/sieve-binary-dumper.c index cb9ffabc8..455b4fe84 100644 --- a/src/lib-sieve/sieve-binary-dumper.c +++ b/src/lib-sieve/sieve-binary-dumper.c @@ -23,7 +23,7 @@ struct sieve_binary_dumper { }; struct sieve_binary_dumper *sieve_binary_dumper_create - (struct sieve_binary *sbin) +(struct sieve_binary *sbin) { pool_t pool; struct sieve_binary_dumper *dumper; @@ -91,25 +91,52 @@ void sieve_binary_dump_sectionf */ bool sieve_binary_dumper_run -(struct sieve_binary_dumper *dumper, struct ostream *stream) +(struct sieve_binary_dumper *dumper, struct ostream *stream, bool verbose) { struct sieve_binary *sbin = dumper->dumpenv.sbin; struct sieve_dumptime_env *denv = &(dumper->dumpenv); int count, i; dumper->dumpenv.stream = stream; + + /* Dump list of binary blocks */ + if ( verbose ) { + count = sieve_binary_block_count(sbin); + + sieve_binary_dump_sectionf + (denv, "Binary blocks (count: %d)", count); + + for ( i = 0; i < count; i++ ) { + struct sieve_binary_block *sblock = sieve_binary_block_get(sbin, i); + + sieve_binary_dumpf(denv, + "%3d: size: %"PRIuSIZE_T" bytes\n", i, + sieve_binary_block_get_size(sblock)); + } + } /* Dump list of used extensions */ count = sieve_binary_extensions_count(sbin); if ( count > 0 ) { - sieve_binary_dump_sectionf(denv, "Required extensions"); + sieve_binary_dump_sectionf + (denv, "Required extensions (block: %d)", SBIN_SYSBLOCK_EXTENSIONS); for ( i = 0; i < count; i++ ) { const struct sieve_extension *ext = sieve_binary_extension_get_by_index (sbin, i); - sieve_binary_dumpf(denv, "%3d: %s (%d)\n", i, sieve_extension_name(ext), - ext->id); + + struct sieve_binary_block *sblock = sieve_binary_extension_get_block + (sbin, ext); + + if ( sblock == NULL ) { + sieve_binary_dumpf(denv, "%3d: %s (id: %d)\n", + i, sieve_extension_name(ext), ext->id); + } else { + sieve_binary_dumpf(denv, "%3d: %s (id: %d; block: %d)\n", + i, sieve_extension_name(ext), ext->id, + sieve_binary_block_get_id(sblock)); + } } } @@ -135,12 +162,11 @@ bool sieve_binary_dumper_run /* Dump main program */ - sieve_binary_dump_sectionf(denv, "Main program (block: %d)", SBIN_SYSBLOCK_MAIN_PROGRAM); - - if ( !sieve_binary_block_set_active(sbin, SBIN_SYSBLOCK_MAIN_PROGRAM, NULL) ) { - return FALSE; - } + sieve_binary_dump_sectionf + (denv, "Main program (block: %d)", SBIN_SYSBLOCK_MAIN_PROGRAM); + dumper->dumpenv.sblock = + sieve_binary_block_get(sbin, SBIN_SYSBLOCK_MAIN_PROGRAM); dumper->dumpenv.cdumper = sieve_code_dumper_create(&(dumper->dumpenv)); if ( dumper->dumpenv.cdumper != NULL ) { diff --git a/src/lib-sieve/sieve-binary-dumper.h b/src/lib-sieve/sieve-binary-dumper.h index 7c55bfcb8..47ff81981 100644 --- a/src/lib-sieve/sieve-binary-dumper.h +++ b/src/lib-sieve/sieve-binary-dumper.h @@ -34,7 +34,7 @@ void sieve_binary_dump_sectionf */ bool sieve_binary_dumper_run - (struct sieve_binary_dumper *dumper, struct ostream *stream); + (struct sieve_binary_dumper *dumper, struct ostream *stream, bool verbose); #endif /* __SIEVE_BINARY_DUMPER_H */ diff --git a/src/lib-sieve/sieve-binary-file.c b/src/lib-sieve/sieve-binary-file.c new file mode 100644 index 000000000..47ab4c955 --- /dev/null +++ b/src/lib-sieve/sieve-binary-file.c @@ -0,0 +1,839 @@ +/* Copyright (c) 2002-2010 Dovecot Sieve authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "str-sanitize.h" +#include "mempool.h" +#include "buffer.h" +#include "hash.h" +#include "array.h" +#include "ostream.h" +#include "eacces-error.h" +#include "safe-mkstemp.h" + +#include "sieve-common.h" +#include "sieve-error.h" +#include "sieve-extensions.h" +#include "sieve-code.h" +#include "sieve-script.h" + +#include "sieve-binary-private.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> + +/* + * Macros + */ + +#define SIEVE_BINARY_MAGIC 0xcafebabe +#define SIEVE_BINARY_MAGIC_OTHER_ENDIAN 0xbebafeca + +#define SIEVE_BINARY_ALIGN(offset) \ + (((offset) + 3) & ~3) +#define SIEVE_BINARY_ALIGN_PTR(ptr) \ + ((void *) SIEVE_BINARY_ALIGN(((size_t) ptr))) + +/* + * Header and record structures of the binary on disk + */ + +struct sieve_binary_header { + uint32_t magic; + uint16_t version_major; + uint16_t version_minor; + uint32_t blocks; +}; + +struct sieve_binary_block_index { + uint32_t id; + uint32_t size; + uint32_t offset; + uint32_t ext_id; +}; + +struct sieve_binary_block_header { + uint32_t id; + uint32_t size; +}; + +/* + * Saving the binary to a file. + */ + +static inline bool _save_skip(struct ostream *stream, size_t size) +{ + if ( (o_stream_seek(stream, stream->offset + size)) <= 0 ) + return FALSE; + + return TRUE; +} + +static inline bool _save_skip_aligned +(struct ostream *stream, size_t size, uoff_t *offset) +{ + uoff_t aligned_offset = SIEVE_BINARY_ALIGN(stream->offset); + + if ( (o_stream_seek(stream, aligned_offset + size)) <= 0 ) + return FALSE; + + if ( offset != NULL ) + *offset = aligned_offset; + + return TRUE; +} + +/* FIXME: Is this even necessary for a file? */ +static bool _save_full(struct ostream *stream, const void *data, size_t size) +{ + size_t bytes_left = size; + const void *pdata = data; + + while ( bytes_left > 0 ) { + ssize_t ret; + + if ( (ret=o_stream_send(stream, pdata, bytes_left)) <= 0 ) + return FALSE; + + pdata = PTR_OFFSET(pdata, ret); + bytes_left -= ret; + } + + return TRUE; +} + +static bool _save_aligned +(struct ostream *stream, const void *data, size_t size, uoff_t *offset) +{ + uoff_t aligned_offset = SIEVE_BINARY_ALIGN(stream->offset); + + o_stream_cork(stream); + + /* Align the data by adding zeroes to the output stream */ + if ( stream->offset < aligned_offset ) { + if ( !_save_skip(stream, aligned_offset - stream->offset) ) + return FALSE; + } + + if ( !_save_full(stream, data, size) ) + return FALSE; + + o_stream_uncork(stream); + + if ( offset != NULL ) + *offset = aligned_offset; + + return TRUE; +} + +static bool _save_block +(struct sieve_binary *sbin, struct ostream *stream, unsigned int id) +{ + struct sieve_binary_block_header block_header; + struct sieve_binary_block *block; + const void *data; + size_t size; + + block = sieve_binary_block_get(sbin, id); + if ( block == NULL ) + return FALSE; + + data = buffer_get_data(block->data, &size); + + block_header.id = id; + block_header.size = size; + + if ( !_save_aligned(stream, &block_header, + sizeof(block_header), &block->offset) ) + return FALSE; + + return _save_aligned(stream, data, size, NULL); +} + +static bool _save_block_index_record +(struct sieve_binary *sbin, struct ostream *stream, unsigned int id) +{ + struct sieve_binary_block *block; + struct sieve_binary_block_index header; + + block = sieve_binary_block_get(sbin, id); + if ( block == NULL ) + return FALSE; + + header.id = id; + header.size = buffer_get_used_size(block->data); + header.ext_id = block->ext_index; + header.offset = block->offset; + + if ( !_save_full(stream, &header, sizeof(header)) ) { + sieve_sys_error("failed to save block index header %d: %m", id); + + return FALSE; + } + + return TRUE; +} + +static bool _sieve_binary_save +(struct sieve_binary *sbin, struct ostream *stream) +{ + struct sieve_binary_header header; + struct sieve_binary_extension_reg *const *regs; + struct sieve_binary_block *ext_block; + unsigned int ext_count, blk_count, i; + uoff_t block_index; + + blk_count = sieve_binary_block_count(sbin); + + /* Signal all extensions to finish generating their blocks */ + + regs = array_get(&sbin->extensions, &ext_count); + for ( i = 0; i < ext_count; i++ ) { + const struct sieve_binary_extension *binext = regs[i]->binext; + + if ( binext != NULL && binext->binary_save != NULL ) + binext->binary_save(regs[i]->extension, sbin, regs[i]->context); + } + + /* Create header */ + + header.magic = SIEVE_BINARY_MAGIC; + header.version_major = SIEVE_BINARY_VERSION_MAJOR; + header.version_minor = SIEVE_BINARY_VERSION_MINOR; + header.blocks = blk_count; + + if ( !_save_aligned(stream, &header, sizeof(header), NULL) ) { + sieve_sys_error("failed to save binary header: %m"); + return FALSE; + } + + /* Skip block index for now */ + + if ( !_save_skip_aligned(stream, + sizeof(struct sieve_binary_block_index) * blk_count, &block_index) ) + return FALSE; + + /* Create block containing all used extensions + * FIXME: Per-extension this should also store binary version numbers. + */ + ext_block = sieve_binary_block_get(sbin, SBIN_SYSBLOCK_EXTENSIONS); + i_assert( ext_block != NULL ); + + ext_count = array_count(&sbin->linked_extensions); + sieve_binary_emit_unsigned(ext_block, ext_count); + + for ( i = 0; i < ext_count; i++ ) { + struct sieve_binary_extension_reg * const *ext + = array_idx(&sbin->linked_extensions, i); + + sieve_binary_emit_cstring + (ext_block, sieve_extension_name((*ext)->extension)); + sieve_binary_emit_unsigned(ext_block, (*ext)->block_id); + } + + /* Save all blocks into the binary */ + + for ( i = 0; i < blk_count; i++ ) { + if ( !_save_block(sbin, stream, i) ) + return FALSE; + } + + /* Create the block index */ + o_stream_seek(stream, block_index); + for ( i = 0; i < blk_count; i++ ) { + if ( !_save_block_index_record(sbin, stream, i) ) + return FALSE; + } + + return TRUE; +} + +bool sieve_binary_save +(struct sieve_binary *sbin, const char *path) +{ + bool result = TRUE; + string_t *temp_path; + struct ostream *stream; + int fd; + mode_t save_mode = + sbin->script == NULL ? 0600 : sieve_script_permissions(sbin->script); + + /* 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_str_new(256); + str_append(temp_path, path); + fd = safe_mkstemp_hostpid(temp_path, save_mode, (uid_t)-1, (gid_t)-1); + if ( fd < 0 ) { + if ( errno == EACCES ) { + sieve_sys_error("failed to save binary temporary file: %s", + eacces_error_get_creating("open", str_c(temp_path))); + } else { + sieve_sys_error("failed to save binary temporary file: " + "open(%s) failed: %m", str_c(temp_path)); + } + return FALSE; + } + + /* Save binary */ + stream = o_stream_create_fd(fd, 0, FALSE); + result = _sieve_binary_save(sbin, stream); + o_stream_destroy(&stream); + + /* Close saved binary */ + if ( close(fd) < 0 ) { + sieve_sys_error("failed to close saved binary temporary file: " + "close(fd=%s) failed: %m", str_c(temp_path)); + } + + /* Replace any original binary atomically */ + if ( result && (rename(str_c(temp_path), path) < 0) ) { + if ( errno == EACCES ) { + sieve_sys_error("failed to replace existing binary: %s", + eacces_error_get_creating("rename", path)); + } else { + sieve_sys_error("failed to replace existing binary: " + "rename(%s, %s) failed: %m", str_c(temp_path), path); + } + result = FALSE; + } + + if ( !result ) { + /* Get rid of temp output (if any) */ + (void) unlink(str_c(temp_path)); + } else { + if ( sbin->path == NULL || strcmp(sbin->path, path) != 0 ) { + sbin->path = p_strdup(sbin->pool, path); + } + } + + return result; +} + +/* + * Binary file management + */ + +bool sieve_binary_file_open + (struct sieve_binary_file *file, const char *path) +{ + int fd; + struct stat st; + + if ( (fd=open(path, O_RDONLY)) < 0 ) { + if ( errno != ENOENT ) { + if ( errno == EACCES ) { + sieve_sys_error("failed to open binary: %s", + eacces_error_get("open", path)); + } else { + sieve_sys_error("failed to open binary: " + "open(%s) failed: %m", path); + } + } + return FALSE; + } + + if ( fstat(fd, &st) < 0 ) { + if ( errno != ENOENT ) { + sieve_sys_error("failed to open binary: " + "fstat(fd=%s) failed: %m", path); + } + return FALSE; + } + + if ( !S_ISREG(st.st_mode) ) { + sieve_sys_error("binary %s is not a regular file", path); + return FALSE; + } + + file->fd = fd; + file->st = st; + + return TRUE; +} + +void sieve_binary_file_close(struct sieve_binary_file **file) +{ + if ( (*file)->fd != -1 ) { + if ( close((*file)->fd) < 0 ) { + sieve_sys_error("failed to close opened binary: " + "close(fd=%s) failed: %m", (*file)->path); + } + } + + pool_unref(&(*file)->pool); + + *file = NULL; +} + +#if 0 /* file_memory is currently unused */ + +/* File loaded/mapped to memory */ + +struct _file_memory { + struct sieve_binary_file binfile; + + /* Pointer to the binary in memory */ + const void *memory; + off_t memory_size; +}; + +static const void *_file_memory_load_data + (struct sieve_binary_file *file, off_t *offset, size_t size) +{ + struct _file_memory *fmem = (struct _file_memory *) file; + + *offset = SIEVE_BINARY_ALIGN(*offset); + + if ( (*offset) + size <= fmem->memory_size ) { + const void *data = PTR_OFFSET(fmem->memory, *offset); + *offset += size; + file->offset = *offset; + + return data; + } + + return NULL; +} + +static buffer_t *_file_memory_load_buffer + (struct sieve_binary_file *file, off_t *offset, size_t size) +{ + struct _file_memory *fmem = (struct _file_memory *) file; + + *offset = SIEVE_BINARY_ALIGN(*offset); + + if ( (*offset) + size <= fmem->memory_size ) { + const void *data = PTR_OFFSET(fmem->memory, *offset); + *offset += size; + file->offset = *offset; + + return buffer_create_const_data(file->pool, data, size); + } + + return NULL; +} + +static bool _file_memory_load(struct sieve_binary_file *file) +{ + struct _file_memory *fmem = (struct _file_memory *) file; + int ret; + size_t size; + void *indata; + + i_assert(file->fd > 0); + + /* Allocate memory buffer + */ + indata = p_malloc(file->pool, file->st.st_size); + size = file->st.st_size; + + file->offset = 0; + fmem->memory = indata; + fmem->memory_size = file->st.st_size; + + /* Return to beginning of the file */ + if ( lseek(file->fd, 0, SEEK_SET) == (off_t) -1 ) { + sieve_sys_error("failed to seek() in binary %s: %m", file->path); + return FALSE; + } + + /* Read the whole file into memory */ + while (size > 0) { + if ( (ret=read(file->fd, indata, size)) <= 0 ) { + sieve_sys_error("failed to read from binary %s: %m", file->path); + break; + } + + indata = PTR_OFFSET(indata, ret); + size -= ret; + } + + if ( size != 0 ) { + /* Failed to read the whole file */ + return FALSE; + } + + return TRUE; +} + +static struct sieve_binary_file *_file_memory_open(const char *path) +{ + pool_t pool; + struct _file_memory *file; + + pool = pool_alloconly_create("sieve_binary_file_memory", 1024); + file = p_new(pool, struct _file_memory, 1); + file->binfile.pool = pool; + file->binfile.path = p_strdup(pool, path); + file->binfile.load = _file_memory_load; + file->binfile.load_data = _file_memory_load_data; + file->binfile.load_buffer = _file_memory_load_buffer; + + if ( !sieve_binary_file_open(&file->binfile, path) ) { + pool_unref(&pool); + return NULL; + } + + return &file->binfile; +} + +#endif /* file_memory is currently unused */ + +/* File open in lazy mode (only read what is needed into memory) */ + +static bool _file_lazy_read +(struct sieve_binary_file *file, off_t *offset, void *buffer, size_t size) +{ + int ret; + void *indata = buffer; + size_t insize = size; + + *offset = SIEVE_BINARY_ALIGN(*offset); + + /* Seek to the correct position */ + if ( *offset != file->offset && + lseek(file->fd, *offset, SEEK_SET) == (off_t) -1 ) { + sieve_sys_error("failed to seek(fd, %lld, SEEK_SET) in binary %s: %m", + (long long) *offset, file->path); + return FALSE; + } + + /* Read record into memory */ + while (insize > 0) { + if ( (ret=read(file->fd, indata, insize)) <= 0 ) { + if ( ret == 0 ) + sieve_sys_error("binary %s is truncated (more data expected)", + file->path); + else + sieve_sys_error("failed to read from binary %s: %m", file->path); + break; + } + + indata = PTR_OFFSET(indata, ret); + insize -= ret; + } + + if ( insize != 0 ) { + /* Failed to read the whole requested record */ + return FALSE; + } + + *offset += size; + file->offset = *offset; + + return TRUE; +} + +static const void *_file_lazy_load_data +(struct sieve_binary_file *file, off_t *offset, size_t size) +{ + void *data = t_malloc(size); + + if ( _file_lazy_read(file, offset, data, size) ) { + return data; + } + + return NULL; +} + +static buffer_t *_file_lazy_load_buffer +(struct sieve_binary_file *file, off_t *offset, size_t size) +{ + buffer_t *buffer = buffer_create_dynamic(file->pool, size); + + if ( _file_lazy_read + (file, offset, buffer_get_space_unsafe(buffer, 0, size), size) ) { + return buffer; + } + + return NULL; +} + +static struct sieve_binary_file *_file_lazy_open(const char *path) +{ + pool_t pool; + struct sieve_binary_file *file; + + pool = pool_alloconly_create("sieve_binary_file_lazy", 4096); + file = p_new(pool, struct sieve_binary_file, 1); + file->pool = pool; + file->path = p_strdup(pool, path); + file->load_data = _file_lazy_load_data; + file->load_buffer = _file_lazy_load_buffer; + + if ( !sieve_binary_file_open(file, path) ) { + pool_unref(&pool); + return NULL; + } + + return file; +} + +/* + * Load binary from a file + */ + +#define LOAD_HEADER(sbin, offset, header) \ + (header *) sbin->file->load_data(sbin->file, offset, sizeof(header)) + +bool sieve_binary_load_block +(struct sieve_binary_block *sblock) +{ + struct sieve_binary *sbin = sblock->sbin; + unsigned int id = sblock->id; + off_t offset = sblock->offset; + const struct sieve_binary_block_header *header = + LOAD_HEADER(sbin, &offset, const struct sieve_binary_block_header); + + if ( header == NULL ) { + sieve_sys_error + ("block %d of loaded binary %s is truncated", id, sbin->path); + return FALSE; + } + + if ( header->id != id ) { + sieve_sys_error("block %d of loaded binary %s has unexpected id %d", id, + sbin->path, header->id); + return FALSE; + } + + sblock->data = sbin->file->load_buffer(sbin->file, &offset, header->size); + if ( sblock->data == NULL ) { + sieve_sys_error("block %d of loaded binary %s has invalid size %d", + id, sbin->path, header->size); + return FALSE; + } + + return TRUE; +} + +static bool _load_block_index_record +(struct sieve_binary *sbin, off_t *offset, unsigned int id) +{ + const struct sieve_binary_block_index *record = + LOAD_HEADER(sbin, offset, const struct sieve_binary_block_index); + struct sieve_binary_block *block; + + if ( record == NULL ) { + sieve_sys_error("failed to read index record for block %d in binary %s", + id, sbin->path); + return FALSE; + } + + if ( record->id != id ) { + sieve_sys_error("block index record %d of loaded binary %s " + "has unexpected id %d", id, sbin->path, record->id); + return FALSE; + } + + block = sieve_binary_block_create_id(sbin, id); + block->ext_index = record->ext_id; + block->offset = record->offset; + + return TRUE; +} + +static bool _sieve_binary_load_extensions(struct sieve_binary_block *sblock) +{ + struct sieve_binary *sbin = sblock->sbin; + sieve_size_t offset = 0; + unsigned int i, count; + bool result = TRUE; + + if ( !sieve_binary_read_unsigned(sblock, &offset, &count) ) + return FALSE; + + for ( i = 0; result && i < count; i++ ) { + T_BEGIN { + string_t *extension; + const struct sieve_extension *ext; + + if ( sieve_binary_read_string(sblock, &offset, &extension) ) { + ext = sieve_extension_get_by_name(sbin->svinst, str_c(extension)); + + if ( ext == NULL ) { + sieve_sys_error("loaded binary %s requires unknown extension '%s'", + sbin->path, str_sanitize(str_c(extension), 128)); + result = FALSE; + } else { + struct sieve_binary_extension_reg *ereg = NULL; + + (void) sieve_binary_extension_register(sbin, ext, &ereg); + if ( !sieve_binary_read_unsigned(sblock, &offset, &ereg->block_id) ) + result = FALSE; + } + } else + result = FALSE; + } T_END; + } + + return result; +} + +static bool _sieve_binary_open(struct sieve_binary *sbin) +{ + bool result = TRUE; + off_t offset = 0; + const struct sieve_binary_header *header; + struct sieve_binary_block *ext_block; + unsigned int i, blk_count; + + /* Verify header */ + + T_BEGIN { + header = LOAD_HEADER(sbin, &offset, const struct sieve_binary_header); + if ( header == NULL ) { + sieve_sys_error("opened binary %s is not even large enough " + "to contain a header.", sbin->path); + result = FALSE; + + } else if ( header->magic != SIEVE_BINARY_MAGIC ) { + if ( header->magic != SIEVE_BINARY_MAGIC_OTHER_ENDIAN ) + sieve_sys_error("opened binary %s has corrupted header (0x%08x)", + sbin->path, header->magic); + result = FALSE; + + } else if ( result && ( + header->version_major != SIEVE_BINARY_VERSION_MAJOR || + header->version_minor != SIEVE_BINARY_VERSION_MINOR ) ) { + + /* Binary is of different version. Caller will have to recompile */ + result = FALSE; + + } else if ( result && header->blocks == 0 ) { + sieve_sys_error("opened binary %s contains no blocks", sbin->path); + result = FALSE; + + } else { + blk_count = header->blocks; + } + } T_END; + + if ( !result ) return FALSE; + + /* Load block index */ + + for ( i = 0; i < blk_count && result; i++ ) { + T_BEGIN { + if ( !_load_block_index_record(sbin, &offset, i) ) { + sieve_sys_error( + "block index record %d of opened binary %s is corrupt", + i, sbin->path); + result = FALSE; + } + } T_END; + } + + if ( !result ) return FALSE; + + /* Load extensions used by this binary */ + + T_BEGIN { + ext_block = sieve_binary_block_get(sbin, SBIN_SYSBLOCK_EXTENSIONS); + if ( ext_block == NULL ) { + result = FALSE; + } else { + if ( !_sieve_binary_load_extensions(ext_block) ) { + sieve_sys_error("extension block of opened binary %s is corrupt", + sbin->path); + result = FALSE; + } + } + } T_END; + + return result; +} + +static bool _sieve_binary_load(struct sieve_binary *sbin) +{ + bool result = TRUE; + unsigned int i, blk_count; + + blk_count = array_count(&sbin->blocks); + if ( blk_count == 1 ) { + /* Binary is empty */ + return TRUE; + } + + /* Load the other blocks */ + + for ( i = 0; result && i < blk_count; i++ ) { + T_BEGIN { + if ( sieve_binary_block_get(sbin, i) == NULL ) + result = FALSE; + } T_END; + } + + return result; +} + +struct sieve_binary *sieve_binary_open +(struct sieve_instance *svinst, const char *path, struct sieve_script *script) +{ + struct sieve_binary_extension_reg *const *regs; + unsigned int ext_count, i; + struct sieve_binary *sbin; + struct sieve_binary_file *file; + + i_assert( script == NULL || sieve_script_svinst(script) == svinst ); + + //file = _file_memory_open(path); + file = _file_lazy_open(path); + if ( file == NULL ) + return NULL; + + /* Create binary object */ + sbin = sieve_binary_create(svinst, script); + sbin->path = p_strdup(sbin->pool, path); + sbin->file = file; + + if ( !_sieve_binary_open(sbin) ) { + sieve_binary_unref(&sbin); + return NULL; + } + + sieve_binary_activate(sbin); + + /* Signal open event to extensions */ + regs = array_get(&sbin->extensions, &ext_count); + for ( i = 0; i < ext_count; i++ ) { + const struct sieve_binary_extension *binext = regs[i]->binext; + + if ( binext != NULL && binext->binary_open != NULL && + !binext->binary_open(regs[i]->extension, sbin, regs[i]->context) ) { + /* Extension thinks its corrupt */ + sieve_binary_unref(&sbin); + return NULL; + } + } + + return sbin; +} + +bool sieve_binary_load(struct sieve_binary *sbin) +{ + i_assert(sbin->file != NULL); + + /* + if ( sbin->file->load != NULL && !sbin->file->load(sbin->file) ) + return FALSE; */ + + if ( !_sieve_binary_load(sbin) ) { + /* Failed to interpret binary header and/or block structure */ + return FALSE; + } + + return TRUE; +} diff --git a/src/lib-sieve/sieve-binary-private.h b/src/lib-sieve/sieve-binary-private.h new file mode 100644 index 000000000..c63cacb8d --- /dev/null +++ b/src/lib-sieve/sieve-binary-private.h @@ -0,0 +1,208 @@ +/* Copyright (c) 2002-2010 Dovecot Sieve authors, see the included COPYING file + */ + +#ifndef __SIEVE_BINARY_PRIVATE_H +#define __SIEVE_BINARY_PRIVATE_H + +#include "sieve-common.h" +#include "sieve-binary.h" +#include "sieve-extensions.h" + +#include <sys/stat.h> + +/* + * Binary file + */ + +struct sieve_binary_file { + pool_t pool; + const char *path; + + struct stat st; + int fd; + off_t offset; + + bool (*load)(struct sieve_binary_file *file); + const void *(*load_data) + (struct sieve_binary_file *file, off_t *offset, size_t size); + buffer_t *(*load_buffer) + (struct sieve_binary_file *file, off_t *offset, size_t size); +}; + +bool sieve_binary_file_open + (struct sieve_binary_file *file, const char *path); +void sieve_binary_file_close(struct sieve_binary_file **file); + +/* + * Internal structures + */ + +/* Extension registration */ + +struct sieve_binary_extension_reg { + /* The identifier of the extension within this binary */ + int index; + + /* Global extension object */ + const struct sieve_extension *extension; + + /* Extension to the binary; typically used to manage extension-specific blocks + * in the binary and as a means to get a binary_free notification to release + * references held by extensions. + */ + const struct sieve_binary_extension *binext; + + /* Context data associated to the binary by this extension */ + void *context; + + /* Main block for this extension */ + unsigned int block_id; +}; + +/* Block */ + +struct sieve_binary_block { + struct sieve_binary *sbin; + unsigned int id; + int ext_index; + + buffer_t *data; + + uoff_t offset; +}; + +/* + * Binary object + */ + +struct sieve_binary { + pool_t pool; + int refcount; + + struct sieve_instance *svinst; + + struct sieve_script *script; + + struct sieve_binary_file *file; + + /* When the binary is loaded into memory or when it is being constructed by + * the generator, extensions can be associated to the binary. The extensions + * array is a sequential list of all linked extensions. The extension_index + * array is a mapping ext_id -> binary_extension. This is used to obtain the + * index code associated with an extension for this particular binary. The + * linked_extensions list all extensions linked to this binary object other + * than the preloaded language features implemented as 'extensions'. + * + * All arrays refer to the same extension registration objects. Upon loading + * a binary, the 'require'd extensions will sometimes need to associate + * context data to the binary object in memory. This is stored in these + * registration objects as well. + */ + ARRAY_DEFINE(extensions, struct sieve_binary_extension_reg *); + ARRAY_DEFINE(extension_index, struct sieve_binary_extension_reg *); + ARRAY_DEFINE(linked_extensions, struct sieve_binary_extension_reg *); + + /* Attributes of a loaded binary */ + const char *path; + + /* Blocks */ + ARRAY_DEFINE(blocks, struct sieve_binary_block *); +}; + +struct sieve_binary *sieve_binary_create + (struct sieve_instance *svinst, struct sieve_script *script); + +/* Blocks management */ + +static inline struct sieve_binary_block *sieve_binary_block_index +(struct sieve_binary *sbin, unsigned int id) +{ + struct sieve_binary_block * const *sblock; + + if ( id >= array_count(&sbin->blocks) ) + return NULL; + + sblock = array_idx(&sbin->blocks, id); + + if ( *sblock == NULL ) { + return NULL; + } + + return *sblock; +} + +static inline size_t _sieve_binary_block_get_size +(const struct sieve_binary_block *sblock) +{ + return buffer_get_used_size(sblock->data); +} + +struct sieve_binary_block *sieve_binary_block_create_id + (struct sieve_binary *sbin, unsigned int id); + +buffer_t *sieve_binary_block_get_buffer + (struct sieve_binary_block *sblock); + +/* Extension registration */ + +static inline struct sieve_binary_extension_reg * + sieve_binary_extension_create_reg +(struct sieve_binary *sbin, const struct sieve_extension *ext) +{ + int index = array_count(&sbin->extensions); + struct sieve_binary_extension_reg *ereg; + + if ( ext->id < 0 ) return NULL; + + ereg = p_new(sbin->pool, struct sieve_binary_extension_reg, 1); + ereg->index = index; + ereg->extension = ext; + + array_idx_set(&sbin->extensions, (unsigned int) index, &ereg); + array_idx_set(&sbin->extension_index, (unsigned int) ext->id, &ereg); + + return ereg; +} + +static inline struct sieve_binary_extension_reg *sieve_binary_extension_get_reg +(struct sieve_binary *sbin, const struct sieve_extension *ext, bool create) +{ + struct sieve_binary_extension_reg *reg = NULL; + + if ( ext->id >= 0 && ext->id < (int) array_count(&sbin->extension_index) ) { + struct sieve_binary_extension_reg * const *ereg = + array_idx(&sbin->extension_index, (unsigned int) ext->id); + + reg = *ereg; + } + + /* Register if not known */ + if ( reg == NULL && create ) + return sieve_binary_extension_create_reg(sbin, ext); + + return reg; +} + +static inline int sieve_binary_extension_register +(struct sieve_binary *sbin, const struct sieve_extension *ext, + struct sieve_binary_extension_reg **reg_r) +{ + struct sieve_binary_extension_reg *ereg; + + if ( (ereg=sieve_binary_extension_get_reg(sbin, ext, FALSE)) == NULL ) { + ereg = sieve_binary_extension_create_reg(sbin, ext); + + if ( ereg == NULL ) return -1; + + array_append(&sbin->linked_extensions, &ereg, 1); + } + + if ( reg_r != NULL ) *reg_r = ereg; + return ereg->index; +} + +/* Load/Save */ + +bool sieve_binary_load_block(struct sieve_binary_block *); + +#endif /* __SIEVE_BINARY_PRIVATE_H */ diff --git a/src/lib-sieve/sieve-binary.c b/src/lib-sieve/sieve-binary.c index 955c3c93e..3f5631159 100644 --- a/src/lib-sieve/sieve-binary.c +++ b/src/lib-sieve/sieve-binary.c @@ -17,155 +17,25 @@ #include "sieve-code.h" #include "sieve-script.h" -#include "sieve-binary.h" - -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <fcntl.h> - -/* - * Config - */ - -#define SIEVE_BINARY_VERSION_MAJOR 0 -#define SIEVE_BINARY_VERSION_MINOR 1 +#include "sieve-binary-private.h" /* - * Macros - */ - -#define SIEVE_BINARY_MAGIC 0xcafebabe -#define SIEVE_BINARY_MAGIC_OTHER_ENDIAN 0xbebafeca - -#define SIEVE_BINARY_ALIGN(offset) \ - (((offset) + 3) & ~3) -#define SIEVE_BINARY_ALIGN_PTR(ptr) \ - ((void *) SIEVE_BINARY_ALIGN(((size_t) ptr))) - -/* - * Forward declarations + * Forward declarations */ -struct sieve_binary_file; - -static bool sieve_binary_file_open - (struct sieve_binary_file *file, const char *path); -static void sieve_binary_file_close(struct sieve_binary_file **file); - -static struct sieve_binary_block *sieve_binary_load_block - (struct sieve_binary *sbin, unsigned int id); - static inline struct sieve_binary_extension_reg *sieve_binary_extension_get_reg (struct sieve_binary *sbin, const struct sieve_extension *ext, bool create); + static inline int sieve_binary_extension_register (struct sieve_binary *sbin, const struct sieve_extension *ext, struct sieve_binary_extension_reg **reg); -static inline sieve_size_t sieve_binary_emit_dynamic_data - (struct sieve_binary *binary, const void *data, size_t size); - -/* - * Internal structures - */ - -/* Extension registration */ - -struct sieve_binary_extension_reg { - /* The identifier of the extension within this binary */ - int index; - - /* Global extension object */ - const struct sieve_extension *extension; - - /* Extension to the binary; typically used to manage extension-specific blocks - * in the binary and as a means to get a binary_free notification to release - * references held by extensions. - */ - const struct sieve_binary_extension *binext; - - /* Context data associated to the binary by this extension */ - void *context; - - /* Main block for this extension */ - unsigned int block_id; -}; - -/* Block */ - -struct sieve_binary_block { - buffer_t *buffer; - int ext_index; - - uoff_t offset; -}; - -/* File */ - -/* FIXME: In essence this is an unbuffered stream implementation. Maybe this - * can be merged with the generic dovecot istream interface. - */ -struct sieve_binary_file { - pool_t pool; - const char *path; - - struct stat st; - int fd; - off_t offset; - - bool (*load)(struct sieve_binary_file *file); - const void *(*load_data) - (struct sieve_binary_file *file, off_t *offset, size_t size); - buffer_t *(*load_buffer) - (struct sieve_binary_file *file, off_t *offset, size_t size); -}; - /* * Binary object */ -struct sieve_binary { - pool_t pool; - int refcount; - - struct sieve_instance *svinst; - - struct sieve_script *script; - - struct sieve_binary_file *file; - - /* When the binary is loaded into memory or when it is being constructed by - * the generator, extensions can be associated to the binary. The extensions - * array is a sequential list of all linked extensions. The extension_index - * array is a mapping ext_id -> binary_extension. This is used to obtain the - * index code associated with an extension for this particular binary. The - * linked_extensions list all extensions linked to this binary object other - * than the preloaded language features implemented as 'extensions'. - * - * All arrays refer to the same extension registration objects. Upon loading - * a binary, the 'require'd extensions will sometimes need to associate - * context data to the binary object in memory. This is stored in these - * registration objects as well. - */ - ARRAY_DEFINE(extensions, struct sieve_binary_extension_reg *); - ARRAY_DEFINE(extension_index, struct sieve_binary_extension_reg *); - ARRAY_DEFINE(linked_extensions, struct sieve_binary_extension_reg *); - - /* Attributes of a loaded binary */ - const char *path; - - /* Blocks */ - ARRAY_DEFINE(blocks, struct sieve_binary_block *); - unsigned int active_block; - - /* Current block buffer: all emit and read functions act upon this buffer */ - buffer_t *data; - const signed char *code; - size_t code_size; -}; - -static struct sieve_binary *sieve_binary_create +struct sieve_binary *sieve_binary_create (struct sieve_instance *svinst, struct sieve_script *script) { pool_t pool; @@ -212,8 +82,7 @@ struct sieve_binary *sieve_binary_create_new(struct sieve_script *script) (void) sieve_binary_block_create(sbin); /* Main program block */ - (void) sieve_binary_block_set_active - (sbin, sieve_binary_block_create(sbin), NULL); + (void) sieve_binary_block_create(sbin); return sbin; } @@ -258,17 +127,6 @@ void sieve_binary_unref(struct sieve_binary **sbin) *sbin = NULL; } -static inline sieve_size_t _sieve_binary_get_code_size -(struct sieve_binary *sbin) -{ - return buffer_get_used_size(sbin->data); -} - -sieve_size_t sieve_binary_get_code_size(struct sieve_binary *sbin) -{ - return _sieve_binary_get_code_size(sbin); -} - pool_t sieve_binary_pool(struct sieve_binary *sbin) { return sbin->pool; @@ -310,1110 +168,232 @@ const char *sieve_binary_script_path(struct sieve_binary *sbin) return ( script == NULL ? NULL : sieve_script_path(script) ); } - /* * Block management */ -static inline struct sieve_binary_block *sieve_binary_block_get -(struct sieve_binary *sbin, unsigned int id) +unsigned int sieve_binary_block_count +(struct sieve_binary *sbin) { - struct sieve_binary_block * const *block; - - if ( id >= array_count(&sbin->blocks) ) - return NULL; - - block = array_idx(&sbin->blocks, id); - - return *block; + return array_count(&sbin->blocks); } -static inline unsigned int sieve_binary_block_add -(struct sieve_binary *sbin, struct sieve_binary_block *block) +struct sieve_binary_block *sieve_binary_block_create(struct sieve_binary *sbin) { - unsigned int id = array_count(&sbin->blocks); + unsigned int id = sieve_binary_block_count(sbin); + struct sieve_binary_block *sblock; - array_append(&sbin->blocks, &block, 1); - return id; -} + sblock = p_new(sbin->pool, struct sieve_binary_block, 1); + sblock->data = buffer_create_dynamic(sbin->pool, 64); + sblock->sbin = sbin; + sblock->id = id; -static inline unsigned int sieve_binary_block_count -(struct sieve_binary *sbin) -{ - return array_count(&sbin->blocks); + array_append(&sbin->blocks, &sblock, 1); + + return sblock; } -void sieve_binary_block_clear +struct sieve_binary_block *sieve_binary_block_create_id (struct sieve_binary *sbin, unsigned int id) { - struct sieve_binary_block *block = sieve_binary_block_get(sbin, id); + struct sieve_binary_block *sblock; - buffer_reset(block->buffer); + sblock = p_new(sbin->pool, struct sieve_binary_block, 1); + + array_idx_set(&sbin->blocks, id, &sblock); + sblock->data = NULL; + sblock->sbin = sbin; + sblock->id = id; + + return sblock; } -bool sieve_binary_block_set_active -(struct sieve_binary *sbin, unsigned int id, unsigned *old_id_r) +static bool sieve_binary_block_fetch(struct sieve_binary_block *sblock) { - struct sieve_binary_block *block = sieve_binary_block_get(sbin, id); - - if ( block == NULL ) return FALSE; - - if ( block->buffer == NULL ) { - if ( sbin->file ) { - /* Try to acces the block in the binary on disk (apperently we were lazy) - */ - if ( sieve_binary_load_block(sbin, id) == NULL || block->buffer == NULL ) - return FALSE; - } else { - /* Block buffer is missing during code generation. This is what we would - * call a bug. FAIL. - */ + struct sieve_binary *sbin = sblock->sbin; + + if ( sbin->file ) { + /* Try to acces the block in the binary on disk (apperently we were lazy) + */ + if ( !sieve_binary_load_block(sblock) || sblock->data == NULL ) { + sieve_sys_error("block %d of loaded binary %s is corrupt", + sblock->id, sbin->path); return FALSE; } + } else { + sblock->data = buffer_create_dynamic(sbin->pool, 64); + return TRUE; } - - if ( old_id_r != NULL ) - *old_id_r = sbin->active_block; - sbin->data = block->buffer; - sbin->code = buffer_get_data(block->buffer, &sbin->code_size); - sbin->active_block = id; - return TRUE; } -unsigned int sieve_binary_block_create(struct sieve_binary *sbin) +struct sieve_binary_block *sieve_binary_block_get +(struct sieve_binary *sbin, unsigned int id) { - struct sieve_binary_block *block; - - block = p_new(sbin->pool, struct sieve_binary_block, 1); - block->buffer = buffer_create_dynamic(sbin->pool, 64); + struct sieve_binary_block *sblock = sieve_binary_block_index(sbin, id); - return sieve_binary_block_add(sbin, block); -} + if ( sblock == NULL ) + return NULL; -static struct sieve_binary_block *sieve_binary_block_create_id -(struct sieve_binary *sbin, unsigned int id) -{ - struct sieve_binary_block *block; - - block = p_new(sbin->pool, struct sieve_binary_block, 1); + if ( sblock->data == NULL && !sieve_binary_block_fetch(sblock) ) + return NULL; - if ( id >= SBIN_SYSBLOCK_LAST ) - array_idx_set(&sbin->blocks, id, &block); - else - (void)sieve_binary_block_add(sbin, block); - - return block; + return sblock; } -/* - * Header and record structures of the binary on disk - */ - -struct sieve_binary_header { - uint32_t magic; - uint16_t version_major; - uint16_t version_minor; - uint32_t blocks; -}; - -struct sieve_binary_block_index { - uint32_t id; - uint32_t size; - uint32_t offset; - uint32_t ext_id; -}; - -struct sieve_binary_block_header { - uint32_t id; - uint32_t size; -}; - -/* - * Saving the binary to a file. - */ - -static inline bool _save_skip(struct ostream *stream, size_t size) +void sieve_binary_block_clear +(struct sieve_binary_block *sblock) { - if ( (o_stream_seek(stream, stream->offset + size)) <= 0 ) - return FALSE; - - return TRUE; + buffer_reset(sblock->data); } -static inline bool _save_skip_aligned -(struct ostream *stream, size_t size, uoff_t *offset) -{ - uoff_t aligned_offset = SIEVE_BINARY_ALIGN(stream->offset); +buffer_t *sieve_binary_block_get_buffer +(struct sieve_binary_block *sblock) +{ + if ( sblock->data == NULL && !sieve_binary_block_fetch(sblock) ) + return NULL; - if ( (o_stream_seek(stream, aligned_offset + size)) <= 0 ) - return FALSE; - - if ( offset != NULL ) - *offset = aligned_offset; - - return TRUE; + return sblock->data; } -/* FIXME: Is this even necessary for a file? */ -static bool _save_full(struct ostream *stream, const void *data, size_t size) +struct sieve_binary *sieve_binary_block_get_binary +(const struct sieve_binary_block *sblock) { - size_t bytes_left = size; - const void *pdata = data; - - while ( bytes_left > 0 ) { - ssize_t ret; - - if ( (ret=o_stream_send(stream, pdata, bytes_left)) <= 0 ) - return FALSE; - - pdata = PTR_OFFSET(pdata, ret); - bytes_left -= ret; - } - - return TRUE; + return sblock->sbin; } -static bool _save_aligned -(struct ostream *stream, const void *data, size_t size, uoff_t *offset) -{ - uoff_t aligned_offset = SIEVE_BINARY_ALIGN(stream->offset); - - o_stream_cork(stream); - - /* Align the data by adding zeroes to the output stream */ - if ( stream->offset < aligned_offset ) { - if ( !_save_skip(stream, aligned_offset - stream->offset) ) - return FALSE; - } - - if ( !_save_full(stream, data, size) ) - return FALSE; - - o_stream_uncork(stream); - - if ( offset != NULL ) - *offset = aligned_offset; - - return TRUE; -} - -static bool _save_block -(struct sieve_binary *sbin, struct ostream *stream, unsigned int id) +unsigned int sieve_binary_block_get_id +(const struct sieve_binary_block *sblock) { - struct sieve_binary_block_header block_header; - struct sieve_binary_block *block; - const void *data; - size_t size; - - block = sieve_binary_block_get(sbin, id); - if ( block == NULL ) - return FALSE; - - data = buffer_get_data(block->buffer, &size); - - block_header.id = id; - block_header.size = size; - - if ( !_save_aligned(stream, &block_header, - sizeof(block_header), &block->offset) ) - return FALSE; - - return _save_aligned(stream, data, size, NULL); + return sblock->id; } -static bool _save_block_index_record -(struct sieve_binary *sbin, struct ostream *stream, unsigned int id) +size_t sieve_binary_block_get_size +(const struct sieve_binary_block *sblock) { - struct sieve_binary_block *block; - struct sieve_binary_block_index header; - - block = sieve_binary_block_get(sbin, id); - if ( block == NULL ) - return FALSE; - - header.id = id; - header.size = buffer_get_used_size(block->buffer); - header.ext_id = block->ext_index; - header.offset = block->offset; - - if ( !_save_full(stream, &header, sizeof(header)) ) { - sieve_sys_error("failed to save block index header %d: %m", id); - - return FALSE; - } - - return TRUE; + return _sieve_binary_block_get_size(sblock); } -static bool _sieve_binary_save -(struct sieve_binary *sbin, struct ostream *stream) +/* + * Up-to-date checking + */ + +bool sieve_binary_up_to_date(struct sieve_binary *sbin) { - struct sieve_binary_header header; struct sieve_binary_extension_reg *const *regs; - unsigned int ext_count, blk_count, i; - uoff_t block_index; - - blk_count = sieve_binary_block_count(sbin); + unsigned int ext_count, i; - /* Signal all extensions to finish generating their blocks */ + i_assert(sbin->file != NULL); + + if ( sbin->script == NULL || sieve_script_newer + (sbin->script, sbin->file->st.st_mtime) ) + return FALSE; regs = array_get(&sbin->extensions, &ext_count); for ( i = 0; i < ext_count; i++ ) { const struct sieve_binary_extension *binext = regs[i]->binext; - if ( binext != NULL && binext->binary_save != NULL ) - binext->binary_save(regs[i]->extension, sbin, regs[i]->context); + if ( binext != NULL && binext->binary_up_to_date != NULL && + !binext->binary_up_to_date(regs[i]->extension, sbin, regs[i]->context) ) + return FALSE; } - - /* Create header */ - header.magic = SIEVE_BINARY_MAGIC; - header.version_major = SIEVE_BINARY_VERSION_MAJOR; - header.version_minor = SIEVE_BINARY_VERSION_MINOR; - header.blocks = blk_count; + return TRUE; +} - if ( !_save_aligned(stream, &header, sizeof(header), NULL) ) { - sieve_sys_error("failed to save binary header: %m"); - return FALSE; - } - - /* Skip block index for now */ - - if ( !_save_skip_aligned(stream, - sizeof(struct sieve_binary_block_index) * blk_count, &block_index) ) - return FALSE; - - /* Create block containing all used extensions - * FIXME: Per-extension this should also store binary version numbers. - */ - if ( !sieve_binary_block_set_active(sbin, SBIN_SYSBLOCK_EXTENSIONS, NULL) ) - return FALSE; - - ext_count = array_count(&sbin->linked_extensions); - sieve_binary_emit_unsigned(sbin, ext_count); +/* + * Activate the binary (after code generation) + */ + +void sieve_binary_activate(struct sieve_binary *sbin) +{ + struct sieve_binary_extension_reg *const *regs; + unsigned int i, ext_count; + /* Load other extensions into binary */ + regs = array_get(&sbin->linked_extensions, &ext_count); for ( i = 0; i < ext_count; i++ ) { - struct sieve_binary_extension_reg * const *ext - = array_idx(&sbin->linked_extensions, i); + const struct sieve_extension *ext = regs[i]->extension; - sieve_binary_emit_cstring(sbin, sieve_extension_name((*ext)->extension)); - sieve_binary_emit_unsigned(sbin, (*ext)->block_id); - } - - if ( !sieve_binary_block_set_active(sbin, SBIN_SYSBLOCK_MAIN_PROGRAM, NULL) ) - return FALSE; - - /* Save all blocks into the binary */ - - for ( i = 0; i < blk_count; i++ ) { - if ( !_save_block(sbin, stream, i) ) - return FALSE; - } - - /* Create the block index */ - o_stream_seek(stream, block_index); - for ( i = 0; i < blk_count; i++ ) { - if ( !_save_block_index_record(sbin, stream, i) ) - return FALSE; + if ( ext != NULL && ext->def != NULL && ext->def->binary_load != NULL ) + ext->def->binary_load(ext, sbin); } +} - return TRUE; -} +/* + * Extension handling + */ -bool sieve_binary_save -(struct sieve_binary *sbin, const char *path) +void sieve_binary_extension_set_context +(struct sieve_binary *sbin, const struct sieve_extension *ext, void *context) { - bool result = TRUE; - string_t *temp_path; - struct ostream *stream; - int fd; - mode_t save_mode = sbin->script == NULL ? 0600 : sieve_script_permissions(sbin->script); + struct sieve_binary_extension_reg *ereg = + sieve_binary_extension_get_reg(sbin, ext, TRUE); - /* 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_str_new(256); - str_append(temp_path, path); - fd = safe_mkstemp_hostpid(temp_path, save_mode, (uid_t)-1, (gid_t)-1); - if ( fd < 0 ) { - if ( errno == EACCES ) { - sieve_sys_error("failed to save binary temporary file: %s", - eacces_error_get_creating("open", str_c(temp_path))); - } else { - sieve_sys_error("failed to save binary temporary file: " - "open(%s) failed: %m", str_c(temp_path)); - } - return FALSE; - } - - /* Save binary */ - stream = o_stream_create_fd(fd, 0, FALSE); - result = _sieve_binary_save(sbin, stream); - o_stream_destroy(&stream); - - /* Close saved binary */ - if ( close(fd) < 0 ) { - sieve_sys_error("failed to close saved binary temporary file: " - "close(fd=%s) failed: %m", str_c(temp_path)); - } + if ( ereg != NULL ) + ereg->context = context; +} - /* Replace any original binary atomically */ - if ( result && (rename(str_c(temp_path), path) < 0) ) { - if ( errno == EACCES ) { - sieve_sys_error("failed to replace existing binary: %s", - eacces_error_get_creating("rename", path)); - } else { - sieve_sys_error("failed to replace existing binary: " - "rename(%s, %s) failed: %m", str_c(temp_path), path); - } - result = FALSE; - } +const void *sieve_binary_extension_get_context + (struct sieve_binary *sbin, const struct sieve_extension *ext) +{ + struct sieve_binary_extension_reg *ereg = + sieve_binary_extension_get_reg(sbin, ext, TRUE); - if ( !result ) { - /* Get rid of temp output (if any) */ - (void) unlink(str_c(temp_path)); - } else { - if ( sbin->path == NULL || strcmp(sbin->path, path) != 0 ) { - sbin->path = p_strdup(sbin->pool, path); - } + if ( ereg != NULL ) { + return ereg->context; } - - return result; + + return NULL; } -/* - * Binary file management - */ - -static bool sieve_binary_file_open - (struct sieve_binary_file *file, const char *path) +void sieve_binary_extension_set +(struct sieve_binary *sbin, const struct sieve_extension *ext, + const struct sieve_binary_extension *bext, void *context) { - int fd; - struct stat st; + struct sieve_binary_extension_reg *ereg = + sieve_binary_extension_get_reg(sbin, ext, TRUE); - if ( (fd=open(path, O_RDONLY)) < 0 ) { - if ( errno != ENOENT ) { - if ( errno == EACCES ) { - sieve_sys_error("failed to open binary: %s", - eacces_error_get("open", path)); - } else { - sieve_sys_error("failed to open binary: " - "open(%s) failed: %m", path); - } - } - return FALSE; - } + if ( ereg != NULL ) { + ereg->binext = bext; - if ( fstat(fd, &st) < 0 ) { - if ( errno != ENOENT ) { - sieve_sys_error("failed to open binary: " - "fstat(fd=%s) failed: %m", path); - } - return FALSE; + if ( context != NULL ) + ereg->context = context; } +} - if ( !S_ISREG(st.st_mode) ) { - sieve_sys_error("binary %s is not a regular file", path); - return FALSE; - } +struct sieve_binary_block *sieve_binary_extension_create_block +(struct sieve_binary *sbin, const struct sieve_extension *ext) +{ + struct sieve_binary_block *sblock; + struct sieve_binary_extension_reg *ereg = + sieve_binary_extension_get_reg(sbin, ext, TRUE); - file->fd = fd; - file->st = st; + i_assert(ereg != NULL); - return TRUE; -} + sblock = sieve_binary_block_create(sbin); -static void sieve_binary_file_close(struct sieve_binary_file **file) -{ - if ( (*file)->fd != -1 ) { - if ( close((*file)->fd) < 0 ) { - sieve_sys_error("failed to close opened binary: " - "close(fd=%s) failed: %m", (*file)->path); - } - } - - pool_unref(&(*file)->pool); + if ( ereg->block_id < SBIN_SYSBLOCK_LAST ) + ereg->block_id = sblock->id; + sblock->ext_index = ereg->index; - *file = NULL; + return sblock; } -#if 0 /* file_memory is currently unused */ - -/* File loaded/mapped to memory */ +struct sieve_binary_block *sieve_binary_extension_get_block +(struct sieve_binary *sbin, const struct sieve_extension *ext) +{ + struct sieve_binary_extension_reg *ereg = + sieve_binary_extension_get_reg(sbin, ext, TRUE); + + i_assert(ereg != NULL); -struct _file_memory { - struct sieve_binary_file binfile; + if ( ereg->block_id < SBIN_SYSBLOCK_LAST ) + return NULL; - /* Pointer to the binary in memory */ - const void *memory; - off_t memory_size; -}; - -static const void *_file_memory_load_data - (struct sieve_binary_file *file, off_t *offset, size_t size) -{ - struct _file_memory *fmem = (struct _file_memory *) file; - - *offset = SIEVE_BINARY_ALIGN(*offset); - - if ( (*offset) + size <= fmem->memory_size ) { - const void *data = PTR_OFFSET(fmem->memory, *offset); - *offset += size; - file->offset = *offset; - - return data; - } - - return NULL; -} - -static buffer_t *_file_memory_load_buffer - (struct sieve_binary_file *file, off_t *offset, size_t size) -{ - struct _file_memory *fmem = (struct _file_memory *) file; - - *offset = SIEVE_BINARY_ALIGN(*offset); - - if ( (*offset) + size <= fmem->memory_size ) { - const void *data = PTR_OFFSET(fmem->memory, *offset); - *offset += size; - file->offset = *offset; - - return buffer_create_const_data(file->pool, data, size); - } - - return NULL; -} - -static bool _file_memory_load(struct sieve_binary_file *file) -{ - struct _file_memory *fmem = (struct _file_memory *) file; - int ret; - size_t size; - void *indata; - - i_assert(file->fd > 0); - - /* Allocate memory buffer - */ - indata = p_malloc(file->pool, file->st.st_size); - size = file->st.st_size; - - file->offset = 0; - fmem->memory = indata; - fmem->memory_size = file->st.st_size; - - /* Return to beginning of the file */ - if ( lseek(file->fd, 0, SEEK_SET) == (off_t) -1 ) { - sieve_sys_error("failed to seek() in binary %s: %m", file->path); - return FALSE; - } - - /* Read the whole file into memory */ - while (size > 0) { - if ( (ret=read(file->fd, indata, size)) <= 0 ) { - sieve_sys_error("failed to read from binary %s: %m", file->path); - break; - } - - indata = PTR_OFFSET(indata, ret); - size -= ret; - } - - if ( size != 0 ) { - /* Failed to read the whole file */ - return FALSE; - } - - return TRUE; -} - -static struct sieve_binary_file *_file_memory_open(const char *path) -{ - pool_t pool; - struct _file_memory *file; - - pool = pool_alloconly_create("sieve_binary_file_memory", 1024); - file = p_new(pool, struct _file_memory, 1); - file->binfile.pool = pool; - file->binfile.path = p_strdup(pool, path); - file->binfile.load = _file_memory_load; - file->binfile.load_data = _file_memory_load_data; - file->binfile.load_buffer = _file_memory_load_buffer; - - if ( !sieve_binary_file_open(&file->binfile, path) ) { - pool_unref(&pool); - return NULL; - } - - return &file->binfile; -} - -#endif /* file_memory is currently unused */ - -/* File open in lazy mode (only read what is needed into memory) */ - -static bool _file_lazy_read -(struct sieve_binary_file *file, off_t *offset, void *buffer, size_t size) -{ - int ret; - void *indata = buffer; - size_t insize = size; - - *offset = SIEVE_BINARY_ALIGN(*offset); - - /* Seek to the correct position */ - if ( *offset != file->offset && - lseek(file->fd, *offset, SEEK_SET) == (off_t) -1 ) { - sieve_sys_error("failed to seek(fd, %lld, SEEK_SET) in binary %s: %m", - (long long) *offset, file->path); - return FALSE; - } - - /* Read record into memory */ - while (insize > 0) { - if ( (ret=read(file->fd, indata, insize)) <= 0 ) { - if ( ret == 0 ) - sieve_sys_error("binary %s is truncated (more data expected)", - file->path); - else - sieve_sys_error("failed to read from binary %s: %m", file->path); - break; - } - - indata = PTR_OFFSET(indata, ret); - insize -= ret; - } - - if ( insize != 0 ) { - /* Failed to read the whole requested record */ - return FALSE; - } - - *offset += size; - file->offset = *offset; - - return TRUE; -} - -static const void *_file_lazy_load_data -(struct sieve_binary_file *file, off_t *offset, size_t size) -{ - void *data = t_malloc(size); - - if ( _file_lazy_read(file, offset, data, size) ) { - return data; - } - - return NULL; -} - -static buffer_t *_file_lazy_load_buffer -(struct sieve_binary_file *file, off_t *offset, size_t size) -{ - buffer_t *buffer = buffer_create_dynamic(file->pool, size); - - if ( _file_lazy_read - (file, offset, buffer_get_space_unsafe(buffer, 0, size), size) ) { - return buffer; - } - - return NULL; -} - -static struct sieve_binary_file *_file_lazy_open(const char *path) -{ - pool_t pool; - struct sieve_binary_file *file; - - pool = pool_alloconly_create("sieve_binary_file_lazy", 4096); - file = p_new(pool, struct sieve_binary_file, 1); - file->pool = pool; - file->path = p_strdup(pool, path); - file->load_data = _file_lazy_load_data; - file->load_buffer = _file_lazy_load_buffer; - - if ( !sieve_binary_file_open(file, path) ) { - pool_unref(&pool); - return NULL; - } - - return file; -} - -/* - * Load binary from a file - */ - -#define LOAD_HEADER(sbin, offset, header) \ - (header *) sbin->file->load_data(sbin->file, offset, sizeof(header)) - -static struct sieve_binary_block *_load_block -(struct sieve_binary *sbin, off_t *offset, unsigned int id) -{ - const struct sieve_binary_block_header *header = - LOAD_HEADER(sbin, offset, const struct sieve_binary_block_header); - struct sieve_binary_block *block; - - if ( header == NULL ) { - sieve_sys_error("block %d of loaded binary %s is truncated", id, sbin->path); - return NULL; - } - - if ( header->id != id ) { - sieve_sys_error("block %d of loaded binary %s has unexpected id %d", id, - sbin->path, header->id); - return NULL; - } - - block = sieve_binary_block_get(sbin, id); - - if ( block == NULL ) { - sieve_sys_error("!!BUG!!: block %d missing in index (impossible) " - "of binary %s", id, sbin->path); - return NULL; - } - - block->buffer = sbin->file->load_buffer(sbin->file, offset, header->size); - if ( block->buffer == NULL ) { - sieve_sys_error("block %d of loaded binary %s has invalid size %d", - id, sbin->path, header->size); - return NULL; - } - - return block; -} - -static struct sieve_binary_block *sieve_binary_load_block -(struct sieve_binary *sbin, unsigned int id) -{ - struct sieve_binary_block *block; - off_t offset; - - block = sieve_binary_block_get(sbin, id); - - if ( block == NULL ) return NULL; - - offset = block->offset; - - return _load_block(sbin, &offset, id); -} - -static bool _load_block_index_record -(struct sieve_binary *sbin, off_t *offset, unsigned int id) -{ - const struct sieve_binary_block_index *record = - LOAD_HEADER(sbin, offset, const struct sieve_binary_block_index); - struct sieve_binary_block *block; - - if ( record == NULL ) { - sieve_sys_error("failed to read index record for block %d in binary %s", - id, sbin->path); - return FALSE; - } - - if ( record->id != id ) { - sieve_sys_error("block index record %d of loaded binary %s " - "has unexpected id %d", id, sbin->path, record->id); - return FALSE; - } - - block = sieve_binary_block_create_id(sbin, id); - block->ext_index = record->ext_id; - block->offset = record->offset; - - return TRUE; -} - -static bool _sieve_binary_load_extensions(struct sieve_binary *sbin) -{ - sieve_size_t offset = 0; - unsigned int i, count; - bool result = TRUE; - - if ( !sieve_binary_block_set_active(sbin, SBIN_SYSBLOCK_EXTENSIONS, NULL) ) - return FALSE; - - if ( !sieve_binary_read_unsigned(sbin, &offset, &count) ) - return FALSE; - - for ( i = 0; result && i < count; i++ ) { - T_BEGIN { - string_t *extension; - const struct sieve_extension *ext; - - if ( sieve_binary_read_string(sbin, &offset, &extension) ) { - ext = sieve_extension_get_by_name(sbin->svinst, str_c(extension)); - - if ( ext == NULL ) { - sieve_sys_error("loaded binary %s requires unknown extension '%s'", - sbin->path, str_sanitize(str_c(extension), 128)); - result = FALSE; - } else { - struct sieve_binary_extension_reg *ereg = NULL; - - (void) sieve_binary_extension_register(sbin, ext, &ereg); - if ( !sieve_binary_read_unsigned(sbin, &offset, &ereg->block_id) ) - result = FALSE; - } - } else - result = FALSE; - } T_END; - } - - return result; -} - -static bool _sieve_binary_open(struct sieve_binary *sbin) -{ - bool result = TRUE; - off_t offset = 0; - const struct sieve_binary_header *header; - struct sieve_binary_block *extensions; - unsigned int i, blk_count; - - /* Verify header */ - - T_BEGIN { - header = LOAD_HEADER(sbin, &offset, const struct sieve_binary_header); - if ( header == NULL ) { - sieve_sys_error("opened binary %s is not even large enough " - "to contain a header.", sbin->path); - result = FALSE; - - } else if ( header->magic != SIEVE_BINARY_MAGIC ) { - if ( header->magic != SIEVE_BINARY_MAGIC_OTHER_ENDIAN ) - sieve_sys_error("opened binary %s has corrupted header (0x%08x)", - sbin->path, header->magic); - result = FALSE; - - } else if ( result && ( - header->version_major != SIEVE_BINARY_VERSION_MAJOR || - header->version_minor != SIEVE_BINARY_VERSION_MINOR ) ) { - - /* Binary is of different version. Caller will have to recompile */ - result = FALSE; - - } else if ( result && header->blocks == 0 ) { - sieve_sys_error("opened binary %s contains no blocks", sbin->path); - result = FALSE; - - } else { - blk_count = header->blocks; - } - } T_END; - - if ( !result ) return FALSE; - - /* Load block index */ - - for ( i = 0; i < blk_count && result; i++ ) { - T_BEGIN { - if ( !_load_block_index_record(sbin, &offset, i) ) { - sieve_sys_error( - "block index record %d of opened binary %s is corrupt", - i, sbin->path); - result = FALSE; - } - } T_END; - } - - if ( !result ) return FALSE; - - /* Load extensions used by this binary */ - - T_BEGIN { - extensions =_load_block(sbin, &offset, 0); - if ( extensions == NULL ) { - result = FALSE; - } else if ( !_sieve_binary_load_extensions(sbin) ) { - sieve_sys_error("extension block of opened binary %s is corrupt", - sbin->path); - result = FALSE; - } - } T_END; - - return result; -} - -static bool _sieve_binary_load(struct sieve_binary *sbin) -{ - bool result = TRUE; - unsigned int i, blk_count; - struct sieve_binary_block *block; - off_t offset; - - blk_count = array_count(&sbin->blocks); - if ( blk_count == 1 ) { - /* Binary is empty */ - return TRUE; - } - - block = sieve_binary_block_get(sbin, SBIN_SYSBLOCK_MAIN_PROGRAM); - offset = block->offset; - - /* Load the other blocks */ - - for ( i = 1; result && i < blk_count; i++ ) { - T_BEGIN { - if ( _load_block(sbin, &offset, i) == NULL ) { - sieve_sys_error("block %d of loaded binary %s is corrupt", - i, sbin->path); - result = FALSE; - } - } T_END; - } - - return result; -} - -struct sieve_binary *sieve_binary_open -(struct sieve_instance *svinst, const char *path, struct sieve_script *script) -{ - struct sieve_binary_extension_reg *const *regs; - unsigned int ext_count, i; - struct sieve_binary *sbin; - struct sieve_binary_file *file; - - i_assert( script == NULL || sieve_script_svinst(script) == svinst ); - - //file = _file_memory_open(path); - file = _file_lazy_open(path); - if ( file == NULL ) - return NULL; - - /* Create binary object */ - sbin = sieve_binary_create(svinst, script); - sbin->path = p_strdup(sbin->pool, path); - sbin->file = file; - - if ( !_sieve_binary_open(sbin) ) { - sieve_binary_unref(&sbin); - return NULL; - } - - sieve_binary_activate(sbin); - - /* Signal open event to extensions */ - regs = array_get(&sbin->extensions, &ext_count); - for ( i = 0; i < ext_count; i++ ) { - const struct sieve_binary_extension *binext = regs[i]->binext; - - if ( binext != NULL && binext->binary_open != NULL && - !binext->binary_open(regs[i]->extension, sbin, regs[i]->context) ) { - /* Extension thinks its corrupt */ - sieve_binary_unref(&sbin); - return NULL; - } - } - - return sbin; -} - -bool sieve_binary_load(struct sieve_binary *sbin) -{ - i_assert(sbin->file != NULL); - - /* - if ( sbin->file->load != NULL && !sbin->file->load(sbin->file) ) - return FALSE; */ - - if ( !_sieve_binary_load(sbin) ) { - /* Failed to interpret binary header and/or block structure */ - return FALSE; - } - - return TRUE; -} - -/* - * Up-to-date checking - */ - -bool sieve_binary_up_to_date(struct sieve_binary *sbin) -{ - struct sieve_binary_extension_reg *const *regs; - unsigned int ext_count, i; - - i_assert(sbin->file != NULL); - - if ( sbin->script == NULL || sieve_script_newer - (sbin->script, sbin->file->st.st_mtime) ) - return FALSE; - - regs = array_get(&sbin->extensions, &ext_count); - for ( i = 0; i < ext_count; i++ ) { - const struct sieve_binary_extension *binext = regs[i]->binext; - - if ( binext != NULL && binext->binary_up_to_date != NULL && - !binext->binary_up_to_date(regs[i]->extension, sbin, regs[i]->context) ) - return FALSE; - } - - return TRUE; -} - -/* - * Activate the binary (after code generation) - */ - -void sieve_binary_activate(struct sieve_binary *sbin) -{ - struct sieve_binary_extension_reg *const *regs; - unsigned int i, ext_count; - - (void)sieve_binary_block_set_active(sbin, SBIN_SYSBLOCK_MAIN_PROGRAM, NULL); - - /* Load other extensions into binary */ - regs = array_get(&sbin->linked_extensions, &ext_count); - for ( i = 0; i < ext_count; i++ ) { - const struct sieve_extension *ext = regs[i]->extension; - - if ( ext != NULL && ext->def != NULL && ext->def->binary_load != NULL ) - ext->def->binary_load(ext, sbin); - } -} - -/* - * Extension handling - */ - -static inline struct sieve_binary_extension_reg * - sieve_binary_extension_create_reg -(struct sieve_binary *sbin, const struct sieve_extension *ext) -{ - int index = array_count(&sbin->extensions); - struct sieve_binary_extension_reg *ereg; - - if ( ext->id < 0 ) return NULL; - - ereg = p_new(sbin->pool, struct sieve_binary_extension_reg, 1); - ereg->index = index; - ereg->extension = ext; - - array_idx_set(&sbin->extensions, (unsigned int) index, &ereg); - array_idx_set(&sbin->extension_index, (unsigned int) ext->id, &ereg); - - return ereg; -} - -static inline struct sieve_binary_extension_reg *sieve_binary_extension_get_reg -(struct sieve_binary *sbin, const struct sieve_extension *ext, bool create) -{ - struct sieve_binary_extension_reg *reg = NULL; - - if ( ext->id >= 0 && ext->id < (int) array_count(&sbin->extension_index) ) { - struct sieve_binary_extension_reg * const *ereg = - array_idx(&sbin->extension_index, (unsigned int) ext->id); - - reg = *ereg; - } - - /* Register if not known */ - if ( reg == NULL && create ) - return sieve_binary_extension_create_reg(sbin, ext); - - return reg; -} - -void sieve_binary_extension_set_context -(struct sieve_binary *sbin, const struct sieve_extension *ext, void *context) -{ - struct sieve_binary_extension_reg *ereg = - sieve_binary_extension_get_reg(sbin, ext, TRUE); - - if ( ereg != NULL ) - ereg->context = context; -} - -const void *sieve_binary_extension_get_context - (struct sieve_binary *sbin, const struct sieve_extension *ext) -{ - struct sieve_binary_extension_reg *ereg = - sieve_binary_extension_get_reg(sbin, ext, TRUE); - - if ( ereg != NULL ) { - return ereg->context; - } - - return NULL; -} - -void sieve_binary_extension_set -(struct sieve_binary *sbin, const struct sieve_extension *ext, - const struct sieve_binary_extension *bext, void *context) -{ - struct sieve_binary_extension_reg *ereg = - sieve_binary_extension_get_reg(sbin, ext, TRUE); - - if ( ereg != NULL ) { - ereg->binext = bext; - - if ( context != NULL ) - ereg->context = context; - } -} - -unsigned int sieve_binary_extension_create_block -(struct sieve_binary *sbin, const struct sieve_extension *ext) -{ - struct sieve_binary_block *block; - unsigned int block_id; - struct sieve_binary_extension_reg *ereg = - sieve_binary_extension_get_reg(sbin, ext, TRUE); - - i_assert(ereg != NULL); - - block = p_new(sbin->pool, struct sieve_binary_block, 1); - block->buffer = buffer_create_dynamic(sbin->pool, 64); - - block_id = sieve_binary_block_add(sbin, block); - - if ( ereg->block_id < SBIN_SYSBLOCK_LAST ) - ereg->block_id = block_id; - block->ext_index = ereg->index; - - return block_id; -} - -unsigned int sieve_binary_extension_get_block -(struct sieve_binary *sbin, const struct sieve_extension *ext) -{ - struct sieve_binary_extension_reg *ereg = - sieve_binary_extension_get_reg(sbin, ext, TRUE); - - i_assert(ereg != NULL); - - return ereg->block_id; -} - -static inline int sieve_binary_extension_register -(struct sieve_binary *sbin, const struct sieve_extension *ext, - struct sieve_binary_extension_reg **reg_r) -{ - struct sieve_binary_extension_reg *ereg; - - if ( (ereg=sieve_binary_extension_get_reg(sbin, ext, FALSE)) == NULL ) { - ereg = sieve_binary_extension_create_reg(sbin, ext); - - if ( ereg == NULL ) return -1; - - array_append(&sbin->linked_extensions, &ereg, 1); - } - - if ( reg_r != NULL ) *reg_r = ereg; - return ereg->index; -} + return sieve_binary_block_get(sbin, ereg->block_id); +} int sieve_binary_extension_link (struct sieve_binary *sbin, const struct sieve_extension *ext) @@ -1421,7 +401,7 @@ int sieve_binary_extension_link return sieve_binary_extension_register(sbin, ext, NULL); } -static inline const struct sieve_extension *_sieve_binary_extension_get_by_index +const struct sieve_extension *sieve_binary_extension_get_by_index (struct sieve_binary *sbin, int index) { struct sieve_binary_extension_reg * const *ereg; @@ -1435,12 +415,6 @@ static inline const struct sieve_extension *_sieve_binary_extension_get_by_index return NULL; } -const struct sieve_extension *sieve_binary_extension_get_by_index -(struct sieve_binary *sbin, int index) -{ - return _sieve_binary_extension_get_by_index(sbin, index); -} - int sieve_binary_extension_get_index (struct sieve_binary *sbin, const struct sieve_extension *ext) { @@ -1454,345 +428,3 @@ int sieve_binary_extensions_count(struct sieve_binary *sbin) { return (int) array_count(&sbin->extensions); } - -/* - * Emission functions - */ - -/* Low-level emission functions */ - -static inline void _sieve_binary_emit_data -(struct sieve_binary *sbin, const void *data, sieve_size_t size) -{ - buffer_append(sbin->data, data, size); -} - -static inline void _sieve_binary_emit_byte -(struct sieve_binary *sbin, unsigned char byte) -{ - _sieve_binary_emit_data(sbin, &byte, 1); -} - -static inline void _sieve_binary_update_data -(struct sieve_binary *sbin, sieve_size_t address, const void *data, - sieve_size_t size) -{ - buffer_write(sbin->data, address, data, size); -} - -sieve_size_t sieve_binary_emit_data -(struct sieve_binary *sbin, const void *data, sieve_size_t size) -{ - sieve_size_t address = _sieve_binary_get_code_size(sbin); - - _sieve_binary_emit_data(sbin, data, size); - - return address; -} - -sieve_size_t sieve_binary_emit_byte -(struct sieve_binary *sbin, unsigned char byte) -{ - sieve_size_t address = _sieve_binary_get_code_size(sbin); - - _sieve_binary_emit_data(sbin, &byte, 1); - - return address; -} - -void sieve_binary_update_data -(struct sieve_binary *sbin, sieve_size_t address, const void *data, - sieve_size_t size) -{ - _sieve_binary_update_data(sbin, address, data, size); -} - -/* Offset emission functions */ - -sieve_size_t sieve_binary_emit_offset(struct sieve_binary *binary, int offset) -{ - int i; - sieve_size_t address = _sieve_binary_get_code_size(binary); - - for ( i = 3; i >= 0; i-- ) { - char c = (char) (offset >> (i * 8)); - _sieve_binary_emit_data(binary, &c, 1); - } - - return address; -} - -void sieve_binary_resolve_offset - (struct sieve_binary *binary, sieve_size_t address) -{ - int i; - int offset = _sieve_binary_get_code_size(binary) - address; - - for ( i = 3; i >= 0; i-- ) { - char c = (char) (offset >> (i * 8)); - _sieve_binary_update_data(binary, address + 3 - i, &c, 1); - } -} - -/* Literal emission */ - -/* FIXME: this integer format is compact, but it might be too slow. - */ - -sieve_size_t sieve_binary_emit_integer -(struct sieve_binary *binary, sieve_number_t integer) -{ - sieve_size_t address = _sieve_binary_get_code_size(binary); - int i; - char buffer[sizeof(sieve_number_t) + 1]; - int bufpos = sizeof(buffer) - 1; - - buffer[bufpos] = integer & 0x7F; - bufpos--; - integer >>= 7; - while ( integer > 0 ) { - buffer[bufpos] = integer & 0x7F; - bufpos--; - integer >>= 7; - } - - bufpos++; - if ( (sizeof(buffer) - bufpos) > 1 ) { - for ( i = bufpos; i < ((int) sizeof(buffer) - 1); i++) { - buffer[i] |= 0x80; - } - } - - _sieve_binary_emit_data(binary, buffer + bufpos, sizeof(buffer) - bufpos); - - return address; -} - -static inline sieve_size_t sieve_binary_emit_dynamic_data - (struct sieve_binary *binary, const void *data, sieve_size_t size) -{ - sieve_size_t address = sieve_binary_emit_integer(binary, (sieve_number_t) size); - - _sieve_binary_emit_data(binary, data, size); - - return address; -} - -sieve_size_t sieve_binary_emit_cstring - (struct sieve_binary *binary, const char *str) -{ - sieve_size_t address = sieve_binary_emit_dynamic_data - (binary, (void *) str, (sieve_size_t) strlen(str)); - _sieve_binary_emit_byte(binary, 0); - - return address; -} - -sieve_size_t sieve_binary_emit_string - (struct sieve_binary *binary, const string_t *str) -{ - sieve_size_t address = sieve_binary_emit_dynamic_data - (binary, (void *) str_data(str), (sieve_size_t) str_len(str)); - _sieve_binary_emit_byte(binary, 0); - - return address; -} - -/* - * Extension emission - */ - -sieve_size_t sieve_binary_emit_extension -(struct sieve_binary *sbin, const struct sieve_extension *ext, - unsigned int offset) -{ - sieve_size_t address = _sieve_binary_get_code_size(sbin); - struct sieve_binary_extension_reg *ereg = NULL; - - (void)sieve_binary_extension_register(sbin, ext, &ereg); - - i_assert(ereg != NULL); - - _sieve_binary_emit_byte(sbin, offset + ereg->index); - return address; -} - -void sieve_binary_emit_extension_object -(struct sieve_binary *sbin, const struct sieve_extension_objects *objs, - unsigned int code) -{ - if ( objs->count > 1 ) - _sieve_binary_emit_byte(sbin, code); -} - -/* - * Code retrieval - */ - -#define ADDR_CODE_AT(binary, address) \ - ((signed char) ((binary)->code[*address])) -#define ADDR_DATA_AT(binary, address) \ - ((unsigned char) ((binary)->code[*address])) -#define ADDR_POINTER(binary, address) \ - ((const char *) (&(binary)->code[*address])) -#define ADDR_BYTES_LEFT(binary, address) \ - ((binary)->code_size - (*address)) -#define ADDR_JUMP(address, offset) \ - (*address) += offset - -/* Literals */ - -bool sieve_binary_read_byte - (struct sieve_binary *binary, sieve_size_t *address, unsigned int *byte_r) -{ - if ( ADDR_BYTES_LEFT(binary, address) >= 1 ) { - if ( byte_r != NULL ) - *byte_r = ADDR_DATA_AT(binary, address); - ADDR_JUMP(address, 1); - - return TRUE; - } - - *byte_r = 0; - return FALSE; -} - -bool sieve_binary_read_code - (struct sieve_binary *binary, sieve_size_t *address, signed int *code_r) -{ - if ( ADDR_BYTES_LEFT(binary, address) >= 1 ) { - if ( code_r != NULL ) - *code_r = ADDR_CODE_AT(binary, address); - ADDR_JUMP(address, 1); - - return TRUE; - } - - *code_r = 0; - return FALSE; -} - - -bool sieve_binary_read_offset - (struct sieve_binary *binary, sieve_size_t *address, int *offset_r) -{ - uint32_t offs = 0; - - if ( ADDR_BYTES_LEFT(binary, address) >= 4 ) { - int i; - - for ( i = 0; i < 4; i++ ) { - offs = (offs << 8) + ADDR_DATA_AT(binary, address); - ADDR_JUMP(address, 1); - } - - if ( offset_r != NULL ) - *offset_r = (int) offs; - - return TRUE; - } - - return FALSE; -} - -/* FIXME: might need negative numbers in the future */ -bool sieve_binary_read_integer - (struct sieve_binary *binary, sieve_size_t *address, sieve_number_t *int_r) -{ - int bits = sizeof(sieve_number_t) * 8; - *int_r = 0; - - if ( ADDR_BYTES_LEFT(binary, address) == 0 ) - return FALSE; - - while ( (ADDR_DATA_AT(binary, address) & 0x80) > 0 ) { - if ( ADDR_BYTES_LEFT(binary, address) > 0 && bits > 0) { - *int_r |= ADDR_DATA_AT(binary, address) & 0x7F; - ADDR_JUMP(address, 1); - - *int_r <<= 7; - bits -= 7; - } else { - /* This is an error */ - return FALSE; - } - } - - *int_r |= ADDR_DATA_AT(binary, address) & 0x7F; - ADDR_JUMP(address, 1); - - return TRUE; -} - -bool sieve_binary_read_string -(struct sieve_binary *binary, sieve_size_t *address, string_t **str_r) -{ - unsigned int strlen = 0; - - if ( !sieve_binary_read_unsigned(binary, address, &strlen) ) - return FALSE; - - if ( strlen > ADDR_BYTES_LEFT(binary, address) ) - return FALSE; - - if ( str_r != NULL ) - *str_r = t_str_new_const(ADDR_POINTER(binary, address), strlen); - ADDR_JUMP(address, strlen); - - if ( ADDR_CODE_AT(binary, address) != 0 ) - return FALSE; - - ADDR_JUMP(address, 1); - - return TRUE; -} - -bool sieve_binary_read_extension -(struct sieve_binary *sbin, sieve_size_t *address, unsigned int *offset_r, - const struct sieve_extension **ext_r) -{ - unsigned int code; - unsigned int offset = *offset_r; - const struct sieve_extension *ext = NULL; - - if ( ADDR_BYTES_LEFT(sbin, address) <= 0 ) - return FALSE; - - (*offset_r) = code = ADDR_DATA_AT(sbin, address); - ADDR_JUMP(address, 1); - - if ( code >= offset ) { - ext = _sieve_binary_extension_get_by_index(sbin, code - offset); - - if ( ext == NULL ) - return FALSE; - } - - (*ext_r) = ext; - - return TRUE; -} - -const void *sieve_binary_read_extension_object -(struct sieve_binary *sbin, sieve_size_t *address, - const struct sieve_extension_objects *objs) -{ - unsigned int code; - - if ( objs->count == 0 ) - return NULL; - - if ( objs->count == 1 ) - return objs->objects; - - if ( ADDR_BYTES_LEFT(sbin, address) <= 0 ) - return NULL; - - code = ADDR_DATA_AT(sbin, address); - ADDR_JUMP(address, 1); - - if ( code >= objs->count ) - return NULL; - - return ((const void *const *) objs->objects)[code]; -} diff --git a/src/lib-sieve/sieve-binary.h b/src/lib-sieve/sieve-binary.h index a30cf2932..877799c39 100644 --- a/src/lib-sieve/sieve-binary.h +++ b/src/lib-sieve/sieve-binary.h @@ -8,6 +8,13 @@ #include "sieve-common.h" +/* + * Config + */ + +#define SIEVE_BINARY_VERSION_MAJOR 0 +#define SIEVE_BINARY_VERSION_MINOR 2 + /* * Binary object */ @@ -65,12 +72,27 @@ enum sieve_binary_system_block { SBIN_SYSBLOCK_LAST }; -bool sieve_binary_block_set_active - (struct sieve_binary *sbin, unsigned int id, unsigned *old_id_r); -unsigned int sieve_binary_block_create(struct sieve_binary *sbin); -void sieve_binary_block_clear +struct sieve_binary_block *sieve_binary_block_create + (struct sieve_binary *sbin); + +unsigned int sieve_binary_block_count + (struct sieve_binary *sbin); + +struct sieve_binary_block *sieve_binary_block_get (struct sieve_binary *sbin, unsigned int id); - + +void sieve_binary_block_clear + (struct sieve_binary_block *sblock); + +size_t sieve_binary_block_get_size + (const struct sieve_binary_block *sblock); + +struct sieve_binary *sieve_binary_block_get_binary + (const struct sieve_binary_block *sblock); + +unsigned int sieve_binary_block_get_id + (const struct sieve_binary_block *sblock); + /* * Extension support */ @@ -103,9 +125,9 @@ void sieve_binary_extension_set (struct sieve_binary *sbin, const struct sieve_extension *ext, const struct sieve_binary_extension *bext, void *context); -unsigned int sieve_binary_extension_create_block +struct sieve_binary_block *sieve_binary_extension_create_block (struct sieve_binary *sbin, const struct sieve_extension *ext); -unsigned int sieve_binary_extension_get_block +struct sieve_binary_block *sieve_binary_extension_get_block (struct sieve_binary *sbin, const struct sieve_extension *ext); int sieve_binary_extension_link @@ -124,68 +146,73 @@ int sieve_binary_extensions_count(struct sieve_binary *sbin); /* Low-level emission functions */ sieve_size_t sieve_binary_emit_data - (struct sieve_binary *binary, const void *data, sieve_size_t size); + (struct sieve_binary_block *sblock, const void *data, sieve_size_t size); sieve_size_t sieve_binary_emit_byte - (struct sieve_binary *binary, unsigned char byte); + (struct sieve_binary_block *sblock, unsigned char byte); void sieve_binary_update_data - (struct sieve_binary *binary, sieve_size_t address, const void *data, + (struct sieve_binary_block *sblock, sieve_size_t address, const void *data, sieve_size_t size); -sieve_size_t sieve_binary_get_code_size(struct sieve_binary *binary); /* Offset emission functions */ sieve_size_t sieve_binary_emit_offset - (struct sieve_binary *binary, int offset); + (struct sieve_binary_block *sblock, int offset); void sieve_binary_resolve_offset - (struct sieve_binary *binary, sieve_size_t address); + (struct sieve_binary_block *sblock, sieve_size_t address); /* Literal emission functions */ sieve_size_t sieve_binary_emit_integer - (struct sieve_binary *binary, sieve_number_t integer); + (struct sieve_binary_block *sblock, sieve_number_t integer); sieve_size_t sieve_binary_emit_string - (struct sieve_binary *binary, const string_t *str); + (struct sieve_binary_block *sblock, const string_t *str); sieve_size_t sieve_binary_emit_cstring - (struct sieve_binary *binary, const char *str); + (struct sieve_binary_block *sblock, const char *str); static inline sieve_size_t sieve_binary_emit_unsigned - (struct sieve_binary *binary, unsigned int count) + (struct sieve_binary_block *sblock, unsigned int count) { - return sieve_binary_emit_integer(binary, count); + return sieve_binary_emit_integer(sblock, count); } - /* Extension emission functions */ sieve_size_t sieve_binary_emit_extension - (struct sieve_binary *sbin, const struct sieve_extension *ext, + (struct sieve_binary_block *sblock, const struct sieve_extension *ext, unsigned int offset); void sieve_binary_emit_extension_object - (struct sieve_binary *sbin, const struct sieve_extension_objects *objs, - unsigned int code); + (struct sieve_binary_block *sblock, + const struct sieve_extension_objects *objs, unsigned int code); /* * Code retrieval */ /* Literals */ + bool sieve_binary_read_byte - (struct sieve_binary *binary, sieve_size_t *address, unsigned int *byte_r); + (struct sieve_binary_block *sblock, sieve_size_t *address, + unsigned int *byte_r); bool sieve_binary_read_code - (struct sieve_binary *binary, sieve_size_t *address, signed int *code_r); + (struct sieve_binary_block *sblock, sieve_size_t *address, + signed int *code_r); bool sieve_binary_read_offset - (struct sieve_binary *binary, sieve_size_t *address, int *offset_r); + (struct sieve_binary_block *sblock, sieve_size_t *address, + int *offset_r); bool sieve_binary_read_integer - (struct sieve_binary *binary, sieve_size_t *address, sieve_number_t *int_r); + (struct sieve_binary_block *sblock, sieve_size_t *address, + sieve_number_t *int_r); bool sieve_binary_read_string - (struct sieve_binary *binary, sieve_size_t *address, string_t **str_r); + (struct sieve_binary_block *sblock, sieve_size_t *address, + string_t **str_r); static inline bool sieve_binary_read_unsigned - (struct sieve_binary *binary, sieve_size_t *address, unsigned int *count_r) +(struct sieve_binary_block *sblock, sieve_size_t *address, + unsigned int *count_r) { sieve_number_t integer; - if ( !sieve_binary_read_integer(binary, address, &integer) ) + if ( !sieve_binary_read_integer(sblock, address, &integer) ) return FALSE; *count_r = integer; @@ -193,12 +220,44 @@ static inline bool sieve_binary_read_unsigned return TRUE; } -/* Extension */ +/* Extensions */ + bool sieve_binary_read_extension - (struct sieve_binary *sbin, sieve_size_t *address, unsigned int *offset_r, - const struct sieve_extension **ext_r); + (struct sieve_binary_block *sblock, sieve_size_t *address, + unsigned int *offset_r, const struct sieve_extension **ext_r); const void *sieve_binary_read_extension_object - (struct sieve_binary *binary, sieve_size_t *address, - const struct sieve_extension_objects *objs); + (struct sieve_binary_block *sblock, sieve_size_t *address, + const struct sieve_extension_objects *objs); + +/* + * Debug info + */ + +/* Writer */ + +struct sieve_binary_debug_writer; + +struct sieve_binary_debug_writer *sieve_binary_debug_writer_init + (struct sieve_binary_block *sblock); +void sieve_binary_debug_writer_deinit + (struct sieve_binary_debug_writer **dwriter); + +void sieve_binary_debug_emit + (struct sieve_binary_debug_writer *dwriter, sieve_size_t code_address, + unsigned int code_line, unsigned int code_column); + +/* Reader */ + +struct sieve_binary_debug_reader *sieve_binary_debug_reader_init + (struct sieve_binary_block *sblock); +void sieve_binary_debug_reader_deinit + (struct sieve_binary_debug_reader **dreader); + + +void sieve_binary_debug_reader_reset + (struct sieve_binary_debug_reader *dreader); + +unsigned int sieve_binary_debug_read_line + (struct sieve_binary_debug_reader *dreader, sieve_size_t code_address); #endif diff --git a/src/lib-sieve/sieve-code-dumper.c b/src/lib-sieve/sieve-code-dumper.c index 872cfd432..1c224c13c 100644 --- a/src/lib-sieve/sieve-code-dumper.c +++ b/src/lib-sieve/sieve-code-dumper.c @@ -39,16 +39,20 @@ struct sieve_code_dumper { const struct sieve_operation *operation; sieve_size_t mark_address; + unsigned int mark_line; + unsigned int mark_last_line; unsigned int indent; /* Dump environment */ struct sieve_dumptime_env *dumpenv; + + struct sieve_binary_debug_reader *dreader; ARRAY_DEFINE(extensions, struct sieve_code_dumper_extension_reg); }; struct sieve_code_dumper *sieve_code_dumper_create - (struct sieve_dumptime_env *denv) +(struct sieve_dumptime_env *denv) { pool_t pool; struct sieve_code_dumper *dumper; @@ -67,9 +71,10 @@ struct sieve_code_dumper *sieve_code_dumper_create } void sieve_code_dumper_free(struct sieve_code_dumper **dumper) -{ +{ + sieve_binary_debug_reader_deinit(&(*dumper)->dreader); + pool_unref(&((*dumper)->pool)); - *dumper = NULL; } @@ -133,6 +138,14 @@ void sieve_code_dumpf va_start(args, fmt); str_printfa(outbuf, "%08llx: ", (unsigned long long) cdumper->mark_address); + if ( cdumper->mark_line > 0 && (cdumper->indent == 0 || + cdumper->mark_line != cdumper->mark_last_line) ) { + str_printfa(outbuf, "%4u: ", cdumper->mark_line); + cdumper->mark_last_line = cdumper->mark_line; + } else { + str_append(outbuf, " "); + } + while ( tab > 0 ) { str_append(outbuf, " "); tab--; @@ -145,15 +158,26 @@ void sieve_code_dumpf o_stream_send(denv->stream, str_data(outbuf), str_len(outbuf)); } +static inline void sieve_code_line_mark +(const struct sieve_dumptime_env *denv, sieve_size_t location) +{ + if ( denv->cdumper->dreader != NULL ) { + denv->cdumper->mark_line = sieve_binary_debug_read_line + (denv->cdumper->dreader, location); + } +} + void sieve_code_mark(const struct sieve_dumptime_env *denv) { denv->cdumper->mark_address = denv->cdumper->pc; + sieve_code_line_mark(denv, denv->cdumper->pc); } void sieve_code_mark_specific (const struct sieve_dumptime_env *denv, sieve_size_t location) { denv->cdumper->mark_address = location; + sieve_code_line_mark(denv, location); } void sieve_code_descend(const struct sieve_dumptime_env *denv) @@ -174,10 +198,10 @@ bool sieve_code_dumper_print_optional_operands { int opt_code = -1; - if ( sieve_operand_optional_present(denv->sbin, address) ) { + if ( sieve_operand_optional_present(denv->sblock, address) ) { while ( opt_code != 0 ) { - if ( !sieve_operand_optional_read(denv->sbin, address, &opt_code) ) { + if ( !sieve_operand_optional_read(denv->sblock, address, &opt_code) ) { return FALSE; } @@ -203,8 +227,10 @@ static bool sieve_code_dumper_print_operation dumper->indent = 0; address = dumper->mark_address = dumper->pc; + sieve_code_line_mark(denv, address); + /* Read operation */ - if ( sieve_operation_read(denv->sbin, &(dumper->pc), oprtn) ) { + if ( sieve_operation_read(denv->sblock, &(dumper->pc), oprtn) ) { const struct sieve_operation_def *op = oprtn->def; if ( op->dump != NULL ) @@ -225,15 +251,41 @@ void sieve_code_dumper_run(struct sieve_code_dumper *dumper) { const struct sieve_dumptime_env *denv = dumper->dumpenv; struct sieve_binary *sbin = denv->sbin; - unsigned int ext_count; + struct sieve_binary_block *sblock = denv->sblock; + unsigned int debug_block_id, ext_count; bool success = TRUE; dumper->pc = 0; + + /* Heading */ + o_stream_send_str(denv->stream, "Address Line Code\n"); + + /* Load debug block */ + sieve_code_mark(denv); + if ( sieve_binary_read_unsigned(sblock, &dumper->pc, &debug_block_id) ) { + struct sieve_binary_block *debug_block = + sieve_binary_block_get(sbin, debug_block_id); + + if ( debug_block == NULL ) { + sieve_code_dumpf(denv, "Invalid id %d for debug block.", debug_block_id); + return; + } else { + /* Initialize debug reader */ + dumper->dreader = sieve_binary_debug_reader_init(debug_block); + + /* Dump block id */ + sieve_code_dumpf(denv, "DEBUG BLOCK: %d", debug_block_id); + } + } else { + sieve_code_dumpf(denv, "Binary code header is corrupt."); + return; + } + /* Load and dump extensions listed in code */ sieve_code_mark(denv); - if ( sieve_binary_read_unsigned(sbin, &dumper->pc, &ext_count) ) { + if ( sieve_binary_read_unsigned(sblock, &dumper->pc, &ext_count) ) { unsigned int i; sieve_code_dumpf(denv, "EXTENSIONS [%d]:", ext_count); @@ -246,7 +298,7 @@ void sieve_code_dumper_run(struct sieve_code_dumper *dumper) T_BEGIN { sieve_code_mark(denv); - if ( !sieve_binary_read_extension(sbin, &dumper->pc, &code, &ext) ) { + if ( !sieve_binary_read_extension(sblock, &dumper->pc, &code, &ext) ) { success = FALSE; break; } @@ -274,7 +326,7 @@ void sieve_code_dumper_run(struct sieve_code_dumper *dumper) } while ( dumper->pc < - sieve_binary_get_code_size(sbin) ) { + sieve_binary_block_get_size(sblock) ) { T_BEGIN { success = sieve_code_dumper_print_operation(dumper); @@ -288,6 +340,6 @@ void sieve_code_dumper_run(struct sieve_code_dumper *dumper) /* Mark end of the binary */ dumper->indent = 0; - dumper->mark_address = sieve_binary_get_code_size(sbin); + dumper->mark_address = sieve_binary_block_get_size(sblock); sieve_code_dumpf(dumper->dumpenv, "[End of code]"); } diff --git a/src/lib-sieve/sieve-code.c b/src/lib-sieve/sieve-code.c index 5ccd5f43c..ea93fbd1a 100644 --- a/src/lib-sieve/sieve-code.c +++ b/src/lib-sieve/sieve-code.c @@ -37,7 +37,7 @@ static struct sieve_coded_stringlist *sieve_coded_stringlist_create { struct sieve_coded_stringlist *strlist; - if ( end > sieve_binary_get_code_size(renv->sbin) ) + if ( end > sieve_binary_block_get_size(renv->sblock) ) return NULL; strlist = t_new(struct sieve_coded_stringlist, 1); @@ -128,7 +128,7 @@ static bool sieve_coded_stringlist_dump { unsigned int i; - if ( end > sieve_binary_get_code_size(denv->sbin) ) + if ( end > sieve_binary_block_get_size(denv->sblock) ) return FALSE; if ( field_name != NULL ) @@ -163,31 +163,31 @@ static bool sieve_coded_stringlist_dump */ void sieve_code_source_line_emit -(struct sieve_binary *sbin, unsigned int source_line) +(struct sieve_binary_block *sblock, unsigned int source_line) { - (void)sieve_binary_emit_unsigned(sbin, source_line); + (void)sieve_binary_emit_unsigned(sblock, source_line); } bool sieve_code_source_line_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address) { - unsigned int number = 0; + unsigned int number = 0; sieve_code_mark(denv); - if (sieve_binary_read_unsigned(denv->sbin, address, &number) ) { - sieve_code_dumpf(denv, "(source line: %lu)", (unsigned long) number); + if (sieve_binary_read_unsigned(denv->sblock, address, &number) ) { + sieve_code_dumpf(denv, "(source line: %lu)", (unsigned long) number); - return TRUE; - } + return TRUE; + } - return FALSE; + return FALSE; } bool sieve_code_source_line_read (const struct sieve_runtime_env *renv, sieve_size_t *address, unsigned int *source_line_r) { - return sieve_binary_read_unsigned(renv->sbin, address, source_line_r); + return sieve_binary_read_unsigned(renv->sblock, address, source_line_r); } /* @@ -217,26 +217,26 @@ const unsigned int sieve_operand_count = */ sieve_size_t sieve_operand_emit -(struct sieve_binary *sbin, const struct sieve_extension *ext, +(struct sieve_binary_block *sblock, const struct sieve_extension *ext, const struct sieve_operand_def *opr_def) { sieve_size_t address; if ( ext != NULL ) { address = sieve_binary_emit_extension - (sbin, ext, sieve_operand_count); + (sblock, ext, sieve_operand_count); sieve_binary_emit_extension_object - (sbin, &opr_def->ext_def->operands, opr_def->code); + (sblock, &opr_def->ext_def->operands, opr_def->code); return address; } - return sieve_binary_emit_byte(sbin, opr_def->code); + return sieve_binary_emit_byte(sblock, opr_def->code); } bool sieve_operand_read -(struct sieve_binary *sbin, sieve_size_t *address, +(struct sieve_binary_block *sblock, sieve_size_t *address, struct sieve_operand *operand) { unsigned int code = sieve_operand_count; @@ -245,7 +245,7 @@ bool sieve_operand_read operand->ext = NULL; operand->def = NULL; - if ( !sieve_binary_read_extension(sbin, address, &code, &operand->ext) ) + if ( !sieve_binary_read_extension(sblock, address, &code, &operand->ext) ) return NULL; if ( operand->ext == NULL ) { @@ -259,19 +259,19 @@ bool sieve_operand_read return FALSE; operand->def = (const struct sieve_operand_def *) - sieve_binary_read_extension_object(sbin, address, + sieve_binary_read_extension_object(sblock, address, &operand->ext->def->operands); return ( operand->def != NULL ); } bool sieve_operand_optional_present -(struct sieve_binary *sbin, sieve_size_t *address) +(struct sieve_binary_block *sblock, sieve_size_t *address) { sieve_size_t tmp_addr = *address; unsigned int op = -1; - if ( sieve_binary_read_byte(sbin, &tmp_addr, &op) && + if ( sieve_binary_read_byte(sblock, &tmp_addr, &op) && (op == SIEVE_OPERAND_OPTIONAL) ) { *address = tmp_addr; return TRUE; @@ -281,9 +281,9 @@ bool sieve_operand_optional_present } bool sieve_operand_optional_read -(struct sieve_binary *sbin, sieve_size_t *address, signed int *id_code) +(struct sieve_binary_block *sblock, sieve_size_t *address, signed int *id_code) { - if ( sieve_binary_read_code(sbin, address, id_code) ) + if ( sieve_binary_read_code(sblock, address, id_code) ) return TRUE; *id_code = 0; @@ -404,17 +404,18 @@ const struct sieve_operand_def catenated_string_operand = { /* Omitted */ -void sieve_opr_omitted_emit(struct sieve_binary *sbin) +void sieve_opr_omitted_emit(struct sieve_binary_block *sblock) { - (void) sieve_operand_emit(sbin, NULL, &omitted_operand); + (void) sieve_operand_emit(sblock, NULL, &omitted_operand); } /* Number */ -void sieve_opr_number_emit(struct sieve_binary *sbin, sieve_number_t number) +void sieve_opr_number_emit +(struct sieve_binary_block *sblock, sieve_number_t number) { - (void) sieve_operand_emit(sbin, NULL, &number_operand); - (void) sieve_binary_emit_integer(sbin, number); + (void) sieve_operand_emit(sblock, NULL, &number_operand); + (void) sieve_binary_emit_integer(sblock, number); } bool sieve_opr_number_dump_data @@ -442,7 +443,7 @@ bool sieve_opr_number_dump sieve_code_mark(denv); - if ( !sieve_operand_read(denv->sbin, address, &operand) ) + if ( !sieve_operand_read(denv->sblock, address, &operand) ) return FALSE; return sieve_opr_number_dump_data(denv, &operand, address, field_name); @@ -471,7 +472,7 @@ bool sieve_opr_number_read { struct sieve_operand operand; - if ( !sieve_operand_read(renv->sbin, address, &operand) ) + if ( !sieve_operand_read(renv->sblock, address, &operand) ) return FALSE; return sieve_opr_number_read_data(renv, &operand, address, number_r); @@ -483,7 +484,7 @@ static bool opr_number_dump { sieve_number_t number = 0; - if (sieve_binary_read_integer(denv->sbin, address, &number) ) { + if (sieve_binary_read_integer(denv->sblock, address, &number) ) { if ( field_name != NULL ) sieve_code_dumpf(denv, "%s: NUM %llu", field_name, (unsigned long long) number); @@ -500,15 +501,15 @@ static bool opr_number_read (const struct sieve_runtime_env *renv, sieve_size_t *address, sieve_number_t *number_r) { - return sieve_binary_read_integer(renv->sbin, address, number_r); + return sieve_binary_read_integer(renv->sblock, address, number_r); } /* String */ -void sieve_opr_string_emit(struct sieve_binary *sbin, string_t *str) +void sieve_opr_string_emit(struct sieve_binary_block *sblock, string_t *str) { - (void) sieve_operand_emit(sbin, NULL, &string_operand); - (void) sieve_binary_emit_string(sbin, str); + (void) sieve_operand_emit(sblock, NULL, &string_operand); + (void) sieve_binary_emit_string(sblock, str); } bool sieve_opr_string_dump_data @@ -541,7 +542,7 @@ bool sieve_opr_string_dump sieve_code_mark(denv); - if ( !sieve_operand_read(denv->sbin, address, &operand) ) { + if ( !sieve_operand_read(denv->sblock, address, &operand) ) { sieve_code_dumpf(denv, "ERROR: INVALID OPERAND"); return FALSE; } @@ -556,7 +557,7 @@ bool sieve_opr_string_dump_ex struct sieve_operand operand; sieve_code_mark(denv); - if ( !sieve_operand_read(denv->sbin, address, &operand) ) { + if ( !sieve_operand_read(denv->sblock, address, &operand) ) { sieve_code_dumpf(denv, "ERROR: INVALID OPERAND"); return FALSE; } @@ -588,7 +589,7 @@ bool sieve_opr_string_read { struct sieve_operand operand; - if ( !sieve_operand_read(renv->sbin, address, &operand) ) { + if ( !sieve_operand_read(renv->sblock, address, &operand) ) { return FALSE; } @@ -601,7 +602,7 @@ bool sieve_opr_string_read_ex { struct sieve_operand operand; - if ( !sieve_operand_read(renv->sbin, address, &operand) ) { + if ( !sieve_operand_read(renv->sblock, address, &operand) ) { return FALSE; } @@ -638,7 +639,7 @@ bool opr_string_dump { string_t *str; - if ( sieve_binary_read_string(denv->sbin, address, &str) ) { + if ( sieve_binary_read_string(denv->sblock, address, &str) ) { _dump_string(denv, str, field_name); return TRUE; @@ -652,39 +653,39 @@ static bool opr_string_read const struct sieve_operand *opr ATTR_UNUSED, sieve_size_t *address, string_t **str_r) { - return sieve_binary_read_string(renv->sbin, address, str_r); + return sieve_binary_read_string(renv->sblock, address, str_r); } /* String list */ void sieve_opr_stringlist_emit_start -(struct sieve_binary *sbin, unsigned int listlen, void **context) +(struct sieve_binary_block *sblock, unsigned int listlen, void **context) { sieve_size_t *end_offset = t_new(sieve_size_t, 1); /* Emit byte identifying the type of operand */ - (void) sieve_operand_emit(sbin, NULL, &stringlist_operand); + (void) sieve_operand_emit(sblock, NULL, &stringlist_operand); /* Give the interpreter an easy way to skip over this string list */ - *end_offset = sieve_binary_emit_offset(sbin, 0); + *end_offset = sieve_binary_emit_offset(sblock, 0); *context = (void *) end_offset; /* Emit the length of the list */ - (void) sieve_binary_emit_unsigned(sbin, listlen); + (void) sieve_binary_emit_unsigned(sblock, listlen); } void sieve_opr_stringlist_emit_item -(struct sieve_binary *sbin, void *context ATTR_UNUSED, string_t *item) +(struct sieve_binary_block *sblock, void *context ATTR_UNUSED, string_t *item) { - (void) sieve_opr_string_emit(sbin, item); + (void) sieve_opr_string_emit(sblock, item); } void sieve_opr_stringlist_emit_end -(struct sieve_binary *sbin, void *context) +(struct sieve_binary_block *sblock, void *context) { sieve_size_t *end_offset = (sieve_size_t *) context; - (void) sieve_binary_resolve_offset(sbin, *end_offset); + (void) sieve_binary_resolve_offset(sblock, *end_offset); } bool sieve_opr_stringlist_dump_data @@ -723,7 +724,7 @@ bool sieve_opr_stringlist_dump sieve_code_mark(denv); - if ( !sieve_operand_read(denv->sbin, address, &operand) ) { + if ( !sieve_operand_read(denv->sblock, address, &operand) ) { return FALSE; } @@ -765,7 +766,7 @@ struct sieve_coded_stringlist *sieve_opr_stringlist_read { struct sieve_operand operand; - if ( !sieve_operand_read(renv->sbin, address, &operand) ) { + if ( !sieve_operand_read(renv->sblock, address, &operand) ) { return NULL; } @@ -781,12 +782,12 @@ static bool opr_stringlist_dump unsigned int length = 0; int end_offset; - if ( !sieve_binary_read_offset(denv->sbin, address, &end_offset) ) + if ( !sieve_binary_read_offset(denv->sblock, address, &end_offset) ) return FALSE; end = pc + end_offset; - if ( !sieve_binary_read_unsigned(denv->sbin, address, &length) ) + if ( !sieve_binary_read_unsigned(denv->sblock, address, &length) ) return FALSE; return sieve_coded_stringlist_dump(denv, address, length, end, field_name); @@ -801,12 +802,12 @@ static struct sieve_coded_stringlist *opr_stringlist_read unsigned int length = 0; int end_offset; - if ( !sieve_binary_read_offset(renv->sbin, address, &end_offset) ) + if ( !sieve_binary_read_offset(renv->sblock, address, &end_offset) ) return NULL; end = pc + end_offset; - if ( !sieve_binary_read_unsigned(renv->sbin, address, &length) ) + if ( !sieve_binary_read_unsigned(renv->sblock, address, &length) ) return NULL; strlist = sieve_coded_stringlist_create(renv, *address, (unsigned int) length, end); @@ -820,10 +821,10 @@ static struct sieve_coded_stringlist *opr_stringlist_read /* Catenated String */ void sieve_opr_catenated_string_emit -(struct sieve_binary *sbin, unsigned int elements) +(struct sieve_binary_block *sblock, unsigned int elements) { - (void) sieve_operand_emit(sbin, NULL, &catenated_string_operand); - (void) sieve_binary_emit_unsigned(sbin, elements); + (void) sieve_operand_emit(sblock, NULL, &catenated_string_operand); + (void) sieve_binary_emit_unsigned(sblock, elements); } static bool opr_catenated_string_dump @@ -834,7 +835,7 @@ static bool opr_catenated_string_dump unsigned int elements = 0; unsigned int i; - if (!sieve_binary_read_unsigned(denv->sbin, address, &elements) ) + if (!sieve_binary_read_unsigned(denv->sblock, address, &elements) ) return FALSE; if ( field_name != NULL ) @@ -861,7 +862,7 @@ static bool opr_catenated_string_read unsigned int elements = 0; unsigned int i; - if ( !sieve_binary_read_unsigned(renv->sbin, address, &elements) ) + if ( !sieve_binary_read_unsigned(renv->sblock, address, &elements) ) return FALSE; /* Parameter str can be NULL if we are requested to only skip and not @@ -978,26 +979,26 @@ const unsigned int sieve_operation_count = */ sieve_size_t sieve_operation_emit -(struct sieve_binary *sbin, const struct sieve_extension *ext, +(struct sieve_binary_block *sblock, const struct sieve_extension *ext, const struct sieve_operation_def *op_def) { sieve_size_t address; if ( ext != NULL ) { address = sieve_binary_emit_extension - (sbin, ext, sieve_operation_count); + (sblock, ext, sieve_operation_count); sieve_binary_emit_extension_object - (sbin, &op_def->ext_def->operations, op_def->code); + (sblock, &op_def->ext_def->operations, op_def->code); return address; } - return sieve_binary_emit_byte(sbin, op_def->code); + return sieve_binary_emit_byte(sblock, op_def->code); } bool sieve_operation_read -(struct sieve_binary *sbin, sieve_size_t *address, +(struct sieve_binary_block *sblock, sieve_size_t *address, struct sieve_operation *oprtn) { unsigned int code = sieve_operation_count; @@ -1006,7 +1007,7 @@ bool sieve_operation_read oprtn->def = NULL; oprtn->ext = NULL; - if ( !sieve_binary_read_extension(sbin, address, &code, &oprtn->ext) ) + if ( !sieve_binary_read_extension(sblock, address, &code, &oprtn->ext) ) return FALSE; if ( !oprtn->ext ) { @@ -1018,7 +1019,7 @@ bool sieve_operation_read } oprtn->def = (const struct sieve_operation_def *) - sieve_binary_read_extension_object(sbin, address, + sieve_binary_read_extension_object(sblock, address, &oprtn->ext->def->operations); return ( oprtn->def != NULL ); @@ -1037,7 +1038,7 @@ static bool opc_jmp_dump unsigned int pc = *address; int offset; - if ( sieve_binary_read_offset(denv->sbin, address, &offset) ) + if ( sieve_binary_read_offset(denv->sblock, address, &offset) ) sieve_code_dumpf(denv, "%s %d [%08x]", sieve_operation_mnemonic(op), offset, pc + offset); else diff --git a/src/lib-sieve/sieve-code.h b/src/lib-sieve/sieve-code.h index 83b4dabff..46963cea5 100644 --- a/src/lib-sieve/sieve-code.h +++ b/src/lib-sieve/sieve-code.h @@ -37,7 +37,7 @@ sieve_size_t sieve_coded_stringlist_get_current_offset */ void sieve_code_source_line_emit - (struct sieve_binary *sbin, unsigned int source_line); + (struct sieve_binary_block *sblock, unsigned int source_line); bool sieve_code_source_line_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address); bool sieve_code_source_line_read @@ -74,16 +74,16 @@ struct sieve_operand { ( (opr)->def == &(definition) ) sieve_size_t sieve_operand_emit - (struct sieve_binary *sbin, const struct sieve_extension *ext, + (struct sieve_binary_block *sblock, const struct sieve_extension *ext, const struct sieve_operand_def *oprnd); bool sieve_operand_read - (struct sieve_binary *sbin, sieve_size_t *address, + (struct sieve_binary_block *sblock, sieve_size_t *address, struct sieve_operand *oprnd); bool sieve_operand_optional_present - (struct sieve_binary *sbin, sieve_size_t *address); + (struct sieve_binary_block *sblock, sieve_size_t *address); bool sieve_operand_optional_read - (struct sieve_binary *sbin, sieve_size_t *address, + (struct sieve_binary_block *sblock, sieve_size_t *address, signed int *id_code); /* @@ -156,7 +156,7 @@ struct sieve_opr_stringlist_interface { /* Omitted */ -void sieve_opr_omitted_emit(struct sieve_binary *sbin); +void sieve_opr_omitted_emit(struct sieve_binary_block *sblock); static inline bool sieve_operand_is_omitted (const struct sieve_operand *operand) @@ -167,7 +167,8 @@ static inline bool sieve_operand_is_omitted /* Number */ -void sieve_opr_number_emit(struct sieve_binary *sbin, sieve_number_t number); +void sieve_opr_number_emit + (struct sieve_binary_block *sblock, sieve_number_t number); bool sieve_opr_number_dump_data (const struct sieve_dumptime_env *denv, const struct sieve_operand *operand, sieve_size_t *address, const char *field_name); @@ -190,7 +191,8 @@ static inline bool sieve_operand_is_number /* String */ -void sieve_opr_string_emit(struct sieve_binary *sbin, string_t *str); +void sieve_opr_string_emit + (struct sieve_binary_block *sblock, string_t *str); bool sieve_opr_string_dump_data (const struct sieve_dumptime_env *denv, const struct sieve_operand *operand, sieve_size_t *address, const char *field_name); @@ -219,11 +221,12 @@ static inline bool sieve_operand_is_string /* String list */ void sieve_opr_stringlist_emit_start - (struct sieve_binary *sbin, unsigned int listlen, void **context); + (struct sieve_binary_block *sblock, unsigned int listlen, void **context); void sieve_opr_stringlist_emit_item - (struct sieve_binary *sbin, void *context ATTR_UNUSED, string_t *item); + (struct sieve_binary_block *sblock, void *context ATTR_UNUSED, + string_t *item); void sieve_opr_stringlist_emit_end - (struct sieve_binary *sbin, void *context); + (struct sieve_binary_block *sblock, void *context); bool sieve_opr_stringlist_dump_data (const struct sieve_dumptime_env *denv, const struct sieve_operand *operand, sieve_size_t *address, const char *field_name); @@ -247,7 +250,7 @@ static inline bool sieve_operand_is_stringlist /* Catenated string */ void sieve_opr_catenated_string_emit - (struct sieve_binary *sbin, unsigned int elements); + (struct sieve_binary_block *sblock, unsigned int elements); /* * Operation object @@ -278,13 +281,13 @@ struct sieve_operation { ( (oprtn)->def == NULL ? "(NULL)" : (oprtn)->def->mnemonic ) sieve_size_t sieve_operation_emit - (struct sieve_binary *sbin, const struct sieve_extension *ext, + (struct sieve_binary_block *sblock, const struct sieve_extension *ext, const struct sieve_operation_def *op_def); bool sieve_operation_read - (struct sieve_binary *sbin, sieve_size_t *address, + (struct sieve_binary_block *sblock, sieve_size_t *address, struct sieve_operation *oprtn); const char *sieve_operation_read_string - (struct sieve_binary *sbin, sieve_size_t *address); + (struct sieve_binary_block *sblock, sieve_size_t *address); /* * Core operations diff --git a/src/lib-sieve/sieve-commands.c b/src/lib-sieve/sieve-commands.c index 705483ede..5245ee2de 100644 --- a/src/lib-sieve/sieve-commands.c +++ b/src/lib-sieve/sieve-commands.c @@ -63,7 +63,7 @@ static bool arg_number_generate (const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, struct sieve_command *cmd ATTR_UNUSED) { - sieve_opr_number_emit(cgenv->sbin, sieve_ast_argument_number(arg)); + sieve_opr_number_emit(cgenv->sblock, sieve_ast_argument_number(arg)); return TRUE; } @@ -72,7 +72,7 @@ static bool arg_string_generate (const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, struct sieve_command *cmd ATTR_UNUSED) { - sieve_opr_string_emit(cgenv->sbin, sieve_ast_argument_str(arg)); + sieve_opr_string_emit(cgenv->sblock, sieve_ast_argument_str(arg)); return TRUE; } @@ -102,7 +102,7 @@ static bool emit_string_list_operand struct sieve_ast_argument *stritem; sieve_opr_stringlist_emit_start - (cgenv->sbin, sieve_ast_strlist_count(strlist), &list_context); + (cgenv->sblock, sieve_ast_strlist_count(strlist), &list_context); stritem = sieve_ast_strlist_first(strlist); while ( stritem != NULL ) { @@ -112,7 +112,7 @@ static bool emit_string_list_operand stritem = sieve_ast_strlist_next(stritem); } - sieve_opr_stringlist_emit_end(cgenv->sbin, list_context); + sieve_opr_stringlist_emit_end(cgenv->sblock, list_context); return TRUE; } @@ -185,7 +185,6 @@ bool sieve_arg_catenated_string_generate (const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, struct sieve_command *cmd) { - struct sieve_binary *sbin = cgenv->sbin; struct sieve_arg_catenated_string *catstr = (struct sieve_arg_catenated_string *) arg->argument->data; struct sieve_ast_argument *strpart; @@ -193,7 +192,7 @@ bool sieve_arg_catenated_string_generate if ( _cat_string_count(catstr) == 1 ) sieve_generate_argument(cgenv, _cat_string_first(catstr), cmd); else { - sieve_opr_catenated_string_emit(sbin, _cat_string_count(catstr)); + sieve_opr_catenated_string_emit(cgenv->sblock, _cat_string_count(catstr)); strpart = _cat_string_first(catstr); while ( strpart != NULL ) { diff --git a/src/lib-sieve/sieve-common.h b/src/lib-sieve/sieve-common.h index 28b601541..d037b165a 100644 --- a/src/lib-sieve/sieve-common.h +++ b/src/lib-sieve/sieve-common.h @@ -86,6 +86,9 @@ struct sieve_coded_stringlist; /* sieve-binary.h */ struct sieve_binary; +struct sieve_binary_block; +struct sieve_binary_debug_writer; +struct sieve_binary_debug_reader; /* sieve-objects.h */ struct sieve_object_def; diff --git a/src/lib-sieve/sieve-comparators.c b/src/lib-sieve/sieve-comparators.c index 6b175ffdb..81dca88e4 100644 --- a/src/lib-sieve/sieve-comparators.c +++ b/src/lib-sieve/sieve-comparators.c @@ -193,7 +193,7 @@ static bool tag_comparator_generate const struct sieve_comparator *cmp = (const struct sieve_comparator *) arg->argument->data; - sieve_opr_comparator_emit(cgenv->sbin, cmp); + sieve_opr_comparator_emit(cgenv->sblock, cmp); return TRUE; } diff --git a/src/lib-sieve/sieve-comparators.h b/src/lib-sieve/sieve-comparators.h index d12d0d8c5..727ab93f5 100644 --- a/src/lib-sieve/sieve-comparators.h +++ b/src/lib-sieve/sieve-comparators.h @@ -120,9 +120,9 @@ extern const struct sieve_operand_class sieve_comparator_operand_class; extern const struct sieve_operand_def comparator_operand; static inline void sieve_opr_comparator_emit -(struct sieve_binary *sbin, const struct sieve_comparator *cmp) +(struct sieve_binary_block *sblock, const struct sieve_comparator *cmp) { - sieve_opr_object_emit(sbin, cmp->object.ext, cmp->object.def); + sieve_opr_object_emit(sblock, cmp->object.ext, cmp->object.def); } static inline bool sieve_opr_comparator_read diff --git a/src/lib-sieve/sieve-dump.h b/src/lib-sieve/sieve-dump.h index 22f99bf03..5e0a96f3c 100644 --- a/src/lib-sieve/sieve-dump.h +++ b/src/lib-sieve/sieve-dump.h @@ -21,6 +21,7 @@ struct sieve_dumptime_env { struct sieve_instance *svinst; struct sieve_binary *sbin; + struct sieve_binary_block *sblock; struct sieve_operation oprtn; diff --git a/src/lib-sieve/sieve-generator.c b/src/lib-sieve/sieve-generator.c index 25c9ee823..0d04b7016 100644 --- a/src/lib-sieve/sieve-generator.c +++ b/src/lib-sieve/sieve-generator.c @@ -18,21 +18,21 @@ */ struct sieve_jumplist *sieve_jumplist_create - (pool_t pool, struct sieve_binary *sbin) +(pool_t pool, struct sieve_binary_block *sblock) { struct sieve_jumplist *jlist; jlist = p_new(pool, struct sieve_jumplist, 1); - jlist->binary = sbin; + jlist->block = sblock; p_array_init(&jlist->jumps, pool, 4); return jlist; } void sieve_jumplist_init_temp - (struct sieve_jumplist *jlist, struct sieve_binary *sbin) +(struct sieve_jumplist *jlist, struct sieve_binary_block *sblock) { - jlist->binary = sbin; + jlist->block = sblock; t_array_init(&jlist->jumps, 4); } @@ -54,7 +54,7 @@ void sieve_jumplist_resolve(struct sieve_jumplist *jlist) for ( i = 0; i < array_count(&jlist->jumps); i++ ) { const sieve_size_t *jump = array_idx(&jlist->jumps, i); - sieve_binary_resolve_offset(jlist->binary, *jump); + sieve_binary_resolve_offset(jlist->block, *jump); } } @@ -70,6 +70,7 @@ struct sieve_generator { struct sieve_error_handler *ehandler; struct sieve_codegen_env genenv; + struct sieve_binary_debug_writer *dwriter; ARRAY_DEFINE(ext_contexts, void *); }; @@ -105,18 +106,19 @@ struct sieve_generator *sieve_generator_create return gentr; } -void sieve_generator_free(struct sieve_generator **generator) +void sieve_generator_free(struct sieve_generator **gentr) { - sieve_ast_unref(&(*generator)->genenv.ast); - - if ( (*generator)->genenv.sbin != NULL ) - sieve_binary_unref(&(*generator)->genenv.sbin); - - sieve_error_handler_unref(&(*generator)->ehandler); + sieve_ast_unref(&(*gentr)->genenv.ast); + + sieve_error_handler_unref(&(*gentr)->ehandler); + sieve_binary_debug_writer_deinit(&(*gentr)->dwriter); + + if ( (*gentr)->genenv.sbin != NULL ) + sieve_binary_unref(&(*gentr)->genenv.sbin); - pool_unref(&((*generator)->pool)); + pool_unref(&((*gentr)->pool)); - *generator = NULL; + *gentr = NULL; } /* @@ -141,11 +143,17 @@ struct sieve_script *sieve_generator_script } struct sieve_binary *sieve_generator_get_binary - (struct sieve_generator *gentr) +(struct sieve_generator *gentr) { return gentr->genenv.sbin; } +struct sieve_binary_block *sieve_generator_get_block +(struct sieve_generator *gentr) +{ + return gentr->genenv.sblock; +} + /* * Error handling */ @@ -218,6 +226,24 @@ const void *sieve_generator_extension_get_context * Code generation API */ +static void sieve_generate_debug_from_ast_node +(const struct sieve_codegen_env *cgenv, struct sieve_ast_node *ast_node) +{ + sieve_size_t address = sieve_binary_block_get_size(cgenv->sblock); + unsigned int line = sieve_ast_node_line(ast_node); + + sieve_binary_debug_emit(cgenv->gentr->dwriter, address, line, 0); +} + +static void sieve_generate_debug_from_ast_argument +(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *ast_arg) +{ + sieve_size_t address = sieve_binary_block_get_size(cgenv->sblock); + unsigned int line = sieve_ast_argument_line(ast_arg); + + sieve_binary_debug_emit(cgenv->gentr->dwriter, address, line, 0); +} + bool sieve_generate_argument (const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, struct sieve_command *cmd) @@ -228,8 +254,12 @@ bool sieve_generate_argument arg_def = arg->argument->def; - return ( arg_def->generate == NULL || - arg_def->generate(cgenv, arg, cmd) ); + if ( arg_def->generate == NULL ) + return TRUE; + + sieve_generate_debug_from_ast_argument(cgenv, arg); + + return arg_def->generate(cgenv, arg, cmd); } bool sieve_generate_arguments @@ -257,10 +287,11 @@ bool sieve_generate_arguments state = ARG_POSITIONAL; else { /* Mark start of optional operands with 0 operand identifier */ - sieve_binary_emit_byte(cgenv->sbin, SIEVE_OPERAND_OPTIONAL); + sieve_binary_emit_byte(cgenv->sblock, SIEVE_OPERAND_OPTIONAL); /* Emit argument id for optional operand */ - sieve_binary_emit_byte(cgenv->sbin, (unsigned char) argument->id_code); + sieve_binary_emit_byte + (cgenv->sblock, (unsigned char) argument->id_code); state = ARG_OPTIONAL; } @@ -270,7 +301,8 @@ bool sieve_generate_arguments state = ARG_POSITIONAL; /* Emit argument id for optional operand (0 marks the end of the optionals) */ - sieve_binary_emit_byte(cgenv->sbin, (unsigned char) argument->id_code); + sieve_binary_emit_byte + (cgenv->sblock, (unsigned char) argument->id_code); break; case ARG_POSITIONAL: @@ -280,7 +312,9 @@ bool sieve_generate_arguments } /* Call the generation function for the argument */ - if ( arg_def->generate != NULL ) { + if ( arg_def->generate != NULL ) { + sieve_generate_debug_from_ast_argument(cgenv, arg); + if ( !arg_def->generate(cgenv, arg, cmd) ) return FALSE; } else if ( state == ARG_POSITIONAL ) break; @@ -290,7 +324,7 @@ bool sieve_generate_arguments /* Mark end of optional list if it is still open */ if ( state == ARG_OPTIONAL ) - sieve_binary_emit_byte(cgenv->sbin, 0); + sieve_binary_emit_byte(cgenv->sblock, 0); if ( last_arg_r != NULL ) *last_arg_r = arg; @@ -311,7 +345,9 @@ bool sieve_generate_argument_parameters const struct sieve_argument_def *parameter = param->argument->def; /* Call the generation function for the parameter */ - if ( parameter->generate != NULL ) { + if ( parameter->generate != NULL ) { + sieve_generate_debug_from_ast_argument(cgenv, param); + if ( !parameter->generate(cgenv, param, cmd) ) return FALSE; } @@ -336,6 +372,8 @@ bool sieve_generate_test tst_def = test->def; if ( tst_def->control_generate != NULL ) { + sieve_generate_debug_from_ast_node(cgenv, tst_node); + if ( tst_def->control_generate(cgenv, test, jlist, jump_true) ) return TRUE; @@ -343,14 +381,15 @@ bool sieve_generate_test } if ( tst_def->generate != NULL ) { + sieve_generate_debug_from_ast_node(cgenv, tst_node); if ( tst_def->generate(cgenv, test) ) { if ( jump_true ) - sieve_operation_emit(cgenv->sbin, NULL, &sieve_jmptrue_operation); + sieve_operation_emit(cgenv->sblock, NULL, &sieve_jmptrue_operation); else - sieve_operation_emit(cgenv->sbin, NULL, &sieve_jmpfalse_operation); - sieve_jumplist_add(jlist, sieve_binary_emit_offset(cgenv->sbin, 0)); + sieve_operation_emit(cgenv->sblock, NULL, &sieve_jmpfalse_operation); + sieve_jumplist_add(jlist, sieve_binary_emit_offset(cgenv->sblock, 0)); return TRUE; } @@ -373,6 +412,8 @@ static bool sieve_generate_command cmd_def = command->def; if ( cmd_def->generate != NULL ) { + sieve_generate_debug_from_ast_node(cgenv, cmd_node); + return cmd_def->generate(cgenv, command); } @@ -396,40 +437,52 @@ bool sieve_generate_block return result; } -bool sieve_generator_run -(struct sieve_generator *gentr, struct sieve_binary **sbin) +struct sieve_binary *sieve_generator_run +(struct sieve_generator *gentr, struct sieve_binary_block **sblock_r) { - bool topmost = ( *sbin == NULL ); - bool result = TRUE; + bool topmost = ( sblock_r == NULL || *sblock_r == NULL ); + struct sieve_binary *sbin; + struct sieve_binary_block *sblock, *debug_block; const struct sieve_extension *const *extensions; unsigned int i, ext_count; + bool result = TRUE; /* Initialize */ - if ( topmost ) - *sbin = sieve_binary_create_new(sieve_ast_script(gentr->genenv.ast)); + if ( topmost ) { + sbin = sieve_binary_create_new(sieve_ast_script(gentr->genenv.ast)); + sblock = sieve_binary_block_get(sbin, SBIN_SYSBLOCK_MAIN_PROGRAM); + } else { + sblock = *sblock_r; + sbin = sieve_binary_block_get_binary(sblock); + } - sieve_binary_ref(*sbin); - - gentr->genenv.sbin = *sbin; + sieve_binary_ref(sbin); + gentr->genenv.sbin = sbin; + gentr->genenv.sblock = sblock; + + /* Create debug block */ + debug_block = sieve_binary_block_create(sbin); + gentr->dwriter = sieve_binary_debug_writer_init(debug_block); + (void)sieve_binary_emit_unsigned + (sblock, sieve_binary_block_get_id(debug_block)); /* Load extensions linked to the AST and emit a list in code */ extensions = sieve_ast_extensions_get(gentr->genenv.ast, &ext_count); - (void) sieve_binary_emit_unsigned(*sbin, ext_count); - for ( i = 0; i < ext_count; i++ ) { + (void) sieve_binary_emit_unsigned(sblock, ext_count); + for ( i = 0; i < ext_count && sbin != NULL; i++ ) { const struct sieve_extension *ext = extensions[i]; /* Link to binary */ - (void)sieve_binary_extension_link(*sbin, ext); + (void)sieve_binary_extension_link(sbin, ext); /* Emit */ - sieve_binary_emit_extension(*sbin, ext, 0); + sieve_binary_emit_extension(sblock, ext, 0); /* Load */ if ( ext->def != NULL && ext->def->generator_load != NULL && - !ext->def->generator_load(ext, &gentr->genenv) ) { + !ext->def->generator_load(ext, &gentr->genenv) ) result = FALSE; - } } /* Generate code */ @@ -439,20 +492,28 @@ bool sieve_generator_run (&gentr->genenv, sieve_ast_root(gentr->genenv.ast))) result = FALSE; else if ( topmost ) - sieve_binary_activate(*sbin); + sieve_binary_activate(sbin); } /* Cleanup */ gentr->genenv.sbin = NULL; - sieve_binary_unref(sbin); - - if ( topmost && !result ) { - sieve_binary_unref(sbin); - *sbin = NULL; + gentr->genenv.sblock = NULL; + sieve_binary_unref(&sbin); + + if ( !result ) { + if ( topmost ) { + sieve_binary_unref(&sbin); + if ( sblock_r != NULL ) + *sblock_r = NULL; + } + sbin = NULL; + } else { + if ( sblock_r != NULL ) + *sblock_r = sblock; } - return result; + return sbin; } diff --git a/src/lib-sieve/sieve-generator.h b/src/lib-sieve/sieve-generator.h index c353bea87..0fb8a1177 100644 --- a/src/lib-sieve/sieve-generator.h +++ b/src/lib-sieve/sieve-generator.h @@ -18,7 +18,9 @@ struct sieve_codegen_env { struct sieve_instance *svinst; struct sieve_script *script; struct sieve_ast *ast; + struct sieve_binary *sbin; + struct sieve_binary_block *sblock; }; struct sieve_generator *sieve_generator_create @@ -36,6 +38,8 @@ struct sieve_script *sieve_generator_script (struct sieve_generator *gentr); struct sieve_binary *sieve_generator_get_binary (struct sieve_generator *gentr); +struct sieve_binary_block *sieve_generator_get_block + (struct sieve_generator *gentr); /* * Error handling @@ -67,14 +71,14 @@ const void *sieve_generator_extension_get_context struct sieve_jumplist { pool_t pool; - struct sieve_binary *binary; + struct sieve_binary_block *block; ARRAY_DEFINE(jumps, sieve_size_t); }; struct sieve_jumplist *sieve_jumplist_create - (pool_t pool, struct sieve_binary *sbin); + (pool_t pool, struct sieve_binary_block *sblock); void sieve_jumplist_init_temp - (struct sieve_jumplist *jlist, struct sieve_binary *sbin); + (struct sieve_jumplist *jlist, struct sieve_binary_block *sblock); void sieve_jumplist_reset (struct sieve_jumplist *jlist); void sieve_jumplist_add @@ -100,8 +104,8 @@ bool sieve_generate_block bool sieve_generate_test (const struct sieve_codegen_env *cgenv, struct sieve_ast_node *tst_node, struct sieve_jumplist *jlist, bool jump_true); -bool sieve_generator_run - (struct sieve_generator *gentr, struct sieve_binary **sbin); +struct sieve_binary *sieve_generator_run + (struct sieve_generator *gentr, struct sieve_binary_block **sblock_r); #endif /* __SIEVE_GENERATOR_H */ diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c index e1bf25471..0c4e5ee76 100644 --- a/src/lib-sieve/sieve-interpreter.c +++ b/src/lib-sieve/sieve-interpreter.c @@ -58,16 +58,20 @@ struct sieve_interpreter { /* Runtime environment */ struct sieve_runtime_env runenv; + + struct sieve_binary_debug_reader *dreader; }; -struct sieve_interpreter *sieve_interpreter_create -(struct sieve_binary *sbin, struct sieve_error_handler *ehandler) +static struct sieve_interpreter *_sieve_interpreter_create +(struct sieve_binary *sbin, struct sieve_binary_block *sblock, + struct sieve_error_handler *ehandler) { unsigned int i, ext_count; struct sieve_interpreter *interp; pool_t pool; struct sieve_instance *svinst; const struct sieve_extension *const *ext_preloaded; + unsigned int debug_block_id; bool success = TRUE; pool = pool_alloconly_create("sieve_interpreter", 4096); @@ -79,6 +83,7 @@ struct sieve_interpreter *sieve_interpreter_create interp->runenv.interp = interp; interp->runenv.sbin = sbin; + interp->runenv.sblock = sblock; sieve_binary_ref(sbin); svinst = sieve_binary_svinst(sbin); @@ -100,13 +105,29 @@ struct sieve_interpreter *sieve_interpreter_create (ext_preloaded[i], &interp->runenv, &interp->pc); } + /* Load debug block */ + if ( sieve_binary_read_unsigned(sblock, &interp->pc, &debug_block_id) ) { + struct sieve_binary_block *debug_block = + sieve_binary_block_get(sbin, debug_block_id); + + if ( debug_block == NULL ) { + sieve_runtime_trace_error(&interp->runenv, "invalid id for debug block"); + success = FALSE; + } else { + /* Initialize debug reader */ + interp->dreader = sieve_binary_debug_reader_init(debug_block); + } + } + /* Load other extensions listed in code */ - if ( sieve_binary_read_unsigned(sbin, &interp->pc, &ext_count) ) { + if ( success && + sieve_binary_read_unsigned(sblock, &interp->pc, &ext_count) ) { + for ( i = 0; i < ext_count; i++ ) { unsigned int code = 0; const struct sieve_extension *ext; - if ( !sieve_binary_read_extension(sbin, &interp->pc, &code, &ext) ) { + if ( !sieve_binary_read_extension(sblock, &interp->pc, &code, &ext) ) { success = FALSE; break; } @@ -129,6 +150,23 @@ struct sieve_interpreter *sieve_interpreter_create return interp; } +struct sieve_interpreter *sieve_interpreter_create +(struct sieve_binary *sbin, struct sieve_error_handler *ehandler) +{ + struct sieve_binary_block *sblock = + sieve_binary_block_get(sbin, SBIN_SYSBLOCK_MAIN_PROGRAM); + + return _sieve_interpreter_create(sbin, sblock, ehandler); +} + +struct sieve_interpreter *sieve_interpreter_create_for_block +(struct sieve_binary_block *sblock, struct sieve_error_handler *ehandler) +{ + struct sieve_binary *sbin = sieve_binary_block_get_binary(sblock); + + return _sieve_interpreter_create(sbin, sblock, ehandler); +} + void sieve_interpreter_free(struct sieve_interpreter **interp) { const struct sieve_interpreter_extension_reg *eregs; @@ -141,6 +179,7 @@ void sieve_interpreter_free(struct sieve_interpreter **interp) eregs[i].intext->free(eregs[i].ext, *interp, eregs[i].context); } + sieve_binary_debug_reader_deinit(&(*interp)->dreader); sieve_binary_unref(&(*interp)->runenv.sbin); sieve_error_handler_unref(&(*interp)->ehandler); @@ -349,13 +388,13 @@ int sieve_interpreter_program_jump sieve_size_t pc = interp->pc; int offset; - if ( !sieve_binary_read_offset(renv->sbin, &(interp->pc), &offset) ) + if ( !sieve_binary_read_offset(renv->sblock, &(interp->pc), &offset) ) { sieve_runtime_trace_error(renv, "invalid jump offset"); return SIEVE_EXEC_BIN_CORRUPT; } - if ( pc + offset <= sieve_binary_get_code_size(renv->sbin) && + if ( pc + offset <= sieve_binary_block_get_size(renv->sblock) && pc + offset > 0 ) { if ( jump ) @@ -394,9 +433,9 @@ int sieve_interpreter_handle_optional_operands { signed int opt_code = -1; - if ( sieve_operand_optional_present(renv->sbin, address) ) { + if ( sieve_operand_optional_present(renv->sblock, address) ) { while ( opt_code != 0 ) { - if ( !sieve_operand_optional_read(renv->sbin, address, &opt_code) ) { + if ( !sieve_operand_optional_read(renv->sblock, address, &opt_code) ) { sieve_runtime_trace_error(renv, "invalid optional operand"); return SIEVE_EXEC_BIN_CORRUPT; } @@ -431,7 +470,7 @@ static int sieve_interpreter_execute_operation { struct sieve_operation *oprtn = &(interp->runenv.oprtn); - if ( sieve_operation_read(interp->runenv.sbin, &(interp->pc), oprtn) ) { + if ( sieve_operation_read(interp->runenv.sblock, &(interp->pc), oprtn) ) { const struct sieve_operation_def *op = oprtn->def; int result = SIEVE_EXEC_OK; @@ -463,7 +502,7 @@ int sieve_interpreter_continue *interrupted = FALSE; while ( ret == SIEVE_EXEC_OK && !interp->interrupted && - interp->pc < sieve_binary_get_code_size(interp->runenv.sbin) ) { + interp->pc < sieve_binary_block_get_size(interp->runenv.sblock) ) { ret = sieve_interpreter_execute_operation(interp); diff --git a/src/lib-sieve/sieve-interpreter.h b/src/lib-sieve/sieve-interpreter.h index 6c0ce14ed..41336be9a 100644 --- a/src/lib-sieve/sieve-interpreter.h +++ b/src/lib-sieve/sieve-interpreter.h @@ -27,6 +27,7 @@ struct sieve_runtime_env { struct sieve_instance *svinst; struct sieve_binary *sbin; + struct sieve_binary_block *sblock; struct sieve_operation oprtn; struct sieve_script *script; @@ -47,6 +48,8 @@ struct sieve_runtime_env { struct sieve_interpreter *sieve_interpreter_create (struct sieve_binary *sbin, struct sieve_error_handler *ehandler); +struct sieve_interpreter *sieve_interpreter_create_for_block + (struct sieve_binary_block *sblock, struct sieve_error_handler *ehandler); void sieve_interpreter_free(struct sieve_interpreter **interp); /* diff --git a/src/lib-sieve/sieve-match-types.c b/src/lib-sieve/sieve-match-types.c index 2ff3eb73a..96d039278 100644 --- a/src/lib-sieve/sieve-match-types.c +++ b/src/lib-sieve/sieve-match-types.c @@ -431,7 +431,7 @@ static bool tag_match_type_generate struct sieve_match_type_context *mtctx = (struct sieve_match_type_context *) arg->argument->data; - (void) sieve_opr_match_type_emit(cgenv->sbin, mtctx->match_type); + (void) sieve_opr_match_type_emit(cgenv->sblock, mtctx->match_type); return TRUE; } diff --git a/src/lib-sieve/sieve-match-types.h b/src/lib-sieve/sieve-match-types.h index df3c85dfa..b96fa7aaa 100644 --- a/src/lib-sieve/sieve-match-types.h +++ b/src/lib-sieve/sieve-match-types.h @@ -201,9 +201,9 @@ static inline bool sieve_operand_is_match_type } static inline void sieve_opr_match_type_emit -(struct sieve_binary *sbin, const struct sieve_match_type *mcht) +(struct sieve_binary_block *sblock, const struct sieve_match_type *mcht) { - sieve_opr_object_emit(sbin, mcht->object.ext, mcht->object.def); + sieve_opr_object_emit(sblock, mcht->object.ext, mcht->object.def); } static inline bool sieve_opr_match_type_read diff --git a/src/lib-sieve/sieve-match.c b/src/lib-sieve/sieve-match.c index ad1a17329..88aa4e517 100644 --- a/src/lib-sieve/sieve-match.c +++ b/src/lib-sieve/sieve-match.c @@ -140,9 +140,9 @@ bool sieve_match_dump_optional_operands (const struct sieve_dumptime_env *denv, sieve_size_t *address, int *opt_code) { if ( *opt_code != SIEVE_MATCH_OPT_END || - sieve_operand_optional_present(denv->sbin, address) ) { + sieve_operand_optional_present(denv->sblock, address) ) { do { - if ( !sieve_operand_optional_read(denv->sbin, address, opt_code) ) + if ( !sieve_operand_optional_read(denv->sblock, address, opt_code) ) return FALSE; switch ( *opt_code ) { @@ -171,9 +171,9 @@ int sieve_match_read_optional_operands { /* Handle any optional arguments */ if ( *opt_code != SIEVE_MATCH_OPT_END || - sieve_operand_optional_present(renv->sbin, address) ) { + sieve_operand_optional_present(renv->sblock, address) ) { do { - if ( !sieve_operand_optional_read(renv->sbin, address, opt_code) ) { + if ( !sieve_operand_optional_read(renv->sblock, address, opt_code) ) { sieve_runtime_trace_error(renv, "invalid optional operand"); return SIEVE_EXEC_BIN_CORRUPT; } diff --git a/src/lib-sieve/sieve-objects.c b/src/lib-sieve/sieve-objects.c index 108ae2f03..614dd1b5e 100644 --- a/src/lib-sieve/sieve-objects.c +++ b/src/lib-sieve/sieve-objects.c @@ -15,21 +15,21 @@ */ void sieve_opr_object_emit -(struct sieve_binary *sbin, const struct sieve_extension *ext, +(struct sieve_binary_block *sblock, const struct sieve_extension *ext, const struct sieve_object_def *obj_def) { struct sieve_extension_objects *objs = (struct sieve_extension_objects *) obj_def->operand->interface; - (void) sieve_operand_emit(sbin, ext, obj_def->operand); + (void) sieve_operand_emit(sblock, ext, obj_def->operand); if ( objs->count > 1 ) { - (void) sieve_binary_emit_byte(sbin, obj_def->code); + (void) sieve_binary_emit_byte(sblock, obj_def->code); } } bool sieve_opr_object_read_data -(struct sieve_binary *sbin, const struct sieve_operand *operand, +(struct sieve_binary_block *sblock, const struct sieve_operand *operand, const struct sieve_operand_class *opclass, sieve_size_t *address, struct sieve_object *obj) { @@ -44,7 +44,7 @@ bool sieve_opr_object_read_data return FALSE; if ( objs->count > 1 ) { - if ( !sieve_binary_read_byte(sbin, address, &obj_code) ) + if ( !sieve_binary_read_byte(sblock, address, &obj_code) ) return FALSE; if ( obj_code < objs->count ) { @@ -69,12 +69,12 @@ bool sieve_opr_object_read { struct sieve_operand operand; - if ( !sieve_operand_read(renv->sbin, address, &operand) ) { + if ( !sieve_operand_read(renv->sblock, address, &operand) ) { return FALSE; } return sieve_opr_object_read_data - (renv->sbin, &operand, opclass, address, obj); + (renv->sblock, &operand, opclass, address, obj); } bool sieve_opr_object_dump @@ -91,12 +91,12 @@ bool sieve_opr_object_dump sieve_code_mark(denv); - if ( !sieve_operand_read(denv->sbin, address, &operand) ) { + if ( !sieve_operand_read(denv->sblock, address, &operand) ) { return FALSE; } if ( !sieve_opr_object_read_data - (denv->sbin, &operand, opclass, address, obj) ) + (denv->sblock, &operand, opclass, address, obj) ) return FALSE; if ( operand.def->class == NULL ) diff --git a/src/lib-sieve/sieve-objects.h b/src/lib-sieve/sieve-objects.h index 2d69164fe..4ffb12196 100644 --- a/src/lib-sieve/sieve-objects.h +++ b/src/lib-sieve/sieve-objects.h @@ -44,11 +44,11 @@ struct sieve_object { */ void sieve_opr_object_emit - (struct sieve_binary *sbin, const struct sieve_extension *ext, + (struct sieve_binary_block *sblock, const struct sieve_extension *ext, const struct sieve_object_def *obj_def); bool sieve_opr_object_read_data - (struct sieve_binary *sbin, const struct sieve_operand *operand, + (struct sieve_binary_block *sblock, const struct sieve_operand *operand, const struct sieve_operand_class *opclass, sieve_size_t *address, struct sieve_object *obj); diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c index 123b46556..55e393fd3 100644 --- a/src/lib-sieve/sieve.c +++ b/src/lib-sieve/sieve.c @@ -156,7 +156,7 @@ static struct sieve_binary *sieve_generate struct sieve_generator *generator = sieve_generator_create(ast, ehandler); struct sieve_binary *sbin = NULL; - (void) sieve_generator_run(generator, &sbin); + sbin = sieve_generator_run(generator, NULL); sieve_generator_free(&generator); @@ -343,11 +343,11 @@ void sieve_close(struct sieve_binary **sbin) * Debugging */ -void sieve_dump(struct sieve_binary *sbin, struct ostream *stream) +void sieve_dump(struct sieve_binary *sbin, struct ostream *stream, bool verbose) { struct sieve_binary_dumper *dumpr = sieve_binary_dumper_create(sbin); - sieve_binary_dumper_run(dumpr, stream); + sieve_binary_dumper_run(dumpr, stream, verbose); sieve_binary_dumper_free(&dumpr); } diff --git a/src/lib-sieve/sieve.h b/src/lib-sieve/sieve.h index ebc340b8c..346328352 100644 --- a/src/lib-sieve/sieve.h +++ b/src/lib-sieve/sieve.h @@ -105,7 +105,7 @@ void sieve_close(struct sieve_binary **sbin); * * Dumps the byte code in human-readable form to the specified ostream. */ -void sieve_dump(struct sieve_binary *sbin, struct ostream *stream); +void sieve_dump(struct sieve_binary *sbin, struct ostream *stream, bool verbose); /* sieve_test: * diff --git a/src/lib-sieve/tst-address.c b/src/lib-sieve/tst-address.c index 76aabfda2..44e52cb49 100644 --- a/src/lib-sieve/tst-address.c +++ b/src/lib-sieve/tst-address.c @@ -191,7 +191,7 @@ static bool tst_address_validate static bool tst_address_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *tst) { - sieve_operation_emit(cgenv->sbin, NULL, &tst_address_operation); + sieve_operation_emit(cgenv->sblock, NULL, &tst_address_operation); /* Generate arguments */ return sieve_generate_arguments(cgenv, tst, NULL); diff --git a/src/lib-sieve/tst-allof.c b/src/lib-sieve/tst-allof.c index 6d610b8e4..5e3eb2fea 100644 --- a/src/lib-sieve/tst-allof.c +++ b/src/lib-sieve/tst-allof.c @@ -36,14 +36,14 @@ static bool tst_allof_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx, struct sieve_jumplist *jumps, bool jump_true) { - struct sieve_binary *sbin = cgenv->sbin; + struct sieve_binary_block *sblock = cgenv->sblock; struct sieve_ast_node *test; struct sieve_jumplist false_jumps; if ( sieve_ast_test_count(ctx->ast_node) > 1 ) { if ( jump_true ) { /* Prepare jumplist */ - sieve_jumplist_init_temp(&false_jumps, sbin); + sieve_jumplist_init_temp(&false_jumps, sblock); } test = sieve_ast_test_first(ctx->ast_node); @@ -67,8 +67,8 @@ static bool tst_allof_generate if ( jump_true ) { /* All tests succeeded, jump to case TRUE */ - sieve_operation_emit(cgenv->sbin, NULL, &sieve_jmp_operation); - sieve_jumplist_add(jumps, sieve_binary_emit_offset(sbin, 0)); + sieve_operation_emit(cgenv->sblock, NULL, &sieve_jmp_operation); + sieve_jumplist_add(jumps, sieve_binary_emit_offset(sblock, 0)); /* All false exits jump here */ sieve_jumplist_resolve(&false_jumps); diff --git a/src/lib-sieve/tst-anyof.c b/src/lib-sieve/tst-anyof.c index 9fbe4775c..55fcd5ba5 100644 --- a/src/lib-sieve/tst-anyof.c +++ b/src/lib-sieve/tst-anyof.c @@ -36,14 +36,14 @@ static bool tst_anyof_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx, struct sieve_jumplist *jumps, bool jump_true) { - struct sieve_binary *sbin = cgenv->sbin; + struct sieve_binary_block *sblock = cgenv->sblock; struct sieve_ast_node *test; struct sieve_jumplist true_jumps; if ( sieve_ast_test_count(ctx->ast_node) > 1 ) { if ( !jump_true ) { /* Prepare jumplist */ - sieve_jumplist_init_temp(&true_jumps, sbin); + sieve_jumplist_init_temp(&true_jumps, sblock); } test = sieve_ast_test_first(ctx->ast_node); @@ -67,8 +67,8 @@ static bool tst_anyof_generate if ( !jump_true ) { /* All tests failed, jump to case FALSE */ - sieve_operation_emit(sbin, NULL, &sieve_jmp_operation); - sieve_jumplist_add(jumps, sieve_binary_emit_offset(sbin, 0)); + sieve_operation_emit(sblock, NULL, &sieve_jmp_operation); + sieve_jumplist_add(jumps, sieve_binary_emit_offset(sblock, 0)); /* All true exits jump here */ sieve_jumplist_resolve(&true_jumps); diff --git a/src/lib-sieve/tst-exists.c b/src/lib-sieve/tst-exists.c index fa7280085..e70b064a1 100644 --- a/src/lib-sieve/tst-exists.c +++ b/src/lib-sieve/tst-exists.c @@ -76,7 +76,7 @@ static bool tst_exists_validate static bool tst_exists_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *tst) { - sieve_operation_emit(cgenv->sbin, NULL, &tst_exists_operation); + sieve_operation_emit(cgenv->sblock, NULL, &tst_exists_operation); /* Generate arguments */ return sieve_generate_arguments(cgenv, tst, NULL); diff --git a/src/lib-sieve/tst-header.c b/src/lib-sieve/tst-header.c index c2ad3dc18..872b3e5da 100644 --- a/src/lib-sieve/tst-header.c +++ b/src/lib-sieve/tst-header.c @@ -117,7 +117,7 @@ static bool tst_header_validate static bool tst_header_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *tst) { - sieve_operation_emit(cgenv->sbin, NULL, &tst_header_operation); + sieve_operation_emit(cgenv->sblock, NULL, &tst_header_operation); /* Generate arguments */ return sieve_generate_arguments(cgenv, tst, NULL); diff --git a/src/lib-sieve/tst-size.c b/src/lib-sieve/tst-size.c index 5accafb36..437a224f1 100644 --- a/src/lib-sieve/tst-size.c +++ b/src/lib-sieve/tst-size.c @@ -200,9 +200,9 @@ bool tst_size_generate (struct tst_size_context_data *) tst->data; if ( ctx_data->type == SIZE_OVER ) - sieve_operation_emit(cgenv->sbin, NULL, &tst_size_over_operation); + sieve_operation_emit(cgenv->sblock, NULL, &tst_size_over_operation); else - sieve_operation_emit(cgenv->sbin, NULL, &tst_size_under_operation); + sieve_operation_emit(cgenv->sblock, NULL, &tst_size_under_operation); /* Generate arguments */ if ( !sieve_generate_arguments(cgenv, tst, NULL) ) diff --git a/src/lib-sieve/tst-truefalse.c b/src/lib-sieve/tst-truefalse.c index 5df1b6a25..d64bd7b08 100644 --- a/src/lib-sieve/tst-truefalse.c +++ b/src/lib-sieve/tst-truefalse.c @@ -43,8 +43,8 @@ static bool tst_false_generate struct sieve_jumplist *jumps, bool jump_true) { if ( !jump_true ) { - sieve_operation_emit(cgenv->sbin, NULL, &sieve_jmp_operation); - sieve_jumplist_add(jumps, sieve_binary_emit_offset(cgenv->sbin, 0)); + sieve_operation_emit(cgenv->sblock, NULL, &sieve_jmp_operation); + sieve_jumplist_add(jumps, sieve_binary_emit_offset(cgenv->sblock, 0)); } return TRUE; @@ -56,8 +56,8 @@ static bool tst_true_generate struct sieve_jumplist *jumps, bool jump_true) { if ( jump_true ) { - sieve_operation_emit(cgenv->sbin, NULL, &sieve_jmp_operation); - sieve_jumplist_add(jumps, sieve_binary_emit_offset(cgenv->sbin, 0)); + sieve_operation_emit(cgenv->sblock, NULL, &sieve_jmp_operation); + sieve_jumplist_add(jumps, sieve_binary_emit_offset(cgenv->sblock, 0)); } return TRUE; diff --git a/src/sieve-tools/debug/cmd-debug-print.c b/src/sieve-tools/debug/cmd-debug-print.c index 32c5e22e6..c6e3cfda5 100644 --- a/src/sieve-tools/debug/cmd-debug-print.c +++ b/src/sieve-tools/debug/cmd-debug-print.c @@ -76,7 +76,7 @@ static bool cmd_debug_print_validate static bool cmd_debug_print_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) { - (void)sieve_operation_emit(cgenv->sbin, cmd->ext, &debug_print_operation); + (void)sieve_operation_emit(cgenv->sblock, cmd->ext, &debug_print_operation); /* Generate arguments */ return sieve_generate_arguments(cgenv, cmd, NULL); diff --git a/src/testsuite/cmd-test-binary.c b/src/testsuite/cmd-test-binary.c index 46bee4b32..c7361a505 100644 --- a/src/testsuite/cmd-test-binary.c +++ b/src/testsuite/cmd-test-binary.c @@ -188,7 +188,7 @@ static bool cmd_test_binary_generate i_assert( ctx_data->binary_op < BINARY_OP_LAST ); /* Emit operation */ - sieve_operation_emit(cgenv->sbin, cmd->ext, + sieve_operation_emit(cgenv->sblock, cmd->ext, test_binary_operations[ctx_data->binary_op]); /* Generate arguments */ @@ -241,7 +241,7 @@ static int cmd_test_binary_operation_execute */ sieve_runtime_trace - (renv, "%s %s:", sieve_operation_mnemonic(op), str_c(binary_name)); + (renv, "%s %s", sieve_operation_mnemonic(op), str_c(binary_name)); if ( sieve_operation_is(op, test_binary_load_operation) ) { struct sieve_binary *sbin = testsuite_binary_load(str_c(binary_name)); diff --git a/src/testsuite/cmd-test-config.c b/src/testsuite/cmd-test-config.c index 9ba9f2fa2..194946936 100644 --- a/src/testsuite/cmd-test-config.c +++ b/src/testsuite/cmd-test-config.c @@ -246,7 +246,7 @@ static bool tag_action_generate i_assert(ctx_data->action < CONFIG_ACTION_LAST); sieve_operation_emit - (cgenv->sbin, cmd->ext, test_config_operations[ctx_data->action]); + (cgenv->sblock, cmd->ext, test_config_operations[ctx_data->action]); while ( param != NULL ) { if ( !sieve_generate_argument(cgenv, param, cmd) ) diff --git a/src/testsuite/cmd-test-fail.c b/src/testsuite/cmd-test-fail.c index 5b634de83..ac43cdda3 100644 --- a/src/testsuite/cmd-test-fail.c +++ b/src/testsuite/cmd-test-fail.c @@ -85,14 +85,14 @@ static bool cmd_test_fail_generate struct testsuite_generator_context *genctx = _get_generator_context(cgenv->gentr); - sieve_operation_emit(cgenv->sbin, cmd->ext, &test_fail_operation); + sieve_operation_emit(cgenv->sblock, cmd->ext, &test_fail_operation); /* Generate arguments */ if ( !sieve_generate_arguments(cgenv, cmd, NULL) ) return FALSE; sieve_jumplist_add(genctx->exit_jumps, - sieve_binary_emit_offset(cgenv->sbin, 0)); + sieve_binary_emit_offset(cgenv->sblock, 0)); return TRUE; } @@ -115,7 +115,7 @@ static bool cmd_test_fail_operation_dump sieve_code_mark(denv); pc = *address; - if ( sieve_binary_read_offset(denv->sbin, address, &offset) ) + if ( sieve_binary_read_offset(denv->sblock, address, &offset) ) sieve_code_dumpf(denv, "offset: %d [%08x]", offset, pc + offset); else return FALSE; diff --git a/src/testsuite/cmd-test-mailbox.c b/src/testsuite/cmd-test-mailbox.c index 8605cc408..e61cc44d6 100644 --- a/src/testsuite/cmd-test-mailbox.c +++ b/src/testsuite/cmd-test-mailbox.c @@ -189,7 +189,7 @@ static bool cmd_test_mailbox_generate i_assert( ctx_data->mailbox_op < MAILBOX_OP_LAST ); /* Emit operation */ - sieve_operation_emit(cgenv->sbin, cmd->ext, + sieve_operation_emit(cgenv->sblock, cmd->ext, test_mailbox_operations[ctx_data->mailbox_op]); /* Generate arguments */ diff --git a/src/testsuite/cmd-test-message.c b/src/testsuite/cmd-test-message.c index c1dbbcc86..8df89a0ba 100644 --- a/src/testsuite/cmd-test-message.c +++ b/src/testsuite/cmd-test-message.c @@ -240,11 +240,11 @@ static bool cmd_test_message_generate i_assert( ctx_data->msg_source < MSG_SOURCE_LAST ); /* Emit operation */ - sieve_operation_emit(cgenv->sbin, cmd->ext, + sieve_operation_emit(cgenv->sblock, cmd->ext, test_message_operations[ctx_data->msg_source]); /* Emit is_test flag */ - sieve_binary_emit_byte(cgenv->sbin, ( cmd->ast_node->type == SAT_TEST )); + sieve_binary_emit_byte(cgenv->sblock, ( cmd->ast_node->type == SAT_TEST )); /* Generate arguments */ if ( !sieve_generate_arguments(cgenv, cmd, NULL) ) @@ -262,7 +262,7 @@ static bool cmd_test_message_smtp_operation_dump { unsigned int is_test; - if ( !sieve_binary_read_byte(denv->sbin, address, &is_test) ) + if ( !sieve_binary_read_byte(denv->sblock, address, &is_test) ) return FALSE; sieve_code_dumpf(denv, "TEST_MESSAGE_SMTP (%s):", @@ -278,7 +278,7 @@ static bool cmd_test_message_mailbox_operation_dump { unsigned int is_test; - if ( !sieve_binary_read_byte(denv->sbin, address, &is_test) ) + if ( !sieve_binary_read_byte(denv->sblock, address, &is_test) ) return FALSE; sieve_code_dumpf(denv, "TEST_MESSAGE_MAILBOX (%s):", @@ -308,7 +308,7 @@ static int cmd_test_message_smtp_operation_execute /* Is test */ - if ( !sieve_binary_read_byte(renv->sbin, address, &is_test) ) { + if ( !sieve_binary_read_byte(renv->sblock, address, &is_test) ) { sieve_runtime_trace_error(renv, "invalid is_test flag"); return SIEVE_EXEC_BIN_CORRUPT; } @@ -353,7 +353,7 @@ static int cmd_test_message_mailbox_operation_execute */ /* Is test */ - if ( !sieve_binary_read_byte(renv->sbin, address, &is_test) ) { + if ( !sieve_binary_read_byte(renv->sblock, address, &is_test) ) { sieve_runtime_trace_error(renv, "invalid is_test flag"); return SIEVE_EXEC_BIN_CORRUPT; } diff --git a/src/testsuite/cmd-test-result-print.c b/src/testsuite/cmd-test-result-print.c index f1525c40a..4af964976 100644 --- a/src/testsuite/cmd-test-result-print.c +++ b/src/testsuite/cmd-test-result-print.c @@ -56,7 +56,7 @@ const struct sieve_operation_def test_result_print_operation = { static bool cmd_test_result_print_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) { - sieve_operation_emit(cgenv->sbin, cmd->ext, &test_result_print_operation); + sieve_operation_emit(cgenv->sblock, cmd->ext, &test_result_print_operation); return TRUE; } diff --git a/src/testsuite/cmd-test-result-reset.c b/src/testsuite/cmd-test-result-reset.c index faea128e9..285afee2a 100644 --- a/src/testsuite/cmd-test-result-reset.c +++ b/src/testsuite/cmd-test-result-reset.c @@ -57,7 +57,7 @@ const struct sieve_operation_def test_result_reset_operation = { static bool cmd_test_result_reset_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *tst) { - sieve_operation_emit(cgenv->sbin, tst->ext, &test_result_reset_operation); + sieve_operation_emit(cgenv->sblock, tst->ext, &test_result_reset_operation); return TRUE; } diff --git a/src/testsuite/cmd-test-set.c b/src/testsuite/cmd-test-set.c index 35df0f9f3..590934c33 100644 --- a/src/testsuite/cmd-test-set.c +++ b/src/testsuite/cmd-test-set.c @@ -97,7 +97,7 @@ static bool cmd_test_set_validate static bool cmd_test_set_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) { - sieve_operation_emit(cgenv->sbin, cmd->ext, &test_set_operation); + sieve_operation_emit(cgenv->sblock, cmd->ext, &test_set_operation); /* Generate arguments */ return sieve_generate_arguments(cgenv, cmd, NULL); @@ -130,7 +130,7 @@ static int cmd_test_set_operation_execute int member_id; if ( !testsuite_object_read_member - (renv->sbin, address, &tobj, &member_id) ) { + (renv->sblock, address, &tobj, &member_id) ) { sieve_runtime_trace_error(renv, "invalid testsuite object member"); return SIEVE_EXEC_BIN_CORRUPT; } diff --git a/src/testsuite/cmd-test.c b/src/testsuite/cmd-test.c index e125878e1..b81382571 100644 --- a/src/testsuite/cmd-test.c +++ b/src/testsuite/cmd-test.c @@ -108,7 +108,7 @@ static bool cmd_test_generate struct testsuite_generator_context *genctx = _get_generator_context(cgenv->gentr); - sieve_operation_emit(cgenv->sbin, cmd->ext, &test_operation); + sieve_operation_emit(cgenv->sblock, cmd->ext, &test_operation); /* Generate arguments */ if ( !sieve_generate_arguments(cgenv, cmd, NULL) ) @@ -121,7 +121,7 @@ static bool cmd_test_generate if ( !sieve_generate_block(cgenv, cmd->ast_node) ) return FALSE; - sieve_operation_emit(cgenv->sbin, cmd->ext, &test_finish_operation); + sieve_operation_emit(cgenv->sblock, cmd->ext, &test_finish_operation); /* Resolve exit jumps to this point */ sieve_jumplist_resolve(genctx->exit_jumps); diff --git a/src/testsuite/testsuite-common.c b/src/testsuite/testsuite-common.c index 1df391fd5..c23c80a2c 100644 --- a/src/testsuite/testsuite-common.c +++ b/src/testsuite/testsuite-common.c @@ -88,12 +88,12 @@ bool testsuite_generator_context_initialize (struct sieve_generator *gentr, const struct sieve_extension *this_ext) { pool_t pool = sieve_generator_pool(gentr); - struct sieve_binary *sbin = sieve_generator_get_binary(gentr); + struct sieve_binary_block *sblock = sieve_generator_get_block(gentr); struct testsuite_generator_context *ctx = p_new(pool, struct testsuite_generator_context, 1); /* Setup exit jumplist */ - ctx->exit_jumps = sieve_jumplist_create(pool, sbin); + ctx->exit_jumps = sieve_jumplist_create(pool, sblock); sieve_generator_extension_set_context(gentr, this_ext, ctx); diff --git a/src/testsuite/testsuite-objects.c b/src/testsuite/testsuite-objects.c index 93a750a13..9c0c11c1e 100644 --- a/src/testsuite/testsuite-objects.c +++ b/src/testsuite/testsuite-objects.c @@ -110,26 +110,27 @@ const struct sieve_operand_def testsuite_object_operand = { }; static void testsuite_object_emit -(struct sieve_binary *sbin, const struct testsuite_object *tobj, int member_id) +(struct sieve_binary_block *sblock, const struct testsuite_object *tobj, + int member_id) { - sieve_opr_object_emit(sbin, tobj->object.ext, tobj->object.def); + sieve_opr_object_emit(sblock, tobj->object.ext, tobj->object.def); if ( tobj->def != NULL && tobj->def->get_member_id != NULL ) { - (void) sieve_binary_emit_byte(sbin, (unsigned char) member_id); + (void) sieve_binary_emit_byte(sblock, (unsigned char) member_id); } } bool testsuite_object_read -(struct sieve_binary *sbin, sieve_size_t *address, +(struct sieve_binary_block *sblock, sieve_size_t *address, struct testsuite_object *tobj) { struct sieve_operand operand; - if ( !sieve_operand_read(sbin, address, &operand) ) + if ( !sieve_operand_read(sblock, address, &operand) ) return FALSE; if ( !sieve_opr_object_read_data - (sbin, &operand, &sieve_testsuite_object_operand_class, address, + (sblock, &operand, &sieve_testsuite_object_operand_class, address, &tobj->object) ) return FALSE; @@ -139,15 +140,15 @@ bool testsuite_object_read } bool testsuite_object_read_member -(struct sieve_binary *sbin, sieve_size_t *address, +(struct sieve_binary_block *sblock, sieve_size_t *address, struct testsuite_object *tobj, int *member_id_r) { - if ( !testsuite_object_read(sbin, address, tobj) ) + if ( !testsuite_object_read(sblock, address, tobj) ) return FALSE; *member_id_r = -1; if ( tobj->def != NULL && tobj->def->get_member_id != NULL ) { - if ( !sieve_binary_read_code(sbin, address, member_id_r) ) + if ( !sieve_binary_read_code(sblock, address, member_id_r) ) return FALSE; } @@ -180,7 +181,8 @@ bool testsuite_object_dump sieve_code_mark(denv); - if ( !testsuite_object_read_member(denv->sbin, address, &object, &member_id) ) + if ( !testsuite_object_read_member + (denv->sblock, address, &object, &member_id) ) return FALSE; sieve_code_dumpf(denv, "%s: %s", @@ -268,7 +270,7 @@ static bool arg_testsuite_object_generate struct testsuite_object_argctx *ctx = (struct testsuite_object_argctx *) arg->argument->data; - testsuite_object_emit(cgenv->sbin, ctx->object, ctx->member); + testsuite_object_emit(cgenv->sblock, ctx->object, ctx->member); return TRUE; } diff --git a/src/testsuite/testsuite-objects.h b/src/testsuite/testsuite-objects.h index a17087038..812376a30 100644 --- a/src/testsuite/testsuite-objects.h +++ b/src/testsuite/testsuite-objects.h @@ -64,10 +64,10 @@ bool testsuite_object_argument_activate */ bool testsuite_object_read - (struct sieve_binary *sbin, sieve_size_t *address, + (struct sieve_binary_block *sblock, sieve_size_t *address, struct testsuite_object *tobj); bool testsuite_object_read_member - (struct sieve_binary *sbin, sieve_size_t *address, + (struct sieve_binary_block *sblock, sieve_size_t *address, struct testsuite_object *tobj, int *member_id_r); bool testsuite_object_dump diff --git a/src/testsuite/testsuite-substitutions.c b/src/testsuite/testsuite-substitutions.c index 7235b301f..bb6d79c4d 100644 --- a/src/testsuite/testsuite-substitutions.c +++ b/src/testsuite/testsuite-substitutions.c @@ -19,7 +19,7 @@ */ void testsuite_opr_substitution_emit - (struct sieve_binary *sbin, const struct testsuite_substitution *tsub, + (struct sieve_binary_block *sblock, const struct testsuite_substitution *tsub, const char *param); /* @@ -126,7 +126,7 @@ static bool arg_testsuite_substitution_generate struct _testsuite_substitution_context *tsctx = (struct _testsuite_substitution_context *) arg->argument->data; - testsuite_opr_substitution_emit(cgenv->sbin, tsctx->tsub, tsctx->param); + testsuite_opr_substitution_emit(cgenv->sblock, tsctx->tsub, tsctx->param); return TRUE; } @@ -156,14 +156,14 @@ const struct sieve_operand_def testsuite_substitution_operand = { }; void testsuite_opr_substitution_emit -(struct sieve_binary *sbin, const struct testsuite_substitution *tsub, +(struct sieve_binary_block *sblock, const struct testsuite_substitution *tsub, const char *param) { /* Default variable storage */ (void) sieve_operand_emit - (sbin, testsuite_ext, &testsuite_substitution_operand); - (void) sieve_binary_emit_unsigned(sbin, tsub->object.def->code); - (void) sieve_binary_emit_cstring(sbin, param); + (sblock, testsuite_ext, &testsuite_substitution_operand); + (void) sieve_binary_emit_unsigned(sblock, tsub->object.def->code); + (void) sieve_binary_emit_cstring(sblock, param); } static bool opr_substitution_dump @@ -175,14 +175,14 @@ static bool opr_substitution_dump const struct testsuite_substitution_def *tsub; string_t *param; - if ( !sieve_binary_read_unsigned(denv->sbin, address, &code) ) + if ( !sieve_binary_read_unsigned(denv->sblock, address, &code) ) return FALSE; tsub = testsuite_substitution_get(code); if ( tsub == NULL ) return FALSE; - if ( !sieve_binary_read_string(denv->sbin, address, ¶m) ) + if ( !sieve_binary_read_string(denv->sblock, address, ¶m) ) return FALSE; if ( field_name != NULL ) @@ -203,7 +203,7 @@ static bool opr_substitution_read_value unsigned int code = 0; string_t *param; - if ( !sieve_binary_read_unsigned(renv->sbin, address, &code) ) + if ( !sieve_binary_read_unsigned(renv->sblock, address, &code) ) return FALSE; tsub = testsuite_substitution_get(code); @@ -214,9 +214,9 @@ static bool opr_substitution_read_value * actually read the argument. */ if ( str == NULL ) - return sieve_binary_read_string(renv->sbin, address, NULL); + return sieve_binary_read_string(renv->sblock, address, NULL); - if ( !sieve_binary_read_string(renv->sbin, address, ¶m) ) + if ( !sieve_binary_read_string(renv->sblock, address, ¶m) ) return FALSE; return tsub->get_value(str_c(param), str); diff --git a/src/testsuite/tst-test-error.c b/src/testsuite/tst-test-error.c index f5ae3b3c7..cb3b9ae24 100644 --- a/src/testsuite/tst-test-error.c +++ b/src/testsuite/tst-test-error.c @@ -163,7 +163,7 @@ static bool tst_test_error_validate static bool tst_test_error_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *tst) { - sieve_operation_emit(cgenv->sbin, tst->ext, &test_error_operation); + sieve_operation_emit(cgenv->sblock, tst->ext, &test_error_operation); /* Generate arguments */ return sieve_generate_arguments(cgenv, tst, NULL); diff --git a/src/testsuite/tst-test-multiscript.c b/src/testsuite/tst-test-multiscript.c index 0daddda3a..7dba89b68 100644 --- a/src/testsuite/tst-test-multiscript.c +++ b/src/testsuite/tst-test-multiscript.c @@ -78,7 +78,7 @@ static bool tst_test_multiscript_validate static bool tst_test_multiscript_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *tst) { - sieve_operation_emit(cgenv->sbin, tst->ext, &test_multiscript_operation); + sieve_operation_emit(cgenv->sblock, tst->ext, &test_multiscript_operation); /* Generate arguments */ return sieve_generate_arguments(cgenv, tst, NULL); diff --git a/src/testsuite/tst-test-result-execute.c b/src/testsuite/tst-test-result-execute.c index c854415ca..b7bfe28fe 100644 --- a/src/testsuite/tst-test-result-execute.c +++ b/src/testsuite/tst-test-result-execute.c @@ -56,7 +56,7 @@ const struct sieve_operation_def test_result_execute_operation = { static bool tst_test_result_execute_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *tst) { - sieve_operation_emit(cgenv->sbin, tst->ext, &test_result_execute_operation); + sieve_operation_emit(cgenv->sblock, tst->ext, &test_result_execute_operation); return TRUE; } diff --git a/src/testsuite/tst-test-result.c b/src/testsuite/tst-test-result.c index d09e87df1..1c0e5a21a 100644 --- a/src/testsuite/tst-test-result.c +++ b/src/testsuite/tst-test-result.c @@ -168,7 +168,7 @@ static bool tst_test_result_validate static bool tst_test_result_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *tst) { - sieve_operation_emit(cgenv->sbin, tst->ext, &test_result_operation); + sieve_operation_emit(cgenv->sblock, tst->ext, &test_result_operation); /* Generate arguments */ return sieve_generate_arguments(cgenv, tst, NULL); diff --git a/src/testsuite/tst-test-script-compile.c b/src/testsuite/tst-test-script-compile.c index b60464017..ad1705289 100644 --- a/src/testsuite/tst-test-script-compile.c +++ b/src/testsuite/tst-test-script-compile.c @@ -78,7 +78,7 @@ static bool tst_test_script_compile_validate static bool tst_test_script_compile_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *tst) { - sieve_operation_emit(cgenv->sbin, tst->ext, &test_script_compile_operation); + sieve_operation_emit(cgenv->sblock, tst->ext, &test_script_compile_operation); /* Generate arguments */ return sieve_generate_arguments(cgenv, tst, NULL); diff --git a/src/testsuite/tst-test-script-run.c b/src/testsuite/tst-test-script-run.c index d36594568..8c2bf0e2c 100644 --- a/src/testsuite/tst-test-script-run.c +++ b/src/testsuite/tst-test-script-run.c @@ -92,7 +92,7 @@ static bool tst_test_script_run_registered static bool tst_test_script_run_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *tst) { - sieve_operation_emit(cgenv->sbin, tst->ext, &test_script_run_operation); + sieve_operation_emit(cgenv->sblock, tst->ext, &test_script_run_operation); return sieve_generate_arguments(cgenv, tst, NULL); } @@ -110,11 +110,11 @@ static bool tst_test_script_run_operation_dump sieve_code_descend(denv); /* Dump optional operands */ - if ( sieve_operand_optional_present(denv->sbin, address) ) { + if ( sieve_operand_optional_present(denv->sblock, address) ) { while ( opt_code != 0 ) { sieve_code_mark(denv); - if ( !sieve_operand_optional_read(denv->sbin, address, &opt_code) ) + if ( !sieve_operand_optional_read(denv->sblock, address, &opt_code) ) return FALSE; switch ( opt_code ) { @@ -150,9 +150,9 @@ static int tst_test_script_run_operation_execute */ /* Optional operands */ - if ( sieve_operand_optional_present(renv->sbin, address) ) { + if ( sieve_operand_optional_present(renv->sblock, address) ) { while ( opt_code != 0 ) { - if ( !sieve_operand_optional_read(renv->sbin, address, &opt_code) ) { + if ( !sieve_operand_optional_read(renv->sblock, address, &opt_code) ) { sieve_runtime_trace_error(renv, "invalid optional operand"); return SIEVE_EXEC_BIN_CORRUPT; } -- GitLab