#ifndef SIEVE_CODE_H #define SIEVE_CODE_H #include "lib.h" #include "buffer.h" #include "mempool.h" #include "array.h" #include "sieve-common.h" #include "sieve-runtime.h" #include "sieve-runtime-trace.h" #include "sieve-dump.h" /* * Operand object */ struct sieve_operand_class { const char *name; }; struct sieve_operand_def { const char *name; const struct sieve_extension_def *ext_def; unsigned int code; const struct sieve_operand_class *class; const void *interface; }; struct sieve_operand { const struct sieve_operand_def *def; const struct sieve_extension *ext; sieve_size_t address; const char *field_name; }; #define sieve_operand_name(opr) \ ( (opr)->def == NULL ? "(NULL)" : (opr)->def->name ) #define sieve_operand_is(opr, definition) \ ( (opr)->def == &(definition) ) sieve_size_t sieve_operand_emit (struct sieve_binary_block *sblock, const struct sieve_extension *ext, const struct sieve_operand_def *oprnd); bool sieve_operand_read (struct sieve_binary_block *sblock, sieve_size_t *address, const char *field_name, struct sieve_operand *oprnd); static inline int sieve_operand_runtime_read (const struct sieve_runtime_env *renv, sieve_size_t *address, const char *field_name, struct sieve_operand *operand) { if ( !sieve_operand_read(renv->sblock, address, field_name, operand) ) { sieve_runtime_trace_operand_error(renv, operand, "invalid operand"); return SIEVE_EXEC_BIN_CORRUPT; } return SIEVE_EXEC_OK; } /* * Optional operands */ int sieve_opr_optional_next (struct sieve_binary_block *sblock, sieve_size_t *address, signed int *opt_code); static inline int sieve_opr_optional_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address, signed int *opt_code) { sieve_size_t pc = *address; int ret; if ( (ret=sieve_opr_optional_next(denv->sblock, address, opt_code)) <= 0 ) return ret; sieve_code_mark_specific(denv, pc); return ret; } static inline int sieve_opr_optional_read (const struct sieve_runtime_env *renv, sieve_size_t *address, signed int *opt_code) { int ret; if ( (ret=sieve_opr_optional_next(renv->sblock, address, opt_code)) < 0 ) sieve_runtime_trace_error(renv, "invalid optional operand code"); return ret; } /* * Core operands */ /* Operand codes */ enum sieve_core_operand { SIEVE_OPERAND_OPTIONAL = 0x00, SIEVE_OPERAND_NUMBER, SIEVE_OPERAND_STRING, SIEVE_OPERAND_STRING_LIST, SIEVE_OPERAND_COMPARATOR, SIEVE_OPERAND_MATCH_TYPE, SIEVE_OPERAND_ADDRESS_PART, SIEVE_OPERAND_CATENATED_STRING, SIEVE_OPERAND_CUSTOM }; /* Operand classes */ extern const struct sieve_operand_class number_class; extern const struct sieve_operand_class string_class; extern const struct sieve_operand_class stringlist_class; /* Operand objects */ extern const struct sieve_operand_def omitted_operand; extern const struct sieve_operand_def number_operand; extern const struct sieve_operand_def string_operand; extern const struct sieve_operand_def stringlist_operand; extern const struct sieve_operand_def catenated_string_operand; extern const struct sieve_operand_def *sieve_operands[]; extern const unsigned int sieve_operand_count; /* Operand object interfaces */ struct sieve_opr_number_interface { bool (*dump) (const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, sieve_size_t *address); int (*read) (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, sieve_size_t *address, sieve_number_t *number_r); }; struct sieve_opr_string_interface { bool (*dump) (const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, sieve_size_t *address); int (*read) (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, sieve_size_t *address, string_t **str_r); }; struct sieve_opr_stringlist_interface { bool (*dump) (const struct sieve_dumptime_env *denv, const struct sieve_operand *oprnd, sieve_size_t *address); int (*read) (const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, sieve_size_t *address, struct sieve_stringlist **strlist_r); }; /* * Core operand functions */ /* Omitted */ void sieve_opr_omitted_emit(struct sieve_binary_block *sblock); static inline bool sieve_operand_is_omitted (const struct sieve_operand *operand) { return ( operand != NULL && operand->def != NULL && operand->def == &omitted_operand ); } /* 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, struct sieve_operand *operand, sieve_size_t *address, const char *field_name); bool sieve_opr_number_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address, const char *field_name); int sieve_opr_number_read_data (const struct sieve_runtime_env *renv, struct sieve_operand *operand, sieve_size_t *address, const char *field_name, sieve_number_t *number_r); int sieve_opr_number_read (const struct sieve_runtime_env *renv, sieve_size_t *address, const char *field_name, sieve_number_t *number_r); static inline bool sieve_operand_is_number (const struct sieve_operand *operand) { return ( operand != NULL && operand->def != NULL && operand->def->class == &number_class ); } /* String */ 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, struct sieve_operand *operand, sieve_size_t *address, const char *field_name); bool sieve_opr_string_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address, const char *field_name); bool sieve_opr_string_dump_ex (const struct sieve_dumptime_env *denv, sieve_size_t *address, const char *field_name, const char *omitted_value); int sieve_opr_string_read_data (const struct sieve_runtime_env *renv, struct sieve_operand *operand, sieve_size_t *address, const char *field_name, string_t **str_r); int sieve_opr_string_read (const struct sieve_runtime_env *renv, sieve_size_t *address, const char *field_name, string_t **str_r); int sieve_opr_string_read_ex (const struct sieve_runtime_env *renv, sieve_size_t *address, const char *field_name, bool optional, string_t **str_r, bool *literal_r); static inline bool sieve_operand_is_string (const struct sieve_operand *operand) { return ( operand != NULL && operand->def != NULL && operand->def->class == &string_class ); } static inline bool sieve_operand_is_string_literal (const struct sieve_operand *operand) { return ( operand != NULL && sieve_operand_is(operand, string_operand) ); } /* String list */ void sieve_opr_stringlist_emit_start (struct sieve_binary_block *sblock, unsigned int listlen, void **context); void sieve_opr_stringlist_emit_item (struct sieve_binary_block *sblock, void *context ATTR_UNUSED, string_t *item); void sieve_opr_stringlist_emit_end (struct sieve_binary_block *sblock, void *context); bool sieve_opr_stringlist_dump_data (const struct sieve_dumptime_env *denv, struct sieve_operand *operand, sieve_size_t *address, const char *field_name); bool sieve_opr_stringlist_dump (const struct sieve_dumptime_env *denv, sieve_size_t *address, const char *field_name); bool sieve_opr_stringlist_dump_ex (const struct sieve_dumptime_env *denv, sieve_size_t *address, const char *field_name, const char *omitted_value); int sieve_opr_stringlist_read_data (const struct sieve_runtime_env *renv, struct sieve_operand *operand, sieve_size_t *address, const char *field_name, struct sieve_stringlist **strlist_r); int sieve_opr_stringlist_read (const struct sieve_runtime_env *renv, sieve_size_t *address, const char *field_name, struct sieve_stringlist **strlist_r); int sieve_opr_stringlist_read_ex (const struct sieve_runtime_env *renv, sieve_size_t *address, const char *field_name, bool optional, struct sieve_stringlist **strlist_r); static inline bool sieve_operand_is_stringlist (const struct sieve_operand *operand) { return ( operand != NULL && operand->def != NULL && (operand->def->class == &stringlist_class || operand->def->class == &string_class) ); } /* Catenated string */ void sieve_opr_catenated_string_emit (struct sieve_binary_block *sblock, unsigned int elements); /* * Operation object */ struct sieve_operation_def { const char *mnemonic; const struct sieve_extension_def *ext_def; unsigned int code; bool (*dump) (const struct sieve_dumptime_env *denv, sieve_size_t *address); int (*execute) (const struct sieve_runtime_env *renv, sieve_size_t *address); }; struct sieve_operation { const struct sieve_operation_def *def; const struct sieve_extension *ext; sieve_size_t address; }; #define sieve_operation_is(oprtn, definition) \ ( (oprtn)->def == &(definition) ) #define sieve_operation_mnemonic(oprtn) \ ( (oprtn)->def == NULL ? "(NULL)" : (oprtn)->def->mnemonic ) sieve_size_t sieve_operation_emit (struct sieve_binary_block *sblock, const struct sieve_extension *ext, const struct sieve_operation_def *op_def); bool sieve_operation_read (struct sieve_binary_block *sblock, sieve_size_t *address, struct sieve_operation *oprtn); const char *sieve_operation_read_string (struct sieve_binary_block *sblock, sieve_size_t *address); /* * Core operations */ /* Opcodes */ enum sieve_operation_code { SIEVE_OPERATION_INVALID, SIEVE_OPERATION_JMP, SIEVE_OPERATION_JMPTRUE, SIEVE_OPERATION_JMPFALSE, SIEVE_OPERATION_STOP, SIEVE_OPERATION_KEEP, SIEVE_OPERATION_DISCARD, SIEVE_OPERATION_REDIRECT, SIEVE_OPERATION_ADDRESS, SIEVE_OPERATION_HEADER, SIEVE_OPERATION_EXISTS, SIEVE_OPERATION_SIZE_OVER, SIEVE_OPERATION_SIZE_UNDER, SIEVE_OPERATION_CUSTOM }; /* Operation objects */ extern const struct sieve_operation_def sieve_jmp_operation; extern const struct sieve_operation_def sieve_jmptrue_operation; extern const struct sieve_operation_def sieve_jmpfalse_operation; extern const struct sieve_operation_def *sieve_operations[]; extern const unsigned int sieve_operations_count; #endif