/* Could not determine the number of sections. */
return NULL;
- /* We can now allocate the memory. */
+ /* Check for too many sections. */
+ if (e_ident[EI_CLASS] == ELFCLASS32)
+ {
+ if (scncnt > SIZE_MAX / (sizeof (Elf_Scn) + sizeof (Elf32_Shdr)))
+ return NULL;
+ }
+ else if (scncnt > SIZE_MAX / (sizeof (Elf_Scn) + sizeof (Elf64_Shdr)))
+ return NULL;
+
+ /* We can now allocate the memory. Even if there are no section headers,
+ we allocate space for a zeroth section in case we need it later. */
+ const size_t scnmax = (scncnt ?: (cmd == ELF_C_RDWR || cmd == ELF_C_RDWR_MMAP)
+ ? 1 : 0);
Elf *elf = allocate_elf (fildes, map_address, offset, maxsize, cmd, parent,
- ELF_K_ELF, scncnt * sizeof (Elf_Scn));
+ ELF_K_ELF, scnmax * sizeof (Elf_Scn));
if (elf == NULL)
/* Not enough memory. */
return NULL;
{
/* We can use the mmapped memory. */
elf->state.elf32.ehdr = ehdr;
+
+ if (unlikely (ehdr->e_shoff >= maxsize)
+ || unlikely (maxsize - ehdr->e_shoff
+ < scncnt * sizeof (Elf32_Shdr)))
+ {
+ free_and_out:
+ free (elf);
+ __libelf_seterrno (ELF_E_INVALID_FILE);
+ return NULL;
+ }
elf->state.elf32.shdr
= (Elf32_Shdr *) ((char *) ehdr + ehdr->e_shoff);
- if (ehdr->e_phnum > 0)
- /* Assign a value only if there really is a program
- header. Otherwise the value remains NULL. */
- elf->state.elf32.phdr
- = (Elf32_Phdr *) ((char *) ehdr + ehdr->e_phoff);
+
- if (ehdr->e_phnum > 0)
++ size_t phnum = ehdr->e_phnum;
++ if (phnum == PN_XNUM && scncnt > 0)
++ phnum = elf->state.elf32.shdr[0].sh_info;
++ if (phnum > 0)
+ {
- /* Assign a value only if there really is a program
- header. Otherwise the value remains NULL. */
++ /* Assign a value only if there really is a program
++ header. Otherwise the value remains NULL. */
+ if (unlikely (ehdr->e_phoff >= maxsize)
+ || unlikely (maxsize - ehdr->e_phoff
- < ehdr->e_phnum * sizeof (Elf32_Phdr)))
++ < phnum * sizeof (Elf32_Phdr)))
+ goto free_and_out;
- elf->state.elf32.phdr
- = (Elf32_Phdr *) ((char *) ehdr + ehdr->e_phoff);
++ elf->state.elf32.phdr
++ = (Elf32_Phdr *) ((char *) ehdr + ehdr->e_phoff);
+ }
for (size_t cnt = 0; cnt < scncnt; ++cnt)
{
{
/* We can use the mmapped memory. */
elf->state.elf64.ehdr = ehdr;
+
+ if (unlikely (ehdr->e_shoff >= maxsize)
+ || unlikely (ehdr->e_shoff
+ + scncnt * sizeof (Elf32_Shdr) > maxsize))
+ goto free_and_out;
elf->state.elf64.shdr
= (Elf64_Shdr *) ((char *) ehdr + ehdr->e_shoff);
- if (ehdr->e_phnum > 0)
- /* Assign a value only if there really is a program
- header. Otherwise the value remains NULL. */
- elf->state.elf64.phdr
- = (Elf64_Phdr *) ((char *) ehdr + ehdr->e_phoff);
+
- if (ehdr->e_phnum > 0)
++ size_t phnum = ehdr->e_phnum;
++ if (phnum == PN_XNUM && scncnt > 0)
++ phnum = elf->state.elf64.shdr[0].sh_info;
++ if (phnum > 0)
+ {
- /* Assign a value only if there really is a program
- header. Otherwise the value remains NULL. */
++ /* Assign a value only if there really is a program
++ header. Otherwise the value remains NULL. */
+ if (unlikely (ehdr->e_phoff >= maxsize)
+ || unlikely (ehdr->e_phoff
- + ehdr->e_phnum
- * sizeof (Elf32_Phdr) > maxsize))
++ + phnum * sizeof (Elf32_Phdr) > maxsize))
+ goto free_and_out;
- elf->state.elf64.phdr
- = (Elf64_Phdr *) ((char *) ehdr + ehdr->e_phoff);
++ elf->state.elf64.phdr
++ = (Elf64_Phdr *) ((char *) ehdr + ehdr->e_phoff);
+ }
for (size_t cnt = 0; cnt < scncnt; ++cnt)
{