@@ -37,14 +37,14 @@ type OLEHeader struct {
3737 Clid [16 ]byte
3838
3939 MinorVersion uint16
40- DllVersion uint16
40+ MajorVersion uint16
4141 ByteOrder uint16
4242 SectorShift uint16
4343 MiniSectorShift uint16
4444 Reserved uint16
4545
4646 Reserved1 uint32
47- Reserved2 uint32
47+ CsectDir uint32 // Count of directory sectors. Only available in version 4.
4848 CsectFat uint32
4949 SectDirStart uint32
5050 Signature uint32
@@ -89,6 +89,9 @@ func NewDirectory(data []byte, index uint32) (*Directory, error) {
8989 if err != nil {
9090 return nil , err
9191 }
92+ if self .Header .Mse == 0 { // Unallocated
93+ return nil , nil
94+ }
9295
9396 self .Name = strings .TrimRight (
9497 string (utf16 .Decode (self .Header .AB [:])), "\x00 " )
@@ -117,7 +120,7 @@ type VBAModule struct {
117120}
118121
119122func (self * OLEFile ) ReadSector (sector uint32 ) []byte {
120- start := 512 + self .SectorSize * int (sector )
123+ start := self .SectorSize * int (sector + 1 )
121124
122125 to_read := self .SectorSize
123126 if start > len (self .data ) || start < 0 {
@@ -145,18 +148,18 @@ func (self *OLEFile) ReadMiniSector(sector uint32) []byte {
145148 return self .ministream [start : start + to_read ]
146149}
147150
148- func (self * OLEFile ) ReadFat (sector uint32 ) uint32 {
151+ func (self * OLEFile ) ReadFat (sector uint32 ) ( uint32 , bool ) {
149152 if int (sector ) >= len (self .Fat ) {
150- return 0
153+ return 0 , false
151154 }
152- return self .Fat [sector ]
155+ return self .Fat [sector ], true
153156}
154157
155- func (self * OLEFile ) ReadMiniFat (sector uint32 ) uint32 {
158+ func (self * OLEFile ) ReadMiniFat (sector uint32 ) ( uint32 , bool ) {
156159 if int (sector ) >= len (self .MiniFat ) {
157- return 0
160+ return 0 , false
158161 }
159- return self .MiniFat [sector ]
162+ return self .MiniFat [sector ], true
160163}
161164
162165func (self * OLEFile ) ReadChain (start uint32 ) []byte {
@@ -170,13 +173,18 @@ func (self *OLEFile) ReadMiniChain(start uint32) []byte {
170173func (self * OLEFile ) _ReadChain (
171174 start uint32 ,
172175 ReadSector func (uint32 ) []byte ,
173- ReadFat func (sector uint32 ) uint32 ) []byte {
176+ ReadFat func (sector uint32 ) (uint32 , bool ),
177+ ) []byte {
174178 check := make (map [uint32 ]bool )
175179 result := []byte {}
176180
177181 for sector := start ; sector != ENDOFCHAIN ; {
178182 result = append (result , ReadSector (sector )... )
179- next := ReadFat (sector )
183+ next , ok := ReadFat (sector )
184+ if ! ok {
185+ DebugPrintf ("invalid sector %x in chain" , sector )
186+ return result
187+ }
180188 _ , pres := check [next ]
181189 if pres {
182190 DebugPrintf ("infinite loop detected at %v to %v starting at %v" ,
@@ -225,6 +233,9 @@ func (self *OLEFile) OpenStreamByName(name string) ([]byte, error) {
225233 return self .GetStream (d .Index ), nil
226234}
227235
236+ // NewOLEFile creates a new OLEFile object from the given data.
237+ //
238+ // The OLE format is described in https://winprotocoldoc.z19.web.core.windows.net/MS-CFB/%5bMS-CFB%5d.pdf
228239func NewOLEFile (data []byte ) (* OLEFile , error ) {
229240 if len (data ) < 8 ||
230241 string (data [:8 ]) != OLE_SIGNATURE {
@@ -238,9 +249,21 @@ func NewOLEFile(data []byte) (*OLEFile, error) {
238249 return nil , err
239250 }
240251
241- if self .Header .SectorShift > MAX_SECTOR_SHIFT {
242- return nil , fmt .Errorf (
243- "Sector size too large: %v" , self .Header .SectorShift )
252+ var expectedSectorShift uint16
253+ switch self .Header .MajorVersion {
254+ case 3 :
255+ expectedSectorShift = sectorShiftV3
256+ case 4 :
257+ expectedSectorShift = sectorShiftV4
258+ default :
259+ return nil , fmt .Errorf ("unsupported major version: %v" , self .Header .MajorVersion )
260+ }
261+ if self .Header .MinorVersion != 0x3E {
262+ return nil , fmt .Errorf ("unsupported minor version: %v" , self .Header .MinorVersion )
263+ }
264+
265+ if self .Header .SectorShift != expectedSectorShift {
266+ return nil , fmt .Errorf ("unexpected sector size: %d" , 1 << self .Header .SectorShift )
244267 }
245268
246269 self .SectorSize = 1 << self .Header .SectorShift
@@ -250,11 +273,11 @@ func NewOLEFile(data []byte) (*OLEFile, error) {
250273 }
251274
252275 self .MiniSectorSize = 1 << self .Header .MiniSectorShift
253- if ( len (data ) - 512 )% self .SectorSize != 0 {
276+ if len (data )% self .SectorSize != 0 {
254277 DebugPrintf ("Last sector has invalid size\n " )
255278 }
256279
257- self .SectorCount = ( len (data ) - 512 ) / self . SectorSize
280+ self .SectorCount = len (data )/ self . SectorSize - 1 // Subtract 1 for the header sector
258281 for _ , sect := range self .Header .SectFat {
259282 if sect != FREESECT {
260283 self .FatSectors = append (self .FatSectors , sect )
@@ -279,7 +302,7 @@ func NewOLEFile(data []byte) (*OLEFile, error) {
279302 }
280303
281304 next := dif_values [len (dif_values )- 1 ]
282- for _ , value := range dif_values [:len (dif_values )- 2 ] {
305+ for _ , value := range dif_values [:len (dif_values )- 1 ] {
283306 if value != FREESECT {
284307 self .FatSectors = append (self .FatSectors , value )
285308 }
@@ -319,6 +342,9 @@ func NewOLEFile(data []byte) (*OLEFile, error) {
319342 if err != nil {
320343 return nil , err
321344 }
345+ if dir_obj == nil { // Unallocated index
346+ continue
347+ }
322348 self .Directory = append (self .Directory , dir_obj )
323349 }
324350
0 commit comments