diff options
author | Jo-Philipp Wich <jo@mein.io> | 2020-12-02 20:21:27 +0100 |
---|---|---|
committer | Jo-Philipp Wich <jo@mein.io> | 2020-12-06 16:49:10 +0100 |
commit | 30d3682b7a35496110044bfe2c02a48eedf52a9f (patch) | |
tree | 35a7c64000f9b0dc1930ee760dbe7117afb6afe7 /ast.h | |
parent | 7caf3331ba7d8f0dd91659e4001c9d8256bf4558 (diff) |
treewide: prevent stale pointer access in opcode handlers
Instead of obtaining and caching direct opcode pointers, use relative
references when dealing with opcodes since direct or indirect calls to
uc_execute_op() might lead to reallocations of the opcode array, shifting
memory addresses and invalidating pointers taken before the invocation.
Such stale pointer accesses could be commonly triggered when one part
of the processed expression was a require() or include() call loading
relatively large ucode sources.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'ast.h')
-rw-r--r-- | ast.h | 43 |
1 files changed, 20 insertions, 23 deletions
@@ -154,34 +154,31 @@ struct uc_extended_type { void (*free)(void *); }; -static inline struct uc_op *uc_get_op(struct uc_state *s, uint32_t off) -{ - if (off == 0 || off > s->poolsize) - return NULL; - - return &s->pool[off - 1]; -} - -static inline struct uc_op *uc_get_child(struct uc_state *s, uint32_t off, int n) -{ - struct uc_op *op = uc_get_op(s, off); - - if (!op || n >= ARRAY_SIZE(op->tree.operand) || !op->tree.operand[n]) - return NULL; - - return uc_get_op(s, op->tree.operand[n]); -} - -static inline uint32_t uc_get_off(struct uc_state *s, struct uc_op *op) { - return op ? (op - s->pool + 1) : 0; -}; - static inline bool uc_is_type(struct json_object *val, int type) { struct uc_op *tag = json_object_get_userdata(val); return (tag && tag->type == type); }; +#define OP(idx) (&state->pool[idx]) +#define OP_POS(idx) OP(idx)->off +#define OP_VAL(idx) OP(idx)->val +#define OP_TYPE(idx) OP(idx)->type +#define OP_NEXT(idx) OP(idx)->tree.next +#define OP_IS_LIST(idx) OP(idx)->is_list +#define OP_IS_ELLIP(idx) OP(idx)->is_ellip +#define OP_IS_FOR_IN(idx) OP(idx)->is_for_in +#define OP_IS_POSTFIX(idx) OP(idx)->is_postfix + +#define OPn_NUM ARRAY_SIZE(((struct uc_op *)NULL)->tree.operand) +#define OPn(idx, n) OP(idx)->tree.operand[n] +#define OPn_POS(idx, n) OP(OPn(idx, n))->off +#define OPn_VAL(idx, n) OP(OPn(idx, n))->val +#define OPn_TYPE(idx, n) OP(OPn(idx, n))->type +#define OPn_IS_LIST(idx, n) OP(OPn(idx, n))->is_list +#define OPn_IS_OVERFLOW(idx, n) OP(OPn(idx, n))->is_overflow + + uint32_t uc_new_op(struct uc_state *s, int type, struct json_object *val, ...); uint32_t uc_wrap_op(struct uc_state *s, uint32_t parent, ...); @@ -189,7 +186,7 @@ uint32_t uc_append_op(struct uc_state *s, uint32_t a, uint32_t b); struct json_object *uc_parse(struct uc_state *s, FILE *fp); void uc_free(struct uc_state *s); -struct json_object *uc_new_func(struct uc_state *s, struct uc_op *decl, struct uc_scope *scope); +struct json_object *uc_new_func(struct uc_state *s, uint32_t decl, struct uc_scope *scope); struct json_object *uc_new_object(struct json_object *proto); struct json_object *uc_new_double(double v); struct json_object *uc_new_null(void); |