diff options
author | Linus Groh <mail@linusgroh.de> | 2021-07-06 16:45:54 +0100 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2021-07-06 17:29:12 +0100 |
commit | 83f61748a528d6d60c216d358c65c9cd6cec0dbc (patch) | |
tree | b38eafba5a205f9ed0246694b3cdcfa97d874029 /Userland | |
parent | 47bd25a2f15b2f4c9b27a149f4452f21330cdbbe (diff) | |
download | serenity-83f61748a528d6d60c216d358c65c9cd6cec0dbc.zip |
LibJS: Don't treat 2^32 - 1 as numeric PropertyName
10.4.2 Array Exotic Objects
https://tc39.es/ecma262/#sec-array-exotic-objects
A String property name P is an array index if and only if
ToString(ToUint32(P)) equals P and ToUint32(P) is not the same value
as 𝔽(2^32 - 1).
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/PropertyName.h | 8 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Tests/object-expression-numeric-property.js | 30 |
2 files changed, 34 insertions, 4 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/PropertyName.h b/Userland/Libraries/LibJS/Runtime/PropertyName.h index 9242822558..62328dfa76 100644 --- a/Userland/Libraries/LibJS/Runtime/PropertyName.h +++ b/Userland/Libraries/LibJS/Runtime/PropertyName.h @@ -31,7 +31,7 @@ public: return {}; if (value.is_symbol()) return value.as_symbol(); - if (value.is_integral_number() && value.as_double() >= 0 && value.as_double() <= NumericLimits<u32>::max()) + if (value.is_integral_number() && value.as_double() >= 0 && value.as_double() < NumericLimits<u32>::max()) return value.as_u32(); auto string = value.to_string(global_object); if (string.is_null()) @@ -49,8 +49,8 @@ public: // FIXME: Replace this with requires(IsUnsigned<T>)? // Needs changes in various places using `int` (but not actually being in the negative range) VERIFY(index >= 0); - if constexpr (NumericLimits<T>::max() > NumericLimits<u32>::max()) - VERIFY(index <= NumericLimits<u32>::max()); + if constexpr (NumericLimits<T>::max() >= NumericLimits<u32>::max()) + VERIFY(index < NumericLimits<u32>::max()); } PropertyName(char const* chars) @@ -131,7 +131,7 @@ public: } auto property_index = m_string.to_uint(TrimWhitespace::No); - if (!property_index.has_value()) { + if (!property_index.has_value() || property_index.value() == NumericLimits<u32>::max()) { m_string_may_be_number = false; return false; } diff --git a/Userland/Libraries/LibJS/Tests/object-expression-numeric-property.js b/Userland/Libraries/LibJS/Tests/object-expression-numeric-property.js new file mode 100644 index 0000000000..575e658390 --- /dev/null +++ b/Userland/Libraries/LibJS/Tests/object-expression-numeric-property.js @@ -0,0 +1,30 @@ +test("numeric properties", () => { + const i32Max = 2 ** 31 - 1; + const u32Max = 2 ** 32 - 1; + const o = { + [-1]: "foo", + 0: "foo", + 1: "foo", + [i32Max - 1]: "foo", + [i32Max]: "foo", + [i32Max + 1]: "foo", + [u32Max - 1]: "foo", + [u32Max]: "foo", + [u32Max + 1]: "foo", + }; + // Numeric properties come first in Object.getOwnPropertyNames()'s output, + // which means we can test what each is treated as internally. + expect(Object.getOwnPropertyNames(o)).toEqual([ + // Numeric properties + "0", + "1", + "2147483646", + "2147483647", + "2147483648", + "4294967294", + // Non-numeric properties + "-1", + "4294967295", // >= 2^32 - 1 + "4294967296", // >= 2^32 - 1 + ]); +}); |