Bug 695438 - Allow all integers in StringIsTypedArrayIndex, r=luke.

This commit is contained in:
Brian Hackett 2014-03-05 12:32:53 -07:00
parent b28812aad1
commit eea6966f89
5 changed files with 38 additions and 26 deletions

View File

@ -14,11 +14,18 @@ function f() {
}
f();
// Integers which don't fit in a double value's mantissa aren't really integers.
// Really big integers not representable with a double or uint64 are still integers.
var bigint = "" + Math.pow(2, 53);
x[bigint] = "twelve";
assertEq(x[bigint], "twelve");
assertEq(x[bigint], undefined);
x["9999999999999999999999"] = "twelve";
assertEq(x["9999999999999999999999"], undefined);
// Except when their toString() makes them not look like integers!
x[9999999999999999999999] = "twelve";
assertEq(x[9999999999999999999999], "twelve");
// Infinity and -Infinity maybe are supposed to be integers, but they aren't currently.

View File

@ -66,9 +66,9 @@ for (constructor of constructors) {
a[-10 >>> 0] = "twelve";
assertEq(a[-10 >>> 0], undefined);
// Watch for overly large indexed properties.
// Watch for really large indexed properties too.
a[Math.pow(2, 53)] = "twelve";
assertEq(a[Math.pow(2, 53)], "twelve");
assertEq(a[Math.pow(2, 53)], undefined);
// Don't define old properties.
Object.defineProperty(a, 5, {value: 3});

View File

@ -3760,7 +3760,7 @@ DefinePropertyOrElement(typename ExecutionModeTraits<mode>::ExclusiveContextType
// Don't define new indexed properties on typed arrays.
if (obj->is<TypedArrayObject>()) {
double index;
uint64_t index;
if (IsTypedArrayIndex(id, &index))
return true;
}
@ -4002,9 +4002,9 @@ LookupOwnPropertyWithFlagsInline(ExclusiveContext *cx,
// so that integer properties on the prototype are ignored even for out
// of bounds accesses.
if (obj->template is<TypedArrayObject>()) {
double index;
uint64_t index;
if (IsTypedArrayIndex(id, &index)) {
if (index >= 0 && index < obj->template as<TypedArrayObject>().length()) {
if (index < obj->template as<TypedArrayObject>().length()) {
objp.set(obj);
MarkDenseOrTypedArrayElementFound<allowGC>(propp);
}
@ -4595,9 +4595,9 @@ LookupPropertyPureInline(JSObject *obj, jsid id, JSObject **objp, Shape **propp)
}
if (current->is<TypedArrayObject>()) {
double index;
uint64_t index;
if (IsTypedArrayIndex(id, &index)) {
if (index >= 0 && index < obj->as<TypedArrayObject>().length()) {
if (index < obj->as<TypedArrayObject>().length()) {
*objp = current;
MarkDenseOrTypedArrayElementFound<NoGC>(propp);
} else {

View File

@ -2500,12 +2500,8 @@ js::AsTypedArrayBuffer(HandleValue v)
}
bool
js::StringIsTypedArrayIndex(JSLinearString *str, double *indexp)
js::StringIsTypedArrayIndex(JSLinearString *str, uint64_t *indexp)
{
// Largest double (2^53 - 1) which can be exactly represented in the
// mantissa of a double.
static const double MAX_INTEGER = 9007199254740991;
const jschar *s = str->chars();
const jschar *end = s + str->length();
@ -2522,7 +2518,7 @@ js::StringIsTypedArrayIndex(JSLinearString *str, double *indexp)
if (!JS7_ISDEC(*s))
return false;
double index = 0;
uint64_t index = 0;
uint32_t digit = JS7_UNDEC(*s++);
/* Don't allow leading zeros. */
@ -2537,17 +2533,17 @@ js::StringIsTypedArrayIndex(JSLinearString *str, double *indexp)
digit = JS7_UNDEC(*s);
/* Watch for mantissa overflows. */
if ((MAX_INTEGER - digit) / 10 < index)
return false;
index = 10 * index + digit;
/* Watch for overflows. */
if ((UINT64_MAX - digit) / 10 < index)
index = UINT64_MAX;
else
index = 10 * index + digit;
}
if (negative)
index = -index;
*indexp = index;
*indexp = UINT64_MAX;
else
*indexp = index;
return true;
}

View File

@ -140,11 +140,14 @@ IsTypedArrayBuffer(HandleValue v);
ArrayBufferObject &
AsTypedArrayBuffer(HandleValue v);
// Return value is whether the string is some integer. If the string is an
// integer which is not representable as a uint64_t, the return value is true
// and the resulting index is UINT64_MAX.
bool
StringIsTypedArrayIndex(JSLinearString *str, double *indexp);
StringIsTypedArrayIndex(JSLinearString *str, uint64_t *indexp);
inline bool
IsTypedArrayIndex(jsid id, double *indexp)
IsTypedArrayIndex(jsid id, uint64_t *indexp)
{
if (JSID_IS_INT(id)) {
int32_t i = JSID_TO_INT(id);
@ -156,7 +159,13 @@ IsTypedArrayIndex(jsid id, double *indexp)
if (MOZ_UNLIKELY(!JSID_IS_STRING(id)))
return false;
return StringIsTypedArrayIndex(JSID_TO_ATOM(id), indexp);
JSAtom *atom = JSID_TO_ATOM(id);
jschar c = atom->chars()[0];
if (!JS7_ISDEC(c) && c != '-')
return false;
return StringIsTypedArrayIndex(atom, indexp);
}
static inline unsigned