changeset 14149:9cc418183cee

4011 ar does weird things with extended ELF sections Reviewed by: Jason King <jason.brian.king@gmail.com> Reviewed by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net> Approved by: Robert Mustacchi <rm@joyent.com>
author Richard Lowe <richlowe@richlowe.net>
date Wed, 07 Aug 2013 17:49:24 -0400
parents fe28bd725808
children 4b808fda2aac
files usr/src/cmd/sgs/ar/common/ar.msg usr/src/cmd/sgs/ar/common/file.c
diffstat 2 files changed, 32 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/sgs/ar/common/ar.msg	Wed Aug 07 01:00:48 2013 -0400
+++ b/usr/src/cmd/sgs/ar/common/ar.msg	Wed Aug 07 17:49:24 2013 -0400
@@ -70,6 +70,8 @@
 @ MSG_ELF_GETSCN_FILE	"ar: %s has no section header or bad elf format: %s\n"
 @ MSG_ELF_GETSCN_AR	"ar: %s(%s) has no section header or bad elf \
 			 format: %s\n"
+@ MSG_ELF_GETSHSTRNDX_FILE "ar: %s has no string table index: %s\n"
+@ MSG_ELF_GETSHSTRNDX_AR "ar: %s(%s) has no string table index: %s\n"
 @ MSG_ELF_MALARCHIVE	"ar: %s: offset %lld: malformed archive: %s\n"
 @ MSG_ELF_RAWFILE	"ar: elf_rawfile() failed: %s\n"
 @ MSG_ELF_VERSION	"ar: libelf.a out of date: %s\n"
--- a/usr/src/cmd/sgs/ar/common/file.c	Wed Aug 07 01:00:48 2013 -0400
+++ b/usr/src/cmd/sgs/ar/common/file.c	Wed Aug 07 17:49:24 2013 -0400
@@ -205,6 +205,7 @@
 {
 	size_t		extent;
 	size_t		padding;
+	size_t		shnum;
 	GElf_Ehdr	ehdr;
 
 
@@ -222,8 +223,11 @@
 	 * 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
@@ -552,11 +556,33 @@
 			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_GETSHSTRNDX_FILE),
+					    fptr->ar_pathname, elf_errmsg(-1));
+				} else {
+					(void) fprintf(stderr,
+					    MSG_INTL(MSG_ELF_GETSHSTRNDX_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,
@@ -640,7 +666,7 @@
 					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) {
@@ -650,6 +676,7 @@
 						}
 						continue;
 					}
+				}
 			}
 		}
 		mem_offset += sizeof (struct ar_hdr) + fptr->ar_size;