summaryrefslogtreecommitdiffhomepage
path: root/ast.h
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2020-12-02 20:21:27 +0100
committerJo-Philipp Wich <jo@mein.io>2020-12-06 16:49:10 +0100
commit30d3682b7a35496110044bfe2c02a48eedf52a9f (patch)
tree35a7c64000f9b0dc1930ee760dbe7117afb6afe7 /ast.h
parent7caf3331ba7d8f0dd91659e4001c9d8256bf4558 (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.h43
1 files changed, 20 insertions, 23 deletions
diff --git a/ast.h b/ast.h
index 126aa65..ecc67b3 100644
--- a/ast.h
+++ b/ast.h
@@ -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);