Skip to content

asm2wasm: incorrect translation of switch for big 64 bit values #1109

@pepyakin

Description

@pepyakin

Source: rust-lang/rust#42630 (comment)

For example:

function () {
  "use asm";

  var abort=env.abort;

  function main() {
    var $0 = i64(), $x = i64();
    $x = i64_const(0,0);
    $0 = $x;
    switch (i64($0)) {
      case i64_const(0,2146435072):  {
          abort();
	  break;
      }
      default: {
        return;
      }
    }
  }
  return { main: main };
}

gets translated to

(module
 (type $FUNCSIG$v (func))
 (import "env" "abort" (func $abort))
 (import "env" "memory" (memory $0 256 256))
 (import "env" "table" (table 0 0 anyfunc))
 (import "env" "memoryBase" (global $memoryBase i32))
 (import "env" "tableBase" (global $tableBase i32))
 (export "main" (func $main))
 (func $main
  (local $$0 i64)
  (local $$x i64)
  (set_local $$x
   (i64.const 0)
  )
  (set_local $$0
   (get_local $$x)
  )
  (block $switch
   (block $switch-default
    (block $switch-case
     (br_table $switch-case $switch-default
      (i32.wrap/i64
       (i64.sub
        (get_local $$0)
        (i64.const 9218868437227405312)
       )
      )
     )
    )
    (block
     (call $abort)
     (br $switch)
    )
   )
   (return)
  )
 )
)

IIUC, i32.wrap/i64 takes i64 and trunctates it to only lower 32 bits. So in this case, result of i32.wrap/i64 will be 0, meaning first switch-case will be taken and then program aborted.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions