@@ -243,6 +243,25 @@ static void checkPointer(const FileContents & contents, const void * p, size_t s
243243}
244244
245245
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+
246265template <ElfFileParams>
247266ElfFile<ElfFileParamNames>::ElfFile(FileContents fContents )
248267 : fileContents(fContents )
@@ -259,14 +278,34 @@ ElfFile<ElfFileParamNames>::ElfFile(FileContents fContents)
259278 if (rdi (hdr ()->e_type ) != ET_EXEC && rdi (hdr ()->e_type ) != ET_DYN)
260279 error (" wrong ELF type" );
261280
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+ }
264293
265294 if (rdi (hdr ()->e_shnum ) == 0 )
266295 error (" no section headers. The input file is probably a statically linked, self-decompressing binary" );
267296
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+ }
270309
271310 if (rdi (hdr ()->e_phentsize ) != sizeof (Elf_Phdr))
272311 error (" program headers have wrong size" );
@@ -295,7 +334,10 @@ ElfFile<ElfFileParamNames>::ElfFile(FileContents fContents)
295334 error (" string table index out of bounds" );
296335
297336 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);
299341 checkPointer (fileContents, shstrtab, shstrtabSize);
300342
301343 if (shstrtabSize == 0 )
@@ -583,7 +625,7 @@ std::string & ElfFile<ElfFileParamNames>::replaceSection(const SectionName & sec
583625 s = std::string (i->second );
584626 } else {
585627 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 ));
587629 }
588630
589631 s.resize (size);
@@ -1193,7 +1235,10 @@ template<ElfFileParams>
11931235std::string ElfFile<ElfFileParamNames>::getInterpreter() const
11941236{
11951237 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);
11971242}
11981243
11991244template <ElfFileParams>
0 commit comments