diff options
author | Luke Wilde <lukew@serenityos.org> | 2023-02-28 19:27:28 +0000 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2023-03-01 10:53:31 +0100 |
commit | ddc7bedca6ba5b6e0b3414e36c4e6bf6826e3e9e (patch) | |
tree | 15be8a6b91d4099a3378036ec1a14545ae4f788d /Userland/Libraries/LibJS | |
parent | 52a6f1ff8cd431d9f8174e6fb4d34fadb89a169e (diff) | |
download | serenity-ddc7bedca6ba5b6e0b3414e36c4e6bf6826e3e9e.zip |
LibJS: Make int_part a double in StringPrototype::to_string
u64 is not big enough to hold extremely large numbers, such as
4.192938423e+54. This would cause an integer underflow on the radix
index when performing something like `toString(36)` and thus cause an
OOB Array read.
Diffstat (limited to 'Userland/Libraries/LibJS')
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/NumberPrototype.cpp | 5 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Tests/builtins/Number/Number.prototype.toString.js | 56 |
2 files changed, 59 insertions, 2 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/NumberPrototype.cpp b/Userland/Libraries/LibJS/Runtime/NumberPrototype.cpp index 1c4d20b7af..a2e11abafc 100644 --- a/Userland/Libraries/LibJS/Runtime/NumberPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/NumberPrototype.cpp @@ -459,7 +459,7 @@ JS_DEFINE_NATIVE_FUNCTION(NumberPrototype::to_string) if (negative) number *= -1; - u64 int_part = floor(number); + double int_part = floor(number); double decimal_part = number - int_part; int radix = (int)radix_mv; @@ -469,8 +469,9 @@ JS_DEFINE_NATIVE_FUNCTION(NumberPrototype::to_string) backwards_characters.append('0'); } else { while (int_part > 0) { - backwards_characters.append(digits[int_part % radix]); + backwards_characters.append(digits[floor(fmod(int_part, radix))]); int_part /= radix; + int_part = floor(int_part); } } diff --git a/Userland/Libraries/LibJS/Tests/builtins/Number/Number.prototype.toString.js b/Userland/Libraries/LibJS/Tests/builtins/Number/Number.prototype.toString.js index 0623175fe5..e448b4cbc8 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/Number/Number.prototype.toString.js +++ b/Userland/Libraries/LibJS/Tests/builtins/Number/Number.prototype.toString.js @@ -70,6 +70,62 @@ describe("correct behavior", () => { expect((30).toString(10.1)).toBe("30"); expect((30).toString(10.9)).toBe("30"); }); + + test("extremely large number with radix", () => { + // NOTE: The answers change depending on the engine, so the important thing here is that it doesn't crash + // and is good enough. + // Example number generated from an ID generator in Raygun4js: https://github.com/MindscapeHQ/raygun4js/blob/777ba6e3cdede42011aa0b7f019473de6380009b/src/raygun.rum/index.js#L1204 + const number = 2.2171010912173817e51; + + [ + [ + 2, + "101111011010000000010001011010101110000101111100111010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + ], + [ + 3, + "122200222200200002020000221212111212020212021222122122201112112001202200202210122011020121220102211210120110", + ], + [ + 4, + "11323100002023111300233213100000000000000000000000000000000000000000000000000000000000", + ], + [5, "20213333043100433442123113244334300004432332001224240433304410013422100304"], + [6, "550003524220341511224004404200404220224024020444420402442220220420"], + [7, "4235625635040541506562064422461122351652161506062250163366335"], + [8, "573200213256057472000000000000000000000000000000000000000"], + [9, "580880602200855367001288271433120018026801542154811843"], + [10, "2.2171010912173817e+51"], + [11, "20941975227252065997040823726473715831623804aa6726"], + [12, "426276185347a25840488044080484880408844840480440"], + [13, "136bc76718505c84cb00730624426c569759715872b8b70"], + [14, "835c3959100c338282668c622a8a060a24602aa6a66cc"], + [15, "5e1ae5933690a58aad6a9546513bbbd49305ec050549"], + [16, "5ed008b570be7400000000000000000000000000000"], + [17, "7f3da30c676ag43gc65022d17gae829c8790d1d479"], + [18, "dba188ded00ha8a6c2800e808c20aagggg4g4822c"], + [19, "1af846i1f7ge0bfb7b4c3f1abd5a70g3bhd592fb6"], + [20, "40d316h12f73ec848404c8c0g4400gc48c400804"], + [21, "cd59ci682hih768393c4d1kc5757jkgg918b2dc"], + [22, "239f104idd3dikgg6e4eccg66aee26a0kc2kac6"], + [23, "93f4b0317667h2gm0gka6ia4h9emj7b6aef4ig"], + [24, "1lca597424748g080gggg80g08gg8880880g80"], + [25, "abii4g0njm70ejj3c39lajgi5l3bdf6gl25ne"], + [26, "2e8foaj1lec80c86cck264caii282m6m8e6a0"], + [27, "hiqii260pnbeqe894nd351nqpo5nm3j45jj3"], + [28, "4qmgqk0rk788oog4c8k0k0cg8o04cocckckc"], + [29, "1d2nmd4bln2jmf0k72sl2ejhmj7m8rq70flk"], + [30, "d8onrgfc6kaik26a4oqmee4ic0ksi0k0k2o"], + [31, "4b4u5lb8fb8ttacfifj5g1iapimkppcehrq"], + [32, "1fd025le2v7800000000000000000000000"], + [33, "h5mgn3kr83kucw13c6102w7n5loohbfct6"], + [34, "6e0244vn6ba0gw8ucgkmuwgk4oi02g8icq"], + [35, "2g7ohyr3v1t7c0jrq621aw56kflrj71pfj"], + [36, "z03wqcmb7dw00g80wow0sksk484wgswsc"], + ].forEach(([radix, result]) => { + expect(number.toString(radix)).toBe(result); + }); + }); }); describe("errors", () => { |