From cc385ef27209ff49b167ea1b142d2dbf4b0bd97e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Kania?= Date: Sun, 16 Aug 2026 21:53:35 +0200 Subject: [PATCH] Fix VDI reads across allocation blocks --- dissect/hypervisor/disk/vdi.py | 2 +- tests/disk/test_vdi.py | 26 +++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/dissect/hypervisor/disk/vdi.py b/dissect/hypervisor/disk/vdi.py index a3c01d5..42a0e9d 100644 --- a/dissect/hypervisor/disk/vdi.py +++ b/dissect/hypervisor/disk/vdi.py @@ -118,7 +118,7 @@ def _read(self, offset: int, length: int) -> bytes: block_idx, offset_in_block = divmod(offset, self.block_size) while length > 0: - read_len = min(length, max(length, self.block_size - offset_in_block)) + read_len = min(length, self.block_size - offset_in_block) block = self.map[block_idx] if block == VDI_IMAGE_BLOCK_FREE: diff --git a/tests/disk/test_vdi.py b/tests/disk/test_vdi.py index 488c2ee..022d30a 100644 --- a/tests/disk/test_vdi.py +++ b/tests/disk/test_vdi.py @@ -1,12 +1,15 @@ from __future__ import annotations import gzip +import struct +from io import BytesIO from pathlib import Path +from types import SimpleNamespace from typing import BinaryIO from unittest.mock import patch from dissect.hypervisor.disk.c_vdi import c_vdi -from dissect.hypervisor.disk.vdi import VDI +from dissect.hypervisor.disk.vdi import VDI, VDIStream from tests._util import absolute_path @@ -34,6 +37,27 @@ def test_vdi() -> None: assert stream.read() == b"" +def test_vdi_read_across_non_contiguous_blocks() -> None: + """Test a single read spanning non-contiguous VDI allocation-map blocks.""" + block_size = 4 + allocation_map = struct.pack(" None: """Test VDI context manager.""" with patch.object(Path, "open", gzip.open), VDI(absolute_path("_data/disk/vdi/basic.vdi.gz")) as vdi: