@@ -550,7 +550,11 @@ def parse(self, streams: List[base.ClrStream], lazy_load=False):
550550 # if table bit is set
551551 if header_struct .MaskValid & 2 ** i != 0 :
552552 # read the row count
553- table_rowcounts .append (self .get_dword_at_rva (cur_rva ))
553+ row_count = self .get_dword_at_rva (cur_rva )
554+ # sanity check
555+ if row_count > self .sizeof ():
556+ logger .warning (f"invalid table { i } row_count { row_count } larger than stream size { self .sizeof ()} " )
557+ table_rowcounts .append (row_count )
554558 # increment to next dword
555559 cur_rva += 4
556560 else :
@@ -576,6 +580,7 @@ def parse(self, streams: List[base.ClrStream], lazy_load=False):
576580 strings_heap ,
577581 guid_heap ,
578582 blob_heap ,
583+ self ,
579584 lazy_load ,
580585 )
581586 except errors .dnFormatError as e :
@@ -618,22 +623,47 @@ def full_loader():
618623 # Setup lazy loading for all tables
619624 for table in self .tables_list :
620625 if table .row_size > 0 and table .num_rows > 0 :
626+ table .rva = cur_rva
627+ table .file_offset = self .get_file_offset (table .rva )
628+ # calculate the table size
629+ table_size = table .row_size * table .num_rows
630+ # sanity check: if table size is more than data in stream
631+ if cur_rva + table_size > self .rva + self .sizeof ():
632+ # the table is too large
633+ err_msg = f"Metadata table { table .name } with row_size { table .row_size } and num_rows { table .num_rows } is larger than stream size { self .sizeof ()} "
634+ deferred_exceptions .append (
635+ errors .dnFormatError (err_msg )
636+ )
637+ logging .warning (err_msg )
638+ # stop processing tables
639+ break
621640 table_data = self .get_data_at_rva (
622641 cur_rva , table .row_size * table .num_rows
623642 )
624643 table .setup_lazy_load (cur_rva , table_data , full_loader )
625- table .file_offset = self .get_file_offset (cur_rva )
626644 cur_rva += table .row_size * table .num_rows
627645 else :
628646 #### parse each table
629647 # here, cur_rva points to start of table rows
630648 for table in self .tables_list :
631649 if table .row_size > 0 and table .num_rows > 0 :
650+ table .rva = cur_rva
651+ table .file_offset = self .get_file_offset (cur_rva )
652+ # calculate the table size
653+ table_size = table .row_size * table .num_rows
654+ # sanity check: if table size is more than data in stream
655+ if cur_rva + table_size > self .rva + self .sizeof ():
656+ # the table is too large
657+ err_msg = f"Metadata table { table .name } with row_size { table .row_size } and num_rows { table .num_rows } is larger than stream size { self .sizeof ()} "
658+ deferred_exceptions .append (
659+ errors .dnFormatError (err_msg )
660+ )
661+ logging .warning (err_msg )
662+ # stop processing tables
663+ break
632664 table_data = self .get_data_at_rva (
633665 cur_rva , table .row_size * table .num_rows
634666 )
635- table .rva = cur_rva
636- table .file_offset = self .get_file_offset (cur_rva )
637667 # parse structures (populates .struct for each row)
638668 table .parse_rows (cur_rva , table_data )
639669 # move to next set of rows
0 commit comments