Print this page
4011 ar does weird things with extended ELF sections
@@ -203,10 +203,11 @@
static void
recover_padding(Elf *elf, ARFILE *file)
{
size_t extent;
size_t padding;
+ size_t shnum;
GElf_Ehdr ehdr;
/* ar(1) only pads objects, so bail if not looking at one */
if (gelf_getclass(elf) == ELFCLASSNONE)
@@ -220,12 +221,15 @@
* object: Find the address at the end of the array and compare
* it to the archive ar_size. If they are within PADSZ bytes, then
* we've found the end, and the difference is padding (We assume
* that no ELF section can fit into PADSZ bytes).
*/
+ if (elf_getshdrnum(elf, &shnum) == -1)
+ return;
+
extent = gelf_getehdr(elf, &ehdr)
- ? (ehdr.e_shoff + (ehdr.e_shnum * ehdr.e_shentsize)) : 0;
+ ? (ehdr.e_shoff + (shnum * ehdr.e_shentsize)) : 0;
/*
* If the extent exceeds the end of the archive member
* (negative padding), then we don't know what is going on
* and simply leave things alone.
@@ -550,15 +554,37 @@
} else {
(void) fprintf(stderr, MSG_INTL(MSG_INTERNAL_01));
exit(1);
}
if (gelf_getehdr(elf, &ehdr) != 0) {
+ size_t shstrndx = 0;
if ((class = gelf_getclass(elf)) == ELFCLASS64) {
fptr->ar_flag |= F_CLASS64;
} else if (class == ELFCLASS32)
fptr->ar_flag |= F_CLASS32;
- scn = elf_getscn(elf, ehdr.e_shstrndx);
+
+ if (elf_getshdrstrndx(elf, &shstrndx) == -1) {
+ if (fptr->ar_pathname != NULL) {
+ (void) fprintf(stderr,
+ MSG_INTL(MSG_ELF_GETSHDRSTRNDX_FILE),
+ fptr->ar_pathname, elf_errmsg(-1));
+ } else {
+ (void) fprintf(stderr,
+ MSG_INTL(MSG_ELF_GETSHDRSTRNDX_AR),
+ arname, fptr->ar_longname,
+ elf_errmsg(-1));
+ }
+ num_errs++;
+ if (newfd) {
+ (void) close(newfd);
+ newfd = 0;
+ }
+ (void) elf_end(elf);
+ continue;
+ }
+
+ scn = elf_getscn(elf, shstrndx);
if (scn == NULL) {
if (fptr->ar_pathname != NULL)
(void) fprintf(stderr,
MSG_INTL(MSG_ELF_GETSCN_FILE),
fptr->ar_pathname, elf_errmsg(-1));
@@ -638,11 +664,11 @@
num_errs++;
(void) elf_end(elf);
continue;
}
*found_obj = 1;
- if (shdr.sh_type == SHT_SYMTAB)
+ if (shdr.sh_type == SHT_SYMTAB) {
if (search_sym_tab(arname, fptr, elf,
scn, &nsyms, symlist,
&num_errs) == -1) {
if (newfd) {
(void) close(newfd);
@@ -650,10 +676,11 @@
}
continue;
}
}
}
+ }
mem_offset += sizeof (struct ar_hdr) + fptr->ar_size;
if (fptr->ar_size & 01)
mem_offset++;
(void) elf_end(elf);
if (newfd) {