asm-js / validator

A reference validator for asm.js.
Apache License 2.0
1.78k stars 148 forks source link

Spec allows standard library functions to be exported #109

Open ghost opened 9 years ago

ghost commented 9 years ago

Sections 6.2 and 6.3 of the specification respectively state the following conditions for valid export statements and valid function tables:

Validating an export declaration [...] succeeds if [for each identifier f,] Δ(f) = imm γ where γ is a function type (σ,…) → τ.

Validating a function table [...] succeeds if [...] for each [identifier] f, Δ(f) = (σ,…) → τ.

(There are two additional conditions for valid function tables that are not relevant here.)

The former condition is not sufficient to ensure that a valid export statement only refers to (asm.js) function definitions. Similarly, the latter condition is not sufficient to ensure that a valid function table only refers to function definitions. (It is also missing an imm classifier.) In both cases, the types of several standard library functions match the required shape, including Math.acos : (double?) → double and Math.imul : (int,int) → signed.

OdinMonkey's validator does not fall into this trap, correctly rejecting modules such as:

(function(std) {
  "use asm"
  var f = std.Math.acos
  function g(){}
  return f          // TypeError: asm.js type error: 'f' is not a function
})

and

(function(std) {
  "use asm"
  var f = std.Math.imul
  function g(){}
  var t = [f]       // TypeError: asm.js type error: function-pointer table's elements must be names of functions
  return g
})

Note that in both cases Δ(f) unifies with imm (σ,...) → τ.

Unfortunately, it does not seem adequate to insist that each argument type σ,... is int, double, or float, and that the return type τ is signed, double, float, or void. Although this includes every valid function definition type (see sections 5.1 and 5.2), it still fails to exclude every standard library function type. Namely, that of Math.imul.

One possibility is to introduce more contextual information into global type assumptions, by augmenting the (im)mutability classifier μ ::= mut | imm (see section 3.1) as follows:

μ ::= (in | ext); (mut | imm)

where in indicates an internal (asm.js) function definition and ext an external (imported) function.

ghost commented 9 years ago

Update:

According to the current errata (https://etherpad.mozilla.org/ibPVJ81u35), Math.imul actually takes intish arguments, so the aforementioned naive solution is adequate. Moreover, it will continue to work when Math.clz32 is added to the standard library, because its return type is fixnum.