File 2706-beam_load-Handle-bs_skip_bits2-instruction-with-inva.patch of Package erlang
From d48247dd20ba17ba63b1b97517e9b5694e4d4d5b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
Date: Tue, 4 Feb 2020 07:39:46 +0100
Subject: [PATCH 06/13] beam_load: Handle bs_skip_bits2 instruction with
invalid sizes
Selectively disabling compiler optimizations could allow bs_skip_bits2
instructions with invalid literals size to be emitted. Teach the loader
to handle them by translating them to a jump to the failure label.
While at it, also translate bs_get_integer2 and bs_get_binary2 with
invalid sizes to jumps to the failure label. That change makes it
possible to use the slightly cheaper `S` operand type instead of `s`
for the size operand.
---
erts/emulator/beam/beam_load.c | 22 ++++++++++++++++++----
erts/emulator/beam/ops.tab | 4 ++--
2 files changed, 20 insertions(+), 6 deletions(-)
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c
index 5c6385a1a5..3fc3b8168e 100644
--- a/erts/emulator/beam/beam_load.c
+++ b/erts/emulator/beam/beam_load.c
@@ -3322,8 +3322,8 @@ gen_get_integer2(LoaderState* stp, GenOpArg Fail, GenOpArg Ms, GenOpArg Live,
}
goto generic;
}
- } else {
- GENOP_NAME_ARITY(op, i_bs_get_integer, 6);
+ } else if (Size.type == TAG_x || Size.type == TAG_y) {
+ GENOP_NAME_ARITY(op, i_bs_get_integer, 6);
op->a[0] = Ms;
op->a[1] = Fail;
op->a[2] = Live;
@@ -3333,6 +3333,9 @@ gen_get_integer2(LoaderState* stp, GenOpArg Fail, GenOpArg Ms, GenOpArg Live,
op->a[5] = Dst;
op->next = NULL;
return op;
+ } else {
+ /* Invalid literal size. */
+ goto error;
}
op->next = NULL;
return op;
@@ -3389,7 +3392,7 @@ gen_get_binary2(LoaderState* stp, GenOpArg Fail, GenOpArg Ms, GenOpArg Live,
op->a[4] = Flags;
op->a[5] = Dst;
}
- } else {
+ } else if (Size.type == TAG_x || Size.type == TAG_y) {
GENOP_NAME_ARITY(op, i_bs_get_binary2, 6);
op->a[0] = Ms;
op->a[1] = Fail;
@@ -3398,6 +3401,9 @@ gen_get_binary2(LoaderState* stp, GenOpArg Fail, GenOpArg Ms, GenOpArg Live,
op->a[4].type = TAG_u;
op->a[4].val = (Unit.val << 3) | Flags.val;
op->a[5] = Dst;
+ } else {
+ /* Invalid literal size. */
+ goto error;
}
op->next = NULL;
return op;
@@ -3634,12 +3640,20 @@ gen_skip_bits2(LoaderState* stp, GenOpArg Fail, GenOpArg Ms,
goto error;
}
}
- } else {
+ } else if (Size.type == TAG_x || Size.type == TAG_y) {
GENOP_NAME_ARITY(op, i_bs_skip_bits2, 4);
op->a[0] = Ms;
op->a[1] = Size;
op->a[2] = Fail;
op->a[3] = Unit;
+ } else {
+ /*
+ * Invalid literal size. Can only happen if compiler
+ * optimizations are selectively disabled. For example,
+ * at the time of writing, [no_copt, no_type_opt] will allow
+ * skip instructions with invalid sizes to slip through.
+ */
+ goto error;
}
op->next = NULL;
return op;
diff --git a/erts/emulator/beam/ops.tab b/erts/emulator/beam/ops.tab
index 1c6f257cdc..fbd720c61b 100644
--- a/erts/emulator/beam/ops.tab
+++ b/erts/emulator/beam/ops.tab
@@ -1162,7 +1162,7 @@ i_bs_get_integer_imm Ms Bits Live Fail Flags Y=y => \
i_bs_get_integer_small_imm xy W f? t x
i_bs_get_integer_imm xy W t f? t x
-i_bs_get_integer xy f? t t s d
+i_bs_get_integer xy f? t t S d
i_bs_get_integer_8 xy f? d
i_bs_get_integer_16 xy f? d
@@ -1175,7 +1175,7 @@ bs_get_binary2 Fail=f Ms=xy Live=u Sz=sq Unit=u Flags=u Dst=d => \
gen_get_binary2(Fail, Ms, Live, Sz, Unit, Flags, Dst)
i_bs_get_binary_imm2 xy f? t W t d
-i_bs_get_binary2 xy f t? s t d
+i_bs_get_binary2 xy f t? S t d
i_bs_get_binary_all2 xy f? t t d
# Fetching float from binaries.
--
2.16.4