From owner-svn-src-all@freebsd.org Fri Jul 24 18:00:54 2015 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id B9C2C9AA82D; Fri, 24 Jul 2015 18:00:54 +0000 (UTC) (envelope-from emaste@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id AA2971DE6; Fri, 24 Jul 2015 18:00:54 +0000 (UTC) (envelope-from emaste@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.70]) by repo.freebsd.org (8.14.9/8.14.9) with ESMTP id t6OI0sYN035598; Fri, 24 Jul 2015 18:00:54 GMT (envelope-from emaste@FreeBSD.org) Received: (from emaste@localhost) by repo.freebsd.org (8.14.9/8.14.9/Submit) id t6OI0sWm035597; Fri, 24 Jul 2015 18:00:54 GMT (envelope-from emaste@FreeBSD.org) Message-Id: <201507241800.t6OI0sWm035597@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: emaste set sender to emaste@FreeBSD.org using -f From: Ed Maste Date: Fri, 24 Jul 2015 18:00:54 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r285845 - head/contrib/elftoolchain/readelf X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 24 Jul 2015 18:00:54 -0000 Author: emaste Date: Fri Jul 24 18:00:53 2015 New Revision: 285845 URL: https://svnweb.freebsd.org/changeset/base/285845 Log: readelf: avoid division by zero on section entry size ELF Tool Chain tickets #439, #444, #445, #467 Reported by: Alexander Cherepanov (#467) Reported by: antiAgainst (others) Reviewed by: brooks MFC after: 1 month Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D2338 Modified: head/contrib/elftoolchain/readelf/readelf.c Modified: head/contrib/elftoolchain/readelf/readelf.c ============================================================================== --- head/contrib/elftoolchain/readelf/readelf.c Fri Jul 24 17:46:43 2015 (r285844) +++ head/contrib/elftoolchain/readelf/readelf.c Fri Jul 24 18:00:53 2015 (r285845) @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -314,6 +315,7 @@ static const char *dwarf_reg(unsigned in static const char *dwarf_regname(struct readelf *re, unsigned int num); static struct dumpop *find_dumpop(struct readelf *re, size_t si, const char *sn, int op, int t); +static int get_ent_count(struct section *s, int *ent_count); static char *get_regoff_str(struct readelf *re, Dwarf_Half reg, Dwarf_Addr off); static const char *get_string(struct readelf *re, int strtab, size_t off); @@ -2901,6 +2903,24 @@ dump_shdr(struct readelf *re) #undef ST_CTL } +/* + * Return number of entries in the given section. We'd prefer ent_count be a + * size_t *, but libelf APIs already use int for section indices. + */ +static int +get_ent_count(struct section *s, int *ent_count) +{ + if (s->entsize == 0) { + warnx("section %s has entry size 0", s->name); + return (0); + } else if (s->sz / s->entsize > INT_MAX) { + warnx("section %s has invalid section count", s->name); + return (0); + } + *ent_count = (int)(s->sz / s->entsize); + return (1); +} + static void dump_dynamic(struct readelf *re) { @@ -2929,8 +2949,8 @@ dump_dynamic(struct readelf *re) /* Determine the actual number of table entries. */ nentries = 0; - jmax = (int) (s->sz / s->entsize); - + if (!get_ent_count(s, &jmax)) + continue; for (j = 0; j < jmax; j++) { if (gelf_getdyn(d, j, &dyn) != &dyn) { warnx("gelf_getdyn failed: %s", @@ -3176,7 +3196,9 @@ dump_rel(struct readelf *re, struct sect else printf("%-12s %-12s %-19s %-16s %s\n", REL_HDR); } - len = d->d_size / s->entsize; + assert(d->d_size == s->sz); + if (!get_ent_count(s, &len)) + return; for (i = 0; i < len; i++) { if (gelf_getrel(d, i, &r) != &r) { warnx("gelf_getrel failed: %s", elf_errmsg(-1)); @@ -3232,7 +3254,9 @@ dump_rela(struct readelf *re, struct sec else printf("%-12s %-12s %-19s %-16s %s\n", RELA_HDR); } - len = d->d_size / s->entsize; + assert(d->d_size == s->sz); + if (!get_ent_count(s, &len)) + return; for (i = 0; i < len; i++) { if (gelf_getrela(d, i, &r) != &r) { warnx("gelf_getrel failed: %s", elf_errmsg(-1)); @@ -3297,7 +3321,7 @@ dump_symtab(struct readelf *re, int i) Elf_Data *d; GElf_Sym sym; const char *name; - int elferr, stab, j; + int elferr, stab, j, len; s = &re->sl[i]; stab = s->link; @@ -3310,12 +3334,14 @@ dump_symtab(struct readelf *re, int i) } if (d->d_size <= 0) return; + if (!get_ent_count(s, &len)) + return; printf("Symbol table (%s)", s->name); - printf(" contains %ju entries:\n", s->sz / s->entsize); + printf(" contains %d entries:\n", len); printf("%7s%9s%14s%5s%8s%6s%9s%5s\n", "Num:", "Value", "Size", "Type", "Bind", "Vis", "Ndx", "Name"); - for (j = 0; (uint64_t)j < s->sz / s->entsize; j++) { + for (j = 0; j < len; j++) { if (gelf_getsym(d, j, &sym) != &sym) { warnx("gelf_getsym failed: %s", elf_errmsg(-1)); continue; @@ -3353,7 +3379,7 @@ dump_symtabs(struct readelf *re) Elf_Data *d; struct section *s; uint64_t dyn_off; - int elferr, i; + int elferr, i, len; /* * If -D is specified, only dump the symbol table specified by @@ -3378,8 +3404,10 @@ dump_symtabs(struct readelf *re) } if (d->d_size <= 0) return; + if (!get_ent_count(s, &len)) + return; - for (i = 0; (uint64_t)i < s->sz / s->entsize; i++) { + for (i = 0; i < len; i++) { if (gelf_getdyn(d, i, &dyn) != &dyn) { warnx("gelf_getdyn failed: %s", elf_errmsg(-1)); continue; @@ -3567,7 +3595,8 @@ dump_gnu_hash(struct readelf *re, struct maskwords = buf[2]; buf += 4; ds = &re->sl[s->link]; - dynsymcount = ds->sz / ds->entsize; + if (!get_ent_count(ds, &dynsymcount)) + return; nchain = dynsymcount - symndx; if (d->d_size != 4 * sizeof(uint32_t) + maskwords * (re->ec == ELFCLASS32 ? sizeof(uint32_t) : sizeof(uint64_t)) + @@ -3996,7 +4025,7 @@ dump_liblist(struct readelf *re) char tbuf[20]; Elf_Data *d; Elf_Lib *lib; - int i, j, k, elferr, first; + int i, j, k, elferr, first, len; for (i = 0; (size_t) i < re->shnum; i++) { s = &re->sl[i]; @@ -4013,8 +4042,10 @@ dump_liblist(struct readelf *re) if (d->d_size <= 0) continue; lib = d->d_buf; + if (!get_ent_count(s, &len)) + continue; printf("\nLibrary list section '%s' ", s->name); - printf("contains %ju entries:\n", s->sz / s->entsize); + printf("contains %d entries:\n", len); printf("%12s%24s%18s%10s%6s\n", "Library", "Time Stamp", "Checksum", "Version", "Flags"); for (j = 0; (uint64_t) j < s->sz / s->entsize; j++) { @@ -4399,7 +4430,7 @@ static void dump_mips_reginfo(struct readelf *re, struct section *s) { Elf_Data *d; - int elferr; + int elferr, len; (void) elf_errno(); if ((d = elf_rawdata(s->scn, NULL)) == NULL) { @@ -4411,9 +4442,10 @@ dump_mips_reginfo(struct readelf *re, st } if (d->d_size <= 0) return; + if (!get_ent_count(s, &len)) + return; - printf("\nSection '%s' contains %ju entries:\n", s->name, - s->sz / s->entsize); + printf("\nSection '%s' contains %d entries:\n", s->name, len); dump_mips_odk_reginfo(re, d->d_buf, d->d_size); }