@@ -243,6 +243,25 @@ static void checkPointer(const FileContents & contents, const void * p, size_t s
243
243
}
244
244
245
245
246
+ static void checkOffset (const FileContents & contents, size_t offset, size_t size)
247
+ {
248
+ size_t end;
249
+
250
+ if (offset > contents->size ()
251
+ || size > contents->size ()
252
+ || __builtin_add_overflow (offset, size, &end)
253
+ || end > contents->size ())
254
+ error (" data offset extends past file end" );
255
+ }
256
+
257
+
258
+ static std::string extractString (const FileContents & contents, size_t offset, size_t size)
259
+ {
260
+ checkOffset (contents, offset, size);
261
+ return { reinterpret_cast <const char *>(contents->data ()) + offset, size };
262
+ }
263
+
264
+
246
265
template <ElfFileParams>
247
266
ElfFile<ElfFileParamNames>::ElfFile(FileContents fContents )
248
267
: fileContents(fContents )
@@ -259,14 +278,34 @@ ElfFile<ElfFileParamNames>::ElfFile(FileContents fContents)
259
278
if (rdi (hdr ()->e_type ) != ET_EXEC && rdi (hdr ()->e_type ) != ET_DYN)
260
279
error (" wrong ELF type" );
261
280
262
- if (rdi (hdr ()->e_phoff ) + rdi (hdr ()->e_phnum ) * rdi (hdr ()->e_phentsize ) > fileContents->size ())
263
- error (" program header table out of bounds" );
281
+ {
282
+ auto ph_offset = rdi (hdr ()->e_phoff );
283
+ auto ph_num = rdi (hdr ()->e_phnum );
284
+ auto ph_entsize = rdi (hdr ()->e_phentsize );
285
+ size_t ph_size, ph_end;
286
+
287
+ if (__builtin_mul_overflow (ph_num, ph_entsize, &ph_size)
288
+ || __builtin_add_overflow (ph_offset, ph_size, &ph_end)
289
+ || ph_end > fileContents->size ()) {
290
+ error (" program header table out of bounds" );
291
+ }
292
+ }
264
293
265
294
if (rdi (hdr ()->e_shnum ) == 0 )
266
295
error (" no section headers. The input file is probably a statically linked, self-decompressing binary" );
267
296
268
- if (rdi (hdr ()->e_shoff ) + rdi (hdr ()->e_shnum ) * rdi (hdr ()->e_shentsize ) > fileContents->size ())
269
- error (" section header table out of bounds" );
297
+ {
298
+ auto sh_offset = rdi (hdr ()->e_shoff );
299
+ auto sh_num = rdi (hdr ()->e_shnum );
300
+ auto sh_entsize = rdi (hdr ()->e_shentsize );
301
+ size_t sh_size, sh_end;
302
+
303
+ if (__builtin_mul_overflow (sh_num, sh_entsize, &sh_size)
304
+ || __builtin_add_overflow (sh_offset, sh_size, &sh_end)
305
+ || sh_end > fileContents->size ()) {
306
+ error (" section header table out of bounds" );
307
+ }
308
+ }
270
309
271
310
if (rdi (hdr ()->e_phentsize ) != sizeof (Elf_Phdr))
272
311
error (" program headers have wrong size" );
@@ -295,7 +334,10 @@ ElfFile<ElfFileParamNames>::ElfFile(FileContents fContents)
295
334
error (" string table index out of bounds" );
296
335
297
336
auto shstrtabSize = rdi (shdrs[shstrtabIndex].sh_size );
298
- char * shstrtab = (char * ) fileContents->data () + rdi (shdrs[shstrtabIndex].sh_offset );
337
+ size_t shstrtabptr;
338
+ if (__builtin_add_overflow (reinterpret_cast <size_t >(fileContents->data ()), rdi (shdrs[shstrtabIndex].sh_offset ), &shstrtabptr))
339
+ error (" string table overflow" );
340
+ const char *shstrtab = reinterpret_cast <const char *>(shstrtabptr);
299
341
checkPointer (fileContents, shstrtab, shstrtabSize);
300
342
301
343
if (shstrtabSize == 0 )
@@ -583,7 +625,7 @@ std::string & ElfFile<ElfFileParamNames>::replaceSection(const SectionName & sec
583
625
s = std::string (i->second );
584
626
} else {
585
627
auto shdr = findSectionHeader (sectionName);
586
- s = std::string (( char *) fileContents-> data () + rdi (shdr.sh_offset ), rdi (shdr.sh_size ));
628
+ s = extractString ( fileContents, rdi (shdr.sh_offset ), rdi (shdr.sh_size ));
587
629
}
588
630
589
631
s.resize (size);
@@ -1193,7 +1235,10 @@ template<ElfFileParams>
1193
1235
std::string ElfFile<ElfFileParamNames>::getInterpreter() const
1194
1236
{
1195
1237
auto shdr = findSectionHeader (" .interp" );
1196
- return std::string ((const char *) fileContents->data () + rdi (shdr.sh_offset ), rdi (shdr.sh_size ) - 1 );
1238
+ auto size = rdi (shdr.sh_size );
1239
+ if (size > 0 )
1240
+ size--;
1241
+ return extractString (fileContents, rdi (shdr.sh_offset ), size);
1197
1242
}
1198
1243
1199
1244
template <ElfFileParams>
0 commit comments