From 9aae34493d05bb394394722e3393bb865ffaa412 Mon Sep 17 00:00:00 2001 From: Paul Guyot Date: Sat, 21 Sep 2024 23:15:53 +0200 Subject: [PATCH] Fix decoding of large index of literals (fix #1272) Signed-off-by: Paul Guyot --- CHANGELOG.md | 3 +- src/libAtomVM/opcodesswitch.h | 26 ++++++++--- tests/erlang_tests/CMakeLists.txt | 2 + tests/erlang_tests/literal_test2.erl | 67 ++++++++++++++++++++++++++++ tests/test.c | 1 + 5 files changed, 92 insertions(+), 7 deletions(-) create mode 100644 tests/erlang_tests/literal_test2.erl diff --git a/CHANGELOG.md b/CHANGELOG.md index a3e23a6da..49addd7a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,8 +27,9 @@ instead ### Fixed - ESP32: content of `boot.avm` partition is not truncated anymore -- ESP32: Fixed gpio:set_int` to accept any pin, not only pin 2 +- ESP32: `Fixed gpio:set_int` to accept any pin, not only pin 2 - Fix memory corruption in `unicode:characters_to_binary` +- Fix handling of large literal indexes ## [0.6.4] - 2024-08-18 diff --git a/src/libAtomVM/opcodesswitch.h b/src/libAtomVM/opcodesswitch.h index 896114868..21ab62378 100644 --- a/src/libAtomVM/opcodesswitch.h +++ b/src/libAtomVM/opcodesswitch.h @@ -145,10 +145,17 @@ typedef dreg_t dreg_gc_safe_t; dest_term = term_from_int(((first_byte & 0xE0) << 3) | *(decode_pc)++); \ break; \ \ - default: \ - fprintf(stderr, "Operand not literal: %x, or unsupported encoding\n", (first_byte)); \ - AVM_ABORT(); \ + case 3: { \ + uint8_t sz = (first_byte >> 5) + 2; \ + avm_int_t val = 0; \ + for (uint8_t vi = 0; vi < sz; vi++) { \ + val <<= 8; \ + val |= *(decode_pc)++; \ + } \ + dest_term = term_from_int(val); \ break; \ + } \ + default: UNREACHABLE(); /* help gcc 8.4 */ \ } \ break; \ \ @@ -549,10 +556,17 @@ static void destroy_extended_registers(Context *ctx, unsigned int live) dest_term = term_from_int(((first_byte & 0xE0) << 3) | *(decode_pc)++); \ break; \ \ - default: \ - fprintf(stderr, "Operand not a literal: %x, or unsupported encoding\n", (first_byte)); \ - AVM_ABORT(); \ + case 3: { \ + uint8_t sz = (first_byte >> 5) + 2; \ + avm_int_t val = 0; \ + for (uint8_t vi = 0; vi < sz; vi++) { \ + val <<= 8; \ + val |= *(decode_pc)++; \ + } \ + dest_term = term_from_int(val); \ break; \ + } \ + default: UNREACHABLE(); /* help gcc 8.4 */ \ } \ break; \ \ diff --git a/tests/erlang_tests/CMakeLists.txt b/tests/erlang_tests/CMakeLists.txt index b323448d3..39597e965 100644 --- a/tests/erlang_tests/CMakeLists.txt +++ b/tests/erlang_tests/CMakeLists.txt @@ -321,6 +321,7 @@ compile_erlang(minuspow63plusoneabs) compile_erlang(minuspow63plustwoabs) compile_erlang(literal_test0) compile_erlang(literal_test1) +compile_erlang(literal_test2) compile_erlang(test_list_eq) compile_erlang(test_tuple_eq) @@ -788,6 +789,7 @@ add_custom_target(erlang_test_modules DEPENDS literal_test0.beam literal_test1.beam + literal_test2.beam test_list_eq.beam test_tuple_eq.beam diff --git a/tests/erlang_tests/literal_test2.erl b/tests/erlang_tests/literal_test2.erl new file mode 100644 index 000000000..36dd69945 --- /dev/null +++ b/tests/erlang_tests/literal_test2.erl @@ -0,0 +1,67 @@ +% +% This file is part of AtomVM. +% +% Copyright 2024 Paul Guyot +% +% Licensed under the Apache License, Version 2.0 (the "License"); +% you may not use this file except in compliance with the License. +% You may obtain a copy of the License at +% +% http://www.apache.org/licenses/LICENSE-2.0 +% +% Unless required by applicable law or agreed to in writing, software +% distributed under the License is distributed on an "AS IS" BASIS, +% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and +% limitations under the License. +% +% SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later +% + +-module(literal_test2). +-export([start/0, f/1, g/1]). + +start() -> + Result = f(<<"duh">>), + <<"1234567890abcdef01234567890abcdef01234567890abcdef01234567890abcdef0duh">> = Result, + 0. + +% This is large enough to have to decode literal index with last encoding. +g(X) -> + << + "1234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0" + "1234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0" + "1234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0" + "1234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0" + "1234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0" + "1234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0" + "1234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0" + "1234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0" + "1234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0" + "1234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0" + "1234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0" + "1234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0" + "1234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0" + "1234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0" + "1234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0" + "1234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0" + "1234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0" + "1234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0" + "1234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0" + "1234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0" + "1234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0" + "1234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0" + "1234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0" + "1234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0" + "1234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0" + "1234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0" + "1234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0" + "1234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0" + "1234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0" + "1234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0" + "1234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF0", + X/binary + >>. + +f(X) -> + <<"1234567890abcdef01234567890abcdef01234567890abcdef01234567890abcdef0", X/binary>>. diff --git a/tests/test.c b/tests/test.c index 70e0f36d1..0ed33d2cc 100644 --- a/tests/test.c +++ b/tests/test.c @@ -336,6 +336,7 @@ struct Test tests[] = { TEST_CASE_EXPECTED(literal_test0, 333575620), TEST_CASE_EXPECTED(literal_test1, 1680), + TEST_CASE(literal_test2), TEST_CASE_EXPECTED(test_list_eq, 1), TEST_CASE_EXPECTED(test_tuple_eq, 1),