From fea72eef5a9d4715639ab07c756a0121bff21beb Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Wed, 31 Jan 2024 19:08:12 +0000 Subject: [PATCH] [PostEmscripten] Fix calcSegmentOffsets for large offsets (#6260) Specifically offsets larger than 2^32 which were being interpreted misinterpreted here as very large int64_t values. --- src/passes/PostEmscripten.cpp | 7 ++--- test/lit/passes/post-emscripten.wast | 42 +++++++++++++++++++++------- 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/src/passes/PostEmscripten.cpp b/src/passes/PostEmscripten.cpp index 6dc32eaa8b1..b7d3e9f917d 100644 --- a/src/passes/PostEmscripten.cpp +++ b/src/passes/PostEmscripten.cpp @@ -95,12 +95,11 @@ static void calcSegmentOffsets(Module& wasm, return; } } - auto it = offsets.find(curr->segment); - if (it != offsets.end()) { + if (offsets.find(curr->segment) != offsets.end()) { Fatal() << "Cannot get offset of passive segment initialized " "multiple times"; } - offsets[curr->segment] = dest->value.getInteger(); + offsets[curr->segment] = dest->value.getUnsigned(); } } searcher(passiveOffsets); searcher.walkModule(&wasm); @@ -317,7 +316,7 @@ struct PostEmscripten : public Pass { // The first operand is the function pointer index, which must be // constant if we are to optimize it statically. if (auto* index = curr->operands[0]->dynCast()) { - size_t indexValue = index->value.getInteger(); + size_t indexValue = index->value.getUnsigned(); if (indexValue >= flatTable.names.size()) { // UB can lead to indirect calls to invalid pointers. return; diff --git a/test/lit/passes/post-emscripten.wast b/test/lit/passes/post-emscripten.wast index cce4b55a5de..1369252a9bf 100644 --- a/test/lit/passes/post-emscripten.wast +++ b/test/lit/passes/post-emscripten.wast @@ -1,18 +1,27 @@ ;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; RUN: wasm-opt %s --post-emscripten -S -o - | filecheck %s +;; RUN: wasm-opt %s --enable-bulk-memory --post-emscripten -S -o - | filecheck %s ;; Checks that the start/stop exports are removed and that the data they ;; refer to is either zero'd out, or the segment emptied. +;; Two of the segments used here are active, so their offsets are trivial +;; to dirive. One segment is passive and its offset is derived from the +;; memory.init instruction. + +;; Explictly use a data address that is larger then INT_MAX to verify +;; that these offset are correctly interpreted as unsigned. + (module + ;; CHECK: (type $0 (func)) + ;; CHECK: (global $em_asm_start i32 (i32.const 1000)) (global $em_asm_start i32 (i32.const 1000)) ;; CHECK: (global $em_asm_stop i32 (i32.const 1011)) (global $em_asm_stop i32 (i32.const 1011)) - ;; CHECK: (global $em_js_start i32 (i32.const 2006)) - (global $em_js_start i32 (i32.const 2006)) - ;; CHECK: (global $em_js_stop i32 (i32.const 2015)) - (global $em_js_stop i32 (i32.const 2015)) + ;; CHECK: (global $em_js_start i32 (i32.const -1294967290)) + (global $em_js_start i32 (i32.const 3000000006)) + ;; CHECK: (global $em_js_stop i32 (i32.const -1294967281)) + (global $em_js_stop i32 (i32.const 3000000015)) ;; CHECK: (global $em_lib_deps_start i32 (i32.const 3000)) (global $em_lib_deps_start i32 (i32.const 3000)) ;; CHECK: (global $em_lib_deps_stop i32 (i32.const 3009)) @@ -21,13 +30,12 @@ (global $foo_start i32 (i32.const 4000)) ;; CHECK: (global $foo_stop i32 (i32.const 4015)) (global $foo_stop i32 (i32.const 4015)) - (memory 10 10) - ;; CHECK: (memory $0 10 10) - + ;; CHECK: (memory $mem 10 10) + (memory $mem 10 10) ;; CHECK: (data $data1 (i32.const 1000) "") (data $data1 (i32.const 1000) "hello world") - ;; CHECK: (data $data2 (i32.const 2000) "hello \00\00\00\00\00\00\00\00\00 world") - (data $data2 (i32.const 2000) "hello DELETE ME world") + ;; CHECK: (data $data2 "hello \00\00\00\00\00\00\00\00\00 world") + (data $data2 "hello DELETE ME world") ;; CHECK: (data $data3 (i32.const 3000) "") (data $data3 (i32.const 3000) "some deps") (export "__start_em_asm" (global $em_asm_start)) @@ -40,4 +48,18 @@ (export "__start_foo" (global $foo_start)) ;; CHECK: (export "__stop_foo" (global $foo_stop)) (export "__stop_foo" (global $foo_stop)) + ;; CHECK: (func $meminit + ;; CHECK-NEXT: (memory.init $data2 + ;; CHECK-NEXT: (i32.const -1294967296) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 21) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $meminit + (memory.init $mem $data2 + (i32.const 3000000000) + (i32.const 0) + (i32.const 21) + ) + ) )