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

openSUSE Build Service is sponsored by