diff --git a/dfindexeddb/indexeddb/chromium/definitions.py b/dfindexeddb/indexeddb/chromium/definitions.py index 48a1e07..9d9f655 100644 --- a/dfindexeddb/indexeddb/chromium/definitions.py +++ b/dfindexeddb/indexeddb/chromium/definitions.py @@ -286,6 +286,7 @@ class V8SerializationTag(IntEnum): BEGIN_JS_SET = ord("'") END_JS_SET = ord(",") ARRAY_BUFFER = ord("B") + IMMUTABLE_ARRAY_BUFFER = ord("C") RESIZABLE_ARRAY_BUFFER = ord("~") ARRAY_BUFFER_TRANSFER = ord("t") ARRAY_BUFFER_VIEW = ord("V") @@ -321,6 +322,7 @@ class V8ArrayBufferViewTag(IntEnum): UINT16_ARRAY = ord("W") INT32_ARRAY = ord("d") UINT32_ARRAY = ord("D") + FLOAT16_ARRAY = ord("h") FLOAT32_ARRAY = ord("f") FLOAT64_ARRAY = ord("F") BIGINT64_ARRAY = ord("q") diff --git a/dfindexeddb/indexeddb/chromium/v8.py b/dfindexeddb/indexeddb/chromium/v8.py index 4a9be50..8467a51 100644 --- a/dfindexeddb/indexeddb/chromium/v8.py +++ b/dfindexeddb/indexeddb/chromium/v8.py @@ -62,7 +62,7 @@ class ValueDeserializer: version (int): the version of the serialized Javascript value/object """ - LATEST_VERSION = 15 + LATEST_VERSION = 16 def __init__(self, stream: BinaryIO, delegate: blink.V8ScriptValueDecoder): """Initializes a ValueDeserializer. @@ -241,6 +241,12 @@ def _ReadObjectInternal(self) -> Tuple[definitions.V8SerializationTag, Any]: parsed_object = self._ReadJSArrayBuffer( is_shared=False, is_resizable=True ) + elif tag == definitions.V8SerializationTag.IMMUTABLE_ARRAY_BUFFER: + parsed_object = self._ReadJSArrayBuffer( + is_shared=False, is_resizable=False + ) + # elif tag == definitions.V8SerializationTag.ARRAY_BUFFER_TRANSFER: + # parsed_object = self._ReadTransferredJSArrayBuffer() elif tag == definitions.V8SerializationTag.SHARED_ARRAY_BUFFER: parsed_object = self._ReadJSArrayBuffer( is_shared=True, is_resizable=False @@ -555,10 +561,10 @@ def _ReadJSArrayBuffer(self, is_shared: bool, is_resizable: bool) -> bytes: if is_shared: raise NotImplementedError("Shared ArrayBuffer not supported yet") - _, byte_length = self.decoder.DecodeUint32Varint() + _, byte_length = self.ReadSizeT() max_byte_length = byte_length if is_resizable: - _, max_byte_length = self.decoder.DecodeUint32Varint() + _, max_byte_length = self.ReadSizeT() if byte_length > max_byte_length: self.objects[next_id] = array_buffer return array_buffer @@ -571,8 +577,8 @@ def _ReadJSArrayBuffer(self, is_shared: bool, is_resizable: bool) -> bytes: def _ReadJSArrayBufferView(self, buffer: bytes) -> ArrayBufferView: """Reads a JSArrayBufferView from the current position.""" _, tag = self.decoder.ReadBytes(1) - _, byte_offset = self.decoder.DecodeUint32Varint() - _, byte_length = self.decoder.DecodeUint32Varint() + _, byte_offset = self.ReadSizeT() + _, byte_length = self.ReadSizeT() if self.version >= 14: # or version_13_broken_data_mode _, flags = self.decoder.DecodeUint32Varint() @@ -604,6 +610,10 @@ def ReadSharedObject(self) -> None: # _, shared_object_id = self.decoder.DecodeUint32Varint() raise NotImplementedError("ValueDeserializer.ReadSharedObject") + def ReadSizeT(self) -> Tuple[int, int]: + """Reads a size_t value.""" + return self.decoder.DecodeUint64Varint() + def ReadHostObject(self) -> Any: """Reads a Host object using the delegate object. diff --git a/tests/dfindexeddb/indexeddb/chromium/v8.py b/tests/dfindexeddb/indexeddb/chromium/v8.py index 9ceae70..840e235 100644 --- a/tests/dfindexeddb/indexeddb/chromium/v8.py +++ b/tests/dfindexeddb/indexeddb/chromium/v8.py @@ -236,18 +236,91 @@ def test_arraybuffer(self) -> None: parsed_value = v8.ValueDeserializer.FromBytes(buffer, None) self.assertEqual(parsed_value, expected_value) + with self.subTest("v16 empty"): + buffer = bytes.fromhex("ff104200") + expected_value = b"" + parsed_value = v8.ValueDeserializer.FromBytes(buffer, None) + self.assertEqual(parsed_value, expected_value) + + with self.subTest("v16 initialised"): + buffer = bytes.fromhex("ff1042080000000000000000") + expected_value = bytes.fromhex("0000000000000000") + parsed_value = v8.ValueDeserializer.FromBytes(buffer, None) + self.assertEqual(parsed_value, expected_value) + + with self.subTest("v16 resizable"): + buffer = bytes.fromhex("ff107e08100000000000000000") + expected_value = bytes.fromhex("0000000000000000") + parsed_value = v8.ValueDeserializer.FromBytes(buffer, None) + self.assertEqual(parsed_value, expected_value) + + with self.subTest("v16 immutable empty"): + buffer = bytes.fromhex("ff104300") + expected_value = b"" + parsed_value = v8.ValueDeserializer.FromBytes(buffer, None) + self.assertEqual(parsed_value, expected_value) + + with self.subTest("v16 immutable initialised"): + buffer = bytes.fromhex("ff1043080000000000000000") + expected_value = bytes.fromhex("0000000000000000") + parsed_value = v8.ValueDeserializer.FromBytes(buffer, None) + self.assertEqual(parsed_value, expected_value) + def test_arraybufferview(self) -> None: """Tests ArrayBufferView decoding.""" - buffer = bytes.fromhex("ff0d42100000000000000000000000000000000056420010") - expected_value = v8.ArrayBufferView( - buffer=bytes.fromhex("00000000000000000000000000000000"), - flags=0, - length=16, - offset=0, - tag=definitions.V8ArrayBufferViewTag.UINT8_ARRAY, - ) - parsed_value = v8.ValueDeserializer.FromBytes(buffer, None) - self.assertEqual(parsed_value, expected_value) + with self.subTest("v13"): + buffer = bytes.fromhex("ff0d42100000000000000000000000000000000056420010") + expected_value = v8.ArrayBufferView( + buffer=bytes.fromhex("00000000000000000000000000000000"), + flags=0, + length=16, + offset=0, + tag=definitions.V8ArrayBufferViewTag.UINT8_ARRAY, + ) + parsed_value = v8.ValueDeserializer.FromBytes(buffer, None) + self.assertEqual(parsed_value, expected_value) + + with self.subTest("v16 ArrayBuffer"): + buffer = bytes.fromhex( + "ff104210000000000000000000000000000000005642001000" + ) + expected_value = v8.ArrayBufferView( + buffer=bytes.fromhex("00000000000000000000000000000000"), + flags=0, + length=16, + offset=0, + tag=definitions.V8ArrayBufferViewTag.UINT8_ARRAY, + ) + parsed_value = v8.ValueDeserializer.FromBytes(buffer, None) + self.assertEqual(parsed_value, expected_value) + + with self.subTest("v16 ImmutableArrayBuffer"): + buffer = bytes.fromhex( + "ff104310000000000000000000000000000000005642001000" + ) + expected_value = v8.ArrayBufferView( + buffer=bytes.fromhex("00000000000000000000000000000000"), + flags=0, + length=16, + offset=0, + tag=definitions.V8ArrayBufferViewTag.UINT8_ARRAY, + ) + parsed_value = v8.ValueDeserializer.FromBytes(buffer, None) + self.assertEqual(parsed_value, expected_value) + + with self.subTest("v16 Float16Array"): + buffer = bytes.fromhex( + "ff104210000000000000000000000000000000005668001000" + ) + expected_value = v8.ArrayBufferView( + buffer=bytes.fromhex("00000000000000000000000000000000"), + flags=0, + length=16, + offset=0, + tag=definitions.V8ArrayBufferViewTag.FLOAT16_ARRAY, + ) + parsed_value = v8.ValueDeserializer.FromBytes(buffer, None) + self.assertEqual(parsed_value, expected_value) def test_date(self) -> None: """Tests date decoding."""