@@ -25,9 +25,15 @@ TDataDirectories = class
2525
2626 procedure Clear ;
2727
28+ procedure NullInvalid (const Msg: TMsgMgr);
29+
2830 // Load array of TImageDataDirectory (va,size) from stream.
29- procedure LoadDirectoriesFromStream (Stream: TStream; const Msg: TMsgMgr;
30- DeclaredCount: integer);
31+ procedure LoadDirectoriesFromStream (
32+ Stream: TStream;
33+ const Msg: TMsgMgr;
34+ DeclaredCount: uint32; // # of rva and sizes
35+ MaxBytes: uint16
36+ );
3137
3238 // Save array of TImageDataDirectory (va,size) to stream.
3339 // Return saved size.
@@ -190,14 +196,46 @@ function TDataDirectories.GetName(Index: integer): string;
190196 Result := ' ' ;
191197end ;
192198
199+ procedure TDataDirectories.NullInvalid (const Msg: TMsgMgr);
200+ var
201+ i: integer;
202+ needToNullDir: boolean;
203+ begin
204+ // Check RVAs.
205+ for i := 0 to self.Count - 1 do
206+ begin
207+ // Empty dir is ok.
208+ if FItems[i].IsEmpty then
209+ continue;
210+
211+ needToNullDir := False;
212+
213+ if (FItems[i].Size = 0 ) and (FItems[i].RVA <> 0 ) then
214+ begin
215+ Msg.Write(SCategoryDataDirecory, ' Directory # %d has size = 0.' , [i]);
216+ needToNullDir := true;
217+ end
218+ else if not TPEImage(FPE).RVAExists(FItems[i].RVA) then
219+ begin
220+ Msg.Write(SCategoryDataDirecory, ' Directory # %d RVA is not in image.' , [i]);
221+ needToNullDir := true;
222+ end ;
223+
224+ if needToNullDir and (PO_NULL_INVALID_DIRECTORY in TPEImage(FPE).Options) then
225+ begin
226+ FItems[i] := NULL_IMAGE_DATA_DIRECTORY;
227+ Msg.Write(SCategoryDataDirecory, ' Directory # %d nulled.' , [i]);
228+ end ;
229+ end ;
230+ end ;
231+
193232procedure TDataDirectories.LoadDirectoriesFromStream ;
194233var
195- CountToEOF : integer; // Count from StartOfs to EOF.
234+ MaxCountPossible : integer;
196235 CountToRead: integer;
197- SizeToEOF : uint64;
236+ SizeToFileEnd : uint64;
198237 Size: uint32;
199- i: integer;
200- needToNullDir: boolean;
238+ MaxSizePossible: uint16;
201239begin
202240 Clear;
203241
@@ -207,26 +245,35 @@ procedure TDataDirectories.LoadDirectoriesFromStream;
207245 exit;
208246 end ;
209247
210- SizeToEOF := (Stream.Size - Stream.Position);
248+ SizeToFileEnd := (Stream.Size - Stream.Position);
211249
212- CountToEOF := SizeToEOF div SizeOf(TImageDataDirectory);
250+ // Max size available for dirs.
251+ if SizeToFileEnd > MaxBytes then
252+ MaxSizePossible := MaxBytes
253+ else
254+ MaxSizePossible := SizeToFileEnd;
213255
214- // File can have part of dword stored. It must be extended with zeros.
215- if (SizeToEOF mod SizeOf(TImageDataDirectory)) <> 0 then
216- inc(CountToEOF);
256+ MaxCountPossible := MaxSizePossible div SizeOf(TImageDataDirectory);
217257
218- CountToRead := DeclaredCount;
258+ // File can have part of dword stored. It must be extended with zeros.
259+ if (MaxSizePossible mod SizeOf(TImageDataDirectory)) <> 0 then
260+ inc(MaxCountPossible);
219261
220262 if DeclaredCount <> TYPICAL_NUMBER_OF_DIRECTORIES then
221- Msg.Write(SCategoryDataDirecory, ' Non-usual count of directories (%d ).' , [DeclaredCount]);
263+ Msg.Write(SCategoryDataDirecory, ' Non-usual count of directories declared (0x%x ).' , [DeclaredCount]);
222264
223- if DeclaredCount > CountToEOF then
265+ if DeclaredCount > MaxCountPossible then
224266 begin
225- CountToRead := CountToEOF ;
267+ CountToRead := MaxCountPossible ;
226268
227269 Msg.Write(SCategoryDataDirecory,
228- ' Declared count of directories is greater than file can contain (%d > %d).' ,
229- [DeclaredCount, CountToEOF]);
270+ ' Declared count of directories is greater than file can contain (0x%x > 0x%x).' ,
271+ [DeclaredCount, MaxCountPossible]);
272+ Msg.Write(SCategoryDataDirecory, ' Fall back to 0x%x.' , [MaxCountPossible]);
273+ end
274+ else
275+ begin
276+ CountToRead := DeclaredCount;
230277 end ;
231278
232279 // Read data directories.
@@ -243,32 +290,7 @@ procedure TDataDirectories.LoadDirectoriesFromStream;
243290 // Set final count.
244291 self.Count := CountToRead;
245292
246- // Check RVAs.
247- for i := 0 to self.Count - 1 do
248- begin
249- // Empty dir is ok.
250- if FItems[i].IsEmpty then
251- continue;
252-
253- needToNullDir := False;
254-
255- if (FItems[i].Size = 0 ) and (FItems[i].RVA <> 0 ) then
256- begin
257- Msg.Write(SCategoryDataDirecory, ' Directory # %d has size = 0.' , [i]);
258- needToNullDir := true;
259- end
260- else if not TPEImage(FPE).RVAExists(FItems[i].RVA) then
261- begin
262- Msg.Write(SCategoryDataDirecory, ' Directory # %d RVA is not in image.' , [i]);
263- needToNullDir := true;
264- end ;
265-
266- if needToNullDir and (PO_NULL_INVALID_DIRECTORY in TPEImage(FPE).Options) then
267- begin
268- FItems[i] := NULL_IMAGE_DATA_DIRECTORY;
269- Msg.Write(SCategoryDataDirecory, ' Directory # %d nulled.' , [i]);
270- end ;
271- end ;
293+ NullInvalid(Msg);
272294end ;
273295
274296function TDataDirectories.SaveToStream (Index: integer; Stream: TStream): boolean;
0 commit comments