Index: contrib/elftoolchain/readelf/readelf.c =================================================================== --- contrib/elftoolchain/readelf/readelf.c +++ contrib/elftoolchain/readelf/readelf.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -314,6 +315,7 @@ 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); @@ -2900,6 +2902,24 @@ #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) { @@ -2928,8 +2948,8 @@ /* 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", @@ -3175,7 +3195,9 @@ 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)); @@ -3231,7 +3253,9 @@ 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)); @@ -3296,7 +3320,7 @@ 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; @@ -3309,12 +3333,14 @@ } 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; @@ -3352,7 +3378,7 @@ 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 @@ -3377,8 +3403,10 @@ } 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; @@ -3566,7 +3594,8 @@ 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)) + @@ -3995,7 +4024,7 @@ 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]; @@ -4012,8 +4041,10 @@ 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++) { @@ -4398,7 +4429,7 @@ 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) { @@ -4410,9 +4441,10 @@ } 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); } Index: readelf/readelf.c =================================================================== --- readelf/readelf.c +++ readelf/readelf.c @@ -2924,6 +2924,10 @@ /* Determine the actual number of table entries. */ nentries = 0; + if (s->entsize == 0) { + warnx("Invalid dynamic section sh_entsize"); + return; + } jmax = (int) (s->sz / s->entsize); for (j = 0; j < jmax; j++) { @@ -3171,6 +3175,10 @@ else printf("%-12s %-12s %-19s %-16s %s\n", REL_HDR); } + if (s->entsize == 0) { + warnx("Invalid sh_entsize"); + return; + } len = d->d_size / s->entsize; for (i = 0; i < len; i++) { if (gelf_getrel(d, i, &r) != &r) { @@ -3227,6 +3235,10 @@ else printf("%-12s %-12s %-19s %-16s %s\n", RELA_HDR); } + if (s->entsize == 0) { + warnx("Invalid sh_entsize"); + return; + } len = d->d_size / s->entsize; for (i = 0; i < len; i++) { if (gelf_getrela(d, i, &r) != &r) { @@ -3305,6 +3317,10 @@ } if (d->d_size <= 0) return; + if (s->entsize == 0) { + warnx("Invalid symbol table sh_entsize"); + return; + } printf("Symbol table (%s)", s->name); printf(" contains %ju entries:\n", s->sz / s->entsize); printf("%7s%9s%14s%5s%8s%6s%9s%5s\n", "Num:", "Value", "Size", "Type", @@ -3373,6 +3389,10 @@ } if (d->d_size <= 0) return; + if (s->entsize == 0) { + warnx("Invalid dynamic section sh_entsize"); + return; + } for (i = 0; (uint64_t)i < s->sz / s->entsize; i++) { if (gelf_getdyn(d, i, &dyn) != &dyn) { @@ -3562,6 +3582,10 @@ maskwords = buf[2]; buf += 4; ds = &re->sl[s->link]; + if (ds->entsize == 0) { + warnx("Invalid .gnu.hash sh_entsize"); + return; + } dynsymcount = ds->sz / ds->entsize; nchain = dynsymcount - symndx; if (d->d_size != 4 * sizeof(uint32_t) + maskwords * @@ -4009,6 +4033,10 @@ continue; lib = d->d_buf; printf("\nLibrary list section '%s' ", s->name); + if (s->entsize == 0) { + warnx("Invalid sh_entsize"); + continue; + } printf("contains %ju entries:\n", s->sz / s->entsize); printf("%12s%24s%18s%10s%6s\n", "Library", "Time Stamp", "Checksum", "Version", "Flags"); @@ -4351,6 +4379,10 @@ } if (d->d_size <= 0) return; + if (s->entsize == 0) { + warnx("Invalid MIPS reginfo sh_entsize"); + return; + } printf("\nSection '%s' contains %ju entries:\n", s->name, s->sz / s->entsize);