Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect validation of br_on_cast and type difference computation #6229

Open
fitzgen opened this issue Jan 19, 2024 · 2 comments
Open

Incorrect validation of br_on_cast and type difference computation #6229

fitzgen opened this issue Jan 19, 2024 · 2 comments

Comments

@fitzgen
Copy link

fitzgen commented Jan 19, 2024

Originally reported as WebAssembly/gc#510

This test case should fail validation with type mismatch: expression has type (ref any) but expected eqref. FWIW, Firefox, wasmparser, and the reference interpreter all give that validation error, however binaryen incorrectly claims it is valid.

The br_on_cast should be typed [externref eqref] -> [externref (ref any)] because diff(anyref, arrayref) = (ref any), but it seems like binaryen is typing it as an identity function.

(module
  (rec
    (type (;0;) (sub (func (result externref eqref))))
    (type (;1;) (array (mut externref)))
  )
  (import "" "" (global (;0;) (mut f32)))
  (func (;0;) (type 0) (result externref eqref)
    ;; []
    block (type 0) (result externref eqref) ;; label = @1
      ;; []
      block ;; label = @2
        ;; []
        loop (result (ref null 0)) ;; label = @3
          ;; []
          ref.null i31
          ;; [i31ref]
          call 0
          ;; [i31ref externref eqref]
          br 2 (;@1;)
          ;; [i31ref externref eqref]
          global.get 0
          ;; [i31ref externref eqref f32]
          f32.ceil
          ;; [i31ref externref eqref f32]
          call 0
          ;; [i31ref externref eqref f32 externref eqref]
          call 2
          ;; [i31ref externref eqref f32 externref eqref externref eqref]
          br_on_cast 2 (;@1;) anyref arrayref
          ;; [i31ref externref eqref f32 externref eqref externref (ref any)]
          br_on_non_null 3 (;@0;) ;; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< validation error should be here
          ref.is_null
          nop
          unreachable
        end
        unreachable
      end
      unreachable
    end
  )
  (func (;1;) (type 0) (result externref eqref)
    unreachable
  )
  (func (;2;) (type 0) (result externref eqref)
    unreachable
  )
  (memory (;0;) 15 18996)
)
@kripken
Copy link
Member

kripken commented Jan 19, 2024

This is likely due to br_on_* not supporting a sent value in addition to the reference itself, which is a current limitation. No real-world code so far does that AFAIK so it has not been a priority to add (and due to it requiring multivalue it has downsides in our IR).

Separately it is odd that this does not fail to validate on the br_on_cast going to a multivalue block. That suggests we are also missing validation there. We only fuzz valid testcases so that was missed I supposed. Adding that validation should be simple.

@tlively
Copy link
Member

tlively commented Jan 22, 2024

FWIW we do report a validation error when parsing this wat directly with --new-wat-parser due to the sent type of br_on_cast not matching the target block type. I assume the original repro was parsed from binary instead; perhaps our binary parser is doing something odd that masks the problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants