Skip to content

Commit be5f710

Browse files
authored
fix: use-after-free in cabi_realloc free_list on repeated export calls (#319)
cabi_realloc tracked all allocations in Runtime.free_list, which post_call freed after each export invocation. When the host calls cabi_realloc during an import to write a return value into guest memory, those allocations may still be referenced by live JS objects across repeated export calls. post_call would free them, causing use-after-free on the next invocation. Fix: remove indiscriminate tracking from cabi_realloc. Only the retptr allocated explicitly in call() is tracked and freed by post_call. Fixes #224
1 parent 499a888 commit be5f710

File tree

1 file changed

+2
-2
lines changed

1 file changed

+2
-2
lines changed

embedding/embedding.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,6 @@ cabi_realloc_adapter(void *ptr, size_t orig_size, size_t org_align,
141141
__attribute__((export_name("cabi_realloc"))) void *
142142
cabi_realloc(void *ptr, size_t orig_size, size_t org_align, size_t new_size) {
143143
void *ret = JS_realloc(Runtime.cx, ptr, orig_size, new_size);
144-
// track all allocations during a function "call" for freeing
145-
Runtime.free_list.push_back(ret);
146144
if (!ret) {
147145
Runtime.engine->abort("(cabi_realloc) Unable to realloc");
148146
}
@@ -233,6 +231,7 @@ __attribute__((export_name("call"))) uint32_t call(uint32_t fn_idx,
233231
if (fn->retptr) {
234232
LOG("(call) setting retptr at arg %d\n", argcnt);
235233
retptr = cabi_realloc(nullptr, 0, 4, fn->retsize);
234+
Runtime.free_list.push_back(retptr);
236235
args[argcnt].setInt32((uint32_t)retptr);
237236
}
238237

@@ -295,6 +294,7 @@ __attribute__((export_name("call"))) uint32_t call(uint32_t fn_idx,
295294
if (!fn->retptr && fn->ret.has_value()) {
296295
LOG("(call) singular return");
297296
retptr = cabi_realloc(0, 0, 4, fn->retsize);
297+
Runtime.free_list.push_back(retptr);
298298
switch (fn->ret.value()) {
299299
case CoreVal::I32:
300300
*((uint32_t *)retptr) = ret.toInt32();

0 commit comments

Comments
 (0)