Skip to content

Binary corruption in binary construction #8760

Closed
@dominicletz

Description

@dominicletz

Describe the bug

When compiling the following code with any erlc from OTP 24.3.x (tested with 24.3.4.17) the resulting .beam file reports corrupted binary padding when executed on an x86_64 linux machine with either of OTP24/OTP25/OTP26/OTP27

To Reproduce

Save the attached erlang code as binary_error.erl and execute the corruption demo:

# Using OTP24 on linux x86_64
erlc binary_error.erl
# Using either of OTP24/25/26/27
erl -eval "binary_error:demo()"
Erlang/OTP 24 [erts-12.3.2.17] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit]

Eshell V12.3.2.17  (abort with ^G)
1> Error <<0,0,0,0,0,0,0,0,0,0,0,0,191,26,214,52,25,183,242,40,245,124,0,0,232,0,
        0,0,0,0,0,0>> != <<0,0,0,0,0,0,0,0,0,0,0,0,46,39,82,188,226,30,28,247,
                           217,209,255,170,91,199,135,225,44,86,233,52>>
...<snip>...
Done found 37 errors in 10000 iterations 

Using the same OTP24 pre compiled .beam file with OTP27 (27.0.1):

$ erl -eval "binary_error:demo()"
Erlang/OTP 27 [erts-15.0.1] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit:ns]

Error <<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,85,9,16,144,126,0,0,128,0,0,0,0,0,0,
        0>> != <<0,0,0,0,0,0,0,0,0,0,0,0,103,31,112,17,76,235,1,188,119,220,82,
                 93,146,95,157,20,149,76,19,28>>
...<snip>...
Done found 63 errors in 10000 iterations 

Expected behavior

It is expected that the padding result of <<0:96/unsigned-integer, Hash:20/binary>> always retains the same 20 bytes of Hash as postfix.

Affected versions

Compiler of OTP24 (24.3.4.17) is causing this issue.
Runtimes of OTP24/25/26/27 are all affected if the compiled .beam file of OTP24 is used.

Additional context

binary_error.erl

-module(binary_error).
-export([demo/0]).

to_bytes32(Hash = <<_:160/unsigned-integer>>) ->
    <<0:96/unsigned-integer, Hash:20/binary>>.

prefix() ->
    <<0:96>>.

process() ->
    Bin = rand:bytes(20),
    Padded = to_bytes32(Bin),
    case Padded =:= <<(prefix())/binary, Bin/binary>> of
        false ->
            io:format("Error ~p != ~p~n", [Padded, <<(prefix())/binary, Bin/binary>>]),
            1;
        true ->
            0
    end.

demo() ->
    Iters = 10000,
    Errors = lists:sum([process() || _ <- lists:seq(1, Iters)]),
    io:format("Done found ~p errors in ~p iterations ~n", [Errors, Iters]).

Metadata

Metadata

Assignees

Labels

bugIssue is reported as a bugteam:VMAssigned to OTP team VM

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions