Fix: Filter: Fix allocation length error
[lttng-tools.git] / src / lib / lttng-ctl / filter / filter-visitor-generate-bytecode.c
index 332a3875a6039e449970bb9ad0b266278b55cb11..52c69567c37422b1039c544185b7289a3433eff4 100644 (file)
@@ -80,11 +80,14 @@ static inline int get_count_order(unsigned int count)
 static
 int bytecode_init(struct lttng_filter_bytecode_alloc **fb)
 {
-       *fb = calloc(sizeof(struct lttng_filter_bytecode_alloc) + INIT_ALLOC_SIZE, 1);
+       uint32_t alloc_len;
+
+       alloc_len = sizeof(struct lttng_filter_bytecode_alloc) + INIT_ALLOC_SIZE;
+       *fb = calloc(alloc_len, 1);
        if (!*fb) {
                return -ENOMEM;
        } else {
-               (*fb)->alloc_len = INIT_ALLOC_SIZE;
+               (*fb)->alloc_len = alloc_len;
                return 0;
        }
 }
@@ -94,21 +97,22 @@ int32_t bytecode_reserve(struct lttng_filter_bytecode_alloc **fb, uint32_t align
 {
        int32_t ret;
        uint32_t padding = offset_align((*fb)->b.len, align);
+       uint32_t new_len = (*fb)->b.len + padding + len;
+       uint32_t new_alloc_len = sizeof(struct lttng_filter_bytecode_alloc) + new_len;
+       uint32_t old_alloc_len = (*fb)->alloc_len;
 
-       if ((*fb)->b.len + padding + len > LTTNG_FILTER_MAX_LEN)
+       if (new_len > LTTNG_FILTER_MAX_LEN)
                return -EINVAL;
 
-       if ((*fb)->b.len + padding + len > (*fb)->alloc_len) {
-               uint32_t new_len =
-                       max_t(uint32_t, 1U << get_count_order((*fb)->b.len + padding + len),
-                               (*fb)->alloc_len << 1);
-               uint32_t old_len = (*fb)->alloc_len;
-
-               *fb = realloc(*fb, sizeof(struct lttng_filter_bytecode_alloc) + new_len);
+       if (new_alloc_len > old_alloc_len) {
+               new_alloc_len =
+                       max_t(uint32_t, 1U << get_count_order(new_alloc_len), old_alloc_len << 1);
+               *fb = realloc(*fb, new_alloc_len);
                if (!*fb)
                        return -ENOMEM;
-               memset(&(*fb)->b.data[old_len], 0, new_len - old_len);
-               (*fb)->alloc_len = new_len;
+               /* We zero directly the memory from start of allocation. */
+               memset(&((char *) *fb)[old_alloc_len], 0, new_alloc_len - old_alloc_len);
+               (*fb)->alloc_len = new_alloc_len;
        }
        (*fb)->b.len += padding;
        ret = (*fb)->b.len;
@@ -239,7 +243,8 @@ int visit_node_load(struct filter_parser_ctx *ctx, struct ir_op *node)
                uint32_t insn_len = sizeof(struct load_op)
                        + sizeof(struct field_ref);
                struct field_ref ref_offset;
-               uint32_t reloc_offset;
+               uint32_t reloc_offset_u32;
+               uint16_t reloc_offset;
 
                insn = calloc(insn_len, 1);
                if (!insn)
@@ -248,7 +253,12 @@ int visit_node_load(struct filter_parser_ctx *ctx, struct ir_op *node)
                ref_offset.offset = (uint16_t) -1U;
                memcpy(insn->data, &ref_offset, sizeof(ref_offset));
                /* reloc_offset points to struct load_op */
-               reloc_offset = bytecode_get_len(&ctx->bytecode->b);
+               reloc_offset_u32 = bytecode_get_len(&ctx->bytecode->b);
+               if (reloc_offset_u32 > LTTNG_FILTER_MAX_LEN - 1) {
+                       free(insn);
+                       return -EINVAL;
+               }
+               reloc_offset = (uint16_t) reloc_offset_u32;
                ret = bytecode_push(&ctx->bytecode, insn, 1, insn_len);
                if (ret) {
                        free(insn);
This page took 0.02449 seconds and 4 git commands to generate.