@@ -120,7 +120,7 @@ func (self *OLEFile) ReadSector(sector uint32) []byte {
120120 start := 512 + self .SectorSize * int (sector )
121121
122122 to_read := self .SectorSize
123- if start > len (self .data ) {
123+ if start > len (self .data ) || start < 0 {
124124 return nil
125125 }
126126
@@ -134,7 +134,7 @@ func (self *OLEFile) ReadMiniSector(sector uint32) []byte {
134134 start := self .MiniSectorSize * int (sector )
135135
136136 to_read := self .MiniSectorSize
137- if start > len (self .ministream ) {
137+ if start > len (self .ministream ) || start < 0 {
138138 return nil
139139 }
140140
@@ -373,6 +373,11 @@ func DecompressStream(compressed_container []byte) []byte {
373373 // compressed_chunk_start := 0
374374 decompressed_chunk_start := 0
375375
376+ if len (compressed_container ) == 0 {
377+ DebugPrintf ("compressed stream is empty" )
378+ return nil
379+ }
380+
376381 sig_byte := compressed_container [compressed_current ]
377382 if sig_byte != 0x01 {
378383 DebugPrintf ("invalid signature byte %02X" , sig_byte )
@@ -382,6 +387,11 @@ func DecompressStream(compressed_container []byte) []byte {
382387 compressed_current += 1
383388
384389 for compressed_current < len (compressed_container ) {
390+ if compressed_current + 2 > len (compressed_container ) {
391+ // At least 2 bytes for the header are needed
392+ DebugPrintf ("Compressed stream ended prematurely" )
393+ break
394+ }
385395 // 2.4.1.1.5
386396 // compressed_chunk_start = compressed_current
387397 compressed_chunk_header := binary .LittleEndian .Uint16 (
@@ -409,6 +419,8 @@ func DecompressStream(compressed_container []byte) []byte {
409419 compressed_end := len (compressed_container )
410420 if compressed_end > compressed_current + int (chunk_size ) {
411421 compressed_end = compressed_current + int (chunk_size )
422+ } else {
423+ DebugPrintf ("Chunk exceeds compressed stream length" )
412424 }
413425
414426 compressed_current += 2
@@ -425,17 +437,22 @@ func DecompressStream(compressed_container []byte) []byte {
425437 flag_byte := compressed_container [compressed_current ]
426438 compressed_current += 1
427439 for bit_index := uint16 (0 ); bit_index < 8 ; bit_index ++ {
428- if compressed_current >= compressed_end {
429- break
430- }
431-
432440 if (1 << bit_index )& flag_byte == 0 { // LiteralToken
441+ if compressed_current >= compressed_end {
442+ DebugPrintf ("Compressed stream ended prematurely" )
443+ break
444+ }
433445 decompressed_container = append (decompressed_container ,
434446 compressed_container [compressed_current ])
435447 compressed_current += 1
436448 continue
437449 }
438450
451+ if compressed_current > compressed_end - 2 {
452+ DebugPrintf ("Compressed stream ended prematurely" )
453+ break
454+ }
455+
439456 // copy tokens
440457 copy_token := binary .LittleEndian .Uint16 (
441458 compressed_container [compressed_current :])
@@ -589,7 +606,7 @@ func ExtractMacros(ofdoc *OLEFile) ([]*VBAModule, error) {
589606 compatversion_size := getUint32 (dir_stream , & i )
590607 check_value ("PROJECTCOMPATVERSION_Size" , 0x4 , compatversion_size )
591608 i += 4 // Skip ProjectCompatVersion
592- } else {
609+ } else if i >= 2 {
593610 i -= 2 // No CompatVersionRecord present - undo read of the ID
594611 }
595612
@@ -657,7 +674,7 @@ func ExtractMacros(ofdoc *OLEFile) ([]*VBAModule, error) {
657674 projecthelpfilepath_id := getUint16 (dir_stream , & i )
658675 check_value ("PROJECTHELPFILEPATH_Id" , 0x0006 , uint32 (projecthelpfilepath_id ))
659676 projecthelpfilepath_sizeof_helpfile1 := int (getUint32 (dir_stream , & i ))
660- if projecthelpfilepath_sizeof_helpfile1 > 260 {
677+ if projecthelpfilepath_sizeof_helpfile1 > 260 || projecthelpfilepath_sizeof_helpfile1 + i > len ( dir_stream ) {
661678 return nil , errors .New (fmt .Sprintf (
662679 "PROJECTHELPFILEPATH_SizeOfHelpFile1 value not in range: %v" , projecthelpfilepath_sizeof_helpfile1 ))
663680 }
@@ -668,6 +685,9 @@ func ExtractMacros(ofdoc *OLEFile) ([]*VBAModule, error) {
668685 projecthelpfilepath_sizeof_helpfile2 := int (getUint32 (dir_stream , & i ))
669686 if projecthelpfilepath_sizeof_helpfile2 != projecthelpfilepath_sizeof_helpfile1 {
670687 return nil , errors .New ("PROJECTHELPFILEPATH_SizeOfHelpFile1 does not equal PROJECTHELPFILEPATH_SizeOfHelpFile2" )
688+ } else if projecthelpfilepath_sizeof_helpfile2 + i > len (dir_stream ) {
689+ return nil , errors .New (fmt .Sprintf (
690+ "PROJECTHELPFILEPATH_SizeOfHelpFile2 value not in range: %v" , projecthelpfilepath_sizeof_helpfile2 ))
671691 }
672692 projecthelpfilepath_helpfile2 := dir_stream [i : i + projecthelpfilepath_sizeof_helpfile2 ]
673693 i += projecthelpfilepath_sizeof_helpfile2
@@ -723,7 +743,7 @@ func ExtractMacros(ofdoc *OLEFile) ([]*VBAModule, error) {
723743 }
724744 // projectconstants_constants_unicode := dir_stream[i : i+projectconstants_sizeof_constants_unicode]
725745 i += projectconstants_sizeof_constants_unicode
726- } else {
746+ } else if i >= 2 {
727747 i -= 2
728748 }
729749
@@ -869,6 +889,10 @@ loop:
869889 // uni_out = lambda unicode_text: unicode_text.encode("utf-8", "replace")
870890 DebugPrintf ("parsing %v modules" , projectmodules_count )
871891 for projectmodule_index := 0 ; projectmodule_index < int (projectmodules_count ); projectmodule_index ++ {
892+ if i >= len (dir_stream )- 2 { // At the very least, there must by a 2-byte ID
893+ return nil , errors .New ("dir_stream index out of range" )
894+ }
895+
872896 modulestreamname_streamname := ""
873897 modulestreamname_streamname_unicode := []byte {}
874898 moduleoffset_textoffset := uint32 (0 )
@@ -877,6 +901,9 @@ loop:
877901
878902 check_value ("MODULENAME_Id" , 0x0019 , uint32 (modulename_id ))
879903 modulename_sizeof_modulename := int (getUint32 (dir_stream , & i ))
904+ if len (dir_stream ) < i + modulename_sizeof_modulename {
905+ return nil , errors .New ("MODULENAME_SizeOfModuleName value not in range" )
906+ }
880907 modulename_modulename := string (dir_stream [i : i + modulename_sizeof_modulename ])
881908 i += modulename_sizeof_modulename
882909
@@ -886,8 +913,10 @@ loop:
886913 // account for optional sections
887914 section_id := getUint16 (dir_stream , & i )
888915 if section_id == 0x0047 {
889- modulename_unicode_sizeof_modulename_unicode := int (binary .LittleEndian .Uint32 (dir_stream [i :]))
890- i += 4
916+ modulename_unicode_sizeof_modulename_unicode := int (getUint32 (dir_stream , & i ))
917+ if len (dir_stream ) < i + modulename_unicode_sizeof_modulename_unicode {
918+ return nil , errors .New ("MODULENAMEUNICODE_SizeOfModuleNameUnicode value not in range" )
919+ }
891920 modulename_unicode_modulename_unicode = dir_stream [i : i +
892921 modulename_unicode_sizeof_modulename_unicode ]
893922 i += modulename_unicode_sizeof_modulename_unicode
@@ -897,12 +926,18 @@ loop:
897926
898927 if section_id == 0x001A {
899928 modulestreamname_sizeof_streamname := int (getUint32 (dir_stream , & i ))
929+ if len (dir_stream ) < i + modulestreamname_sizeof_streamname {
930+ return nil , errors .New ("MODULESTREAMNAME_SizeOfStreamName value not in range" )
931+ }
900932 modulestreamname_streamname = string (dir_stream [i : i + modulestreamname_sizeof_streamname ])
901933 i = i + modulestreamname_sizeof_streamname
902934
903935 modulestreamname_reserved := getUint16 (dir_stream , & i )
904936 check_value ("MODULESTREAMNAME_Reserved" , 0x0032 , uint32 (modulestreamname_reserved ))
905937 modulestreamname_sizeof_streamname_unicode := int (getUint32 (dir_stream , & i ))
938+ if len (dir_stream ) < i + modulestreamname_sizeof_streamname_unicode {
939+ return nil , errors .New ("MODULESTREAMNAME_SizeOfStreamNameUnicode value not in range" )
940+ }
906941 modulestreamname_streamname_unicode = dir_stream [i : i +
907942 modulestreamname_sizeof_streamname_unicode ]
908943 i += modulestreamname_sizeof_streamname_unicode
@@ -1004,6 +1039,11 @@ loop:
10041039
10051040 DebugPrintf ("length of code_data = %v" , len (code_data ))
10061041 DebugPrintf ("offset of code_data = %v" , moduleoffset_textoffset )
1042+ if int (moduleoffset_textoffset ) > len (code_data ) {
1043+ DebugPrintf ("invalid offset for module %v: %v" ,
1044+ modulestreamname_streamname , moduleoffset_textoffset )
1045+ continue
1046+ }
10071047 code_data = code_data [moduleoffset_textoffset :]
10081048 if len (code_data ) > 0 {
10091049 result = append (result , & VBAModule {
0 commit comments