Observability of NaN distinctions — is this a concern?

Brandon Benvie bbenvie at mozilla.com
Tue Mar 26 11:11:26 PDT 2013


On 3/26/2013 10:39 AM, Brandon Benvie wrote:
> On 3/26/2013 10:03 AM, Brandon Benvie wrote:
>> On 3/26/2013 1:12 AM, Jussi Kalliokoski wrote:
>>> The NaN distinction is only observable in the byte array, not if you 
>>> extract the value, because at that point it becomes an ES NaN value, 
>>> so that example is invalid.
>> It becomes observable on the read end by doing:
>>
>>     float64array[0] = shouldBeImmutable.foo;
>>     new Uint32Array(float64array.buffer)[0]; // or [1] depending on 
>> endianness
>>
>> ...unless you canonicalize the NaN on either on the read or the 
>> write. This is pretty damning.
> It does appear that in practice (at least in V8 and SpiderMonkey), the 
> attempt to write a different NaN does not succeed. It still is 
> possible to use a packed NaN to deliver information as a kind of 
> secret communication channel. Demonstration:
> ... snip code ...

Sorry, I screwed this up here trying to figure out why NaN packing is 
not working in Spidermonkey but is in V8. Curiously different results.

   var buff = new ArrayBuffer(8);
   var f64 = new Float64Array(buff);
   var ui32 = new Uint32Array(buff);
   ui32[1] = 0xfff80000; // may need to be 0 depending on endianness

   function packNaN(value){
     ui32[0] = value; // may need to be 1 depending on endianness
     return f64[0];
   }

   function unpackNaN(nan){
     f64[0] = nan;
     return ui32[0]; // may need to be 1 depending on endianness
   }

   var shouldBeImmutable = Object.freeze({ foo: packNaN(1500) });
   console.log(shouldBeImmutable.foo) // NaN
   console.log(unpackNaN(shouldBeImmutable.foo)); // 1500 in V8, 0 in SM
   Object.defineProperty(shouldBeImmutable, 'foo', { value: 
packNaN(2000) });
   console.log(unpackNaN(shouldBeImmutable.foo)); // 1500 in V8, 0 in SM


More information about the es-discuss mailing list