Remove unnecessary max-allocation limit checks from bytecode runtime

Allocations for bytecode signatures to work need not check against the
memory allocation limit, as bytecode signatures are considered trusted
user input.

You may note that I did not remove allocation limits from the bytecode
API functions that may be called by the signatures such as adding json
objects, hashsets, lzma and bz2 decompressors, etc. This is because it
is likely that a bytecode signature may call them more times based on
the structure of the file being scanned - particularly for the json objects.
This commit is contained in:
Micah Snyder 2024-01-09 16:28:51 -05:00 committed by Micah Snyder
parent 9dc80eb8e7
commit 609ace2e3c
3 changed files with 50 additions and 50 deletions

View file

@ -340,12 +340,12 @@ cl_error_t cli_bytecode_context_setfuncid(struct cli_bc_ctx *ctx, const struct c
ctx->numParams = func->numArgs;
ctx->funcid = funcid;
if (func->numArgs) {
ctx->operands = cli_max_malloc(sizeof(*ctx->operands) * func->numArgs);
ctx->operands = malloc(sizeof(*ctx->operands) * func->numArgs);
if (!ctx->operands) {
cli_errmsg("bytecode: error allocating memory for parameters\n");
return CL_EMEM;
}
ctx->opsizes = cli_max_malloc(sizeof(*ctx->opsizes) * func->numArgs);
ctx->opsizes = malloc(sizeof(*ctx->opsizes) * func->numArgs);
if (!ctx->opsizes) {
cli_errmsg("bytecode: error allocating memory for opsizes\n");
return CL_EMEM;
@ -359,7 +359,7 @@ cl_error_t cli_bytecode_context_setfuncid(struct cli_bc_ctx *ctx, const struct c
}
s += 8; /* return value */
ctx->bytes = s;
ctx->values = cli_max_malloc(s);
ctx->values = malloc(s);
if (!ctx->values) {
cli_errmsg("bytecode: error allocating memory for parameters\n");
return CL_EMEM;
@ -507,7 +507,7 @@ static inline operand_t readOperand(struct cli_bc_func *func, unsigned char *p,
uint16_t ty;
p[*off] |= 0x20;
/* TODO: unique constants */
func->constants = cli_max_realloc2(func->constants, (func->numConstants + 1) * sizeof(*func->constants));
func->constants = cli_safer_realloc2(func->constants, (func->numConstants + 1) * sizeof(*func->constants));
if (!func->constants) {
*ok = false;
return MAX_OP;
@ -565,7 +565,7 @@ static inline char *readData(const unsigned char *p, unsigned *off, unsigned len
*ok = false;
return 0;
}
dat = cli_max_malloc(l);
dat = malloc(l);
if (!dat) {
cli_errmsg("Cannot allocate memory for data\n");
*ok = false;
@ -679,12 +679,12 @@ static cl_error_t parseHeader(struct cli_bc *bc, unsigned char *buffer, unsigned
return CL_EMALFDB;
}
bc->funcs = cli_max_calloc(bc->num_func, sizeof(*bc->funcs));
bc->funcs = calloc(bc->num_func, sizeof(*bc->funcs));
if (!bc->funcs) {
cli_errmsg("Out of memory allocating %u functions\n", bc->num_func);
return CL_EMEM;
}
bc->types = cli_max_calloc(bc->num_types, sizeof(*bc->types));
bc->types = calloc(bc->num_types, sizeof(*bc->types));
if (!bc->types) {
cli_errmsg("Out of memory allocating %u types\n", bc->num_types);
return CL_EMEM;
@ -737,7 +737,7 @@ static void parseType(struct cli_bc *bc, struct cli_bc_type *ty,
*ok = false;
return;
}
ty->containedTypes = cli_max_malloc(sizeof(*ty->containedTypes) * ty->numElements);
ty->containedTypes = malloc(sizeof(*ty->containedTypes) * ty->numElements);
if (!ty->containedTypes) {
cli_errmsg("Out of memory allocating %u types\n", ty->numElements);
*ok = false;
@ -926,7 +926,7 @@ static cl_error_t parseApis(struct cli_bc *bc, unsigned char *buffer)
cli_errmsg("Out of memory allocating apis bitset\n");
return CL_EMEM;
}
apity2ty = cli_max_calloc(cli_apicall_maxtypes, sizeof(*cli_apicall_types));
apity2ty = calloc(cli_apicall_maxtypes, sizeof(*cli_apicall_types));
if (!apity2ty) {
cli_errmsg("Out of memory allocating apity2ty\n");
return CL_EMEM;
@ -1041,12 +1041,12 @@ static cl_error_t parseGlobals(struct cli_bc *bc, unsigned char *buffer)
return CL_BREAK;
}
numglobals = readNumber(buffer, &offset, len, &ok);
bc->globals = cli_max_calloc(numglobals, sizeof(*bc->globals));
bc->globals = calloc(numglobals, sizeof(*bc->globals));
if (!bc->globals) {
cli_errmsg("bytecode: OOM allocating memory for %u globals\n", numglobals);
return CL_EMEM;
}
bc->globaltys = cli_max_calloc(numglobals, sizeof(*bc->globaltys));
bc->globaltys = calloc(numglobals, sizeof(*bc->globaltys));
if (!bc->globaltys) {
cli_errmsg("bytecode: OOM allocating memory for %u global types\n", numglobals);
return CL_EMEM;
@ -1060,7 +1060,7 @@ static cl_error_t parseGlobals(struct cli_bc *bc, unsigned char *buffer)
comp = type_components(bc, bc->globaltys[i], &ok);
if (!ok)
return CL_EMALFDB;
bc->globals[i] = cli_max_malloc(sizeof(*bc->globals[0]) * comp);
bc->globals[i] = malloc(sizeof(*bc->globals[0]) * comp);
if (!bc->globals[i])
return CL_EMEM;
readConstant(bc, i, comp, buffer, &offset, len, &ok);
@ -1089,7 +1089,7 @@ static cl_error_t parseMD(struct cli_bc *bc, unsigned char *buffer)
}
b = bc->dbgnode_cnt;
bc->dbgnode_cnt += numMD;
bc->dbgnodes = cli_max_realloc(bc->dbgnodes, bc->dbgnode_cnt * sizeof(*bc->dbgnodes));
bc->dbgnodes = cli_safer_realloc(bc->dbgnodes, bc->dbgnode_cnt * sizeof(*bc->dbgnodes));
if (!bc->dbgnodes)
return CL_EMEM;
for (i = 0; i < numMD; i++) {
@ -1101,7 +1101,7 @@ static cl_error_t parseMD(struct cli_bc *bc, unsigned char *buffer)
return CL_EMALFDB;
}
bc->dbgnodes[b + i].numelements = el;
bc->dbgnodes[b + i].elements = elts = cli_max_calloc(el, sizeof(*elts));
bc->dbgnodes[b + i].elements = elts = calloc(el, sizeof(*elts));
if (!elts)
return CL_EMEM;
for (j = 0; j < el; j++) {
@ -1161,7 +1161,7 @@ static cl_error_t parseFunctionHeader(struct cli_bc *bc, unsigned fn, unsigned c
if (!all_locals) {
func->types = NULL;
} else {
func->types = cli_max_calloc(all_locals, sizeof(*func->types));
func->types = calloc(all_locals, sizeof(*func->types));
if (!func->types) {
cli_errmsg("Out of memory allocating function arguments\n");
return CL_EMEM;
@ -1189,7 +1189,7 @@ static cl_error_t parseFunctionHeader(struct cli_bc *bc, unsigned fn, unsigned c
func->numValues = func->numArgs + func->numLocals;
func->insn_idx = 0;
func->numConstants = 0;
func->allinsts = cli_max_calloc(func->numInsts, sizeof(*func->allinsts));
func->allinsts = calloc(func->numInsts, sizeof(*func->allinsts));
if (!func->allinsts) {
cli_errmsg("Out of memory allocating instructions\n");
return CL_EMEM;
@ -1199,7 +1199,7 @@ static cl_error_t parseFunctionHeader(struct cli_bc *bc, unsigned fn, unsigned c
cli_errmsg("Invalid basic block count\n");
return CL_EMALFDB;
}
func->BB = cli_max_calloc(func->numBB, sizeof(*func->BB));
func->BB = calloc(func->numBB, sizeof(*func->BB));
if (!func->BB) {
cli_errmsg("Out of memory allocating basic blocks\n");
return CL_EMEM;
@ -1303,7 +1303,7 @@ static cl_error_t parseBB(struct cli_bc *bc, unsigned func, unsigned bb, unsigne
if (!numOp) {
inst.u.ops.ops = NULL;
} else {
inst.u.ops.ops = cli_max_calloc(numOp, sizeof(*inst.u.ops.ops));
inst.u.ops.ops = calloc(numOp, sizeof(*inst.u.ops.ops));
if (!inst.u.ops.ops) {
cli_errmsg("Out of memory allocating operands\n");
return CL_EMEM;
@ -1348,7 +1348,7 @@ static cl_error_t parseBB(struct cli_bc *bc, unsigned func, unsigned bb, unsigne
if (ok) {
inst.u.ops.numOps = numOp + 2;
inst.u.ops.opsizes = NULL;
inst.u.ops.ops = cli_max_calloc(numOp + 2, sizeof(*inst.u.ops.ops));
inst.u.ops.ops = calloc(numOp + 2, sizeof(*inst.u.ops.ops));
if (!inst.u.ops.ops) {
cli_errmsg("Out of memory allocating operands\n");
return CL_EMEM;
@ -1468,7 +1468,7 @@ static cl_error_t parseBB(struct cli_bc *bc, unsigned func, unsigned bb, unsigne
cli_errmsg("invalid number of dbg nodes, expected: %u, got: %u\n", bcfunc->numInsts, num);
return CL_EMALFDB;
}
bcfunc->dbgnodes = cli_max_malloc(num * sizeof(*bcfunc->dbgnodes));
bcfunc->dbgnodes = malloc(num * sizeof(*bcfunc->dbgnodes));
if (!bcfunc->dbgnodes) {
cli_errmsg("Unable to allocate memory for dbg nodes: %u\n", num * (uint32_t)sizeof(*bcfunc->dbgnodes));
return CL_EMEM;
@ -1659,7 +1659,7 @@ cl_error_t cli_bytecode_load(struct cli_bc *bc, FILE *f, struct cli_dbio *dbio,
cli_errmsg("Error at bytecode line %u\n", row);
return rc;
}
buffer = cli_max_malloc(linelength);
buffer = malloc(linelength);
if (!buffer) {
cli_errmsg("Out of memory allocating line of length %u\n", linelength);
return CL_EMEM;
@ -2135,7 +2135,7 @@ static cl_error_t cli_bytecode_prepare_interpreter(struct cli_bc *bc)
unsigned bcglobalid = cli_apicall_maxglobal - _FIRST_GLOBAL + 2;
cl_error_t ret = CL_SUCCESS;
bc->numGlobalBytes = 0;
gmap = cli_max_malloc(bc->num_globals * sizeof(*gmap));
gmap = malloc(bc->num_globals * sizeof(*gmap));
if (!gmap) {
cli_errmsg("interpreter: Unable to allocate memory for global map: %zu\n", bc->num_globals * sizeof(*gmap));
return CL_EMEM;
@ -2149,7 +2149,7 @@ static cl_error_t cli_bytecode_prepare_interpreter(struct cli_bc *bc)
bc->numGlobalBytes += typesize(bc, ty);
}
if (bc->numGlobalBytes) {
bc->globalBytes = cli_max_calloc(1, bc->numGlobalBytes);
bc->globalBytes = calloc(1, bc->numGlobalBytes);
if (!bc->globalBytes) {
cli_errmsg("interpreter: Unable to allocate memory for globalBytes: %u\n", bc->numGlobalBytes);
free(gmap);
@ -2215,7 +2215,7 @@ static cl_error_t cli_bytecode_prepare_interpreter(struct cli_bc *bc)
for (i = 0; i < bc->num_func && ret == CL_SUCCESS; i++) {
struct cli_bc_func *bcfunc = &bc->funcs[i];
unsigned totValues = bcfunc->numValues + bcfunc->numConstants + bc->num_globals;
unsigned *map = cli_max_malloc(sizeof(*map) * (size_t)totValues);
unsigned *map = malloc(sizeof(*map) * (size_t)totValues);
if (!map) {
cli_errmsg("interpreter: Unable to allocate memory for map: %zu\n", sizeof(*map) * (size_t)totValues);
free(gmap);
@ -2311,7 +2311,7 @@ static cl_error_t cli_bytecode_prepare_interpreter(struct cli_bc *bc)
if (ret != CL_SUCCESS)
break;
if (inst->u.ops.numOps > 0) {
inst->u.ops.opsizes = cli_max_malloc(sizeof(*inst->u.ops.opsizes) * inst->u.ops.numOps);
inst->u.ops.opsizes = malloc(sizeof(*inst->u.ops.opsizes) * inst->u.ops.numOps);
if (!inst->u.ops.opsizes) {
cli_errmsg("Out of memory when allocating operand sizes\n");
ret = CL_EMEM;
@ -2407,7 +2407,7 @@ static cl_error_t add_selfcheck(struct cli_all_bc *bcs)
struct cli_bc_inst *inst;
struct cli_bc *bc;
bcs->all_bcs = cli_max_realloc2(bcs->all_bcs, sizeof(*bcs->all_bcs) * (bcs->count + 1));
bcs->all_bcs = cli_safer_realloc2(bcs->all_bcs, sizeof(*bcs->all_bcs) * (bcs->count + 1));
if (!bcs->all_bcs) {
cli_errmsg("cli_loadcbc: Can't allocate memory for bytecode entry\n");
return CL_EMEM;
@ -2608,7 +2608,7 @@ static cl_error_t run_builtin_or_loaded(struct cli_all_bc *bcs, uint8_t kind, co
if (!bc) {
/* no loaded bytecode found, load the builtin one! */
struct cli_dbio dbio;
bc = cli_max_calloc(1, sizeof(*bc));
bc = calloc(1, sizeof(*bc));
if (!bc) {
cli_errmsg("Out of memory allocating bytecode\n");
return CL_EMEM;

View file

@ -286,17 +286,17 @@ static always_inline struct stack_entry *pop_stack(struct stack *stack,
*(uint8_t *)&values[p] = x
#define WRITE16(p, x) \
CHECK_GT(func->numBytes, p + 1); \
CHECK_EQ((p)&1, 0); \
CHECK_EQ((p) & 1, 0); \
TRACE_W(x, p, 16); \
*(uint16_t *)&values[p] = x
#define WRITE32(p, x) \
CHECK_GT(func->numBytes, p + 3); \
CHECK_EQ((p)&3, 0); \
CHECK_EQ((p) & 3, 0); \
TRACE_W(x, p, 32); \
*(uint32_t *)&values[p] = x
#define WRITE64(p, x) \
CHECK_GT(func->numBytes, p + 7); \
CHECK_EQ((p)&7, 0); \
CHECK_EQ((p) & 7, 0); \
TRACE_W(x, p, 64); \
*(uint64_t *)&values[p] = x
#define WRITEP(x, p) \
@ -348,8 +348,8 @@ static always_inline struct stack_entry *pop_stack(struct stack *stack,
}
#define READPOP(x, p, asize) \
{ \
if ((p)&0x40000000) { \
unsigned ptr__ = (p)&0xbfffffff; \
if ((p) & 0x40000000) { \
unsigned ptr__ = (p) & 0xbfffffff; \
CHECK_GT(func->numBytes, ptr__); \
TRACE_PTR(ptr__, asize); \
x = (void *)&values[ptr__]; \
@ -364,17 +364,17 @@ static always_inline struct stack_entry *pop_stack(struct stack *stack,
TRACE_R(x)
#define READOLD16(x, p) \
CHECK_GT(func->numBytes, p + 1); \
CHECK_EQ((p)&1, 0); \
CHECK_EQ((p) & 1, 0); \
x = *(uint16_t *)&old_values[p]; \
TRACE_R(x)
#define READOLD32(x, p) \
CHECK_GT(func->numBytes, p + 3); \
CHECK_EQ((p)&3, 0); \
CHECK_EQ((p) & 3, 0); \
x = *(uint32_t *)&old_values[p]; \
TRACE_R(x)
#define READOLD64(x, p) \
CHECK_GT(func->numBytes, p + 7); \
CHECK_EQ((p)&7, 0); \
CHECK_EQ((p) & 7, 0); \
x = *(uint64_t *)&old_values[p]; \
TRACE_R(x)
@ -596,7 +596,7 @@ static inline int64_t ptr_register_stack(struct ptr_infos *infos,
uint32_t off, uint32_t size)
{
unsigned n = infos->nstacks + 1;
struct ptr_info *sinfos = cli_max_realloc(infos->stack_infos,
struct ptr_info *sinfos = cli_safer_realloc(infos->stack_infos,
sizeof(*sinfos) * n);
if (!sinfos)
return 0;
@ -613,7 +613,7 @@ static inline int64_t ptr_register_glob_fixedid(struct ptr_infos *infos,
{
struct ptr_info *sinfos;
if (n > infos->nglobs) {
sinfos = cli_max_realloc(infos->glob_infos, sizeof(*sinfos) * n);
sinfos = cli_safer_realloc(infos->glob_infos, sizeof(*sinfos) * n);
if (!sinfos)
return 0;
memset(sinfos + infos->nglobs, 0, (n - infos->nglobs) * sizeof(*sinfos));

View file

@ -54,7 +54,7 @@ cli_events_t *cli_events_new(unsigned max_event)
if (!ev)
return NULL;
ev->max = max_event;
ev->events = cli_max_calloc(max_event, sizeof(*ev->events));
ev->events = calloc(max_event, sizeof(*ev->events));
if (!ev->events) {
free(ev);
return NULL;
@ -132,7 +132,7 @@ static inline void ev_chain(cli_events_t *ctx, struct cli_event *ev, union ev_va
union ev_val *chain;
uint32_t siz = sizeof(*chain) * (ev->count + 1);
chain = cli_max_realloc(ev->u.v_chain, siz);
chain = cli_safer_realloc(ev->u.v_chain, siz);
if (!chain) {
cli_event_error_oom(ctx, siz);
return;
@ -294,7 +294,7 @@ void cli_event_data(cli_events_t *ctx, unsigned id, const void *data, uint32_t l
}
switch (ev->multiple) {
case multiple_last: {
void *v_data = cli_max_realloc2(ev->u.v_data, len);
void *v_data = cli_safer_realloc2(ev->u.v_data, len);
if (v_data) {
ev->u.v_data = v_data;
memcpy(v_data, data, len);
@ -305,7 +305,7 @@ void cli_event_data(cli_events_t *ctx, unsigned id, const void *data, uint32_t l
break;
}
case multiple_concat: {
void *v_data = cli_max_realloc2(ev->u.v_data, ev->count + len);
void *v_data = cli_safer_realloc2(ev->u.v_data, ev->count + len);
if (v_data) {
ev->u.v_data = v_data;
memcpy((char *)v_data + ev->count, data, len);