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) {