Bug 619283 - Built-in JS methods must not box undefined or null into the global object when called, both to comply with ES5 and to prevent inadvertent global object exposure to secure JS variants. r=dmandelin

This commit is contained in:
Jeff Walden
2011-01-26 13:37:45 -08:00
parent 62c930a048
commit e3f53dd06d
61 changed files with 1358 additions and 616 deletions

View File

@@ -1403,6 +1403,15 @@ GetAndCacheLocalTime(JSContext *cx, JSObject *obj, Value *vp, jsdouble *time = N
return true;
}
static inline bool
GetThisUTCTime(JSContext *cx, Value *vp, jsdouble *dp)
{
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
return GetUTCTime(cx, obj, vp, dp);
}
/*
* See ECMA 15.9.5.4 thru 15.9.5.23
*/
@@ -1410,19 +1419,21 @@ static JSBool
date_getTime(JSContext *cx, uintN argc, Value *vp)
{
jsdouble result;
if (!GetUTCTime(cx, ComputeThisFromVp(cx, vp), vp, &result))
return JS_FALSE;
if (!GetThisUTCTime(cx, vp, &result))
return false;
vp->setNumber(result);
return JS_TRUE;
return true;
}
static JSBool
date_getYear(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
if (!GetAndCacheLocalTime(cx, obj, vp))
return JS_FALSE;
return false;
Value yearVal = obj->getSlot(JSObject::JSSLOT_DATE_LOCAL_YEAR);
if (yearVal.isInt32()) {
@@ -1433,13 +1444,16 @@ date_getYear(JSContext *cx, uintN argc, Value *vp)
*vp = yearVal;
}
return JS_TRUE;
return true;
}
static JSBool
date_getFullYear(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
if (!GetAndCacheLocalTime(cx, obj, vp))
return JS_FALSE;
@@ -1451,113 +1465,120 @@ static JSBool
date_getUTCFullYear(JSContext *cx, uintN argc, Value *vp)
{
jsdouble result;
if (!GetUTCTime(cx, ComputeThisFromVp(cx, vp), vp, &result))
return JS_FALSE;
if (!GetThisUTCTime(cx, vp, &result))
return false;
if (JSDOUBLE_IS_FINITE(result))
result = YearFromTime(result);
vp->setNumber(result);
return JS_TRUE;
return true;
}
static JSBool
date_getMonth(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
if (!GetAndCacheLocalTime(cx, obj, vp))
return JS_FALSE;
return false;
*vp = obj->getSlot(JSObject::JSSLOT_DATE_LOCAL_MONTH);
return JS_TRUE;
return true;
}
static JSBool
date_getUTCMonth(JSContext *cx, uintN argc, Value *vp)
{
jsdouble result;
if (!GetUTCTime(cx, ComputeThisFromVp(cx, vp), vp, &result))
return JS_FALSE;
if (!GetThisUTCTime(cx, vp, &result))
return false;
if (JSDOUBLE_IS_FINITE(result))
result = MonthFromTime(result);
vp->setNumber(result);
return JS_TRUE;
return true;
}
static JSBool
date_getDate(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
if (!GetAndCacheLocalTime(cx, obj, vp))
return JS_FALSE;
return false;
*vp = obj->getSlot(JSObject::JSSLOT_DATE_LOCAL_DATE);
return JS_TRUE;
return true;
}
static JSBool
date_getUTCDate(JSContext *cx, uintN argc, Value *vp)
{
jsdouble result;
if (!GetUTCTime(cx, ComputeThisFromVp(cx, vp), vp, &result))
return JS_FALSE;
if (!GetThisUTCTime(cx, vp, &result))
return false;
if (JSDOUBLE_IS_FINITE(result))
result = DateFromTime(result);
vp->setNumber(result);
return JS_TRUE;
return true;
}
static JSBool
date_getDay(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
if (!GetAndCacheLocalTime(cx, obj, vp))
return JS_FALSE;
return false;
*vp = obj->getSlot(JSObject::JSSLOT_DATE_LOCAL_DAY);
return JS_TRUE;
return true;
}
static JSBool
date_getUTCDay(JSContext *cx, uintN argc, Value *vp)
{
jsdouble result;
if (!GetUTCTime(cx, ComputeThisFromVp(cx, vp), vp, &result))
return JS_FALSE;
if (!GetThisUTCTime(cx, vp, &result))
return false;
if (JSDOUBLE_IS_FINITE(result))
result = WeekDay(result);
vp->setNumber(result);
return JS_TRUE;
return true;
}
static JSBool
date_getHours(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
if (!GetAndCacheLocalTime(cx, obj, vp))
return JS_FALSE;
return false;
*vp = obj->getSlot(JSObject::JSSLOT_DATE_LOCAL_HOURS);
return JS_TRUE;
return true;
}
static JSBool
date_getUTCHours(JSContext *cx, uintN argc, Value *vp)
{
jsdouble result;
if (!GetUTCTime(cx, ComputeThisFromVp(cx, vp), vp, &result))
return JS_FALSE;
if (!GetThisUTCTime(cx, vp, &result))
return false;
if (JSDOUBLE_IS_FINITE(result))
result = HourFromTime(result);
@@ -1569,27 +1590,29 @@ date_getUTCHours(JSContext *cx, uintN argc, Value *vp)
static JSBool
date_getMinutes(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
if (!GetAndCacheLocalTime(cx, obj, vp))
return JS_FALSE;
return false;
*vp = obj->getSlot(JSObject::JSSLOT_DATE_LOCAL_MINUTES);
return JS_TRUE;
return true;
}
static JSBool
date_getUTCMinutes(JSContext *cx, uintN argc, Value *vp)
{
jsdouble result;
if (!GetUTCTime(cx, ComputeThisFromVp(cx, vp), vp, &result))
return JS_FALSE;
if (!GetThisUTCTime(cx, vp, &result))
return false;
if (JSDOUBLE_IS_FINITE(result))
result = MinFromTime(result);
vp->setNumber(result);
return JS_TRUE;
return true;
}
/* Date.getSeconds is mapped to getUTCSeconds */
@@ -1597,12 +1620,15 @@ date_getUTCMinutes(JSContext *cx, uintN argc, Value *vp)
static JSBool
date_getUTCSeconds(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
if (!GetAndCacheLocalTime(cx, obj, vp))
return JS_FALSE;
return false;
*vp = obj->getSlot(JSObject::JSSLOT_DATE_LOCAL_SECONDS);
return JS_TRUE;
return true;
}
/* Date.getMilliseconds is mapped to getUTCMilliseconds */
@@ -1611,43 +1637,48 @@ static JSBool
date_getUTCMilliseconds(JSContext *cx, uintN argc, Value *vp)
{
jsdouble result;
if (!GetUTCTime(cx, ComputeThisFromVp(cx, vp), vp, &result))
return JS_FALSE;
if (!GetThisUTCTime(cx, vp, &result))
return false;
if (JSDOUBLE_IS_FINITE(result))
result = msFromTime(result);
vp->setNumber(result);
return JS_TRUE;
return true;
}
static JSBool
date_getTimezoneOffset(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj;
jsdouble utctime, localtime, result;
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
obj = ComputeThisFromVp(cx, vp);
jsdouble utctime;
if (!GetUTCTime(cx, obj, vp, &utctime))
return JS_FALSE;
return false;
jsdouble localtime;
if (!GetAndCacheLocalTime(cx, obj, NULL, &localtime))
return JS_FALSE;
return false;
/*
* Return the time zone offset in minutes for the current locale that is
* appropriate for this time. This value would be a constant except for
* daylight savings time.
*/
result = (utctime - localtime) / msPerMinute;
jsdouble result = (utctime - localtime) / msPerMinute;
vp->setNumber(result);
return JS_TRUE;
return true;
}
static JSBool
date_setTime(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
if (!InstanceOf(cx, obj, &js_DateClass, vp + 2))
return false;
@@ -1666,7 +1697,6 @@ date_setTime(JSContext *cx, uintN argc, Value *vp)
static JSBool
date_makeTime(JSContext *cx, uintN maxargs, JSBool local, uintN argc, Value *vp)
{
JSObject *obj;
Value *argv;
uintN i;
jsdouble args[4], *argp, *stop;
@@ -1676,7 +1706,10 @@ date_makeTime(JSContext *cx, uintN maxargs, JSBool local, uintN argc, Value *vp)
jsdouble msec_time;
jsdouble result;
obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
if (!GetUTCTime(cx, obj, vp, &result))
return false;
@@ -1805,7 +1838,6 @@ date_setUTCHours(JSContext *cx, uintN argc, Value *vp)
static JSBool
date_makeDate(JSContext *cx, uintN maxargs, JSBool local, uintN argc, Value *vp)
{
JSObject *obj;
Value *argv;
uintN i;
jsdouble lorutime; /* local or UTC version of *date */
@@ -1813,7 +1845,10 @@ date_makeDate(JSContext *cx, uintN maxargs, JSBool local, uintN argc, Value *vp)
jsdouble year, month, day;
jsdouble result;
obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
if (!GetUTCTime(cx, obj, vp, &result))
return false;
@@ -1914,7 +1949,9 @@ date_setUTCFullYear(JSContext *cx, uintN argc, Value *vp)
static JSBool
date_setYear(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
jsdouble result;
if (!GetUTCTime(cx, obj, vp, &result))
@@ -1989,23 +2026,21 @@ static JSBool
date_utc_format(JSContext *cx, Value *vp,
void (*printFunc)(char*, size_t, jsdouble))
{
char buf[100];
JSString *str;
jsdouble utctime;
if (!GetThisUTCTime(cx, vp, &utctime))
return false;
if (!GetUTCTime(cx, ComputeThisFromVp(cx, vp), vp, &utctime))
return JS_FALSE;
if (!JSDOUBLE_IS_FINITE(utctime)) {
char buf[100];
if (!JSDOUBLE_IS_FINITE(utctime))
JS_snprintf(buf, sizeof buf, js_NaN_date_str);
} else {
else
(*printFunc)(buf, sizeof buf, utctime);
}
str = JS_NewStringCopyZ(cx, buf);
JSString *str = JS_NewStringCopyZ(cx, buf);
if (!str)
return JS_FALSE;
return false;
vp->setString(str);
return JS_TRUE;
return true;
}
static JSBool
@@ -2025,7 +2060,7 @@ static JSBool
date_toJSON(JSContext *cx, uintN argc, Value *vp)
{
/* Step 1. */
JSObject *obj = js_ValueToNonNullObject(cx, vp[1]);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
@@ -2208,17 +2243,15 @@ date_format(JSContext *cx, jsdouble date, formatspec format, Value *rval)
}
static JSBool
date_toLocaleHelper(JSContext *cx, const char *format, Value *vp)
date_toLocaleHelper(JSContext *cx, JSObject *obj, const char *format, Value *vp)
{
JSObject *obj;
char buf[100];
JSString *str;
PRMJTime split;
jsdouble utctime;
obj = ComputeThisFromVp(cx, vp);
if (!GetUTCTime(cx, obj, vp, &utctime))
return JS_FALSE;
return false;
if (!JSDOUBLE_IS_FINITE(utctime)) {
JS_snprintf(buf, sizeof buf, js_NaN_date_str);
@@ -2254,19 +2287,23 @@ date_toLocaleHelper(JSContext *cx, const char *format, Value *vp)
str = JS_NewStringCopyZ(cx, buf);
if (!str)
return JS_FALSE;
return false;
vp->setString(str);
return JS_TRUE;
return true;
}
static JSBool
date_toLocaleString(JSContext *cx, uintN argc, Value *vp)
{
/* Use '%#c' for windows, because '%c' is
* backward-compatible and non-y2k with msvc; '%#c' requests that a
* full year be used in the result string.
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
/*
* Use '%#c' for windows, because '%c' is backward-compatible and non-y2k
* with msvc; '%#c' requests that a full year be used in the result string.
*/
return date_toLocaleHelper(cx,
return date_toLocaleHelper(cx, obj,
#if defined(_WIN32) && !defined(__MWERKS__)
"%#c"
#else
@@ -2278,11 +2315,15 @@ date_toLocaleString(JSContext *cx, uintN argc, Value *vp)
static JSBool
date_toLocaleDateString(JSContext *cx, uintN argc, Value *vp)
{
/* Use '%#x' for windows, because '%x' is
* backward-compatible and non-y2k with msvc; '%#x' requests that a
* full year be used in the result string.
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
/*
* Use '%#x' for windows, because '%x' is backward-compatible and non-y2k
* with msvc; '%#x' requests that a full year be used in the result string.
*/
return date_toLocaleHelper(cx,
return date_toLocaleHelper(cx, obj,
#if defined(_WIN32) && !defined(__MWERKS__)
"%#x"
#else
@@ -2294,7 +2335,11 @@ date_toLocaleDateString(JSContext *cx, uintN argc, Value *vp)
static JSBool
date_toLocaleTimeString(JSContext *cx, uintN argc, Value *vp)
{
return date_toLocaleHelper(cx, "%X", vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
return date_toLocaleHelper(cx, obj, "%X", vp);
}
static JSBool
@@ -2303,24 +2348,27 @@ date_toLocaleFormat(JSContext *cx, uintN argc, Value *vp)
if (argc == 0)
return date_toLocaleString(cx, argc, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
JSString *fmt = js_ValueToString(cx, vp[2]);
if (!fmt)
return JS_FALSE;
return false;
vp[2].setString(fmt);
JSAutoByteString fmtbytes(cx, fmt);
if (!fmtbytes)
return JS_FALSE;
return false;
return date_toLocaleHelper(cx, fmtbytes.ptr(), vp);
return date_toLocaleHelper(cx, obj, fmtbytes.ptr(), vp);
}
static JSBool
date_toTimeString(JSContext *cx, uintN argc, Value *vp)
{
jsdouble utctime;
if (!GetUTCTime(cx, ComputeThisFromVp(cx, vp), vp, &utctime))
return JS_FALSE;
if (!GetThisUTCTime(cx, vp, &utctime))
return false;
return date_format(cx, utctime, FORMATSPEC_TIME, vp);
}
@@ -2328,9 +2376,8 @@ static JSBool
date_toDateString(JSContext *cx, uintN argc, Value *vp)
{
jsdouble utctime;
if (!GetUTCTime(cx, ComputeThisFromVp(cx, vp), vp, &utctime))
return JS_FALSE;
if (!GetThisUTCTime(cx, vp, &utctime))
return false;
return date_format(cx, utctime, FORMATSPEC_DATE, vp);
}
@@ -2342,31 +2389,28 @@ static JSBool
date_toSource(JSContext *cx, uintN argc, Value *vp)
{
jsdouble utctime;
char *numStr, *bytes;
JSString *str;
if (!GetUTCTime(cx, ComputeThisFromVp(cx, vp), vp, &utctime))
return JS_FALSE;
if (!GetThisUTCTime(cx, vp, &utctime))
return false;
ToCStringBuf cbuf;
numStr = NumberToCString(cx, &cbuf, utctime);
char *numStr = NumberToCString(cx, &cbuf, utctime);
if (!numStr) {
JS_ReportOutOfMemory(cx);
return JS_FALSE;
return false;
}
bytes = JS_smprintf("(new %s(%s))", js_Date_str, numStr);
char *bytes = JS_smprintf("(new %s(%s))", js_Date_str, numStr);
if (!bytes) {
JS_ReportOutOfMemory(cx);
return JS_FALSE;
return false;
}
str = JS_NewStringCopyZ(cx, bytes);
JSString *str = JS_NewStringCopyZ(cx, bytes);
js_free(bytes);
if (!str)
return JS_FALSE;
return false;
vp->setString(str);
return JS_TRUE;
return true;
}
#endif
@@ -2374,16 +2418,17 @@ static JSBool
date_toString(JSContext *cx, uintN argc, Value *vp)
{
jsdouble utctime;
if (!GetThisUTCTime(cx, vp, &utctime))
return false;
if (!GetUTCTime(cx, ComputeThisFromVp(cx, vp), vp, &utctime))
return JS_FALSE;
return date_format(cx, utctime, FORMATSPEC_FULL, vp);
}
static JSBool
date_valueOf(JSContext *cx, uintN argc, Value *vp)
{
/* It is an error to call date_valueOf on a non-date object, but we don't
/*
* It is an error to call date_valueOf on a non-date object, but we don't
* need to check for that explicitly here because every path calls
* GetUTCTime, which does the check.
*/
@@ -2392,13 +2437,18 @@ date_valueOf(JSContext *cx, uintN argc, Value *vp)
if (argc == 0)
return date_getTime(cx, argc, vp);
/* Verify this before extracting a string from the first argument. */
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
/* Convert to number only if the hint was given, otherwise favor string. */
JSString *str = js_ValueToString(cx, vp[2]);
if (!str)
return JS_FALSE;
return false;
JSLinearString *linear_str = str->ensureLinear(cx);
if (!linear_str)
return JS_FALSE;
return false;
JSAtom *number_str = cx->runtime->atomState.typeAtoms[JSTYPE_NUMBER];
if (EqualStrings(linear_str, number_str))
return date_getTime(cx, argc, vp);