diff options
author | Kostis Sagonas <[email protected]> | 2015-10-12 07:53:20 +0200 |
---|---|---|
committer | Kostis Sagonas <[email protected]> | 2015-10-12 07:53:20 +0200 |
commit | d94a8ef6dc136dd2eedf3c3ad4bc053ca8fdd1b0 (patch) | |
tree | a5e54dfd9d03b28ab6ede0cca054ad5892edaa2d | |
parent | 4f9905824002bebc33c2914669b4c364927cb0ee (diff) | |
download | otp-d94a8ef6dc136dd2eedf3c3ad4bc053ca8fdd1b0.tar.gz otp-d94a8ef6dc136dd2eedf3c3ad4bc053ca8fdd1b0.tar.bz2 otp-d94a8ef6dc136dd2eedf3c3ad4bc053ca8fdd1b0.zip |
Fix edge case of Size = 0 in bs_put_integer
copy_offset_int_big was assuming (Offset + Size - 1) (Tmp9 in the first
BB) would not underflow. It was also unconditionally reading and writing
the binary even when Size was zero, unlike copy_int_little, which is the
only other case of bs_put_integer that does not have a short-circuit on
Size = 0.
This was causing segfaults when constructing binaries starting with a
zero-length integer field, because a logical right shift was used to
compute an offset in bytes (which became 0x1fffffffffffffff) to read in
the binary.
Tests, taken from the emulator bs_construct_SUITE, were also added.
The complete credit for the report and the fix goes to Magnus Lång.
-rw-r--r-- | lib/hipe/rtl/hipe_rtl_binary_construct.erl | 9 | ||||
-rw-r--r-- | lib/hipe/test/bs_SUITE_data/bs_construct.erl | 16 |
2 files changed, 22 insertions, 3 deletions
diff --git a/lib/hipe/rtl/hipe_rtl_binary_construct.erl b/lib/hipe/rtl/hipe_rtl_binary_construct.erl index 40bd22aa8e..692bad7d96 100644 --- a/lib/hipe/rtl/hipe_rtl_binary_construct.erl +++ b/lib/hipe/rtl/hipe_rtl_binary_construct.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2009. All Rights Reserved. +%% Copyright Ericsson AB 2007-2015. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -1192,7 +1192,10 @@ copy_little_word(Base, Offset, NewOffset, Word) -> hipe_rtl:mk_store(Base, TmpOffset, Word, byte), hipe_rtl:mk_alu(NewOffset, Offset, 'add', hipe_rtl:mk_imm(32))]. -copy_offset_int_big(Base, Offset, NewOffset, Size, Tmp1) when is_integer(Size) -> +copy_offset_int_big(_Base, Offset, NewOffset, 0, _Tmp1) -> + [hipe_rtl:mk_move(NewOffset, Offset)]; +copy_offset_int_big(Base, Offset, NewOffset, Size, Tmp1) + when is_integer(Size), Size > 0 -> Tmp2 = hipe_rtl:mk_new_reg(), Tmp3 = hipe_rtl:mk_new_reg(), Tmp4 = hipe_rtl:mk_new_reg(), @@ -1203,7 +1206,7 @@ copy_offset_int_big(Base, Offset, NewOffset, Size, Tmp1) when is_integer(Size) - Tmp9 = hipe_rtl:mk_new_reg(), OldByte = hipe_rtl:mk_new_reg(), TmpOffset = hipe_rtl:mk_new_reg(), - BranchLbl = hipe_rtl:mk_new_label(), + BranchLbl = hipe_rtl:mk_new_label(), BodyLbl = hipe_rtl:mk_new_label(), EndLbl = hipe_rtl:mk_new_label(), NextLbl = hipe_rtl:mk_new_label(), diff --git a/lib/hipe/test/bs_SUITE_data/bs_construct.erl b/lib/hipe/test/bs_SUITE_data/bs_construct.erl index 9cc9ac848c..37a54c1981 100644 --- a/lib/hipe/test/bs_SUITE_data/bs_construct.erl +++ b/lib/hipe/test/bs_SUITE_data/bs_construct.erl @@ -13,6 +13,7 @@ test() -> ok = bs5(), 16#10000008 = bit_size(large_bin(1, 2, 3, 4)), ok = bad_ones(), + ok = zero_width(), ok. %%-------------------------------------------------------------------- @@ -126,3 +127,18 @@ bad_ones() -> Bin123 = <<1,2,3>>, ?FAIL(<<Bin123/float>>), ok. + +%%-------------------------------------------------------------------- +%% Taken from the emulator bs_construct_SUITE - seg faulted till 18.1 + +zero_width() -> + Z = id(0), + Small = id(42), + Big = id(1 bsl 128), % puts stuff on the heap + <<>> = <<Small:Z>>, + <<>> = <<Small:0>>, + <<>> = <<Big:Z>>, + <<>> = <<Big:0>>, + ok. + +id(X) -> X. |