@@ -488,6 +488,7 @@ class VHDXInspector(FileInspector):
488488 """
489489 METAREGION = '8B7CA206-4790-4B9A-B8FE-575F050F886E'
490490 VIRTUAL_DISK_SIZE = '2FA54224-CD1B-4876-B211-5DBED83BF4B8'
491+ VHDX_METADATA_TABLE_MAX_SIZE = 32 * 2048 # From qemu
491492
492493 def __init__ (self , * a , ** k ):
493494 super (VHDXInspector , self ).__init__ (* a , ** k )
@@ -602,6 +603,8 @@ def _find_meta_entry(self, desired_guid):
602603 item_offset , item_length , _reserved = struct .unpack (
603604 '<III' ,
604605 meta_buffer [entry_offset + 16 :entry_offset + 28 ])
606+ item_length = min (item_length ,
607+ self .VHDX_METADATA_TABLE_MAX_SIZE )
605608 self .region ('metadata' ).length = len (meta_buffer )
606609 self ._log .debug ('Found entry at offset %x' , item_offset )
607610 # Metadata item offset is from the beginning of the metadata
@@ -652,7 +655,7 @@ def __str__(self):
652655#
653656# https://www.vmware.com/app/vmdk/?src=vmdk
654657class VMDKInspector (FileInspector ):
655- """vmware VMDK format (monolithicSparse variant only)
658+ """vmware VMDK format (monolithicSparse and streamOptimized variants only)
656659
657660 This needs to store the 512 byte header and the descriptor region
658661 which should be just after that. The descriptor region is some
@@ -683,7 +686,6 @@ def post_process(self):
683686
684687 if sig != b'KDMV' :
685688 raise ImageFormatError ('Signature KDMV not found: %r' % sig )
686- return
687689
688690 if ver not in (1 , 2 , 3 ):
689691 raise ImageFormatError ('Unsupported format version %i' % ver )
@@ -693,9 +695,18 @@ def post_process(self):
693695 # header, which we cannot support since we stream.
694696 raise ImageFormatError ('Unsupported VMDK footer' )
695697
698+ # Since we parse both desc_sec and desc_num (the location of the
699+ # VMDK's descriptor, expressed in 512 bytes sectors) we enforce a
700+ # check on the bounds to create a reasonable CaptureRegion. This
701+ # is similar to how it's done in qemu.
702+ desc_offset = desc_sec * 512
703+ desc_size = min (desc_num * 512 , self .DESC_MAX_SIZE )
704+ if desc_offset != self .DESC_OFFSET :
705+ raise ImageFormatError ("Wrong descriptor location" )
706+
696707 if not self .has_region ('descriptor' ):
697708 self .new_region ('descriptor' , CaptureRegion (
698- desc_sec * 512 , desc_num * 512 ))
709+ desc_offset , desc_size ))
699710
700711 @property
701712 def format_match (self ):
@@ -721,7 +732,7 @@ def virtual_size(self):
721732 vmdktype = descriptor [type_idx :type_end ]
722733 else :
723734 vmdktype = b'formatnotfound'
724- if vmdktype != b'monolithicSparse' :
735+ if vmdktype not in ( b'monolithicSparse' , b'streamOptimized' ) :
725736 LOG .warning ('Unsupported VMDK format %s' , vmdktype )
726737 return 0
727738
0 commit comments