On Mar 26, 2013, at 1:29 AM, Oliver Hunt wrote:

> 
> Ok, I'll try to go over this again, because for whatever reason it doesn't 
> appear to stick:
> 
> If you have a double-typed array, and access a member:
> typedArray[0]
> 
> Then in ES it is a double that can be one of these values: +Infinitity, 
> -Infinity, NaN, or a discrete value representable in IEEE double spec.  There 
> are no signaling NaNs, nor is there any exposure of what the underlying bit 
> pattern of the NaN is.
> 
> So the runtime loads this double, and then stores it somewhere, anywhere, it 
> doesn't matter where, eg.
> var tmp = typedArray[0];
> 
> Now you store it:
> typedArray[whatever] = tmp;
> 
> The specification must allow a bitwise comparison of typedArray[whatever] to 
> typedArray[0] to return false, as it is not possible for any NaN-boxing 
> engine to maintain the bit equality that you would otherwise desire, as that 
> would be trivially exploitable.  When I say security and correctness i mean 
> it in the "can't be remotely pwned" sense.
> 
> Given that we can't guarantee that the bit pattern will remain unchanged the 
> spec should mandate normalizing to the non-signalling NaN.
> 
> --Oliver

Oliver,

Let's look at actual ES6 spec. language and see if there is actually anything 
you would like to see changed.  The encoding of NaNs is only discussed in three 
places:

Section 8.1.5, first paragraph says:  

The Number type has exactly 18437736874454810627 (that is, 264253+3) values, 
representing the double-precision 64-bit format IEEE 754 values as specified in 
the IEEE Standard for Binary Floating-Point Arithmetic, except that the 
9007199254740990 (that is, 2532) distinct “Not-a-Number” values of the IEEE 
Standard are represented in ECMAScript as a single special NaN value. (Note 
that the NaN value is produced by the program expression NaN.) In some 
implementations, external code might be able to detect a difference between 
various Not-a-Number values, but such behaviour is implementation-dependent; to 
ECMAScript code, all NaN values are indistinguishable from each other.

This is very old text, most of which dates to ES1. It is defining the ES Number 
type, which is an abstraction, not an actual bit-level encoding. To me it say 
these things:
   1) Unlike the the IEEE 64-bit floating point type.  The ES Number type has 
only a single NaN value. 
   2) An implementations are free to internally encode the Number type any why 
it desires (as long is it observably conforms to all the requirements of 
section 8.1.5).
   3) In particular, an implementation  might have multiple internal bit 
patterns all of which correspond to the single NaN element of the Number type.  
   4) A corollary of 3) is that implementation are not required to internally 
canonicalize NaNs, that is an implementation level design decision.
   5) Implementations are not required to canonicalize NaNs when they are 
passed or otherwise made visible to non-ES code.  Hence such code may be able 
to observe details of the NaN encoding, including whether or not a canonical 
NaN value is used internally by the ES implementation.

Is there anything you think should change in the above specification text?

Section 15.13.5.1.3 defines the GetValueFromBuffer abstraction operation which 
is currently the only place in the ES6 spec. where a ES Number value is 
retrieved from an ArrayBuffer. Step 8 of the specification algorithm is:
8       If type is “Float64” , then
        rawValue is interpreted, taking into accont the value of isBigEndian,  
as a bit string encoding of an IEEE 754-208 binary64 value.
        If rawValue is any an IEEE 754-208 binary64 NaN value, return the NaN 
Number value.
        Return the Number value that is encoded by rawValue.
Step 7 is similar but deals with Float32 values.

To me it say these things:
   1) In all cases, an ES Number value (as defined in 8.1.5) is returned.
   2) All IEEE NaN values are logically canonicalized as the single ES NaN 
value.
   3) No additional requirements for ES Numbers, beyond those in 8.1.5 are 
introduced.  Actual representation remains up to implementation.

Should anything change? If 8.1.5 continues to not mandate any particular or 
single encoding representation of a NaN, I don't see why this should either.

Section 15.13.5.1.4 defines the SetValueInBuffer abstraction operation which is 
currently the only place in the ES6 spec. where a ES Number value is stored 
into a ArrayBuffer. Step 8 of the specification algorithm is:

8.      Else, if type is “Float64” , then
        Set rawValue to the 8 bytes that are the IEEE-868-2005 binary64 format 
encoding of value. If isBigEndian is true, the bytes are arranged in big endian 
order.  Otherwise, the bytes are arranged in little endian order.  If value is 
NaN, rawValue is may be set to any implementation choosen non-signaling NaN 
encoding.
Step 7 is similar but deals with Float32 values.

To me it say these things:
   1) When storing into an ArrayBuffer, canonicalization of ES NaN to some 
particular IEEE NaN is permitted but not required.
   2) The actual ArrayBuffer bit-level representation of NaN values is 
completely implementation dependent.  It need not even be consistent across 
multiple stores. .
   3) External observers of such a stored value may be able to detect NaN 
encoding differences by observing Numbers stored into ArrayBuffers.  This is 
allowed by 8.1.5
   4) The actual encoding of a NaN value in an ArrayBuffer is observable by ES 
code by overly a non-float typed Array on an ArrayBuffer where a Number has 
been stored using the above steps.

Point 4 seems to be in conflict with the 8.1.5 requirement "to ECMAScript code, 
all NaN values are indistinguishable from each other.".  However, consider that 
what is being observed is not directly an ES Number NaN value but instead a bit 
pattern that according to15.13.5.1.4 above may not be a direct reflection of 
the Number NaN that was stored. So maybe it slips by.

So, again any change requests?

From a spec. perspective we could require canonicalization to some specific 
IEEE NaN (how do we pick one?) in 15.13.5.4.  If we are going to do that, we 
presumably also should require canonicalization of endian-ness which is also 
observable and arguably a bigger interop hazard than NaNs.  However, I think 
the performance arguments for not canonicalizing endian-ness in typed array are 
stronger.  If we are going to continue to  let endian-ness be implementation 
determined then I don't think there is much point in worrying about changing 
the the handling of NaNs in 15.13.5.1.4. But, I'm flexible.

Allen







_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to