From 4cf399593bb09fec957544df1cb1e1a5b299d5b4 Mon Sep 17 00:00:00 2001 From: dcode Date: Tue, 22 Mar 2022 14:30:17 +0100 Subject: [PATCH] Mitigate crash on arrays of void or v128 --- src/compiler.ts | 28 ++++++++++++++++++++++++---- src/module.ts | 11 +++++++++++ src/util/binary.ts | 11 +++++++++++ 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/src/compiler.ts b/src/compiler.ts index 454720221d..73959fefc0 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -39,6 +39,7 @@ import { getConstValueI64High, getConstValueF32, getConstValueF64, + getConstValueV128, getBlockChildCount, getBlockChildAt, getBlockName, @@ -193,6 +194,7 @@ import { writeI64, writeF32, writeF64, + writeV128, uniqueMap, isPowerOf2, v128_zero, @@ -1929,6 +1931,20 @@ export class Compiler extends DiagnosticEmitter { } break; } + case TypeRef.V128: { + for (let i = 0; i < length; ++i) { + let value = values[i]; + assert(getExpressionType(value) == elementTypeRef); + assert(getExpressionId(value) == ExpressionId.Const); + writeV128(getConstValueV128(value), buf, pos); + pos += 16; + } + break; + } + case TypeRef.None: { + // nothing to write + break; + } default: assert(false); } return pos; @@ -8269,11 +8285,15 @@ export class Compiler extends DiagnosticEmitter { let elementExpression = expressions[i]; if (elementExpression.kind != NodeKind.OMITTED) { let expr = this.compileExpression(elementExpression, elementType, Constraints.CONV_IMPLICIT); - let precomp = module.runExpression(expr, ExpressionRunnerFlags.PreserveSideeffects); - if (precomp) { - expr = precomp; - } else { + if (getExpressionType(expr) != elementType.toRef()) { isStatic = false; + } else { + let precomp = module.runExpression(expr, ExpressionRunnerFlags.PreserveSideeffects); + if (precomp) { + expr = precomp; + } else { + isStatic = false; + } } values[i] = expr; } else { diff --git a/src/module.ts b/src/module.ts index f002621e80..1375d86a44 100644 --- a/src/module.ts +++ b/src/module.ts @@ -2665,6 +2665,17 @@ export function getConstValueF64(expr: ExpressionRef): f64 { return binaryen._BinaryenConstGetValueF64(expr); } +export function getConstValueV128(expr: ExpressionRef): Uint8Array { + let cArr = binaryen._malloc(16); + binaryen._BinaryenConstGetValueV128(expr, cArr); + let out = new Uint8Array(16); + for (let i = 0; i < 16; ++i) { + out[i] = binaryen.__i32_load8_u(cArr + i); + } + binaryen._free(cArr); + return out; +} + export function isConstZero(expr: ExpressionRef): bool { if (getExpressionId(expr) != ExpressionId.Const) return false; var type = getExpressionType(expr); diff --git a/src/util/binary.ts b/src/util/binary.ts index ea31c07f2e..5557e0ca25 100644 --- a/src/util/binary.ts +++ b/src/util/binary.ts @@ -87,3 +87,14 @@ export function writeF64(value: f64, buffer: Uint8Array, offset: i32): void { writeI32(i64_low(valueI64), buffer, offset); writeI32(i64_high(valueI64), buffer, offset + 4); } + +/** Reads a 128-bit vector from the specified buffer. */ +export function readV128(buffer: Uint8Array, offset: i32): Uint8Array { + return buffer.slice(offset, offset + 16); +} + +/** Writes a 128-bit vector to the specified buffer. */ +export function writeV128(value: Uint8Array, buffer: Uint8Array, offset: i32): void { + assert(value.length == 16); + buffer.set(value, offset); +}