【问题标题】:C to WebAssembly fails when indexing pointer索引指针时 C 到 WebAssembly 失败
【发布时间】:2020-02-21 11:16:54
【问题描述】:

我正在尝试使用 C 到 WebAssembly。但我无法理解以下内容:

int atAddressN(unsigned int idx) {
  unsigned int* intptr = 0;
  return intptr[idx];
}

int atAddress2(unsigned int idx) {
  unsigned int* intptr = 0;
  return intptr[2];
}

结果如下 wasm/wat:

(module
 (table 0 anyfunc)
 (memory $0 1)
 (export "memory" (memory $0))
 (export "atAddressN" (func $atAddressN))
 (export "atAddress2" (func $atAddress2))
 (func $atAddressN (; 0 ;) (param $0 i32) (result i32)
  (unreachable)
  (unreachable)
 )
 (func $atAddress2 (; 1 ;) (param $0 i32) (result i32)
  (i32.load offset=8
   (i32.const 0)
  )
 )
)

所以第二个函数没问题,但第一个函数只产生(unreachable)。我应该做些什么来让它编译好吗?

【问题讨论】:

  • 当您取消引用空指针时,这两个函数都会导致 未定义的行为
  • 内存是事先布局好的(用Webassembly.Memory从JS调用),原则上应该没问题。
  • 我会开始尝试普通的 C 语言。

标签: c webassembly


【解决方案1】:

空指针解引用确实是个问题,改成:

int atAddressN(unsigned int* intptr, unsigned int idx) {
  return intptr[idx];
}

int atAddress2(unsigned int* intptr, unsigned int idx) {
  return intptr[2];
}

结果

(module
 (table 0 anyfunc)
 (memory $0 1)
 (export "memory" (memory $0))
 (export "atAddressN" (func $atAddressN))
 (export "atAddress2" (func $atAddress2))
 (func $atAddressN (; 0 ;) (param $0 i32) (param $1 i32) (result i32)
  (i32.load
   (i32.add
    (get_local $0)
    (i32.shl
     (get_local $1)
     (i32.const 2)
    )
   )
  )
 )
 (func $atAddress2 (; 1 ;) (param $0 i32) (param $1 i32) (result i32)
  (i32.load offset=8
   (get_local $0)
  )
 )
)

然后我将使用0 作为第一个参数调用该函数。

【讨论】:

    【解决方案2】:

    创建一个调用该函数的测试用例,使用调试符号-g 进行编译,并使用gdb 之类的调试器逐步完成它。这是一个典型的调试会话。

    程序收到信号SIGSEGV,分段错误。 0x0000000000401147 在 atAddressN (idx=3) 在 e.c:4 4 返回intptr[idx];

    (gdb) print intptr[idx]
    Cannot access memory at address 0xc
    

    gdb print 命令揭示了这个问题。

    在测试方面,WebAssembly 并没有什么特别之处。这些测试的孩子通常也可以编译为可执行文件。

    //test.c
    int main (){ printf("int 3 is %i\n", atAddressN(3)); return 0;}
    

    【讨论】:

    • 它可能依赖于 WebAssembly 引擎,但是当从 Chrome 中使用时,您会为引擎预先分配一个内存,然后它似乎从 0x0 开始。我不确定这是否在所有 WebAssembly 实现中都很常见,尽管我还没有找到任何其他机制来确定此内存映射到哪个地址。
    • 我没试过。但是,如果有人想在 WebAssembly 中编写自修改代码,则类似于答案 #7447013。像 Tigress 一样更改内存权限并修改生成的 WebAssembly。也许没有使用编译器优化,-O0 所以损坏的代码不会得到优化。
    • 我认为 WebAssembly 不允许访问代码内存。也没有堆栈指针,从这个意义上说,这一切都非常严格/安全。 AFAIK 堆从 0x0 开始(如果没有 const 数据)。不确定 Tigress 是做什么的,也许有某种嵌入式 VM?
    • 是的。 Tigress 正在虚拟化。这可能就是他们提出这一主张的方式。 tigress.wtf/introduction.html 假设出于混淆目的在 WebAssembly 中实现自己的解释器和虚拟机没有任何限制。还有缓冲区溢出和其他漏洞的可能性,但没有专业产品应该依赖这些......
    猜你喜欢
    • 2014-03-14
    • 2023-02-08
    • 2014-09-25
    • 2021-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-14
    • 1970-01-01
    相关资源
    最近更新 更多