diff --git a/interpreter/binary/decode.ml b/interpreter/binary/decode.ml index df6c9e63a9..d996a5f4b1 100644 --- a/interpreter/binary/decode.ml +++ b/interpreter/binary/decode.ml @@ -310,6 +310,7 @@ let memop s = let has_var = Int32.logand flags 0x40l <> 0l in let x = if has_var then at var s else Source.(0l @@ no_region) in let align = Int32.(to_int (logand flags 0x3fl)) in + require (align < 32) s pos "malformed memop alignment"; let offset = u32 s in x, align, offset diff --git a/test/core/align.wast b/test/core/align.wast index 93064649d3..817a1dfb24 100644 --- a/test/core/align.wast +++ b/test/core/align.wast @@ -864,3 +864,120 @@ (assert_trap (invoke "store" (i32.const 65532) (i64.const -1)) "out of bounds memory access") ;; No memory was changed (assert_return (invoke "load" (i32.const 65532)) (i32.const 0)) + +;; Test invalid alignment values that may cause overflow when parsed. +;; These use the binary format, because it stores alignment as a base-2 exponent. + +;; Signed 32-bit overflow +(assert_invalid + (module binary + "\00asm" "\01\00\00\00" + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\05\03\01\00\01" ;; Memory section: 1 memory + "\0a\0a\01" ;; Code section: 1 function + + ;; function 0 + "\08\00" + "\41\00" ;; i32.const 0 + "\28\1f\00" ;; i32.load offset=0 align=2**31 + "\1a" ;; drop + "\0b" ;; end + ) + "alignment must not be larger than natural" +) + +;; Unsigned 32-bit overflow +(assert_malformed + (module binary + "\00asm" "\01\00\00\00" + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\05\03\01\00\01" ;; Memory section: 1 memory + "\0a\0a\01" ;; Code section: 1 function + + ;; function 0 + "\08\00" + "\41\00" ;; i32.const 0 + "\28\20\00" ;; i32.load offset=0 align=2**32 + "\1a" ;; drop + "\0b" ;; end + ) + "malformed memop alignment" +) + +;; 32-bit out of range +(assert_malformed + (module binary + "\00asm" "\01\00\00\00" + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\05\03\01\00\01" ;; Memory section: 1 memory + "\0a\0a\01" ;; Code section: 1 function + + ;; function 0 + "\08\00" + "\41\00" ;; i32.const 0 + "\28\21\00" ;; i32.load offset=0 align=2**33 + "\1a" ;; drop + "\0b" ;; end + ) + "malformed memop alignment" +) + +;; Signed 64-bit overflow +(assert_malformed + (module binary + "\00asm" "\01\00\00\00" + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\05\03\01\00\01" ;; Memory section: 1 memory + "\0a\0a\01" ;; Code section: 1 function + + ;; function 0 + "\08\00" + "\41\00" ;; i32.const 0 + "\28\3f\00" ;; i32.load offset=0 align=2**63 + "\1a" ;; drop + "\0b" ;; end + ) + "malformed memop alignment" +) + +;; Unsigned 64-bit overflow +(assert_invalid + (module binary + "\00asm" "\01\00\00\00" + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\05\03\01\00\01" ;; Memory section: 1 memory + "\0a\0a\01" ;; Code section: 1 function + + ;; function 0 + "\08\00" + "\41\00" ;; i32.const 0 + "\28\40\00" ;; i32.load offset=0 align=2**64 (parsed as align=0, memidx present) + "\1a" ;; drop + "\0b" ;; end + ) + "type mismatch" +) + +;; 64-bit out of range +(assert_invalid + (module binary + "\00asm" "\01\00\00\00" + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\05\03\01\00\01" ;; Memory section: 1 memory + "\0a\0a\01" ;; Code section: 1 function + + ;; function 0 + "\08\00" + "\41\00" ;; i32.const 0 + "\28\41\00" ;; i32.load offset=0 align=2**65 (parsed as align=1, memidx present) + "\1a" ;; drop + "\0b" ;; end + ) + "type mismatch" +) diff --git a/test/core/run.py b/test/core/run.py index bdc2a447af..21036065d6 100755 --- a/test/core/run.py +++ b/test/core/run.py @@ -19,6 +19,7 @@ parser.add_argument("--wasm", metavar="", default=os.path.join(interpDir, "wasm")) parser.add_argument("--js", metavar="") parser.add_argument("--generate-js-only", action='store_true') +parser.add_argument("--failfast", action='store_true') parser.add_argument("--out", metavar="", default=outputDir) parser.add_argument("file", nargs='*') arguments = parser.parse_args() @@ -120,4 +121,4 @@ def _runTestFile(self, inputPath): for fileName in inputFiles: testName = 'test ' + os.path.basename(fileName) setattr(RunTests, testName, lambda self, file=fileName: self._runTestFile(file)) - unittest.main() + unittest.main(failfast=arguments.failfast) diff --git a/test/meta/Makefile b/test/meta/Makefile index 20e9adb2f5..05a42beb79 100644 --- a/test/meta/Makefile +++ b/test/meta/Makefile @@ -1,10 +1,10 @@ SHARED_MEM=false # SpiderMonkey shell -JSSHELL=~/mozilla-central/js/src/build-debug/dist/bin/js -e 'const WITH_SHARED_MEMORY=$(SHARED_MEM);' -f common.js +#JSSHELL=~/mozilla-central/js/src/build-debug/dist/bin/js -e 'const WITH_SHARED_MEMORY=$(SHARED_MEM);' -f common.js # Node.js -#JSSHELL=./noderun.sh $(SHARED_MEM) +JSSHELL=./noderun.sh $(SHARED_MEM) TARGETDIR=../core