From dd0cced92f9f653d017b3f2adcc05d69d61def77 Mon Sep 17 00:00:00 2001 From: devgianlu Date: Fri, 25 Apr 2025 20:54:37 +0200 Subject: [PATCH] LibJS: Prevent huge memory allocations for bigint left shift --- Libraries/LibJS/Runtime/ErrorTypes.h | 1 + Libraries/LibJS/Runtime/Value.cpp | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Libraries/LibJS/Runtime/ErrorTypes.h b/Libraries/LibJS/Runtime/ErrorTypes.h index 787f935a023..4bf78e0aa8c 100644 --- a/Libraries/LibJS/Runtime/ErrorTypes.h +++ b/Libraries/LibJS/Runtime/ErrorTypes.h @@ -21,6 +21,7 @@ M(BigIntBadOperatorOtherType, "Cannot use {} operator with BigInt and other type") \ M(BigIntFromNonIntegral, "Cannot convert non-integral number to BigInt") \ M(BigIntInvalidValue, "Invalid value for BigInt: {}") \ + M(BigIntSizeExceeded, "Maximum BigInt size exceeded") \ M(BindingNotInitialized, "Binding {} is not initialized") \ M(BufferOutOfBounds, "{} contains a property which references a value at an index not contained within its buffer's bounds") \ M(ByteLengthExceedsMaxByteLength, "ArrayBuffer byte length of {} exceeds the max byte length of {}") \ diff --git a/Libraries/LibJS/Runtime/Value.cpp b/Libraries/LibJS/Runtime/Value.cpp index 9745cb039c0..918c9ccd02c 100644 --- a/Libraries/LibJS/Runtime/Value.cpp +++ b/Libraries/LibJS/Runtime/Value.cpp @@ -1593,8 +1593,13 @@ ThrowCompletionOr left_shift(VM& vm, Value lhs, Value rhs) return Value(lhs_i32 << shift_count); } if (both_bigint(lhs_numeric, rhs_numeric)) { + // AD-HOC: Prevent allocating huge amounts of memory. + auto rhs_bigint = rhs_numeric.as_bigint().big_integer().unsigned_value(); + if (rhs_bigint.byte_length() > sizeof(u32)) + return vm.throw_completion(ErrorType::BigIntSizeExceeded); + // 6.1.6.2.9 BigInt::leftShift ( x, y ), https://tc39.es/ecma262/#sec-numeric-types-bigint-leftShift - auto multiplier_divisor = Crypto::SignedBigInteger { Crypto::NumberTheory::Power(Crypto::UnsignedBigInteger(2), rhs_numeric.as_bigint().big_integer().unsigned_value()) }; + auto multiplier_divisor = Crypto::SignedBigInteger { Crypto::NumberTheory::Power(Crypto::UnsignedBigInteger(2), rhs_bigint) }; // 1. If y < 0ℤ, then if (rhs_numeric.as_bigint().big_integer().is_negative()) {