Repository: bytecodealliance/wasm-tools
Pull request #1341 (2023-12-18 17:13:58)

wit-component: Reserve table offset 0 for the null function pointer
Placing a function at zero address violates most application's assumptions about null pointers. This patch reserves table offset 0 for the null function pointer. This convention follows wasm-ld's table layout.

CC: @dicej 

kateinoigakukun: Sure!

Patch:
diff --git a/crates/wit-component/src/linking.rs b/crates/wit-component/src/linking.rs
index eea2ddad..56adb738 100644
--- a/crates/wit-component/src/linking.rs
+++ b/crates/wit-component/src/linking.rs
@@ -323,7 +323,11 @@ fn make_env_module<'a>(
     }
 
     let mut memory_offset = stack_size_bytes;
-    let mut table_offset = 0;
+
+    // Table offset 0 is reserved for the null function pointer.
+    // This convention follows wasm-ld's table layout:
+    // https://github.com/llvm/llvm-project/blob/913622d012f72edb5ac3a501cef8639d0ebe471b/lld/wasm/Driver.cpp#L581-L584
+    let mut table_offset = 1;
     let mut globals = GlobalSection::new();
     let mut exports = ExportSection::new();
 


Test patch:
diff --git a/crates/wit-component/tests/components/link-bare-funcs/component.wat b/crates/wit-component/tests/components/link-bare-funcs/component.wat
index f2849f91..085b43b2 100644
--- a/crates/wit-component/tests/components/link-bare-funcs/component.wat
+++ b/crates/wit-component/tests/components/link-bare-funcs/component.wat
@@ -6,13 +6,13 @@
   (core module (;0;)
     (type (;0;) (func (param i32 i32 i32 i32) (result i32)))
     (import "foo" "cabi_realloc" (func (;0;) (type 0)))
-    (table (;0;) 0 funcref)
+    (table (;0;) 1 funcref)
     (memory (;0;) 17)
     (global (;0;) (mut i32) i32.const 1048576)
     (global (;1;) i32 i32.const 1048592)
-    (global (;2;) i32 i32.const 0)
+    (global (;2;) i32 i32.const 1)
     (global (;3;) i32 i32.const 1048592)
-    (global (;4;) i32 i32.const 0)
+    (global (;4;) i32 i32.const 1)
     (global (;5;) (mut i32) i32.const 1048608)
     (global (;6;) (mut i32) i32.const 1114112)
     (export "cabi_realloc" (func 0))
@@ -98,8 +98,8 @@
     (import "env" "__indirect_function_table" (table (;0;) 0 funcref))
     (func (;0;) (type 0))
     (start 0)
-    (elem (;0;) (i32.const 0) func)
-    (elem (;1;) (i32.const 0) func)
+    (elem (;0;) (i32.const 1) func)
+    (elem (;1;) (i32.const 1) func)
     (data (;0;) (i32.const 1048576) "\00\00\00\00\00\00\10\00")
     (@producers
       (processed-by "wit-component" "$CARGO_PKG_VERSION")
diff --git a/crates/wit-component/tests/components/link-circular/component.wat b/crates/wit-component/tests/components/link-circular/component.wat
index f8aadfcc..16276da9 100644
--- a/crates/wit-component/tests/components/link-circular/component.wat
+++ b/crates/wit-component/tests/components/link-circular/component.wat
@@ -10,16 +10,16 @@
     (type (;0;) (func (param i32) (result i32)))
     (func (;0;) (type 0) (param i32) (result i32)
       local.get 0
-      i32.const 0
+      i32.const 1
       call_indirect (type 0)
     )
-    (table (;0;) 1 funcref)
+    (table (;0;) 2 funcref)
     (memory (;0;) 17)
     (global (;0;) (mut i32) i32.const 1048576)
     (global (;1;) i32 i32.const 1048592)
-    (global (;2;) i32 i32.const 0)
+    (global (;2;) i32 i32.const 1)
     (global (;3;) i32 i32.const 1048592)
-    (global (;4;) i32 i32.const 0)
+    (global (;4;) i32 i32.const 1)
     (global (;5;) (mut i32) i32.const 1048592)
     (global (;6;) (mut i32) i32.const 1114112)
     (export "__stack_pointer" (global 0))
@@ -72,8 +72,8 @@
     (import "foo" "foo" (func (;0;) (type 2)))
     (func (;1;) (type 0))
     (start 1)
-    (elem (;0;) (i32.const 0) func)
-    (elem (;1;) (i32.const 0) func 0)
+    (elem (;0;) (i32.const 1) func)
+    (elem (;1;) (i32.const 1) func 0)
     (data (;0;) (i32.const 1048576) "\00\00\00\00\00\00\10\00")
     (@producers
       (processed-by "wit-component" "$CARGO_PKG_VERSION")
diff --git a/crates/wit-component/tests/components/link-dl-openable/component.wat b/crates/wit-component/tests/components/link-dl-openable/component.wat
index 05b4a4f7..d1c540de 100644
--- a/crates/wit-component/tests/components/link-dl-openable/component.wat
+++ b/crates/wit-component/tests/components/link-dl-openable/component.wat
@@ -7,11 +7,11 @@
   )
   (import "test:test/test" (instance (;0;) (type 0)))
   (core module (;0;)
-    (table (;0;) 3 funcref)
+    (table (;0;) 4 funcref)
     (memory (;0;) 17)
     (global (;0;) (mut i32) i32.const 1048576)
     (global (;1;) i32 i32.const 1048688)
-    (global (;2;) i32 i32.const 3)
+    (global (;2;) i32 i32.const 4)
     (global (;3;) (mut i32) i32.const 1048688)
     (global (;4;) (mut i32) i32.const 1114112)
     (export "__stack_pointer" (global 0))
@@ -61,9 +61,9 @@
       i32.store
     )
     (start 3)
-    (elem (;0;) (i32.const 0) func 0 1 2)
-    (elem (;1;) (i32.const 3) func)
-    (data (;0;) (i32.const 1048576) "foo\00bar\00baz\00test:test/test#foo\00\00what\03\00\00\00\04\00\10\00\00\00\00\00\03\00\00\00\08\00\10\00\01\00\00\00\12\00\00\00\0c\00\10\00\02\00\00\00\04\00\00\00 \00\10\00\00\00\00\00\03\00\00\00\00\00\10\00\04\00\00\00$\00\10\00\01\00\00\00T\00\10\00")
+    (elem (;0;) (i32.const 1) func 0 1 2)
+    (elem (;1;) (i32.const 4) func)
+    (data (;0;) (i32.const 1048576) "foo\00bar\00baz\00test:test/test#foo\00\00what\03\00\00\00\04\00\10\00\01\00\00\00\03\00\00\00\08\00\10\00\02\00\00\00\12\00\00\00\0c\00\10\00\03\00\00\00\04\00\00\00 \00\10\00\00\00\00\00\03\00\00\00\00\00\10\00\04\00\00\00$\00\10\00\01\00\00\00T\00\10\00")
     (@producers
       (processed-by "wit-component" "$CARGO_PKG_VERSION")
     )
diff --git a/crates/wit-component/tests/components/link-duplicate-symbols/component.wat b/crates/wit-component/tests/components/link-duplicate-symbols/component.wat
index f267ac4b..04ce2271 100644
--- a/crates/wit-component/tests/components/link-duplicate-symbols/component.wat
+++ b/crates/wit-component/tests/components/link-duplicate-symbols/component.wat
@@ -10,16 +10,16 @@
     (type (;0;) (func (param i32) (result i32)))
     (func (;0;) (type 0) (param i32) (result i32)
       local.get 0
-      i32.const 0
+      i32.const 1
       call_indirect (type 0)
     )
-    (table (;0;) 1 funcref)
+    (table (;0;) 2 funcref)
     (memory (;0;) 17)
     (global (;0;) (mut i32) i32.const 1048576)
     (global (;1;) i32 i32.const 1048592)
-    (global (;2;) i32 i32.const 0)
+    (global (;2;) i32 i32.const 1)
     (global (;3;) i32 i32.const 1048592)
-    (global (;4;) i32 i32.const 0)
+    (global (;4;) i32 i32.const 1)
     (global (;5;) (mut i32) i32.const 1048592)
     (global (;6;) (mut i32) i32.const 1114112)
     (export "__stack_pointer" (global 0))
@@ -73,8 +73,8 @@
     (import "bar" "foo" (func (;0;) (type 2)))
     (func (;1;) (type 0))
     (start 1)
-    (elem (;0;) (i32.const 0) func)
-    (elem (;1;) (i32.const 0) func 0)
+    (elem (;0;) (i32.const 1) func)
+    (elem (;1;) (i32.const 1) func 0)
     (data (;0;) (i32.const 1048576) "\00\00\00\00\00\00\10\00")
     (@producers
       (processed-by "wit-component" "$CARGO_PKG_VERSION")
diff --git a/crates/wit-component/tests/components/link-got-func/component.wat b/crates/wit-component/tests/components/link-got-func/component.wat
index c54b8955..915d947b 100644
--- a/crates/wit-component/tests/components/link-got-func/component.wat
+++ b/crates/wit-component/tests/components/link-got-func/component.wat
@@ -10,17 +10,17 @@
     (type (;0;) (func (param i32) (result i32)))
     (func (;0;) (type 0) (param i32) (result i32)
       local.get 0
-      i32.const 0
+      i32.const 1
       call_indirect (type 0)
     )
-    (table (;0;) 1 funcref)
+    (table (;0;) 2 funcref)
     (memory (;0;) 17)
     (global (;0;) (mut i32) i32.const 1048576)
     (global (;1;) i32 i32.const 1048592)
-    (global (;2;) i32 i32.const 0)
+    (global (;2;) i32 i32.const 1)
     (global (;3;) i32 i32.const 1048592)
-    (global (;4;) i32 i32.const 0)
-    (global (;5;) (mut i32) i32.const 0)
+    (global (;4;) i32 i32.const 1)
+    (global (;5;) (mut i32) i32.const 1)
     (global (;6;) (mut i32) i32.const 1048592)
     (global (;7;) (mut i32) i32.const 1114112)
     (export "__stack_pointer" (global 0))
@@ -67,8 +67,8 @@
     (import "bar" "foo" (func (;0;) (type 2)))
     (func (;1;) (type 0))
     (start 1)
-    (elem (;0;) (i32.const 0) func)
-    (elem (;1;) (i32.const 0) func 0)
+    (elem (;0;) (i32.const 1) func)
+    (elem (;1;) (i32.const 1) func 0)
     (data (;0;) (i32.const 1048576) "\00\00\00\00\00\00\10\00")
     (@producers
       (processed-by "wit-component" "$CARGO_PKG_VERSION")
diff --git a/crates/wit-component/tests/components/link-initialize/component.wat b/crates/wit-component/tests/components/link-initialize/component.wat
index dbbf3dae..d801299f 100644
--- a/crates/wit-component/tests/components/link-initialize/component.wat
+++ b/crates/wit-component/tests/components/link-initialize/component.wat
@@ -7,16 +7,16 @@
   )
   (import "test:test/test" (instance (;0;) (type 0)))
   (core module (;0;)
-    (table (;0;) 0 funcref)
+    (table (;0;) 1 funcref)
     (memory (;0;) 17)
     (global (;0;) (mut i32) i32.const 1048576)
     (global (;1;) i32 i32.const 1048592)
-    (global (;2;) i32 i32.const 0)
+    (global (;2;) i32 i32.const 1)
     (global (;3;) (mut i32) i32.const 0)
     (global (;4;) i32 i32.const 1048624)
-    (global (;5;) i32 i32.const 0)
+    (global (;5;) i32 i32.const 1)
     (global (;6;) i32 i32.const 1048624)
-    (global (;7;) i32 i32.const 0)
+    (global (;7;) i32 i32.const 1)
     (global (;8;) (mut i32) i32.const 0)
     (global (;9;) (mut i32) i32.const 1048640)
     (global (;10;) (mut i32) i32.const 1114112)
@@ -173,8 +173,8 @@
       call 3
     )
     (start 4)
-    (elem (;0;) (i32.const 0) func)
-    (elem (;1;) (i32.const 0) func)
+    (elem (;0;) (i32.const 1) func)
+    (elem (;1;) (i32.const 1) func)
     (data (;0;) (i32.const 1048576) "\00\00\00\00\00\00\10\00")
     (@producers
       (processed-by "wit-component" "$CARGO_PKG_VERSION")
diff --git a/crates/wit-component/tests/components/link-resources/component.wat b/crates/wit-component/tests/components/link-resources/component.wat
index ef038e32..b36255f5 100644
--- a/crates/wit-component/tests/components/link-resources/component.wat
+++ b/crates/wit-component/tests/components/link-resources/component.wat
@@ -1,12 +1,12 @@
 (component
   (core module (;0;)
-    (table (;0;) 0 funcref)
+    (table (;0;) 1 funcref)
     (memory (;0;) 17)
     (global (;0;) (mut i32) i32.const 1048576)
     (global (;1;) i32 i32.const 1048592)
-    (global (;2;) i32 i32.const 0)
+    (global (;2;) i32 i32.const 1)
     (global (;3;) i32 i32.const 1048592)
-    (global (;4;) i32 i32.const 0)
+    (global (;4;) i32 i32.const 1)
     (global (;5;) (mut i32) i32.const 1048592)
     (global (;6;) (mut i32) i32.const 1114112)
     (export "__stack_pointer" (global 0))
@@ -61,8 +61,8 @@
     (import "env" "__indirect_function_table" (table (;0;) 0 funcref))
     (func (;0;) (type 0))
     (start 0)
-    (elem (;0;) (i32.const 0) func)
-    (elem (;1;) (i32.const 0) func)
+    (elem (;0;) (i32.const 1) func)
+    (elem (;1;) (i32.const 1) func)
     (data (;0;) (i32.const 1048576) "\00\00\00\00\00\00\10\00")
     (@producers
       (processed-by "wit-component" "$CARGO_PKG_VERSION")
diff --git a/crates/wit-component/tests/components/link-stubs/component.wat b/crates/wit-component/tests/components/link-stubs/component.wat
index 3797346f..2768e916 100644
--- a/crates/wit-component/tests/components/link-stubs/component.wat
+++ b/crates/wit-component/tests/components/link-stubs/component.wat
@@ -7,13 +7,13 @@
   )
   (import "test:test/test" (instance (;0;) (type 0)))
   (core module (;0;)
-    (table (;0;) 0 funcref)
+    (table (;0;) 2 funcref)
     (memory (;0;) 17)
     (global (;0;) (mut i32) i32.const 1048576)
     (global (;1;) i32 i32.const 1048592)
-    (global (;2;) i32 i32.const 0)
+    (global (;2;) i32 i32.const 1)
     (global (;3;) i32 i32.const 1048592)
-    (global (;4;) i32 i32.const 0)
+    (global (;4;) i32 i32.const 2)
     (global (;5;) (mut i32) i32.const 1048592)
     (global (;6;) (mut i32) i32.const 1114112)
     (export "__stack_pointer" (global 0))
@@ -64,8 +64,8 @@
     (import "env" "__indirect_function_table" (table (;0;) 0 funcref))
     (func (;0;) (type 0))
     (start 0)
-    (elem (;0;) (i32.const 0) func)
-    (elem (;1;) (i32.const 0) func)
+    (elem (;0;) (i32.const 1) func)
+    (elem (;1;) (i32.const 2) func)
     (data (;0;) (i32.const 1048576) "\00\00\00\00\00\00\10\00")
     (@producers
       (processed-by "wit-component" "$CARGO_PKG_VERSION")
diff --git a/crates/wit-component/tests/components/link-weak-import/component.wat b/crates/wit-component/tests/components/link-weak-import/component.wat
index 3c1d1d6a..d57404e1 100644
--- a/crates/wit-component/tests/components/link-weak-import/component.wat
+++ b/crates/wit-component/tests/components/link-weak-import/component.wat
@@ -7,13 +7,13 @@
   )
   (import "test:test/test" (instance (;0;) (type 0)))
   (core module (;0;)
-    (table (;0;) 0 funcref)
+    (table (;0;) 2 funcref)
     (memory (;0;) 17)
     (global (;0;) (mut i32) i32.const 1048576)
     (global (;1;) i32 i32.const 1048592)
-    (global (;2;) i32 i32.const 0)
+    (global (;2;) i32 i32.const 1)
     (global (;3;) i32 i32.const 1048592)
-    (global (;4;) i32 i32.const 0)
+    (global (;4;) i32 i32.const 2)
     (global (;5;) (mut i32) i32.const 1048592)
     (global (;6;) (mut i32) i32.const 1114112)
     (export "__stack_pointer" (global 0))
@@ -66,8 +66,8 @@
     (import "env" "__indirect_function_table" (table (;0;) 0 funcref))
     (func (;0;) (type 0))
     (start 0)
-    (elem (;0;) (i32.const 0) func)
-    (elem (;1;) (i32.const 0) func)
+    (elem (;0;) (i32.const 1) func)
+    (elem (;1;) (i32.const 2) func)
     (data (;0;) (i32.const 1048576) "\00\00\00\00\00\00\10\00")
     (@producers
       (processed-by "wit-component" "$CARGO_PKG_VERSION")
diff --git a/crates/wit-component/tests/components/link/component.wat b/crates/wit-component/tests/components/link/component.wat
index b35218f1..d78029e7 100644
--- a/crates/wit-component/tests/components/link/component.wat
+++ b/crates/wit-component/tests/components/link/component.wat
@@ -7,16 +7,16 @@
   )
   (import "test:test/test" (instance (;0;) (type 0)))
   (core module (;0;)
-    (table (;0;) 0 funcref)
+    (table (;0;) 1 funcref)
     (memory (;0;) 17)
     (global (;0;) (mut i32) i32.const 1048576)
     (global (;1;) i32 i32.const 1048592)
-    (global (;2;) i32 i32.const 0)
+    (global (;2;) i32 i32.const 1)
     (global (;3;) (mut i32) i32.const 0)
     (global (;4;) i32 i32.const 1048624)
-    (global (;5;) i32 i32.const 0)
+    (global (;5;) i32 i32.const 1)
     (global (;6;) i32 i32.const 1048624)
-    (global (;7;) i32 i32.const 0)
+    (global (;7;) i32 i32.const 1)
     (global (;8;) (mut i32) i32.const 0)
     (global (;9;) (mut i32) i32.const 1048640)
     (global (;10;) (mut i32) i32.const 1114112)
@@ -173,8 +173,8 @@
       call 3
     )
     (start 4)
-    (elem (;0;) (i32.const 0) func)
-    (elem (;1;) (i32.const 0) func)
+    (elem (;0;) (i32.const 1) func)
+    (elem (;1;) (i32.const 1) func)
     (data (;0;) (i32.const 1048576) "\00\00\00\00\00\00\10\00")
     (@producers
       (processed-by "wit-component" "$CARGO_PKG_VERSION")