Commit b588a3c6 authored by Jakob Kummerow's avatar Jakob Kummerow Committed by V8 LUCI CQ

[bigint] Make deserialization of invalid data more robust

There is no -0n, and we'd therefore never serialize such a BigInt.
But we can't trust serialized data to not have gotten corrupted
(or be fuzzer-generated), so guard against this case when
deserializing.

Fixed: chromium:1359937
Change-Id: If11d9a364480bae51911cc4a0ce8a719853139fe
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3904414Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Reviewed-by: 's avatarNico Hartmann <nicohartmann@chromium.org>
Auto-Submit: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/main@{#83362}
parent bf35ae0d
...@@ -343,6 +343,8 @@ void MutableBigInt::Canonicalize(MutableBigInt result) { ...@@ -343,6 +343,8 @@ void MutableBigInt::Canonicalize(MutableBigInt result) {
} }
DCHECK_IMPLIES(result.length() > 0, DCHECK_IMPLIES(result.length() > 0,
result.digit(result.length() - 1) != 0); // MSD is non-zero. result.digit(result.length() - 1) != 0); // MSD is non-zero.
// Callers that don't require trimming must ensure this themselves.
DCHECK_IMPLIES(result.length() == 0, result.sign() == false);
} }
template <typename IsolateT> template <typename IsolateT>
...@@ -1379,6 +1381,8 @@ MaybeHandle<BigInt> BigInt::FromSerializedDigits( ...@@ -1379,6 +1381,8 @@ MaybeHandle<BigInt> BigInt::FromSerializedDigits(
DCHECK(digits_storage.length() == bytelength); DCHECK(digits_storage.length() == bytelength);
bool sign = SignBits::decode(bitfield); bool sign = SignBits::decode(bitfield);
int length = (bytelength + kDigitSize - 1) / kDigitSize; // Round up. int length = (bytelength + kDigitSize - 1) / kDigitSize; // Round up.
// There is no -0n. Reject corrupted serialized data.
if (length == 0 && sign == true) return {};
Handle<MutableBigInt> result = Handle<MutableBigInt> result =
MutableBigInt::Cast(isolate->factory()->NewBigInt(length)); MutableBigInt::Cast(isolate->factory()->NewBigInt(length));
result->initialize_bitfield(sign, length); result->initialize_bitfield(sign, length);
......
...@@ -595,6 +595,24 @@ TEST_F(ValueSerializerTest, DecodeBigInt) { ...@@ -595,6 +595,24 @@ TEST_F(ValueSerializerTest, DecodeBigInt) {
0x2A, // Digit: 42 0x2A, // Digit: 42
}, },
[this](Local<Value> value) { ExpectScriptTrue("result === 42n"); }); [this](Local<Value> value) { ExpectScriptTrue("result === 42n"); });
InvalidDecodeTest({
0xFF, 0x0F, // Version 15
0x5A, // BigInt
0x01, // Bitfield: sign = true, bytelength = 0
});
// From a philosophical standpoint, we could reject this case as invalid as
// well, but it would require extra code and probably isn't worth it, so
// we quietly normalize this invalid input to {0n}.
DecodeTestFutureVersions(
{
0xFF, 0x0F, // Version 15
0x5A, // BigInt
0x09, // Bitfield: sign = true, bytelength = 4
0x00, 0x00, 0x00, 0x00 // Digits.
},
[this](Local<Value> value) {
ExpectScriptTrue("(result | result) === 0n");
});
} }
// String constants (in UTF-8) used for string encoding tests. // String constants (in UTF-8) used for string encoding tests.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment