Corner cases for e_shnum vs e_shstrndx
modified: p_lx_elf.cpp
This commit is contained in:
+30
-14
@@ -1645,9 +1645,10 @@ PackLinuxElf32::invert_pt_dynamic(Elf32_Dyn const *dynp)
|
||||
}
|
||||
}
|
||||
unsigned const e_shstrndx = get_te16(&ehdri.e_shstrndx);
|
||||
if (e_shnum <= e_shstrndx) {
|
||||
if (e_shnum <= e_shstrndx
|
||||
&& !(0==e_shnum && 0==e_shstrndx) ) {
|
||||
char msg[40]; snprintf(msg, sizeof(msg),
|
||||
"bad .e_shstrndx %d > .e_shnum %d", e_shstrndx, e_shnum);
|
||||
"bad .e_shstrndx %d >= .e_shnum %d", e_shstrndx, e_shnum);
|
||||
throwCantPack(msg);
|
||||
}
|
||||
}
|
||||
@@ -1956,12 +1957,11 @@ bool PackLinuxElf32::canPack()
|
||||
phdri= (Elf32_Phdr *)((size_t)e_phoff + file_image); // do not free() !!
|
||||
shdri= (Elf32_Shdr *)((size_t)e_shoff + file_image); // do not free() !!
|
||||
|
||||
if (!e_shnum) {
|
||||
sec_strndx = NULL;
|
||||
shstrtab = NULL;
|
||||
}
|
||||
else {
|
||||
if (e_shnum) {
|
||||
unsigned const e_shstrndx = get_te16(&ehdr->e_shstrndx);
|
||||
if (e_shstrndx) {
|
||||
if (e_shnum <= e_shstrndx) {
|
||||
char msg[40]; snprintf(msg, sizeof(msg),
|
||||
"bad e_shstrndx %#x >= e_shnum %d", e_shstrndx, e_shnum);
|
||||
@@ -1975,6 +1975,7 @@ bool PackLinuxElf32::canPack()
|
||||
throwCantPack(msg);
|
||||
}
|
||||
shstrtab = (char const *)(sh_offset + file_image);
|
||||
}
|
||||
sec_dynsym = elf_find_section_type(Elf32_Shdr::SHT_DYNSYM);
|
||||
if (sec_dynsym) {
|
||||
unsigned const sh_link = get_te32(&sec_dynsym->sh_link);
|
||||
@@ -1985,13 +1986,17 @@ bool PackLinuxElf32::canPack()
|
||||
sec_dynstr = &shdri[sh_link];
|
||||
}
|
||||
|
||||
if (sec_strndx) {
|
||||
unsigned const sh_name = get_te32(&sec_strndx->sh_name);
|
||||
if (Elf32_Shdr::SHT_STRTAB != get_te32(&sec_strndx->sh_type)
|
||||
|| file_size <= (off_t)sh_name // FIXME: weak
|
||||
|| 0!=strcmp((char const *)".shstrtab", &shstrtab[sh_name]) ) {
|
||||
|| (sh_name
|
||||
&& 0!=strcmp((char const *)".shstrtab", &shstrtab[sh_name]))
|
||||
) {
|
||||
throwCantPack("bad e_shstrndx");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
phdr= phdri;
|
||||
for (int j= e_phnum; --j>=0; ++phdr)
|
||||
@@ -2239,12 +2244,11 @@ PackLinuxElf64::canPack()
|
||||
phdri= (Elf64_Phdr *)((size_t)e_phoff + file_image); // do not free() !!
|
||||
shdri= (Elf64_Shdr *)((size_t)e_shoff + file_image); // do not free() !!
|
||||
|
||||
if (!e_shnum) {
|
||||
sec_strndx = NULL;
|
||||
shstrtab = NULL;
|
||||
}
|
||||
else {
|
||||
if (e_shnum) {
|
||||
unsigned const e_shstrndx = get_te16(&ehdr->e_shstrndx);
|
||||
if (e_shstrndx) {
|
||||
if (e_shnum <= e_shstrndx) {
|
||||
char msg[40]; snprintf(msg, sizeof(msg),
|
||||
"bad e_shstrndx %#x >= e_shnum %d", e_shstrndx, e_shnum);
|
||||
@@ -2258,6 +2262,7 @@ PackLinuxElf64::canPack()
|
||||
throwCantPack(msg);
|
||||
}
|
||||
shstrtab = (char const *)(sh_offset + file_image);
|
||||
}
|
||||
sec_dynsym = elf_find_section_type(Elf64_Shdr::SHT_DYNSYM);
|
||||
if (sec_dynsym) {
|
||||
upx_uint64_t const sh_link = get_te64(&sec_dynsym->sh_link);
|
||||
@@ -2268,13 +2273,17 @@ PackLinuxElf64::canPack()
|
||||
sec_dynstr = &shdri[sh_link];
|
||||
}
|
||||
|
||||
if (sec_strndx) {
|
||||
unsigned const sh_name = get_te32(&sec_strndx->sh_name);
|
||||
if (Elf64_Shdr::SHT_STRTAB != get_te32(&sec_strndx->sh_type)
|
||||
|| file_size <= (off_t)sh_name // FIXME: weak
|
||||
|| 0!=strcmp((char const *)".shstrtab", &shstrtab[sh_name]) ) {
|
||||
|| (sh_name
|
||||
&& 0!=strcmp((char const *)".shstrtab", &shstrtab[sh_name]))
|
||||
) {
|
||||
throwCantPack("bad e_shstrndx");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
phdr= phdri;
|
||||
for (int j= e_phnum; --j>=0; ++phdr)
|
||||
@@ -4251,6 +4260,7 @@ void PackLinuxElf64::unpack(OutputFile *fo)
|
||||
"bad DYNAMIC", get_te64(&dynhdr->p_offset), get_te64(&dynhdr->p_filesz));
|
||||
dynstr = (char const *)elf_find_dynamic(Elf64_Dyn::DT_STRTAB);
|
||||
sec_dynsym = elf_find_section_type(Elf64_Shdr::SHT_DYNSYM);
|
||||
if (sec_dynsym) {
|
||||
upx_uint64_t const off_dynsym = get_te64(&sec_dynsym->sh_offset);
|
||||
upx_uint64_t const sz_dynsym = get_te64(&sec_dynsym->sh_size);
|
||||
Elf64_Sym *const sym0 = (Elf64_Sym *)ibuf.subref(
|
||||
@@ -4269,6 +4279,7 @@ void PackLinuxElf64::unpack(OutputFile *fo)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fo) {
|
||||
fo->write(ibuf + ph.u_len, xct_off - ph.u_len);
|
||||
}
|
||||
@@ -4668,9 +4679,10 @@ PackLinuxElf32::check_pt_dynamic(Elf32_Phdr const *const phdr)
|
||||
unsigned t = get_te32(&phdr->p_offset), s = sizeof(Elf32_Dyn) + t;
|
||||
unsigned vaddr = get_te32(&phdr->p_vaddr);
|
||||
unsigned filesz = get_te32(&phdr->p_filesz), memsz = get_te32(&phdr->p_memsz);
|
||||
unsigned align = get_te32(&phdr->p_align);
|
||||
if (s < t || file_size < (off_t)s
|
||||
|| (3 & t) || (7 & (filesz | memsz)) // .balign 4; 8==sizeof(Elf32_Dyn)
|
||||
|| (-1+ page_size) & (t ^ vaddr)
|
||||
|| (-1+ align) & (t ^ vaddr)
|
||||
|| filesz < sizeof(Elf32_Dyn)
|
||||
|| memsz < sizeof(Elf32_Dyn)
|
||||
|| filesz < memsz) {
|
||||
@@ -4748,9 +4760,10 @@ PackLinuxElf64::check_pt_dynamic(Elf64_Phdr const *const phdr)
|
||||
upx_uint64_t t = get_te64(&phdr->p_offset), s = sizeof(Elf64_Dyn) + t;
|
||||
upx_uint64_t vaddr = get_te64(&phdr->p_vaddr);
|
||||
upx_uint64_t filesz = get_te64(&phdr->p_filesz), memsz = get_te64(&phdr->p_memsz);
|
||||
upx_uint64_t align = get_te64(&phdr->p_align);
|
||||
if (s < t || (upx_uint64_t)file_size < s
|
||||
|| (7 & t) || (0xf & (filesz | memsz)) // .balign 8; 16==sizeof(Elf64_Dyn)
|
||||
|| (-1+ page_size) & (t ^ vaddr)
|
||||
|| (-1+ align) & (t ^ vaddr)
|
||||
|| filesz < sizeof(Elf64_Dyn)
|
||||
|| memsz < sizeof(Elf64_Dyn)
|
||||
|| filesz < memsz) {
|
||||
@@ -4860,9 +4873,10 @@ PackLinuxElf64::invert_pt_dynamic(Elf64_Dyn const *dynp)
|
||||
}
|
||||
}
|
||||
unsigned const e_shstrndx = get_te16(&ehdri.e_shstrndx);
|
||||
if (e_shnum <= e_shstrndx) {
|
||||
if (e_shnum <= e_shstrndx
|
||||
&& !(0==e_shnum && 0==e_shstrndx) ) {
|
||||
char msg[40]; snprintf(msg, sizeof(msg),
|
||||
"bad .e_shstrndx %d > .e_shnum %d", e_shstrndx, e_shnum);
|
||||
"bad .e_shstrndx %d >= .e_shnum %d", e_shstrndx, e_shnum);
|
||||
throwCantPack(msg);
|
||||
}
|
||||
}
|
||||
@@ -5123,6 +5137,7 @@ void PackLinuxElf32::unpack(OutputFile *fo)
|
||||
"bad DYNAMIC", get_te32(&dynhdr->p_offset), get_te32(&dynhdr->p_filesz));
|
||||
dynstr = (char const *)elf_find_dynamic(Elf32_Dyn::DT_STRTAB);
|
||||
sec_dynsym = elf_find_section_type(Elf32_Shdr::SHT_DYNSYM);
|
||||
if (sec_dynsym) {
|
||||
unsigned const off_dynsym = get_te32(&sec_dynsym->sh_offset);
|
||||
unsigned const sz_dynsym = get_te32(&sec_dynsym->sh_size);
|
||||
Elf32_Sym *const sym0 = (Elf32_Sym *)ibuf.subref(
|
||||
@@ -5141,6 +5156,7 @@ void PackLinuxElf32::unpack(OutputFile *fo)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fo) {
|
||||
fo->write(ibuf + ph.u_len, xct_off - ph.u_len);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user