Skip to content

Commit abd7122

Browse files
committed
opcodesswitch: fix "invalid read" error in bs_append
live parameter doesn't include passed x registers (used as opcode argument). e.g.: `bs_append src=x[2] live=2` The fix is storing src in x[live] and keeping live + 1 alive registers. This issue has been noticed with binaries compiled with OTP-21. Fixes #1571 Signed-off-by: Davide Bettio <davide@uninstall.it>
1 parent a580744 commit abd7122

File tree

2 files changed

+5
-5
lines changed

2 files changed

+5
-5
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ memory error
5959
- Fixed concurrency and memory leak related to links and monitors
6060
- Fixed issues with parsing of line references for stack traces
6161
- Fixed memory corruption issue with `erlang:make_tuple/2`
62+
- Fix potential use after free with code generated from OTP <= 24
6263

6364
### Changed
6465

src/libAtomVM/opcodesswitch.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4337,9 +4337,6 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
43374337
uint32_t unit;
43384338
DECODE_LITERAL(unit, pc);
43394339
term src;
4340-
#ifdef IMPL_EXECUTE_LOOP
4341-
const uint8_t *src_pc = pc;
4342-
#endif
43434340
DECODE_COMPACT_TERM(src, pc)
43444341
term flags;
43454342
UNUSED(flags);
@@ -4367,8 +4364,10 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
43674364

43684365
size_t src_size = term_binary_size(src);
43694366
TRIM_LIVE_REGS(live);
4367+
// there is always room for a MAX_REG + 1 register, used as working register
4368+
x_regs[live] = src;
43704369
// TODO: further investigate extra_val
4371-
if (UNLIKELY(memory_ensure_free_with_roots(ctx, src_size + term_binary_heap_size(size_val / 8) + extra_val, live, x_regs, MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) {
4370+
if (UNLIKELY(memory_ensure_free_with_roots(ctx, src_size + term_binary_heap_size(size_val / 8) + extra_val, live + 1, x_regs, MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) {
43724371
RAISE_ERROR(OUT_OF_MEMORY_ATOM);
43734372
}
43744373
#endif
@@ -4378,7 +4377,7 @@ HOT_FUNC int scheduler_entry_point(GlobalContext *glb)
43784377

43794378
#ifdef IMPL_EXECUTE_LOOP
43804379
TRACE("bs_append/8, fail=%u size=%li unit=%u src=0x%lx dreg=%c%i\n", (unsigned) fail, size_val, (unsigned) unit, src, T_DEST_REG(dreg));
4381-
DECODE_COMPACT_TERM(src, src_pc)
4380+
src = x_regs[live];
43824381
term t = term_create_empty_binary(src_size + size_val / 8, &ctx->heap, ctx->global);
43834382
memcpy((void *) term_binary_data(t), (void *) term_binary_data(src), src_size);
43844383

0 commit comments

Comments
 (0)