When parsing an embedded VMDK descriptor, VmdkDisk (in vmdk.py) always decodes the raw descriptor bytes as utf-8, without checking the descriptor's own encoding= attribute first. VMware Workstation running on a Chinese-locale (or other non-UTF‑8 locale) Windows host can write descriptors that declare encoding="GBK". Decoding such a descriptor as utf-8 does not raise an error (errors="replace" is used), but it silently corrupts any non-ASCII characters in the descriptor — including the extent filenames (ddb.filename / RW ... "diskname-sXXX.vmdk" lines).
As a result, the disk/extent filename parsed from the descriptor no longer matches the actual file on disk, and opening the split/multi-extent VMDK fails with a FileNotFoundError, even though the referenced file physically exists (just under its correctly-encoded name).
To Reproduce
- Create (or obtain) a split VMDK on a GBK-locale Windows host where the descriptor declares
encoding="GBK" and the disk name / extent filenames contain non-ASCII (e.g. Chinese) characters, e.g.:
# Disk DescriptorFile
version=1
encoding="GBK"
CID=369b13fd
parentCID=ffffffff
createType="twoGbMaxExtentSparse"
...
RW 4192256 SPARSE "CentOS 64 副本-s001.vmdk"
- Open the VMDK via
dissect.hypervisor / dissect.target:
from dissect.target.containers.vmdk import VmdkContainer
VmdkContainer(path)
Expected behavior
The descriptor should be re-decoded using the encoding declared in its own encoding= attribute (falling back to utf-8 when absent or unsupported), so that extent filenames containing non-ASCII characters are parsed correctly and the referenced extent files can be located and opened.
Actual behavior
Because the descriptor is decoded as utf-8 regardless of the declared encoding, non-ASCII characters in the extent filename are mangled (e.g. 副本 becomes λ), and opening the disk fails:
Traceback (most recent call last):
File "dissect\target\container.py", line 236, in open
return container(item, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "dissect\target\helpers\lazy.py", line 68, in __call__
return self._load()(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "dissect\target\containers\vmdk.py", line 20, in __init__
self.vmdk = vmdk.VMDK(fh)
^^^^^^^^^^^^^
File "dissect\hypervisor\disk\vmdk.py", line 66, in __init__
sdisk_fh = path.with_name(extent.filename).open("rb")
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "pathlib.py", line 1013, in open
FileNotFoundError: [Errno 2] No such file or directory: 'E:\\VM\\Centos_74_3_FZ_TEST\\CentOS 64 λ-s001.vmdk'
Note that CentOS 64 λ-s001.vmdk is the corrupted extent filename produced by decoding GBK-encoded bytes as UTF‑8 with errors="replace"; the actual file on disk has a correctly-encoded (Chinese) name and does exist.
Environment
dissect.hypervisor version: (fill in pip show dissect.hypervisor)
- OS: Windows (VMDK created/exported on a GBK-locale host)
- Python version: (fill in)
Suggested fix
After the initial best-effort decode of the descriptor, check self.descriptor.attr.get("encoding") and, if it differs from utf-8, re-parse the raw descriptor bytes using that encoding (with a safe fallback to the original utf-8 parse if the declared encoding is invalid/unsupported by Python's codec registry).
When parsing an embedded VMDK descriptor, VmdkDisk (in vmdk.py) always decodes the raw descriptor bytes as
utf-8, without checking the descriptor's ownencoding=attribute first. VMware Workstation running on a Chinese-locale (or other non-UTF‑8 locale) Windows host can write descriptors that declareencoding="GBK". Decoding such a descriptor asutf-8does not raise an error (errors="replace"is used), but it silently corrupts any non-ASCII characters in the descriptor — including theextentfilenames (ddb.filename/RW ... "diskname-sXXX.vmdk"lines).As a result, the disk/extent filename parsed from the descriptor no longer matches the actual file on disk, and opening the split/multi-extent VMDK fails with a
FileNotFoundError, even though the referenced file physically exists (just under its correctly-encoded name).To Reproduce
encoding="GBK"and the disk name / extent filenames contain non-ASCII (e.g. Chinese) characters, e.g.:dissect.hypervisor/dissect.target:Expected behavior
The descriptor should be re-decoded using the encoding declared in its own
encoding=attribute (falling back toutf-8when absent or unsupported), so that extent filenames containing non-ASCII characters are parsed correctly and the referenced extent files can be located and opened.Actual behavior
Because the descriptor is decoded as
utf-8regardless of the declaredencoding, non-ASCII characters in the extent filename are mangled (e.g.副本becomesλ), and opening the disk fails:Note that
CentOS 64 λ-s001.vmdkis the corrupted extent filename produced by decoding GBK-encoded bytes as UTF‑8 witherrors="replace"; the actual file on disk has a correctly-encoded (Chinese) name and does exist.Environment
dissect.hypervisorversion: (fill inpip show dissect.hypervisor)Suggested fix
After the initial best-effort decode of the descriptor, check
self.descriptor.attr.get("encoding")and, if it differs fromutf-8, re-parse the raw descriptor bytes using that encoding (with a safe fallback to the originalutf-8parse if the declared encoding is invalid/unsupported by Python's codec registry).