Skip to content

Commit dc06901

Browse files
committed
Fix crash when decoding extended literals with a large index
Fix a bug where the VM could crash if an extended literal with a large index was encountered. Signed-off-by: Paul Guyot <pguyot@kallisys.net>
1 parent 1e5e1e9 commit dc06901

File tree

5 files changed

+13651
-14
lines changed

5 files changed

+13651
-14
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ instead
3838
- ESP32: content of `boot.avm` partition is not truncated anymore
3939
- ESP32: `Fixed gpio:set_int` to accept any pin, not only pin 2
4040
- Fix memory corruption in `unicode:characters_to_binary`
41-
- Fix handling of large literal indexes
41+
- Fix handling of large literal indexes and large extended literal indexes
4242
- `unicode:characters_to_list`: fixed bogus out_of_memory error on some platforms such as ESP32
4343
- Fix crash in Elixir library when doing `inspect(:atom)`
4444
- General inspect() compliance with Elixir behavior (but there are still some minor differences)

src/libAtomVM/opcodesswitch.h

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -180,11 +180,22 @@ typedef dreg_t dreg_gc_safe_t;
180180
case COMPACT_EXTENDED: \
181181
switch (first_byte) { \
182182
case COMPACT_EXTENDED_LITERAL: { \
183-
uint8_t ext = ((*(decode_pc)++) & 0xF); \
184-
if (ext == 0x8) { \
185-
(decode_pc)++; \
186-
} else if (ext != 0) { \
187-
AVM_ABORT(); \
183+
uint8_t first_extended_byte = *(decode_pc)++; \
184+
switch (((first_extended_byte) >> 3) & 0x3) { \
185+
case 0: \
186+
case 2: \
187+
break; \
188+
\
189+
case 1: \
190+
(decode_pc)++; \
191+
break; \
192+
\
193+
case 3: { \
194+
uint8_t sz = (first_extended_byte >> 5) + 2; \
195+
decode_pc += sz; \
196+
break; \
197+
} \
198+
default: UNREACHABLE(); /* help gcc 8.4 */ \
188199
} \
189200
break; \
190201
} \
@@ -594,14 +605,28 @@ static void destroy_extended_registers(Context *ctx, unsigned int live)
594605
switch (first_byte) { \
595606
case COMPACT_EXTENDED_LITERAL: { \
596607
uint8_t first_extended_byte = *(decode_pc)++; \
597-
if (!(first_extended_byte & 0xF)) { \
598-
dest_term = module_load_literal(mod, first_extended_byte >> 4, ctx); \
599-
} else if ((first_extended_byte & 0xF) == 0x8) { \
600-
uint8_t byte_1 = *(decode_pc)++; \
601-
uint16_t index = (((uint16_t) first_extended_byte & 0xE0) << 3) | byte_1; \
602-
dest_term = module_load_literal(mod, index, ctx); \
603-
} else { \
604-
VM_ABORT(); \
608+
switch (((first_extended_byte) >> 3) & 0x3) { \
609+
case 0: \
610+
case 2: \
611+
dest_term = module_load_literal(mod, first_extended_byte >> 4, ctx); \
612+
break; \
613+
case 1: { \
614+
uint8_t byte_1 = *(decode_pc)++; \
615+
uint16_t index = (((uint16_t) first_extended_byte & 0xE0) << 3) | byte_1; \
616+
dest_term = module_load_literal(mod, index, ctx); \
617+
break; \
618+
} \
619+
case 3: { \
620+
uint8_t sz = (first_extended_byte >> 5) + 2; \
621+
avm_int_t val = 0; \
622+
for (uint8_t vi = 0; vi < sz; vi++) { \
623+
val <<= 8; \
624+
val |= *(decode_pc)++; \
625+
} \
626+
dest_term = module_load_literal(mod, val, ctx); \
627+
break; \
628+
} \
629+
default: UNREACHABLE(); /* help gcc 8.4 */ \
605630
} \
606631
if (UNLIKELY(term_is_invalid_term(dest_term))) { \
607632
RAISE_ERROR(OUT_OF_MEMORY_ATOM); \

tests/erlang_tests/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@ compile_erlang(minuspow63plustwoabs)
322322
compile_erlang(literal_test0)
323323
compile_erlang(literal_test1)
324324
compile_erlang(literal_test2)
325+
compile_erlang(test_extended_literal_large)
325326

326327
compile_erlang(test_list_eq)
327328
compile_erlang(test_tuple_eq)
@@ -791,6 +792,7 @@ add_custom_target(erlang_test_modules DEPENDS
791792
literal_test0.beam
792793
literal_test1.beam
793794
literal_test2.beam
795+
test_extended_literal_large.beam
794796

795797
test_list_eq.beam
796798
test_tuple_eq.beam

0 commit comments

Comments
 (0)