x86/x86asm: fix panic on truncated VEX/EVEX prefix

decodeAVX guards every read from src except the opcode byte itself, so a
stream ending exactly at the end of a VEX or EVEX prefix indexes out of
range instead of reporting a truncated instruction:

	c5 fc         panic: index out of range [2] with length 2
	c4 e2 7d      panic: index out of range [3] with length 3
	62 f1 7c 48   panic: index out of range [4] with length 4

Add the missing bounds check and extend TestDecodeDoesNotCrash with the
three prefix forms.

Fixes golang/go#81447.

Change-Id: Id68526e432646ea95d2c1b84d715444ad2d4fb9a
GitHub-Last-Rev: 2a9c2bcbcd58bf223e12b76e9821baf50829dff8
GitHub-Pull-Request: golang/arch#25
Reviewed-on: https://go-review.googlesource.com/c/arch/+/830644
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
diff --git a/x86/x86asm/avx.go b/x86/x86asm/avx.go
index 148f72b..82c3472 100644
--- a/x86/x86asm/avx.go
+++ b/x86/x86asm/avx.go
@@ -76,6 +76,9 @@
 
 	_ = evex_z // TODO: use zeroing mask if needed for output
 
+	if pos >= len(src) {
+		return inst, errors.New("truncated")
+	}
 	opbyte := src[pos]
 	pos++
 
diff --git a/x86/x86asm/decode_test.go b/x86/x86asm/decode_test.go
index 4543cd2..e409a2f 100644
--- a/x86/x86asm/decode_test.go
+++ b/x86/x86asm/decode_test.go
@@ -75,6 +75,11 @@
 		[]byte{},
 		[]byte{0xc5},
 		[]byte{0xc4},
+		// Streams ending exactly at the end of a VEX or EVEX prefix,
+		// leaving no opcode byte.
+		[]byte{0xc5, 0xfc},
+		[]byte{0xc4, 0xe2, 0x7d},
+		[]byte{0x62, 0xf1, 0x7c, 0x48},
 	}
 	for _, test := range cases {
 		_, err := Decode([]byte(test), 64) // the only goal is that this line does not panic