diff --git a/src/libAtomVM/term.h b/src/libAtomVM/term.h index f4286ed168..af0613abd3 100644 --- a/src/libAtomVM/term.h +++ b/src/libAtomVM/term.h @@ -1040,6 +1040,9 @@ static inline term term_maybe_create_sub_binary(term binary, size_t offset, size { if (term_is_refc_binary(binary) && len >= SUB_BINARY_MIN) { return term_alloc_sub_binary(binary, offset, len, heap); + } else if (term_is_sub_binary(binary) && len >= SUB_BINARY_MIN) { + const term *boxed_value = term_to_const_term_ptr(binary); + return term_alloc_sub_binary(boxed_value[3], boxed_value[2] + offset, len, heap); } else { const char *data = term_binary_data(binary); return term_from_literal_binary(data + offset, len, heap, glb); diff --git a/tests/erlang_tests/test_sub_binaries.erl b/tests/erlang_tests/test_sub_binaries.erl index de5052b163..ba304fd018 100644 --- a/tests/erlang_tests/test_sub_binaries.erl +++ b/tests/erlang_tests/test_sub_binaries.erl @@ -56,6 +56,7 @@ start() -> test_common() -> ok = run_test(fun() -> test_count_binary() end), + ok = run_test(fun() -> test_sub_sub_binary() end), ok. test_atom() -> @@ -72,6 +73,14 @@ test_atom() -> ok = run_test(fun() -> test_bit_syntax_get_binary() end), ok. +test_sub_sub_binary() -> + Bin = create_binary(get_largest_heap_binary_size()), + + SubBin = binary:part(Bin, 1, 7), + <<2, 3, 4, 5, 6, 7, 8>> = SubBin, + <<4, 5, 6, 7, 8>> = binary:part(SubBin, 2, 5), + ok. + test_heap_sub_binary() -> MemoryBinarySize = erlang:memory(binary), HeapSize0 = get_heap_size(), @@ -80,7 +89,7 @@ test_heap_sub_binary() -> HeapSize1 = get_heap_size(), ?VERIFY(HeapSize0 < HeapSize1), - SubBin = binary:part(Bin, 1, 7), + SubBin = binary:part(Bin, 1, 47), HeapSize2 = get_heap_size(), ?VERIFY(HeapSize1 < HeapSize2), ?VERIFY((HeapSize2 - HeapSize1) >= 8), @@ -104,11 +113,19 @@ test_const_sub_binary() -> LargeSubBin = binary:part(?LITERAL_BIN, 1, BinarySize - 1), HeapSize2 = get_heap_size(), - ?VERIFY(HeapSize2 < HeapSize1 + erlang:byte_size(LargeSubBin)), + ?VERIFY((HeapSize2 - HeapSize1) >= 8), + ?VERIFY((HeapSize2 - HeapSize1) < BinarySize div 4), + ?VERIFY(MemoryBinarySize == erlang:memory(binary)), + + SubSubBin = binary:part(LargeSubBin, 0, BinarySize - 2), + HeapSize3 = get_heap_size(), + ?VERIFY((HeapSize3 - HeapSize2) >= 8), + ?VERIFY((HeapSize3 - HeapSize2) < BinarySize div 4), ?VERIFY(MemoryBinarySize == erlang:memory(binary)), id(SmallSubBin), id(LargeSubBin), + id(SubSubBin), ok. test_non_const_sub_binary() -> @@ -126,7 +143,7 @@ test_non_const_sub_binary() -> LargeSubBin = binary:part(Bin, 1, BinarySize - 1), HeapSize3 = get_heap_size(), - ?VERIFY(HeapSize3 < HeapSize2 + erlang:byte_size(LargeSubBin)), + ?VERIFY((HeapSize3 - HeapSize2) < BinarySize div 4), ?VERIFY(MemoryBinarySize + 1024 == erlang:memory(binary)), id(String),