Fix structured cloning deserialization bug that could create invalid Date objects. Bug 602806, r=gal.

This commit is contained in:
Jason Orendorff 2010-12-03 12:15:06 -06:00
parent 3718e3fee4
commit 4b36cd08d6
6 changed files with 50 additions and 7 deletions

View File

@ -719,8 +719,13 @@ JSStructuredCloneReader::startRead(Value *vp)
case SCTAG_DATE_OBJECT: {
jsdouble d;
if (!in.readDouble(&d))
if (!in.readDouble(&d) || !checkDouble(d))
return false;
if (d == d && d != TIMECLIP(d)) {
JS_ReportErrorNumber(context(), js_GetErrorMessage, NULL, JSMSG_SC_BAD_SERIALIZED_DATA,
"date");
return false;
}
JSObject *obj = js_NewDateObjectMsec(context(), d);
if (!obj)
return false;

View File

@ -152,7 +152,6 @@ using namespace js;
* Supporting functions - ECMA 15.9.1.*
*/
#define HalfTimeDomain 8.64e15
#define HoursPerDay 24.0
#define MinutesPerDay (HoursPerDay * MinutesPerHour)
#define MinutesPerHour 60.0
@ -482,10 +481,6 @@ msFromTime(jsdouble t)
return result;
}
#define TIMECLIP(d) ((JSDOUBLE_IS_FINITE(d) \
&& !((d < 0 ? -d : d) > HalfTimeDomain)) \
? js_DoubleToInteger(d + (+0.)) : js_NaN)
/**
* end of ECMA 'support' functions
*/

View File

@ -54,6 +54,12 @@ JSObject::isDate() const
return getClass() == &js_DateClass;
}
#define HalfTimeDomain 8.64e15
#define TIMECLIP(d) ((JSDOUBLE_IS_FINITE(d) \
&& !((d < 0 ? -d : d) > HalfTimeDomain)) \
? js_DoubleToInteger(d + (+0.)) : js_NaN)
extern JSObject *
js_InitDateClass(JSContext *cx, JSObject *obj);

View File

@ -0,0 +1,31 @@
// -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/licenses/publicdomain/
function assertThrows(f) {
var ok = false;
try {
f();
} catch (exc) {
ok = true;
}
if (!ok)
throw new TypeError("Assertion failed: " + f + " did not throw as expected");
}
// Don't allow forging bogus Date objects.
var buf = serialize(new Date(NaN));
var a = [1/0, -1/0,
Number.MIN_VALUE, -Number.MIN_VALUE,
Math.PI, 1286523948674.5,
Number.MAX_VALUE, -Number.MAX_VALUE,
8.64e15 + 1, -(8.64e15 + 1)];
for (var i = 0; i < a.length; i++) {
var n = a[i];
var nbuf = serialize(n);
for (var j = 0; j < 8; j++)
buf[j + 8] = nbuf[j];
assertThrows(function () { deserialize(buf); });
}
reportCompare(0, 0);

View File

@ -26,7 +26,6 @@ var a = [new Boolean(true),
new String("\0123\u4567"),
new Date(0),
new Date(-0),
new Date(Math.PI),
new Date(0x7fffffff),
new Date(-0x7fffffff),
new Date(0x80000000),
@ -40,9 +39,14 @@ var a = [new Boolean(true),
new Date(-8.64e15),
new Date(NaN)];
function primitive(a) {
return a instanceof Date ? +a : a.constructor(a);
}
for (var i = 0; i < a.length; i++) {
var x = a[i];
var expectedSource = x.toSource();
var expectedPrimitive = primitive(x);
var expectedProto = x.__proto__;
var expectedString = Object.prototype.toString.call(x);
x.expando = 1;
@ -50,6 +54,7 @@ for (var i = 0; i < a.length; i++) {
var y = deserialize(serialize(x));
assertEq(y.toSource(), expectedSource);
assertEq(primitive(y), expectedPrimitive);
assertEq(y.__proto__, expectedProto);
assertEq(Object.prototype.toString.call(y), expectedString);
assertEq("expando" in y, false);

View File

@ -22,4 +22,5 @@ skip-if(!xulRuntime.shell) script clone-leaf-object.js
skip-if(!xulRuntime.shell) script clone-object.js
skip-if(!xulRuntime.shell) script clone-typed-array.js
skip-if(!xulRuntime.shell) script clone-errors.js
skip-if(!xulRuntime.shell) script clone-forge.js
script set-property-non-extensible.js