Skip to content

Out of bounds memory access with Os & BINARYEN_IGNORE_IMPLICIT_TRAPS=1 #8941

@tklajnscek

Description

@tklajnscek

Compiling the following program with 1.38.37 fastcomp using
emcc -Os -s BINARYEN_IGNORE_IMPLICIT_TRAPS=1 test.cpp -o test.js
causes the program to misbehave and crash with
RuntimeError: memory access out of bounds

The optimizer removes the conditional surrounding the access to dontAccess and merges it all into one block.

Here's the minimal repro code:

int len = 0;
unsigned* dontAccess = 0;

int main() {
   if (len == 0 || dontAccess[len - 1]) {
      len += 1;
   }
   return 0;
}

Omitting BINARYEN_IGNORE_IMPLICIT_TRAPS or changing the optimization level to e.g. O3 fixes it.
Here's the WAST output of the working version. Notice the nested ifs.

func (result i32)
(local i32)
  i32.const 1024
  i32.load offset=0 align=4
  tee_local 0
  if <== CHECK IF LEN IS NON-ZERO AND AVOID ACCESSING THE ARRAY
    get_local 0
    i32.const -1
    i32.add
    i32.const 2
    i32.shl
    i32.load offset=0 align=4
    i32.eqz
    if
      i32.const 0
      return
    end
  end
  i32.const 1024
  get_local 0
  i32.const 1
  i32.add
  i32.store offset=0 align=4
  i32.const 0
end

Here's the WAST output from the failing case. The ifs have been flattened and both memory accesses always happen unconditionally (to len and to the start of dontAccess) causing an invalid memory read.

func (result i32)
(local i32)
  i32.const 1024
  i32.load offset=0 align=4
  tee_local 0
  i32.eqz <== CHECK IF LEN IS ZERO 
  get_local 0
  i32.const -1
  i32.add
  i32.const 2
  i32.shl
  i32.load offset=0 align=4 <== THIS CRASHES
  i32.or <== NAIVELY OR THE RESULTS OF BOTH COMPARISONS
  if
    i32.const 1024
    get_local 0
    i32.const 1
    i32.add
    i32.store offset=0 align=4
  end
  i32.const 0
end

This does work with the latest upstream Clang 9 based Emscripten, but I think it's still worth investigating since the upstream doesn't seem to be read for prime time yet.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions