summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ir/table-utils.h9
-rw-r--r--test/lit/passes/directize_all-features.wast174
2 files changed, 182 insertions, 1 deletions
diff --git a/src/ir/table-utils.h b/src/ir/table-utils.h
index a94691e9f..5299ba3e1 100644
--- a/src/ir/table-utils.h
+++ b/src/ir/table-utils.h
@@ -20,6 +20,7 @@
#include "ir/element-utils.h"
#include "ir/literal-utils.h"
#include "ir/module-utils.h"
+#include "support/stdckdint.h"
#include "wasm-traversal.h"
#include "wasm.h"
@@ -40,7 +41,13 @@ struct FlatTable {
return;
}
Index start = offset->cast<Const>()->value.geti32();
- Index end = start + segment->data.size();
+ Index size = segment->data.size();
+ Index end;
+ if (std::ckd_add(&end, start, size) || end > table.initial) {
+ // Overflow.
+ valid = false;
+ return;
+ }
if (end > names.size()) {
names.resize(end);
}
diff --git a/test/lit/passes/directize_all-features.wast b/test/lit/passes/directize_all-features.wast
index 706a86c46..1e46e42c1 100644
--- a/test/lit/passes/directize_all-features.wast
+++ b/test/lit/passes/directize_all-features.wast
@@ -1586,3 +1586,177 @@
)
)
)
+
+;; The elem's offset is way out of bounds, which we should not error on, and do
+;; nothing otherwise.
+(module
+ ;; CHECK: (type $v (func))
+ ;; IMMUT: (type $v (func))
+ (type $v (func))
+
+ (table 10 10 funcref)
+
+ (elem (i32.const -1) $0)
+
+ ;; CHECK: (table $0 10 10 funcref)
+
+ ;; CHECK: (elem $0 (i32.const -1) $0)
+
+ ;; CHECK: (func $0 (type $v)
+ ;; CHECK-NEXT: (call_indirect $0 (type $v)
+ ;; CHECK-NEXT: (i32.const -1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; IMMUT: (table $0 10 10 funcref)
+
+ ;; IMMUT: (elem $0 (i32.const -1) $0)
+
+ ;; IMMUT: (func $0 (type $v)
+ ;; IMMUT-NEXT: (call_indirect $0 (type $v)
+ ;; IMMUT-NEXT: (i32.const -1)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
+ (func $0
+ (call_indirect (type $v)
+ (i32.const -1)
+ )
+ )
+)
+
+;; Another elem offset that is way out of bounds.
+(module
+ ;; CHECK: (type $v (func))
+ ;; IMMUT: (type $v (func))
+ (type $v (func))
+
+ (table 10 10 funcref)
+
+ (elem (i32.const -2) $0)
+
+ ;; CHECK: (table $0 10 10 funcref)
+
+ ;; CHECK: (elem $0 (i32.const -2) $0)
+
+ ;; CHECK: (func $0 (type $v)
+ ;; CHECK-NEXT: (call_indirect $0 (type $v)
+ ;; CHECK-NEXT: (i32.const -2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; IMMUT: (table $0 10 10 funcref)
+
+ ;; IMMUT: (elem $0 (i32.const -2) $0)
+
+ ;; IMMUT: (func $0 (type $v)
+ ;; IMMUT-NEXT: (call_indirect $0 (type $v)
+ ;; IMMUT-NEXT: (i32.const -2)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
+ (func $0
+ (call_indirect (type $v)
+ (i32.const -2)
+ )
+ )
+)
+
+;; The elem is just out of bounds due to its offset.
+(module
+ ;; CHECK: (type $v (func))
+ ;; IMMUT: (type $v (func))
+ (type $v (func))
+
+ (table 10 10 funcref)
+
+ (elem (i32.const 10) $0)
+
+ ;; CHECK: (table $0 10 10 funcref)
+
+ ;; CHECK: (elem $0 (i32.const 10) $0)
+
+ ;; CHECK: (func $0 (type $v)
+ ;; CHECK-NEXT: (call_indirect $0 (type $v)
+ ;; CHECK-NEXT: (i32.const 10)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; IMMUT: (table $0 10 10 funcref)
+
+ ;; IMMUT: (elem $0 (i32.const 10) $0)
+
+ ;; IMMUT: (func $0 (type $v)
+ ;; IMMUT-NEXT: (call_indirect $0 (type $v)
+ ;; IMMUT-NEXT: (i32.const 10)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
+ (func $0
+ (call_indirect (type $v)
+ (i32.const 10)
+ )
+ )
+)
+
+;; The elem is just out of bounds due to its length.
+(module
+ ;; CHECK: (type $v (func))
+ ;; IMMUT: (type $v (func))
+ (type $v (func))
+
+ (table 10 10 funcref)
+
+ (elem (i32.const 9) $0 $0)
+
+ ;; CHECK: (table $0 10 10 funcref)
+
+ ;; CHECK: (elem $0 (i32.const 9) $0 $0)
+
+ ;; CHECK: (func $0 (type $v)
+ ;; CHECK-NEXT: (call_indirect $0 (type $v)
+ ;; CHECK-NEXT: (i32.const 9)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; IMMUT: (table $0 10 10 funcref)
+
+ ;; IMMUT: (elem $0 (i32.const 9) $0 $0)
+
+ ;; IMMUT: (func $0 (type $v)
+ ;; IMMUT-NEXT: (call_indirect $0 (type $v)
+ ;; IMMUT-NEXT: (i32.const 9)
+ ;; IMMUT-NEXT: )
+ ;; IMMUT-NEXT: )
+ (func $0
+ (call_indirect (type $v)
+ ;; We could in theory optimize this, as the out of bounds part is after us,
+ ;; but the wasm traps anyhow, so leave it alone.
+ (i32.const 9)
+ )
+ )
+)
+
+;; The elem is ok, and we can optimize.
+(module
+ ;; CHECK: (type $v (func))
+ ;; IMMUT: (type $v (func))
+ (type $v (func))
+
+ (table 10 10 funcref)
+
+ (elem (i32.const 9) $0)
+
+ ;; CHECK: (table $0 10 10 funcref)
+
+ ;; CHECK: (elem $0 (i32.const 9) $0)
+
+ ;; CHECK: (func $0 (type $v)
+ ;; CHECK-NEXT: (call $0)
+ ;; CHECK-NEXT: )
+ ;; IMMUT: (table $0 10 10 funcref)
+
+ ;; IMMUT: (elem $0 (i32.const 9) $0)
+
+ ;; IMMUT: (func $0 (type $v)
+ ;; IMMUT-NEXT: (call $0)
+ ;; IMMUT-NEXT: )
+ (func $0
+ (call_indirect (type $v)
+ (i32.const 9)
+ )
+ )
+)