diff options
Diffstat (limited to 'src/readelf.c')
| -rw-r--r-- | src/readelf.c | 305 |
1 files changed, 194 insertions, 111 deletions
diff --git a/src/readelf.c b/src/readelf.c index 3df0836d7029e..db0b35a506a71 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -27,7 +27,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: readelf.c,v 1.141 2018/04/12 16:50:52 christos Exp $") +FILE_RCSID("@(#)$File: readelf.c,v 1.144 2018/07/08 23:37:33 christos Exp $") #endif #ifdef BUILTIN_ELF @@ -62,13 +62,12 @@ private uint64_t getu64(int, uint64_t); #define MAX_PHNUM 128 #define MAX_SHNUM 32768 -#define SIZE_UNKNOWN ((off_t)-1) +#define SIZE_UNKNOWN CAST(off_t, -1) private int toomany(struct magic_set *ms, const char *name, uint16_t num) { - if (file_printf(ms, ", too many %s (%u)", name, num - ) == -1) + if (file_printf(ms, ", too many %s (%u)", name, num) == -1) return -1; return 0; } @@ -143,54 +142,55 @@ getu64(int swap, uint64_t value) #define elf_getu64(swap, value) getu64(swap, value) #define xsh_addr (clazz == ELFCLASS32 \ - ? (void *)&sh32 \ - : (void *)&sh64) + ? CAST(void *, &sh32) \ + : CAST(void *, &sh64)) #define xsh_sizeof (clazz == ELFCLASS32 \ ? sizeof(sh32) \ : sizeof(sh64)) -#define xsh_size (size_t)(clazz == ELFCLASS32 \ +#define xsh_size CAST(size_t, (clazz == ELFCLASS32 \ ? elf_getu32(swap, sh32.sh_size) \ - : elf_getu64(swap, sh64.sh_size)) -#define xsh_offset (off_t)(clazz == ELFCLASS32 \ + : elf_getu64(swap, sh64.sh_size))) +#define xsh_offset CAST(off_t, (clazz == ELFCLASS32 \ ? elf_getu32(swap, sh32.sh_offset) \ - : elf_getu64(swap, sh64.sh_offset)) + : elf_getu64(swap, sh64.sh_offset))) #define xsh_type (clazz == ELFCLASS32 \ ? elf_getu32(swap, sh32.sh_type) \ : elf_getu32(swap, sh64.sh_type)) #define xsh_name (clazz == ELFCLASS32 \ ? elf_getu32(swap, sh32.sh_name) \ : elf_getu32(swap, sh64.sh_name)) + #define xph_addr (clazz == ELFCLASS32 \ - ? (void *) &ph32 \ - : (void *) &ph64) + ? CAST(void *, &ph32) \ + : CAST(void *, &ph64)) #define xph_sizeof (clazz == ELFCLASS32 \ ? sizeof(ph32) \ : sizeof(ph64)) #define xph_type (clazz == ELFCLASS32 \ ? elf_getu32(swap, ph32.p_type) \ : elf_getu32(swap, ph64.p_type)) -#define xph_offset (off_t)(clazz == ELFCLASS32 \ +#define xph_offset CAST(off_t, (clazz == ELFCLASS32 \ ? elf_getu32(swap, ph32.p_offset) \ - : elf_getu64(swap, ph64.p_offset)) -#define xph_align (size_t)((clazz == ELFCLASS32 \ - ? (off_t) (ph32.p_align ? \ - elf_getu32(swap, ph32.p_align) : 4) \ - : (off_t) (ph64.p_align ? \ - elf_getu64(swap, ph64.p_align) : 4))) -#define xph_vaddr (size_t)((clazz == ELFCLASS32 \ - ? (off_t) (ph32.p_vaddr ? \ - elf_getu32(swap, ph32.p_vaddr) : 4) \ - : (off_t) (ph64.p_vaddr ? \ - elf_getu64(swap, ph64.p_vaddr) : 4))) -#define xph_filesz (size_t)((clazz == ELFCLASS32 \ + : elf_getu64(swap, ph64.p_offset))) +#define xph_align CAST(size_t, (clazz == ELFCLASS32 \ + ? CAST(off_t, (ph32.p_align ? \ + elf_getu32(swap, ph32.p_align) : 4))\ + : CAST(off_t, (ph64.p_align ? \ + elf_getu64(swap, ph64.p_align) : 4)))) +#define xph_vaddr CAST(size_t, (clazz == ELFCLASS32 \ + ? CAST(off_t, (ph32.p_vaddr ? \ + elf_getu32(swap, ph32.p_vaddr) : 4))\ + : CAST(off_t, (ph64.p_vaddr ? \ + elf_getu64(swap, ph64.p_vaddr) : 4)))) +#define xph_filesz CAST(size_t, (clazz == ELFCLASS32 \ ? elf_getu32(swap, ph32.p_filesz) \ : elf_getu64(swap, ph64.p_filesz))) -#define xnh_addr (clazz == ELFCLASS32 \ - ? (void *)&nh32 \ - : (void *)&nh64) -#define xph_memsz (size_t)((clazz == ELFCLASS32 \ +#define xph_memsz CAST(size_t, ((clazz == ELFCLASS32 \ ? elf_getu32(swap, ph32.p_memsz) \ - : elf_getu64(swap, ph64.p_memsz))) + : elf_getu64(swap, ph64.p_memsz)))) +#define xnh_addr (clazz == ELFCLASS32 \ + ? CAST(void *, &nh32) \ + : CAST(void *, &nh64)) #define xnh_sizeof (clazz == ELFCLASS32 \ ? sizeof(nh32) \ : sizeof(nh64)) @@ -203,24 +203,36 @@ getu64(int swap, uint64_t value) #define xnh_descsz (clazz == ELFCLASS32 \ ? elf_getu32(swap, nh32.n_descsz) \ : elf_getu32(swap, nh64.n_descsz)) -#define prpsoffsets(i) (clazz == ELFCLASS32 \ - ? prpsoffsets32[i] \ - : prpsoffsets64[i]) + +#define xdh_addr (clazz == ELFCLASS32 \ + ? CAST(void *, &dh32) \ + : CAST(void *, &dh64)) +#define xdh_sizeof (clazz == ELFCLASS32 \ + ? sizeof(dh32) \ + : sizeof(dh64)) +#define xdh_tag (clazz == ELFCLASS32 \ + ? elf_getu32(swap, dh32.d_tag) \ + : elf_getu64(swap, dh64.d_tag)) +#define xdh_val (clazz == ELFCLASS32 \ + ? elf_getu32(swap, dh32.d_un.d_val) \ + : elf_getu64(swap, dh64.d_un.d_val)) + #define xcap_addr (clazz == ELFCLASS32 \ - ? (void *)&cap32 \ - : (void *)&cap64) + ? CAST(void *, &cap32) \ + : CAST(void *, &cap64)) #define xcap_sizeof (clazz == ELFCLASS32 \ - ? sizeof cap32 \ - : sizeof cap64) + ? sizeof(cap32) \ + : sizeof(cap64)) #define xcap_tag (clazz == ELFCLASS32 \ ? elf_getu32(swap, cap32.c_tag) \ : elf_getu64(swap, cap64.c_tag)) #define xcap_val (clazz == ELFCLASS32 \ ? elf_getu32(swap, cap32.c_un.c_val) \ : elf_getu64(swap, cap64.c_un.c_val)) + #define xauxv_addr (clazz == ELFCLASS32 \ - ? (void *)&auxv32 \ - : (void *)&auxv64) + ? CAST(void *, &auxv32) \ + : CAST(void *, &auxv64)) #define xauxv_sizeof (clazz == ELFCLASS32 \ ? sizeof(auxv32) \ : sizeof(auxv64)) @@ -231,6 +243,10 @@ getu64(int swap, uint64_t value) ? elf_getu32(swap, auxv32.a_v) \ : elf_getu64(swap, auxv64.a_v)) +#define prpsoffsets(i) (clazz == ELFCLASS32 \ + ? prpsoffsets32[i] \ + : prpsoffsets64[i]) + #ifdef ELFCORE /* * Try larger offsets first to avoid false matches @@ -266,8 +282,8 @@ static const size_t prpsoffsets64[] = { 16, /* FreeBSD, 64-bit */ }; -#define NOFFSETS32 (sizeof prpsoffsets32 / sizeof prpsoffsets32[0]) -#define NOFFSETS64 (sizeof prpsoffsets64 / sizeof prpsoffsets64[0]) +#define NOFFSETS32 (sizeof(prpsoffsets32) / sizeof(prpsoffsets32[0])) +#define NOFFSETS64 (sizeof(prpsoffsets64) / sizeof(prpsoffsets64[0])) #define NOFFSETS (clazz == ELFCLASS32 ? NOFFSETS32 : NOFFSETS64) @@ -346,7 +362,8 @@ dophn_core(struct magic_set *ms, int clazz, int swap, int fd, off_t off, * Loop through all the program headers. */ for ( ; num; num--) { - if (pread(fd, xph_addr, xph_sizeof, off) < (ssize_t)xph_sizeof) { + if (pread(fd, xph_addr, xph_sizeof, off) < + CAST(ssize_t, xph_sizeof)) { file_badread(ms); return -1; } @@ -389,7 +406,7 @@ static void do_note_netbsd_version(struct magic_set *ms, int swap, void *v) { uint32_t desc; - (void)memcpy(&desc, v, sizeof(desc)); + memcpy(&desc, v, sizeof(desc)); desc = elf_getu32(swap, desc); if (file_printf(ms, ", for NetBSD") == -1) @@ -435,7 +452,7 @@ do_note_freebsd_version(struct magic_set *ms, int swap, void *v) { uint32_t desc; - (void)memcpy(&desc, v, sizeof(desc)); + memcpy(&desc, v, sizeof(desc)); desc = elf_getu32(swap, desc); if (file_printf(ms, ", for FreeBSD") == -1) return; @@ -533,12 +550,19 @@ do_bid_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, } if (file_printf(ms, ", BuildID[%s]=", btype) == -1) return 1; - (void)memcpy(desc, &nbuf[doff], descsz); + memcpy(desc, &nbuf[doff], descsz); for (i = 0; i < descsz; i++) if (file_printf(ms, "%02x", desc[i]) == -1) return 1; return 1; } + if (namesz == 4 && strcmp((char *)&nbuf[noff], "Go") == 0 && + type == NT_GO_BUILD_ID && descsz < 128) { + if (file_printf(ms, ", Go BuildID=%s", + (char *)&nbuf[doff]) == -1) + return 1; + return 1; + } return 0; } @@ -557,7 +581,7 @@ do_os_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 && type == NT_GNU_VERSION && descsz == 16) { uint32_t desc[4]; - (void)memcpy(desc, &nbuf[doff], sizeof(desc)); + memcpy(desc, &nbuf[doff], sizeof(desc)); *flags |= FLAGS_DID_OS_NOTE; if (file_printf(ms, ", for GNU/") == -1) @@ -624,7 +648,7 @@ do_os_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, *flags |= FLAGS_DID_OS_NOTE; if (file_printf(ms, ", for DragonFly") == -1) return 1; - (void)memcpy(&desc, &nbuf[doff], sizeof(desc)); + memcpy(&desc, &nbuf[doff], sizeof(desc)); desc = elf_getu32(swap, desc); if (file_printf(ms, " %d.%d.%d", desc / 100000, desc / 10000 % 10, desc % 10000) == -1) @@ -654,7 +678,7 @@ do_pax_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, int did = 0; *flags |= FLAGS_DID_NETBSD_PAX; - (void)memcpy(&desc, &nbuf[doff], sizeof(desc)); + memcpy(&desc, &nbuf[doff], sizeof(desc)); desc = elf_getu32(swap, desc); if (desc && file_printf(ms, ", PaX: ") == -1) @@ -825,7 +849,8 @@ do_core_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, cname = (unsigned char *) &nbuf[doff + prpsoffsets(i)]; - for (cp = cname; *cp && isprint(*cp); cp++) + for (cp = cname; cp < nbuf + size && *cp + && isprint(*cp); cp++) continue; /* * Linux apparently appends a space at the end @@ -953,7 +978,7 @@ do_auxv_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, nval = 0; for (size_t off = 0; off + elsize <= descsz; off += elsize) { - (void)memcpy(xauxv_addr, &nbuf[doff + off], xauxv_sizeof); + memcpy(xauxv_addr, &nbuf[doff + off], xauxv_sizeof); /* Limit processing to 50 vector entries to prevent DoS */ if (nval++ >= 50) { file_error(ms, 0, "Too many ELF Auxv elements"); @@ -1018,6 +1043,38 @@ do_auxv_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, } private size_t +dodynamic(struct magic_set *ms, void *vbuf, size_t offset, size_t size, + int clazz, int swap) +{ + Elf32_Dyn dh32; + Elf64_Dyn dh64; + unsigned char *dbuf = CAST(unsigned char *, vbuf); + + if (xdh_sizeof + offset > size) { + /* + * We're out of note headers. + */ + return xdh_sizeof + offset; + } + + memcpy(xdh_addr, &dbuf[offset], xdh_sizeof); + offset += xdh_sizeof; + + switch (xdh_tag) { + case DT_FLAGS_1: + if (xdh_val == DF_1_PIE) + ms->mode |= 0111; + else + ms->mode &= ~0111; + break; + default: + break; + } + return offset; +} + + +private size_t donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size, int clazz, int swap, size_t align, int *flags, uint16_t *notecount, int fd, off_t ph_off, int ph_num, off_t fsize) @@ -1039,7 +1096,7 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size, return xnh_sizeof + offset; } - (void)memcpy(xnh_addr, &nbuf[offset], xnh_sizeof); + memcpy(xnh_addr, &nbuf[offset], xnh_sizeof); offset += xnh_sizeof; namesz = xnh_namesz; @@ -1053,14 +1110,14 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size, } if (namesz & 0x80000000) { - (void)file_printf(ms, ", bad note name size %#lx", - (unsigned long)namesz); + file_printf(ms, ", bad note name size %#lx", + CAST(unsigned long, namesz)); return 0; } if (descsz & 0x80000000) { - (void)file_printf(ms, ", bad note description size %#lx", - (unsigned long)descsz); + file_printf(ms, ", bad note description size %#lx", + CAST(unsigned long, descsz)); return 0; } @@ -1114,35 +1171,25 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size, return offset; } - if (namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0) { + if (namesz == 7 && strcmp(CAST(char *, &nbuf[noff]), "NetBSD") == 0) { + int descw, flag; + const char *str, *tag; if (descsz > 100) descsz = 100; switch (xnh_type) { case NT_NETBSD_VERSION: return offset; case NT_NETBSD_MARCH: - if (*flags & FLAGS_DID_NETBSD_MARCH) - return offset; - *flags |= FLAGS_DID_NETBSD_MARCH; - if (file_printf(ms, ", compiled for: %.*s", - (int)descsz, (const char *)&nbuf[doff]) == -1) - return offset; + flag = FLAGS_DID_NETBSD_MARCH; + tag = "compiled for"; break; case NT_NETBSD_CMODEL: - if (*flags & FLAGS_DID_NETBSD_CMODEL) - return offset; - *flags |= FLAGS_DID_NETBSD_CMODEL; - if (file_printf(ms, ", compiler model: %.*s", - (int)descsz, (const char *)&nbuf[doff]) == -1) - return offset; + flag = FLAGS_DID_NETBSD_CMODEL; + tag = "compiler model"; break; case NT_NETBSD_EMULATION: - if (*flags & FLAGS_DID_NETBSD_EMULATION) - return offset; - *flags |= FLAGS_DID_NETBSD_EMULATION; - if (file_printf(ms, ", emulation: %.*s", - (int)descsz, (const char *)&nbuf[doff]) == -1) - return offset; + flag = FLAGS_DID_NETBSD_EMULATION; + tag = "emulation:"; break; default: if (*flags & FLAGS_DID_NETBSD_UNKNOWN) @@ -1150,8 +1197,15 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size, *flags |= FLAGS_DID_NETBSD_UNKNOWN; if (file_printf(ms, ", note=%u", xnh_type) == -1) return offset; - break; + return offset; } + + if (*flags & flag) + return offset; + str = CAST(const char *, &nbuf[doff]); + descw = CAST(int, descsz); + *flags |= flag; + file_printf(ms, ", %s: %.*s", tag, descw, str); return offset; } @@ -1232,7 +1286,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, /* Read offset of name section to be able to read section names later */ if (pread(fd, xsh_addr, xsh_sizeof, CAST(off_t, (off + size * strtab))) - < (ssize_t)xsh_sizeof) { + < CAST(ssize_t, xsh_sizeof)) { if (file_printf(ms, ", missing section headers") == -1) return -1; return 0; @@ -1241,7 +1295,8 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, for ( ; num; num--) { /* Read the name of this section. */ - if ((namesize = pread(fd, name, sizeof(name) - 1, name_off + xsh_name)) == -1) { + if ((namesize = pread(fd, name, sizeof(name) - 1, + name_off + xsh_name)) == -1) { file_badread(ms); return -1; } @@ -1251,7 +1306,8 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, stripped = 0; } - if (pread(fd, xsh_addr, xsh_sizeof, off) < (ssize_t)xsh_sizeof) { + if (pread(fd, xsh_addr, xsh_sizeof, off) < + CAST(ssize_t, xsh_sizeof)) { file_badread(ms); return -1; } @@ -1277,14 +1333,15 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, /* Things we can determine when we seek */ switch (xsh_type) { case SHT_NOTE: - if ((uintmax_t)(xsh_size + xsh_offset) > - (uintmax_t)fsize) { + if (CAST(uintmax_t, (xsh_size + xsh_offset)) > + CAST(uintmax_t, fsize)) { if (file_printf(ms, ", note offset/size %#" INTMAX_T_FORMAT "x+%#" INTMAX_T_FORMAT "x exceeds" " file size %#" INTMAX_T_FORMAT "x", - (uintmax_t)xsh_offset, (uintmax_t)xsh_size, - (uintmax_t)fsize) == -1) + CAST(uintmax_t, xsh_offset), + CAST(uintmax_t, xsh_size), + CAST(uintmax_t, fsize)) == -1) return -1; return 0; } @@ -1294,7 +1351,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, return -1; } if (pread(fd, nbuf, xsh_size, xsh_offset) < - (ssize_t)xsh_size) { + CAST(ssize_t, xsh_size)) { file_badread(ms); free(nbuf); return -1; @@ -1302,9 +1359,9 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, noff = 0; for (;;) { - if (noff >= (off_t)xsh_size) + if (noff >= CAST(off_t, xsh_size)) break; - noff = donote(ms, nbuf, (size_t)noff, + noff = donote(ms, nbuf, CAST(size_t, noff), xsh_size, clazz, swap, 4, flags, notecount, fd, 0, 0, 0); if (noff == 0) @@ -1326,7 +1383,8 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, if (nbadcap > 5) break; - if (lseek(fd, xsh_offset, SEEK_SET) == (off_t)-1) { + if (lseek(fd, xsh_offset, SEEK_SET) + == CAST(off_t, -1)) { file_badseek(ms); return -1; } @@ -1335,11 +1393,12 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, Elf32_Cap cap32; Elf64_Cap cap64; char cbuf[/*CONSTCOND*/ - MAX(sizeof cap32, sizeof cap64)]; - if ((coff += xcap_sizeof) > (off_t)xsh_size) + MAX(sizeof(cap32), sizeof(cap64))]; + if ((coff += xcap_sizeof) > + CAST(off_t, xsh_size)) break; - if (read(fd, cbuf, (size_t)xcap_sizeof) != - (ssize_t)xcap_sizeof) { + if (read(fd, cbuf, CAST(size_t, xcap_sizeof)) != + CAST(ssize_t, xcap_sizeof)) { file_badread(ms); return -1; } @@ -1373,7 +1432,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, #endif break; } - (void)memcpy(xcap_addr, cbuf, xcap_sizeof); + memcpy(xcap_addr, cbuf, xcap_sizeof); switch (xcap_tag) { case CA_SUNW_NULL: break; @@ -1388,8 +1447,9 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, ", with unknown capability " "%#" INT64_T_FORMAT "x = %#" INT64_T_FORMAT "x", - (unsigned long long)xcap_tag, - (unsigned long long)xcap_val) == -1) + CAST(unsigned long long, xcap_tag), + CAST(unsigned long long, xcap_val)) + == -1) return -1; if (nbadcap++ > 2) coff = xsh_size; @@ -1442,12 +1502,12 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, if (file_printf(ms, " unknown hardware capability %#" INT64_T_FORMAT "x", - (unsigned long long)cap_hw1) == -1) + CAST(unsigned long long, cap_hw1)) == -1) return -1; } else { if (file_printf(ms, " hardware capability %#" INT64_T_FORMAT "x", - (unsigned long long)cap_hw1) == -1) + CAST(unsigned long long, cap_hw1)) == -1) return -1; } } @@ -1464,7 +1524,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, if (file_printf(ms, ", with unknown software capability %#" INT64_T_FORMAT "x", - (unsigned long long)cap_sf1) == -1) + CAST(unsigned long long, cap_sf1)) == -1) return -1; } return 0; @@ -1483,9 +1543,9 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, Elf32_Phdr ph32; Elf64_Phdr ph64; const char *linking_style = "statically"; - const char *interp = ""; unsigned char nbuf[BUFSIZ]; char ibuf[BUFSIZ]; + char interp[BUFSIZ]; ssize_t bufsize; size_t offset, align, len; @@ -1495,8 +1555,11 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, return 0; } + interp[0] = '\0'; for ( ; num; num--) { - if (pread(fd, xph_addr, xph_sizeof, off) < (ssize_t)xph_sizeof) { + int doread; + if (pread(fd, xph_addr, xph_sizeof, off) < + CAST(ssize_t, xph_sizeof)) { file_badread(ms); return -1; } @@ -1509,6 +1572,7 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, switch (xph_type) { case PT_DYNAMIC: linking_style = "dynamically"; + doread = 1; break; case PT_NOTE: if (sh_num) /* Did this through section headers */ @@ -1517,21 +1581,16 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, align < 4) { if (file_printf(ms, ", invalid note alignment %#lx", - (unsigned long)align) == -1) + CAST(unsigned long, align)) == -1) return -1; align = 4; } /*FALLTHROUGH*/ case PT_INTERP: - len = xph_filesz < sizeof(nbuf) ? xph_filesz - : sizeof(nbuf); - bufsize = pread(fd, nbuf, len, xph_offset); - if (bufsize == -1) { - file_badread(ms); - return -1; - } + doread = 1; break; default: + doread = 0; if (fsize != SIZE_UNKNOWN && xph_offset > fsize) { /* Maybe warn here? */ continue; @@ -1539,14 +1598,37 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, break; } + if (doread) { + len = xph_filesz < sizeof(nbuf) ? xph_filesz + : sizeof(nbuf); + bufsize = pread(fd, nbuf, len, xph_offset); + if (bufsize == -1) { + file_badread(ms); + return -1; + } + } else + len = 0; + /* Things we can determine when we seek */ switch (xph_type) { + case PT_DYNAMIC: + offset = 0; + for (;;) { + if (offset >= (size_t)bufsize) + break; + offset = dodynamic(ms, nbuf, offset, + CAST(size_t, bufsize), clazz, swap); + if (offset == 0) + break; + } + break; + case PT_INTERP: if (bufsize && nbuf[0]) { nbuf[bufsize - 1] = '\0'; - interp = (const char *)nbuf; + memcpy(interp, nbuf, bufsize); } else - interp = "*empty*"; + strlcpy(interp, "*empty*", sizeof(interp)); break; case PT_NOTE: /* @@ -1558,7 +1640,7 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, if (offset >= (size_t)bufsize) break; offset = donote(ms, nbuf, offset, - (size_t)bufsize, clazz, swap, align, + CAST(size_t, bufsize), clazz, swap, align, flags, notecount, fd, 0, 0, 0); if (offset == 0) break; @@ -1587,7 +1669,7 @@ file_tryelf(struct magic_set *ms, const struct buffer *b) size_t nbytes = b->flen; union { int32_t l; - char c[sizeof (int32_t)]; + char c[sizeof(int32_t)]; } u; int clazz; int swap; @@ -1615,7 +1697,8 @@ file_tryelf(struct magic_set *ms, const struct buffer *b) /* * If we cannot seek, it must be a pipe, socket or fifo. */ - if((lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) && (errno == ESPIPE)) + if((lseek(fd, CAST(off_t, 0), SEEK_SET) == CAST(off_t, -1)) + && (errno == ESPIPE)) fd = file_pipe2file(ms, fd, buf, nbytes); if (fstat(fd, &st) == -1) { |
