diff options
author | Maria Matejka <mq@ucw.cz> | 2022-03-02 10:01:44 +0100 |
---|---|---|
committer | Maria Matejka <mq@ucw.cz> | 2022-03-02 10:01:44 +0100 |
commit | d071aca7aaf7a4add9e0d1d93029fb9a0fad560a (patch) | |
tree | 89999b8a4ab23b2243f8cbfca7bb700e85fae36b /filter | |
parent | fcb4dd0c831339c4374ace17d8f2ae6ebfeed279 (diff) | |
parent | 2c13759136951ef0e70a3e3c2b2d3c9a387f7ed9 (diff) |
Merge commit '2c13759136951ef0e70a3e3c2b2d3c9a387f7ed9' into haugesund
Diffstat (limited to 'filter')
-rw-r--r-- | filter/config.Y | 8 | ||||
-rw-r--r-- | filter/decl.m4 | 24 | ||||
-rw-r--r-- | filter/f-inst.c | 1 | ||||
-rw-r--r-- | filter/filter.c | 63 |
4 files changed, 61 insertions, 35 deletions
diff --git a/filter/config.Y b/filter/config.Y index 8916ea97..f27fbbaa 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -290,7 +290,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN, MIN, MAX, EMPTY, FILTER, WHERE, EVAL, ATTRIBUTE, - BT_ASSERT, BT_TEST_SUITE, BT_CHECK_ASSIGN, BT_TEST_SAME, FORMAT) + BT_ASSERT, BT_TEST_SUITE, BT_CHECK_ASSIGN, BT_TEST_SAME, FORMAT, STACKS) %nonassoc THEN %nonassoc ELSE @@ -314,6 +314,12 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN, CF_GRAMMAR +conf: FILTER STACKS expr expr ';' { + new_config->filter_vstk = $3; + new_config->filter_estk = $4; + } + ; + conf: filter_def ; filter_def: FILTER symbol { $2 = cf_define_symbol($2, SYM_FILTER, filter, NULL); cf_push_scope( $2 ); } diff --git a/filter/decl.m4 b/filter/decl.m4 index 5242c04c..44537aaa 100644 --- a/filter/decl.m4 +++ b/filter/decl.m4 @@ -32,6 +32,7 @@ m4_divert(-1)m4_dnl # # 101 content of per-inst struct # 102 constructor arguments +# 110 constructor attributes # 103 constructor body # 104 dump line item content # (there may be nothing in dump-line content and @@ -45,6 +46,7 @@ m4_divert(-1)m4_dnl # Here are macros to allow you to _divert to the right directions. m4_define(FID_STRUCT_IN, `m4_divert(101)') m4_define(FID_NEW_ARGS, `m4_divert(102)') +m4_define(FID_NEW_ATTRIBUTES, `m4_divert(110)') m4_define(FID_NEW_BODY, `m4_divert(103)') m4_define(FID_DUMP_BODY, `m4_divert(104)m4_define([[FID_DUMP_BODY_EXISTS]])') m4_define(FID_LINEARIZE_BODY, `m4_divert(105)') @@ -106,15 +108,18 @@ FID_STRUCT_IN()m4_dnl struct f_inst * f$1; FID_NEW_ARGS()m4_dnl , struct f_inst * f$1 +FID_NEW_ATTRIBUTES()m4_dnl +NONNULL(m4_eval($1+1)) FID_NEW_BODY()m4_dnl whati->f$1 = f$1; -for (const struct f_inst *child = f$1; child; child = child->next) { - what->size += child->size; +const struct f_inst *child$1 = f$1; +do { + what->size += child$1->size; FID_IFCONST([[ - if (child->fi_code != FI_CONSTANT) + if (child$1->fi_code != FI_CONSTANT) constargs = 0; ]]) -} +} while (child$1 = child$1->next); FID_LINEARIZE_BODY pos = linearize(dest, whati->f$1, pos); FID_INTERPRET_BODY()') @@ -190,6 +195,7 @@ FID_INTERPRET_BODY()') # that was needed in the former implementation. m4_define(LINEX, `FID_INTERPRET_EXEC()LINEX_($1)FID_INTERPRET_NEW()return $1 FID_INTERPRET_BODY()') m4_define(LINEX_, `do { + if (fstk->ecnt + 1 >= fstk->elen) runtime("Filter execution stack overflow"); fstk->estk[fstk->ecnt].pos = 0; fstk->estk[fstk->ecnt].line = $1; fstk->estk[fstk->ecnt].ventry = fstk->vcnt; @@ -227,7 +233,7 @@ FID_INTERPRET_BODY()') # state the result and put it to the right place. m4_define(RESULT, `RESULT_TYPE([[$1]]) RESULT_([[$1]],[[$2]],[[$3]])') m4_define(RESULT_, `RESULT_VAL([[ (struct f_val) { .type = $1, .val.$2 = $3 } ]])') -m4_define(RESULT_VAL, `FID_HIC(, [[do { res = $1; fstk->vcnt++; } while (0)]], +m4_define(RESULT_VAL, `FID_HIC(, [[do { res = $1; f_vcnt_check_overflow(1); fstk->vcnt++; } while (0)]], [[return fi_constant(what, $1)]])') m4_define(RESULT_VOID, `RESULT_VAL([[ (struct f_val) { .type = T_VOID } ]])') @@ -309,7 +315,9 @@ m4_undivert(107)m4_dnl FID_NEW()m4_dnl Constructor and interpreter code together FID_HIC( [[m4_dnl Public declaration of constructor in H file -struct f_inst *f_new_inst_]]INST_NAME()[[(enum f_instruction_code fi_code +struct f_inst * +m4_undivert(110)m4_dnl +f_new_inst_]]INST_NAME()[[(enum f_instruction_code fi_code m4_undivert(102)m4_dnl );]], [[m4_dnl The one case in The Big Switch inside interpreter @@ -321,7 +329,9 @@ m4_undivert(102)m4_dnl break; ]], [[m4_dnl Constructor itself -struct f_inst *f_new_inst_]]INST_NAME()[[(enum f_instruction_code fi_code +struct f_inst * +m4_undivert(110)m4_dnl +f_new_inst_]]INST_NAME()[[(enum f_instruction_code fi_code m4_undivert(102)m4_dnl ) { diff --git a/filter/f-inst.c b/filter/f-inst.c index 901d2939..a88021e6 100644 --- a/filter/f-inst.c +++ b/filter/f-inst.c @@ -1103,6 +1103,7 @@ curline.vbase = curline.ventry; /* Storage for local variables */ + f_vcnt_check_overflow(sym->function->vars); memset(&(fstk->vstk[fstk->vcnt]), 0, sizeof(struct f_val) * sym->function->vars); fstk->vcnt += sym->function->vars; } diff --git a/filter/filter.c b/filter/filter.c index e505d570..7004b96d 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -50,30 +50,28 @@ enum f_exception { FE_RETURN = 0x1, }; - -struct filter_stack { - /* Value stack for execution */ -#define F_VAL_STACK_MAX 4096 - uint vcnt; /* Current value stack size; 0 for empty */ - uint ecnt; /* Current execute stack size; 0 for empty */ - - struct f_val vstk[F_VAL_STACK_MAX]; /* The stack itself */ - - /* Instruction stack for execution */ -#define F_EXEC_STACK_MAX 4096 - struct { - const struct f_line *line; /* The line that is being executed */ - uint pos; /* Instruction index in the line */ - uint ventry; /* Value stack depth on entry */ - uint vbase; /* Where to index variable positions from */ - enum f_exception emask; /* Exception mask */ - } estk[F_EXEC_STACK_MAX]; +struct filter_exec_stack { + const struct f_line *line; /* The line that is being executed */ + uint pos; /* Instruction index in the line */ + uint ventry; /* Value stack depth on entry */ + uint vbase; /* Where to index variable positions from */ + enum f_exception emask; /* Exception mask */ }; /* Internal filter state, to be allocated on stack when executing filters */ struct filter_state { /* Stacks needed for execution */ - struct filter_stack *stack; + struct filter_stack { + /* Current filter stack depth */ + + /* Value stack */ + uint vcnt, vlen; + struct f_val *vstk; + + /* Instruction stack for execution */ + uint ecnt, elen; + struct filter_exec_stack *estk; + } stack; /* The route we are processing. This may be NULL to indicate no route available. */ struct rte **rte; @@ -95,10 +93,13 @@ struct filter_state { }; _Thread_local static struct filter_state filter_state; -_Thread_local static struct filter_stack filter_stack; void (*bt_assert_hook)(int result, const struct f_line_item *assert); +#define _f_stack_init(fs, px, def) ((fs).stack.px##stk = alloca(sizeof(*(fs).stack.px##stk) * ((fs).stack.px##len = (config && config->filter_##px##stk) ? config->filter_##px##stk : (def)))) + +#define f_stack_init(fs) ( _f_stack_init(fs, v, 128), _f_stack_init(fs, e, 128) ) + static inline void f_cache_eattrs(struct filter_state *fs) { fs->eattrs = &((*fs->rte)->attrs->eattrs); @@ -163,15 +164,17 @@ interpret(struct filter_state *fs, const struct f_line *line, struct f_val *val) ASSERT(line->args == 0); /* Initialize the filter stack */ - struct filter_stack *fstk = fs->stack; + struct filter_stack *fstk = &fs->stack; fstk->vcnt = line->vars; memset(fstk->vstk, 0, sizeof(struct f_val) * line->vars); /* The same as with the value stack. Not resetting the stack for performance reasons. */ fstk->ecnt = 1; - fstk->estk[0].line = line; - fstk->estk[0].pos = 0; + fstk->estk[0] = (struct filter_exec_stack) { + .line = line, + .pos = 0, + }; #define curline fstk->estk[fstk->ecnt-1] @@ -191,6 +194,8 @@ interpret(struct filter_state *fs, const struct f_line *line, struct f_val *val) #define v2 vv(1) #define v3 vv(2) +#define f_vcnt_check_overflow(n) do { if (fstk->vcnt + n >= fstk->vlen) runtime("Filter execution stack overflow"); } while (0) + #define runtime(fmt, ...) do { \ if (!(fs->flags & FF_SILENT)) \ log_rl(&rl_runtime_err, L_ERR "filters, line %d: " fmt, what->lineno, ##__VA_ARGS__); \ @@ -276,12 +281,13 @@ f_run(const struct filter *filter, struct rte **rte, struct linpool *tmp_pool, i /* Initialize the filter state */ filter_state = (struct filter_state) { - .stack = &filter_stack, .rte = rte, .pool = tmp_pool, .flags = flags, }; + f_stack_init(filter_state); + LOG_BUFFER_INIT(filter_state.buf); /* Run the interpreter itself */ @@ -340,11 +346,12 @@ enum filter_return f_eval_rte(const struct f_line *expr, struct rte **rte, struct linpool *tmp_pool) { filter_state = (struct filter_state) { - .stack = &filter_stack, .rte = rte, .pool = tmp_pool, }; + f_stack_init(filter_state); + LOG_BUFFER_INIT(filter_state.buf); ASSERT(!((*rte)->flags & REF_COW)); @@ -363,10 +370,11 @@ enum filter_return f_eval(const struct f_line *expr, struct linpool *tmp_pool, struct f_val *pres) { filter_state = (struct filter_state) { - .stack = &filter_stack, .pool = tmp_pool, }; + f_stack_init(filter_state); + LOG_BUFFER_INIT(filter_state.buf); enum filter_return fret = interpret(&filter_state, expr, pres); @@ -383,10 +391,11 @@ f_eval_int(const struct f_line *expr) { /* Called independently in parse-time to eval expressions */ filter_state = (struct filter_state) { - .stack = &filter_stack, .pool = cfg_mem, }; + f_stack_init(filter_state); + struct f_val val; LOG_BUFFER_INIT(filter_state.buf); |