@@ -28,13 +28,12 @@ implementation
2828 PE.Imports.Func,
2929 PE.Imports.Lib;
3030
31- type
32- TFuncs = TList<TPEImportFunctionDelayed>;
33-
34- procedure ParseTable (
31+ // Testing mode: check if read fields are correct.
32+ function ParseTable (
3533 const PE: TPEImage;
3634 const Table: TDelayLoadDirectoryTable;
37- const Funcs: TFuncs);
35+ Testing: boolean
36+ ): boolean;
3837var
3938 DllName: string;
4039 FnName: string;
@@ -43,23 +42,54 @@ procedure ParseTable(
4342 Ilt: TImportLookupTable;
4443 iFunc: uint32;
4544var
45+ iLen: integer;
4646 Ordinal: UInt16;
4747 Hint: UInt16 absolute Ordinal;
4848 Iat: TRVA;
49- SubValue: UInt32 ;
49+ SubValue: uint32 ;
5050 Lib: TPEImportLibrary;
5151begin
5252 if Table.UsesVA then
5353 SubValue := PE.ImageBase
5454 else
5555 SubValue := 0 ;
5656
57+ if Testing then
58+ begin
59+ if (Table.Name = 0 ) or (Table.Name < SubValue) then
60+ begin
61+ PE.Msg.Write(' Delayed Import: Name address incorrect.' );
62+ exit(false);
63+ end ;
64+
65+ if (Table.DelayImportNameTable = 0 ) or (Table.DelayImportNameTable < SubValue) then
66+ begin
67+ PE.Msg.Write(' Delayed Import: Name table address incorrect.' );
68+ exit(false);
69+ end ;
70+
71+ if (Table.DelayImportAddressTable = 0 ) or (Table.DelayImportAddressTable < SubValue) then
72+ begin
73+ PE.Msg.Write(' Delayed Import: Address table incorrect.' );
74+ exit(false);
75+ end ;
76+ end ;
77+
5778 if not PE.SeekRVA(Table.Name - SubValue) then
58- exit;
79+ exit(false) ;
5980
60- DllName := PE.ReadANSIString;
61- Lib := TPEImportLibrary.Create(DLLName);
62- PE.ImportsDelayed.Add(Lib);
81+ if not PE.ReadAnsiStringLen(MAX_PATH_WIN, iLen, DllName) then
82+ exit(false);
83+
84+ if not Testing then
85+ begin
86+ Lib := TPEImportLibrary.Create(DllName);
87+ PE.ImportsDelayed.Add(Lib);
88+ end
89+ else
90+ begin
91+ Lib := nil ; // compiler friendly
92+ end ;
6393
6494 iFunc := 0 ;
6595 Iat := Table.DelayImportAddressTable - SubValue;
@@ -84,17 +114,26 @@ procedure ParseTable(
84114 begin
85115 // Import by name. Get hint/name
86116 if not PE.SeekRVA(HintNameRva - SubValue) then
87- raise Exception.Create(' Error reading delayed import hint/name.' );
117+ begin
118+ PE.Msg.Write(' Delayed Import: incorrect Hint/Name RVA encountered.' );
119+ exit(false);
120+ end ;
121+
88122 Hint := PE.ReadWord(2 );
89123 FnName := PE.ReadANSIString;
90124 end ;
91125
92- Fn := TPEImportFunctionDelayed.Create(FnName, Ordinal);
93- Lib.Functions.Add(Fn);
126+ if not Testing then
127+ begin
128+ Fn := TPEImportFunctionDelayed.Create(FnName, Ordinal);
129+ Lib.Functions.Add(Fn);
130+ end ;
94131
95132 inc(Iat, PE.ImageWordSize);
96133 inc(iFunc);
97134 end ;
135+
136+ exit(true);
98137end ;
99138
100139function TPEImportDelayedParser.Parse : TParserResult;
@@ -104,33 +143,32 @@ function TPEImportDelayedParser.Parse: TParserResult;
104143 ofs: uint32;
105144 Table: TDelayLoadDirectoryTable;
106145 Tables: TList<TDelayLoadDirectoryTable>;
107- Funcs: TFuncs;
108146 TablesUseRVA: boolean;
109147begin
110148 PE := TPEImage(FPE);
111149
112- Result := PR_ERROR;
150+ result := PR_ERROR;
113151
114152 // If no imports, it's ok.
115153 if not PE.DataDirectories.Get(DDIR_DELAYIMPORT, @ddir) then
116- Exit (PR_OK);
154+ exit (PR_OK);
117155 if ddir.IsEmpty then
118- Exit (PR_OK);
156+ exit (PR_OK);
119157
120158 // Seek import dir.
121159 if not PE.SeekRVA(ddir.VirtualAddress) then
122- Exit ;
160+ exit ;
123161
124162 Tables := TList<TDelayLoadDirectoryTable>.Create;
125163 try
126164
127165 // Delay-load dir. tables.
128166 ofs := 0 ;
129- TablesUseRVA := True ; // default, compiler-friendly
130- while True do
167+ TablesUseRVA := true ; // default, compiler-friendly
168+ while true do
131169 begin
132170 if ofs > ddir.Size then
133- Exit (PR_ERROR);
171+ exit (PR_ERROR);
134172
135173 if not PE.ReadEx(Table, SizeOf(Table)) then
136174 break;
@@ -150,7 +188,7 @@ function TPEImportDelayedParser.Parse: TParserResult;
150188 begin
151189 // Normally all tables must use either VA or RVA. No mix allowed.
152190 // If mix found it must be not real table.
153- // For example, Delphi ( some versions for sure) use(d) such optimization.
191+ // For example, some Delphi versions used such optimization.
154192 break;
155193 end ;
156194
@@ -159,18 +197,13 @@ function TPEImportDelayedParser.Parse: TParserResult;
159197 end ;
160198
161199 // Parse tables.
162- if Tables.Count = 0 then
163- Exit(PR_OK);
164-
165- Funcs := TFuncs.Create;
166- try
167- for Table in Tables do
168- ParseTable(PE, Table, Funcs);
169- finally
170- Funcs.Free;
171- end ;
200+ for Table in Tables do
201+ // First test if fields are correct
202+ if ParseTable(PE, Table, true) then
203+ // Then do real reading.
204+ ParseTable(PE, Table, false);
172205
173- Result := PR_OK;
206+ exit( PR_OK) ;
174207 finally
175208 Tables.Free;
176209 end ;
0 commit comments