diff options
Diffstat (limited to 'contrib/file/src')
-rw-r--r-- | contrib/file/src/Makefile.in | 8 | ||||
-rw-r--r-- | contrib/file/src/apprentice.c | 269 | ||||
-rw-r--r-- | contrib/file/src/compress.c | 17 | ||||
-rw-r--r-- | contrib/file/src/elfclass.h | 16 | ||||
-rw-r--r-- | contrib/file/src/file.c | 3 | ||||
-rw-r--r-- | contrib/file/src/file.h | 8 | ||||
-rw-r--r-- | contrib/file/src/file_opts.h | 7 | ||||
-rw-r--r-- | contrib/file/src/funcs.c | 27 | ||||
-rw-r--r-- | contrib/file/src/getline.c | 2 | ||||
-rw-r--r-- | contrib/file/src/magic.c | 8 | ||||
-rw-r--r-- | contrib/file/src/magic.h | 1 | ||||
-rw-r--r-- | contrib/file/src/magic.h.in | 1 | ||||
-rw-r--r-- | contrib/file/src/readelf.c | 510 | ||||
-rw-r--r-- | contrib/file/src/softmagic.c | 41 |
14 files changed, 549 insertions, 369 deletions
diff --git a/contrib/file/src/Makefile.in b/contrib/file/src/Makefile.in index f1779f9..41cb9f5 100644 --- a/contrib/file/src/Makefile.in +++ b/contrib/file/src/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. +# Makefile.in generated by automake 1.14 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. @@ -81,9 +81,9 @@ build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = file$(EXEEXT) subdir = src -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am strcasestr.c \ - pread.c strlcpy.c vasprintf.c getopt_long.c asctime_r.c \ - strlcat.c ctime_r.c getline.c asprintf.c fmtcheck.c \ +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am ctime_r.c \ + vasprintf.c asctime_r.c asprintf.c strcasestr.c pread.c \ + getline.c strlcpy.c strlcat.c fmtcheck.c getopt_long.c \ $(top_srcdir)/depcomp $(include_HEADERS) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ diff --git a/contrib/file/src/apprentice.c b/contrib/file/src/apprentice.c index cfea6be..47b4c87 100644 --- a/contrib/file/src/apprentice.c +++ b/contrib/file/src/apprentice.c @@ -32,7 +32,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: apprentice.c,v 1.227 2014/11/28 02:46:39 christos Exp $") +FILE_RCSID("@(#)$File: apprentice.c,v 1.229 2015/01/01 17:07:34 christos Exp $") #endif /* lint */ #include "magic.h" @@ -528,6 +528,7 @@ file_ms_alloc(int flags) ms->name_max = FILE_NAME_MAX; ms->elf_shnum_max = FILE_ELF_SHNUM_MAX; ms->elf_phnum_max = FILE_ELF_PHNUM_MAX; + ms->elf_notes_max = FILE_ELF_NOTES_MAX; return ms; free: free(ms); @@ -1604,6 +1605,145 @@ check_cond(struct magic_set *ms, int cond, uint32_t cont_level) } #endif /* ENABLE_CONDITIONALS */ +private int +parse_indirect_modifier(struct magic_set *ms, struct magic *m, const char **lp) +{ + const char *l = *lp; + + while (!isspace((unsigned char)*++l)) + switch (*l) { + case CHAR_INDIRECT_RELATIVE: + m->str_flags |= INDIRECT_RELATIVE; + break; + default: + if (ms->flags & MAGIC_CHECK) + file_magwarn(ms, "indirect modifier `%c' " + "invalid", *l); + *lp = l; + return -1; + } + *lp = l; + return 0; +} + +private void +parse_op_modifier(struct magic_set *ms, struct magic *m, const char **lp, + int op) +{ + const char *l = *lp; + char *t; + uint64_t val; + + ++l; + m->mask_op |= op; + val = (uint64_t)strtoull(l, &t, 0); + l = t; + m->num_mask = file_signextend(ms, m, val); + eatsize(&l); + *lp = l; +} + +private int +parse_string_modifier(struct magic_set *ms, struct magic *m, const char **lp) +{ + const char *l = *lp; + char *t; + int have_range = 0; + + while (!isspace((unsigned char)*++l)) { + switch (*l) { + case '0': case '1': case '2': + case '3': case '4': case '5': + case '6': case '7': case '8': + case '9': + if (have_range && (ms->flags & MAGIC_CHECK)) + file_magwarn(ms, "multiple ranges"); + have_range = 1; + m->str_range = CAST(uint32_t, strtoul(l, &t, 0)); + if (m->str_range == 0) + file_magwarn(ms, "zero range"); + l = t - 1; + break; + case CHAR_COMPACT_WHITESPACE: + m->str_flags |= STRING_COMPACT_WHITESPACE; + break; + case CHAR_COMPACT_OPTIONAL_WHITESPACE: + m->str_flags |= STRING_COMPACT_OPTIONAL_WHITESPACE; + break; + case CHAR_IGNORE_LOWERCASE: + m->str_flags |= STRING_IGNORE_LOWERCASE; + break; + case CHAR_IGNORE_UPPERCASE: + m->str_flags |= STRING_IGNORE_UPPERCASE; + break; + case CHAR_REGEX_OFFSET_START: + m->str_flags |= REGEX_OFFSET_START; + break; + case CHAR_BINTEST: + m->str_flags |= STRING_BINTEST; + break; + case CHAR_TEXTTEST: + m->str_flags |= STRING_TEXTTEST; + break; + case CHAR_TRIM: + m->str_flags |= STRING_TRIM; + break; + case CHAR_PSTRING_1_LE: +#define SET_LENGTH(a) m->str_flags = (m->str_flags & ~PSTRING_LEN) | (a) + if (m->type != FILE_PSTRING) + goto bad; + SET_LENGTH(PSTRING_1_LE); + break; + case CHAR_PSTRING_2_BE: + if (m->type != FILE_PSTRING) + goto bad; + SET_LENGTH(PSTRING_2_BE); + break; + case CHAR_PSTRING_2_LE: + if (m->type != FILE_PSTRING) + goto bad; + SET_LENGTH(PSTRING_2_LE); + break; + case CHAR_PSTRING_4_BE: + if (m->type != FILE_PSTRING) + goto bad; + SET_LENGTH(PSTRING_4_BE); + break; + case CHAR_PSTRING_4_LE: + switch (m->type) { + case FILE_PSTRING: + case FILE_REGEX: + break; + default: + goto bad; + } + SET_LENGTH(PSTRING_4_LE); + break; + case CHAR_PSTRING_LENGTH_INCLUDES_ITSELF: + if (m->type != FILE_PSTRING) + goto bad; + m->str_flags |= PSTRING_LENGTH_INCLUDES_ITSELF; + break; + default: + bad: + if (ms->flags & MAGIC_CHECK) + file_magwarn(ms, "string modifier `%c' " + "invalid", *l); + goto out; + } + /* allow multiple '/' for readability */ + if (l[1] == '/' && !isspace((unsigned char)l[2])) + l++; + } + if (string_modifier_check(ms, m) == -1) + goto out; + *lp = l; + return 0; +out: + *lp = l; + return -1; +} + /* * parse one line from magic file, put into magic[index++] if valid */ @@ -1873,118 +2013,27 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line, m->str_range = 0; m->str_flags = m->type == FILE_PSTRING ? PSTRING_1_LE : 0; if ((op = get_op(*l)) != -1) { - if (!IS_STRING(m->type)) { - uint64_t val; - ++l; - m->mask_op |= op; - val = (uint64_t)strtoull(l, &t, 0); - l = t; - m->num_mask = file_signextend(ms, m, val); - eatsize(&l); - } - else if (op == FILE_OPDIVIDE) { - int have_range = 0; - while (!isspace((unsigned char)*++l)) { - switch (*l) { - case '0': case '1': case '2': - case '3': case '4': case '5': - case '6': case '7': case '8': - case '9': - if (have_range && - (ms->flags & MAGIC_CHECK)) - file_magwarn(ms, - "multiple ranges"); - have_range = 1; - m->str_range = CAST(uint32_t, - strtoul(l, &t, 0)); - if (m->str_range == 0) - file_magwarn(ms, - "zero range"); - l = t - 1; - break; - case CHAR_COMPACT_WHITESPACE: - m->str_flags |= - STRING_COMPACT_WHITESPACE; - break; - case CHAR_COMPACT_OPTIONAL_WHITESPACE: - m->str_flags |= - STRING_COMPACT_OPTIONAL_WHITESPACE; - break; - case CHAR_IGNORE_LOWERCASE: - m->str_flags |= STRING_IGNORE_LOWERCASE; - break; - case CHAR_IGNORE_UPPERCASE: - m->str_flags |= STRING_IGNORE_UPPERCASE; - break; - case CHAR_REGEX_OFFSET_START: - m->str_flags |= REGEX_OFFSET_START; - break; - case CHAR_BINTEST: - m->str_flags |= STRING_BINTEST; - break; - case CHAR_TEXTTEST: - m->str_flags |= STRING_TEXTTEST; - break; - case CHAR_TRIM: - m->str_flags |= STRING_TRIM; - break; - case CHAR_PSTRING_1_LE: - if (m->type != FILE_PSTRING) - goto bad; - m->str_flags = (m->str_flags & ~PSTRING_LEN) | PSTRING_1_LE; - break; - case CHAR_PSTRING_2_BE: - if (m->type != FILE_PSTRING) - goto bad; - m->str_flags = (m->str_flags & ~PSTRING_LEN) | PSTRING_2_BE; - break; - case CHAR_PSTRING_2_LE: - if (m->type != FILE_PSTRING) - goto bad; - m->str_flags = (m->str_flags & ~PSTRING_LEN) | PSTRING_2_LE; - break; - case CHAR_PSTRING_4_BE: - if (m->type != FILE_PSTRING) - goto bad; - m->str_flags = (m->str_flags & ~PSTRING_LEN) | PSTRING_4_BE; - break; - case CHAR_PSTRING_4_LE: - switch (m->type) { - case FILE_PSTRING: - case FILE_REGEX: - break; - default: - goto bad; - } - m->str_flags = (m->str_flags & ~PSTRING_LEN) | PSTRING_4_LE; - break; - case CHAR_PSTRING_LENGTH_INCLUDES_ITSELF: - if (m->type != FILE_PSTRING) - goto bad; - m->str_flags |= PSTRING_LENGTH_INCLUDES_ITSELF; - break; - default: - bad: - if (ms->flags & MAGIC_CHECK) - file_magwarn(ms, - "string extension `%c' " - "invalid", *l); - return -1; - } - /* allow multiple '/' for readability */ - if (l[1] == '/' && - !isspace((unsigned char)l[2])) - l++; + if (IS_STRING(m->type)) { + int r; + + if (op != FILE_OPDIVIDE) { + if (ms->flags & MAGIC_CHECK) + file_magwarn(ms, + "invalid string/indirect op: " + "`%c'", *t); + return -1; } - if (string_modifier_check(ms, m) == -1) + + if (m->type == FILE_INDIRECT) + r = parse_indirect_modifier(ms, m, &l); + else + r = parse_string_modifier(ms, m, &l); + if (r == -1) return -1; - } - else { - if (ms->flags & MAGIC_CHECK) - file_magwarn(ms, "invalid string op: %c", *t); - return -1; - } + } else + parse_op_modifier(ms, m, &l, op); } + /* * We used to set mask to all 1's here, instead let's just not do * anything if mask = 0 (unless you have a better idea) diff --git a/contrib/file/src/compress.c b/contrib/file/src/compress.c index 4a6f42e..e968bb4 100644 --- a/contrib/file/src/compress.c +++ b/contrib/file/src/compress.c @@ -35,7 +35,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: compress.c,v 1.75 2014/12/04 15:56:46 christos Exp $") +FILE_RCSID("@(#)$File: compress.c,v 1.77 2014/12/12 16:33:01 christos Exp $") #endif #include "magic.h" @@ -45,6 +45,7 @@ FILE_RCSID("@(#)$File: compress.c,v 1.75 2014/12/04 15:56:46 christos Exp $") #endif #include <string.h> #include <errno.h> +#include <signal.h> #if !defined(__MINGW32__) && !defined(WIN32) #include <sys/ioctl.h> #endif @@ -103,10 +104,12 @@ file_zmagic(struct magic_set *ms, int fd, const char *name, size_t i, nsz; int rv = 0; int mime = ms->flags & MAGIC_MIME; + sig_t osigpipe; if ((ms->flags & MAGIC_COMPRESS) == 0) return 0; + osigpipe = signal(SIGPIPE, SIG_IGN); for (i = 0; i < ncompr; i++) { if (nbytes < compr[i].maglen) continue; @@ -133,6 +136,7 @@ file_zmagic(struct magic_set *ms, int fd, const char *name, } } error: + (void)signal(SIGPIPE, osigpipe); free(newbuf); ms->flags |= MAGIC_COMPRESS; return rv; @@ -508,11 +512,16 @@ err: strerror(errno)); #endif n = NODATA; - } else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + } else if (!WIFEXITED(status)) { #ifdef DEBUG - (void)fprintf(stderr, "Child status (0x%x)\n", status); + (void)fprintf(stderr, "Child not exited (0x%x)\n", + status); +#endif + } else if (WEXITSTATUS(status) != 0) { +#ifdef DEBUG + (void)fprintf(stderr, "Child exited (0x%d)\n", + WEXITSTATUS(status)); #endif - n = NODATA; } (void) close(fdin[0]); diff --git a/contrib/file/src/elfclass.h b/contrib/file/src/elfclass.h index e144d11..5360b0b 100644 --- a/contrib/file/src/elfclass.h +++ b/contrib/file/src/elfclass.h @@ -32,17 +32,18 @@ swap = (u.c[sizeof(int32_t) - 1] + 1) != elfhdr.e_ident[EI_DATA]; type = elf_getu16(swap, elfhdr.e_type); + notecount = ms->elf_notes_max; switch (type) { #ifdef ELFCORE case ET_CORE: phnum = elf_getu16(swap, elfhdr.e_phnum); if (phnum > ms->elf_phnum_max) - return toomany(ms, "program", phnum); + return toomany(ms, "program headers", phnum); flags |= FLAGS_IS_CORE; if (dophn_core(ms, clazz, swap, fd, (off_t)elf_getu(swap, elfhdr.e_phoff), phnum, (size_t)elf_getu16(swap, elfhdr.e_phentsize), - fsize, &flags) == -1) + fsize, &flags, ¬ecount) == -1) return -1; break; #endif @@ -57,22 +58,25 @@ if (dophn_exec(ms, clazz, swap, fd, (off_t)elf_getu(swap, elfhdr.e_phoff), phnum, (size_t)elf_getu16(swap, elfhdr.e_phentsize), - fsize, &flags, shnum) == -1) + fsize, shnum, &flags, ¬ecount) == -1) return -1; /*FALLTHROUGH*/ case ET_REL: shnum = elf_getu16(swap, elfhdr.e_shnum); if (shnum > ms->elf_shnum_max) - return toomany(ms, "section", shnum); + return toomany(ms, "section headers", shnum); if (doshn(ms, clazz, swap, fd, (off_t)elf_getu(swap, elfhdr.e_shoff), shnum, (size_t)elf_getu16(swap, elfhdr.e_shentsize), - fsize, &flags, elf_getu16(swap, elfhdr.e_machine), - (int)elf_getu16(swap, elfhdr.e_shstrndx)) == -1) + fsize, elf_getu16(swap, elfhdr.e_machine), + (int)elf_getu16(swap, elfhdr.e_shstrndx), + &flags, ¬ecount) == -1) return -1; break; default: break; } + if (notecount == 0) + return toomany(ms, "notes", ms->elf_notes_max); return 1; diff --git a/contrib/file/src/file.c b/contrib/file/src/file.c index 148f806..546fd8b 100644 --- a/contrib/file/src/file.c +++ b/contrib/file/src/file.c @@ -32,7 +32,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: file.c,v 1.159 2014/11/28 02:46:39 christos Exp $") +FILE_RCSID("@(#)$File: file.c,v 1.160 2014/12/16 23:18:40 christos Exp $") #endif /* lint */ #include "magic.h" @@ -125,6 +125,7 @@ private struct { { "name", MAGIC_PARAM_NAME_MAX, 0 }, { "elf_phnum", MAGIC_PARAM_ELF_PHNUM_MAX, 0 }, { "elf_shnum", MAGIC_PARAM_ELF_SHNUM_MAX, 0 }, + { "elf_notes", MAGIC_PARAM_ELF_NOTES_MAX, 0 }, }; private char *progname; /* used throughout */ diff --git a/contrib/file/src/file.h b/contrib/file/src/file.h index 14fa836..01aa37a 100644 --- a/contrib/file/src/file.h +++ b/contrib/file/src/file.h @@ -27,7 +27,7 @@ */ /* * file.h - definitions for file(1) program - * @(#)$File: file.h,v 1.161 2014/12/04 15:56:46 christos Exp $ + * @(#)$File: file.h,v 1.164 2015/01/01 17:07:34 christos Exp $ */ #ifndef __file_h__ @@ -234,6 +234,7 @@ struct magic { (t) == FILE_LESTRING16 || \ (t) == FILE_REGEX || \ (t) == FILE_SEARCH || \ + (t) == FILE_INDIRECT || \ (t) == FILE_NAME || \ (t) == FILE_USE) @@ -346,6 +347,8 @@ struct magic { #define STRING_IGNORE_CASE (STRING_IGNORE_LOWERCASE|STRING_IGNORE_UPPERCASE) #define STRING_DEFAULT_RANGE 100 +#define INDIRECT_RELATIVE BIT(0) +#define CHAR_INDIRECT_RELATIVE 'r' /* list of magic entries */ struct mlist { @@ -407,10 +410,12 @@ struct magic_set { uint16_t name_max; uint16_t elf_shnum_max; uint16_t elf_phnum_max; + uint16_t elf_notes_max; #define FILE_INDIR_MAX 15 #define FILE_NAME_MAX 30 #define FILE_ELF_SHNUM_MAX 32768 #define FILE_ELF_PHNUM_MAX 128 +#define FILE_ELF_NOTES_MAX 256 }; /* Type for Unicode characters */ @@ -476,6 +481,7 @@ protected int file_looks_utf8(const unsigned char *, size_t, unichar *, size_t *); protected size_t file_pstring_length_size(const struct magic *); protected size_t file_pstring_get_length(const struct magic *, const char *); +protected char * file_printable(char *, size_t, const char *); #ifdef __EMX__ protected int file_os2_apptype(struct magic_set *, const char *, const void *, size_t); diff --git a/contrib/file/src/file_opts.h b/contrib/file/src/file_opts.h index 9cb1d01..3286ac6 100644 --- a/contrib/file/src/file_opts.h +++ b/contrib/file/src/file_opts.h @@ -43,8 +43,13 @@ OPT('0', "print0", 0, " terminate filenames with ASCII NUL\n") #if defined(HAVE_UTIME) || defined(HAVE_UTIMES) OPT('p', "preserve-date", 0, " preserve access times on files\n") #endif +OPT('P', "parameter", 0, " set file engine parameter limits\n" + " indir 15 recursion limit for indirection\n" + " name 30 use limit for name/use magic\n" + " elf_notes 256 max ELF notes processed\n" + " elf_phnum 128 max ELF prog sections processed\n" + " elf_shnum 32768 max ELF sections processed\n") OPT('r', "raw", 0, " don't translate unprintable chars to \\ooo\n") -OPT('R', "recursion", 0, " set maximum recursion level\n") OPT('s', "special-files", 0, " treat special (block/char devices) files as\n" " ordinary ones\n") OPT('C', "compile", 0, " compile file specified by -m\n") diff --git a/contrib/file/src/funcs.c b/contrib/file/src/funcs.c index f190349..a60ccaa 100644 --- a/contrib/file/src/funcs.c +++ b/contrib/file/src/funcs.c @@ -27,7 +27,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: funcs.c,v 1.77 2014/11/28 02:46:39 christos Exp $") +FILE_RCSID("@(#)$File: funcs.c,v 1.79 2014/12/16 20:52:49 christos Exp $") #endif /* lint */ #include "magic.h" @@ -531,3 +531,28 @@ file_pop_buffer(struct magic_set *ms, file_pushbuf_t *pb) free(pb); return rbuf; } + +/* + * convert string to ascii printable format. + */ +protected char * +file_printable(char *buf, size_t bufsiz, const char *str) +{ + char *ptr, *eptr; + const unsigned char *s = (const unsigned char *)str; + + for (ptr = buf, eptr = ptr + bufsiz - 1; ptr < eptr && *s; s++) { + if (isprint(*s)) { + *ptr++ = *s; + continue; + } + if (ptr >= eptr - 3) + break; + *ptr++ = '\\'; + *ptr++ = ((*s >> 6) & 7) + '0'; + *ptr++ = ((*s >> 3) & 7) + '0'; + *ptr++ = ((*s >> 0) & 7) + '0'; + } + *ptr = '\0'; + return buf; +} diff --git a/contrib/file/src/getline.c b/contrib/file/src/getline.c index ab5e115..b00de01 100644 --- a/contrib/file/src/getline.c +++ b/contrib/file/src/getline.c @@ -80,7 +80,7 @@ getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp) } } -ssize_t +public ssize_t getline(char **buf, size_t *bufsiz, FILE *fp) { return getdelim(buf, bufsiz, '\n', fp); diff --git a/contrib/file/src/magic.c b/contrib/file/src/magic.c index b0cf11c..d16f8c6 100644 --- a/contrib/file/src/magic.c +++ b/contrib/file/src/magic.c @@ -33,7 +33,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: magic.c,v 1.90 2014/12/04 15:56:46 christos Exp $") +FILE_RCSID("@(#)$File: magic.c,v 1.91 2014/12/16 23:18:40 christos Exp $") #endif /* lint */ #include "magic.h" @@ -554,6 +554,9 @@ magic_setparam(struct magic_set *ms, int param, const void *val) case MAGIC_PARAM_ELF_SHNUM_MAX: ms->elf_shnum_max = *(const size_t *)val; return 0; + case MAGIC_PARAM_ELF_NOTES_MAX: + ms->elf_notes_max = *(const size_t *)val; + return 0; default: errno = EINVAL; return -1; @@ -576,6 +579,9 @@ magic_getparam(struct magic_set *ms, int param, void *val) case MAGIC_PARAM_ELF_SHNUM_MAX: *(size_t *)val = ms->elf_shnum_max; return 0; + case MAGIC_PARAM_ELF_NOTES_MAX: + *(size_t *)val = ms->elf_notes_max; + return 0; default: errno = EINVAL; return -1; diff --git a/contrib/file/src/magic.h b/contrib/file/src/magic.h index 94cb397..721712f 100644 --- a/contrib/file/src/magic.h +++ b/contrib/file/src/magic.h @@ -107,6 +107,7 @@ int magic_errno(magic_t); #define MAGIC_PARAM_NAME_MAX 1 #define MAGIC_PARAM_ELF_PHNUM_MAX 2 #define MAGIC_PARAM_ELF_SHNUM_MAX 3 +#define MAGIC_PARAM_ELF_NOTES_MAX 4 int magic_setparam(magic_t, int, const void *); int magic_getparam(magic_t, int, void *); diff --git a/contrib/file/src/magic.h.in b/contrib/file/src/magic.h.in index 856478b..0d4c5ce 100644 --- a/contrib/file/src/magic.h.in +++ b/contrib/file/src/magic.h.in @@ -107,6 +107,7 @@ int magic_errno(magic_t); #define MAGIC_PARAM_NAME_MAX 1 #define MAGIC_PARAM_ELF_PHNUM_MAX 2 #define MAGIC_PARAM_ELF_SHNUM_MAX 3 +#define MAGIC_PARAM_ELF_NOTES_MAX 4 int magic_setparam(magic_t, int, const void *); int magic_getparam(magic_t, int, void *); diff --git a/contrib/file/src/readelf.c b/contrib/file/src/readelf.c index 08a2afb..d159620 100644 --- a/contrib/file/src/readelf.c +++ b/contrib/file/src/readelf.c @@ -27,7 +27,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: readelf.c,v 1.111 2014/12/09 02:47:45 christos Exp $") +FILE_RCSID("@(#)$File: readelf.c,v 1.117 2014/12/16 23:29:42 christos Exp $") #endif #ifdef BUILTIN_ELF @@ -43,14 +43,14 @@ FILE_RCSID("@(#)$File: readelf.c,v 1.111 2014/12/09 02:47:45 christos Exp $") #ifdef ELFCORE private int dophn_core(struct magic_set *, int, int, int, off_t, int, size_t, - off_t, int *); + off_t, int *, uint16_t *); #endif private int dophn_exec(struct magic_set *, int, int, int, off_t, int, size_t, - off_t, int *, int); + off_t, int, int *, uint16_t *); private int doshn(struct magic_set *, int, int, int, off_t, int, size_t, - off_t, int *, int, int); + off_t, int, int, int *, uint16_t *); private size_t donote(struct magic_set *, void *, size_t, size_t, int, - int, size_t, int *); + int, size_t, int *, uint16_t *); #define ELF_ALIGN(a) ((((a) + align - 1) / align) * align) @@ -67,7 +67,7 @@ private uint64_t getu64(int, uint64_t); private int toomany(struct magic_set *ms, const char *name, uint16_t num) { - if (file_printf(ms, ", too many %s header sections (%u)", name, num + if (file_printf(ms, ", too many %s (%u)", name, num ) == -1) return -1; return 0; @@ -293,15 +293,19 @@ private const char os_style_names[][8] = { "NetBSD", }; -#define FLAGS_DID_CORE 0x01 -#define FLAGS_DID_NOTE 0x02 -#define FLAGS_DID_BUILD_ID 0x04 -#define FLAGS_DID_CORE_STYLE 0x08 -#define FLAGS_IS_CORE 0x10 +#define FLAGS_DID_CORE 0x001 +#define FLAGS_DID_OS_NOTE 0x002 +#define FLAGS_DID_BUILD_ID 0x004 +#define FLAGS_DID_CORE_STYLE 0x008 +#define FLAGS_DID_NETBSD_PAX 0x010 +#define FLAGS_DID_NETBSD_MARCH 0x020 +#define FLAGS_DID_NETBSD_CMODEL 0x040 +#define FLAGS_DID_NETBSD_UNKNOWN 0x080 +#define FLAGS_IS_CORE 0x100 private int dophn_core(struct magic_set *ms, int clazz, int swap, int fd, off_t off, - int num, size_t size, off_t fsize, int *flags) + int num, size_t size, off_t fsize, int *flags, uint16_t *notecount) { Elf32_Phdr ph32; Elf64_Phdr ph64; @@ -319,7 +323,7 @@ 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) == -1) { + if (pread(fd, xph_addr, xph_sizeof, off) < (ssize_t)xph_sizeof) { file_badread(ms); return -1; } @@ -347,7 +351,7 @@ dophn_core(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, 4, flags); + clazz, swap, 4, flags, notecount); if (offset == 0) break; @@ -477,132 +481,127 @@ do_note_freebsd_version(struct magic_set *ms, int swap, void *v) } } -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) +private int +do_bid_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, + int swap __attribute__((__unused__)), uint32_t namesz, uint32_t descsz, + size_t noff, size_t doff, int *flags) { - Elf32_Nhdr nh32; - Elf64_Nhdr nh64; - size_t noff, doff; -#ifdef ELFCORE - int os_style = -1; -#endif - uint32_t namesz, descsz; - unsigned char *nbuf = CAST(unsigned char *, vbuf); - - if (xnh_sizeof + offset > size) { - /* - * We're out of note headers. - */ - return xnh_sizeof + offset; - } - - (void)memcpy(xnh_addr, &nbuf[offset], xnh_sizeof); - offset += xnh_sizeof; - - namesz = xnh_namesz; - descsz = xnh_descsz; - if ((namesz == 0) && (descsz == 0)) { - /* - * We're out of note headers. - */ - return (offset >= size) ? offset : size; - } - - if (namesz & 0x80000000) { - (void)file_printf(ms, ", bad note name size 0x%lx", - (unsigned long)namesz); - return 0; - } - - if (descsz & 0x80000000) { - (void)file_printf(ms, ", bad note description size 0x%lx", - (unsigned long)descsz); - return 0; - } - - - noff = offset; - doff = ELF_ALIGN(offset + namesz); - - if (offset + namesz > size) { - /* - * We're past the end of the buffer. - */ - return doff; - } - - offset = ELF_ALIGN(doff + descsz); - if (doff + descsz > size) { - /* - * We're past the end of the buffer. - */ - return (offset >= size) ? offset : size; + if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 && + type == NT_GNU_BUILD_ID && (descsz == 16 || descsz == 20)) { + uint8_t desc[20]; + uint32_t i; + *flags |= FLAGS_DID_BUILD_ID; + if (file_printf(ms, ", BuildID[%s]=", descsz == 16 ? "md5/uuid" : + "sha1") == -1) + return 1; + (void)memcpy(desc, &nbuf[doff], descsz); + for (i = 0; i < descsz; i++) + if (file_printf(ms, "%02x", desc[i]) == -1) + return 1; + return 1; } + return 0; +} - if ((*flags & (FLAGS_DID_NOTE|FLAGS_DID_BUILD_ID)) == - (FLAGS_DID_NOTE|FLAGS_DID_BUILD_ID)) - goto core; - +private int +do_os_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, + int swap, uint32_t namesz, uint32_t descsz, + size_t noff, size_t doff, int *flags) +{ if (namesz == 5 && strcmp((char *)&nbuf[noff], "SuSE") == 0 && - xnh_type == NT_GNU_VERSION && descsz == 2) { + type == NT_GNU_VERSION && descsz == 2) { + *flags |= FLAGS_DID_OS_NOTE; file_printf(ms, ", for SuSE %d.%d", nbuf[doff], nbuf[doff + 1]); + return 1; } + if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 && - xnh_type == NT_GNU_VERSION && descsz == 16) { + type == NT_GNU_VERSION && descsz == 16) { uint32_t desc[4]; (void)memcpy(desc, &nbuf[doff], sizeof(desc)); + *flags |= FLAGS_DID_OS_NOTE; if (file_printf(ms, ", for GNU/") == -1) - return size; + return 1; switch (elf_getu32(swap, desc[0])) { case GNU_OS_LINUX: if (file_printf(ms, "Linux") == -1) - return size; + return 1; break; case GNU_OS_HURD: if (file_printf(ms, "Hurd") == -1) - return size; + return 1; break; case GNU_OS_SOLARIS: if (file_printf(ms, "Solaris") == -1) - return size; + return 1; break; case GNU_OS_KFREEBSD: if (file_printf(ms, "kFreeBSD") == -1) - return size; + return 1; break; case GNU_OS_KNETBSD: if (file_printf(ms, "kNetBSD") == -1) - return size; + return 1; break; default: if (file_printf(ms, "<unknown>") == -1) - return size; + return 1; } if (file_printf(ms, " %d.%d.%d", elf_getu32(swap, desc[1]), elf_getu32(swap, desc[2]), elf_getu32(swap, desc[3])) == -1) - return size; - *flags |= FLAGS_DID_NOTE; - return size; + return 1; + return 1; } - if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 && - xnh_type == NT_GNU_BUILD_ID && (descsz == 16 || descsz == 20)) { - uint8_t desc[20]; - uint32_t i; - if (file_printf(ms, ", BuildID[%s]=", descsz == 16 ? "md5/uuid" : - "sha1") == -1) - return size; - (void)memcpy(desc, &nbuf[doff], descsz); - for (i = 0; i < descsz; i++) - if (file_printf(ms, "%02x", desc[i]) == -1) - return size; - *flags |= FLAGS_DID_BUILD_ID; + if (namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0) { + if (type == NT_NETBSD_VERSION && descsz == 4) { + *flags |= FLAGS_DID_OS_NOTE; + do_note_netbsd_version(ms, swap, &nbuf[doff]); + return 1; + } + } + + if (namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0) { + if (type == NT_FREEBSD_VERSION && descsz == 4) { + *flags |= FLAGS_DID_OS_NOTE; + do_note_freebsd_version(ms, swap, &nbuf[doff]); + return 1; + } + } + + if (namesz == 8 && strcmp((char *)&nbuf[noff], "OpenBSD") == 0 && + type == NT_OPENBSD_VERSION && descsz == 4) { + *flags |= FLAGS_DID_OS_NOTE; + if (file_printf(ms, ", for OpenBSD") == -1) + return 1; + /* Content of note is always 0 */ + return 1; + } + + if (namesz == 10 && strcmp((char *)&nbuf[noff], "DragonFly") == 0 && + type == NT_DRAGONFLY_VERSION && descsz == 4) { + uint32_t desc; + *flags |= FLAGS_DID_OS_NOTE; + if (file_printf(ms, ", for DragonFly") == -1) + return 1; + (void)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) + return 1; + return 1; } + return 0; +} +private int +do_pax_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, + int swap, uint32_t namesz, uint32_t descsz, + size_t noff, size_t doff, int *flags) +{ if (namesz == 4 && strcmp((char *)&nbuf[noff], "PaX") == 0 && - xnh_type == NT_NETBSD_PAX && descsz == 4) { + type == NT_NETBSD_PAX && descsz == 4) { static const char *pax[] = { "+mprotect", "-mprotect", @@ -615,80 +614,32 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size, size_t i; int did = 0; + *flags |= FLAGS_DID_NETBSD_PAX; (void)memcpy(&desc, &nbuf[doff], sizeof(desc)); desc = elf_getu32(swap, desc); if (desc && file_printf(ms, ", PaX: ") == -1) - return size; + return 1; for (i = 0; i < __arraycount(pax); i++) { if (((1 << i) & desc) == 0) continue; if (file_printf(ms, "%s%s", did++ ? "," : "", pax[i]) == -1) - return size; + return 1; } + return 1; } + return 0; +} - if (namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0) { - switch (xnh_type) { - case NT_NETBSD_VERSION: - if (descsz == 4) { - do_note_netbsd_version(ms, swap, &nbuf[doff]); - *flags |= FLAGS_DID_NOTE; - return size; - } - break; - case NT_NETBSD_MARCH: - if (file_printf(ms, ", compiled for: %.*s", (int)descsz, - (const char *)&nbuf[doff]) == -1) - return size; - break; - case NT_NETBSD_CMODEL: - if (file_printf(ms, ", compiler model: %.*s", - (int)descsz, (const char *)&nbuf[doff]) == -1) - return size; - break; - default: - if (file_printf(ms, ", note=%u", xnh_type) == -1) - return size; - break; - } - return size; - } - - if (namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0) { - if (xnh_type == NT_FREEBSD_VERSION && descsz == 4) { - do_note_freebsd_version(ms, swap, &nbuf[doff]); - *flags |= FLAGS_DID_NOTE; - return size; - } - } - - if (namesz == 8 && strcmp((char *)&nbuf[noff], "OpenBSD") == 0 && - xnh_type == NT_OPENBSD_VERSION && descsz == 4) { - if (file_printf(ms, ", for OpenBSD") == -1) - return size; - /* Content of note is always 0 */ - *flags |= FLAGS_DID_NOTE; - return size; - } - - if (namesz == 10 && strcmp((char *)&nbuf[noff], "DragonFly") == 0 && - xnh_type == NT_DRAGONFLY_VERSION && descsz == 4) { - uint32_t desc; - if (file_printf(ms, ", for DragonFly") == -1) - return size; - (void)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) - return size; - *flags |= FLAGS_DID_NOTE; - return size; - } - -core: +private int +do_core_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, + int swap, uint32_t namesz, uint32_t descsz, + size_t noff, size_t doff, int *flags, size_t size, int clazz) +{ +#ifdef ELFCORE + int os_style = -1; /* * Sigh. The 2.0.36 kernel in Debian 2.1, at * least, doesn't correctly implement name @@ -717,20 +668,17 @@ core: os_style = OS_STYLE_NETBSD; } -#ifdef ELFCORE - if ((*flags & FLAGS_DID_CORE) != 0) - return size; - if (os_style != -1 && (*flags & FLAGS_DID_CORE_STYLE) == 0) { if (file_printf(ms, ", %s-style", os_style_names[os_style]) == -1) - return size; + return 1; *flags |= FLAGS_DID_CORE_STYLE; } switch (os_style) { case OS_STYLE_NETBSD: - if (xnh_type == NT_NETBSD_CORE_PROCINFO) { + if (type == NT_NETBSD_CORE_PROCINFO) { + char sbuf[512]; uint32_t signo; /* * Extract the program name. It is at @@ -738,8 +686,9 @@ core: * including the terminating NUL. */ if (file_printf(ms, ", from '%.31s'", - &nbuf[doff + 0x7c]) == -1) - return size; + file_printable(sbuf, sizeof(sbuf), + (const char *)&nbuf[doff + 0x7c])) == -1) + return 1; /* * Extract the signal number. It is at @@ -749,14 +698,14 @@ core: sizeof(signo)); if (file_printf(ms, " (signal %u)", elf_getu32(swap, signo)) == -1) - return size; + return 1; *flags |= FLAGS_DID_CORE; - return size; + return 1; } break; default: - if (xnh_type == NT_PRPSINFO && *flags & FLAGS_IS_CORE) { + if (type == NT_PRPSINFO && *flags & FLAGS_IS_CORE) { size_t i, j; unsigned char c; /* @@ -824,7 +773,7 @@ core: * Try next offsets, in case this match is * in the middle of a string. */ - for (k = i + 1 ; k < NOFFSETS ; k++) { + for (k = i + 1 ; k < NOFFSETS; k++) { size_t no; int adjust = 1; if (prpsoffsets(k) >= prpsoffsets(i)) @@ -849,9 +798,9 @@ core: cp--; if (file_printf(ms, ", from '%.*s'", (int)(cp - cname), cname) == -1) - return size; + return 1; *flags |= FLAGS_DID_CORE; - return size; + return 1; tryanother: ; @@ -860,6 +809,129 @@ core: break; } #endif + return 0; +} + +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) +{ + Elf32_Nhdr nh32; + Elf64_Nhdr nh64; + size_t noff, doff; + uint32_t namesz, descsz; + unsigned char *nbuf = CAST(unsigned char *, vbuf); + + if (*notecount == 0) + return 0; + --*notecount; + + if (xnh_sizeof + offset > size) { + /* + * We're out of note headers. + */ + return xnh_sizeof + offset; + } + + (void)memcpy(xnh_addr, &nbuf[offset], xnh_sizeof); + offset += xnh_sizeof; + + namesz = xnh_namesz; + descsz = xnh_descsz; + if ((namesz == 0) && (descsz == 0)) { + /* + * We're out of note headers. + */ + return (offset >= size) ? offset : size; + } + + if (namesz & 0x80000000) { + (void)file_printf(ms, ", bad note name size 0x%lx", + (unsigned long)namesz); + return 0; + } + + if (descsz & 0x80000000) { + (void)file_printf(ms, ", bad note description size 0x%lx", + (unsigned long)descsz); + return 0; + } + + noff = offset; + doff = ELF_ALIGN(offset + namesz); + + if (offset + namesz > size) { + /* + * We're past the end of the buffer. + */ + return doff; + } + + offset = ELF_ALIGN(doff + descsz); + if (doff + descsz > size) { + /* + * We're past the end of the buffer. + */ + return (offset >= size) ? offset : size; + } + + if ((*flags & FLAGS_DID_OS_NOTE) == 0) { + if (do_os_note(ms, nbuf, xnh_type, swap, + namesz, descsz, noff, doff, flags)) + return size; + } + + if ((*flags & FLAGS_DID_BUILD_ID) == 0) { + if (do_bid_note(ms, nbuf, xnh_type, swap, + namesz, descsz, noff, doff, flags)) + return size; + } + + if ((*flags & FLAGS_DID_NETBSD_PAX) == 0) { + if (do_pax_note(ms, nbuf, xnh_type, swap, + namesz, descsz, noff, doff, flags)) + return size; + } + + if ((*flags & FLAGS_DID_CORE) == 0) { + if (do_core_note(ms, nbuf, xnh_type, swap, + namesz, descsz, noff, doff, flags, size, clazz)) + return size; + } + + if (namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0) { + if (descsz > 100) + descsz = 100; + switch (xnh_type) { + case NT_NETBSD_VERSION: + return size; + case NT_NETBSD_MARCH: + if (*flags & FLAGS_DID_NETBSD_MARCH) + return size; + *flags |= FLAGS_DID_NETBSD_MARCH; + if (file_printf(ms, ", compiled for: %.*s", + (int)descsz, (const char *)&nbuf[doff]) == -1) + return size; + break; + case NT_NETBSD_CMODEL: + if (*flags & FLAGS_DID_NETBSD_CMODEL) + return size; + *flags |= FLAGS_DID_NETBSD_CMODEL; + if (file_printf(ms, ", compiler model: %.*s", + (int)descsz, (const char *)&nbuf[doff]) == -1) + return size; + break; + default: + if (*flags & FLAGS_DID_NETBSD_UNKNOWN) + return size; + *flags |= FLAGS_DID_NETBSD_UNKNOWN; + if (file_printf(ms, ", note=%u", xnh_type) == -1) + return size; + break; + } + return size; + } + return offset; } @@ -915,7 +987,8 @@ static const cap_desc_t cap_desc_386[] = { private int doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, - size_t size, off_t fsize, int *flags, int mach, int strtab) + size_t size, off_t fsize, int mach, int strtab, int *flags, + uint16_t *notecount) { Elf32_Shdr sh32; Elf64_Shdr sh64; @@ -926,6 +999,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, uint64_t cap_hw1 = 0; /* SunOS 5.x hardware capabilites */ uint64_t cap_sf1 = 0; /* SunOS 5.x software capabilites */ char name[50]; + ssize_t namesize; if (size != xsh_sizeof) { if (file_printf(ms, ", corrupted section header size") == -1) @@ -934,7 +1008,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, off + size * strtab) == -1) { + if (pread(fd, xsh_addr, xsh_sizeof, off + size * strtab) < (ssize_t)xsh_sizeof) { file_badread(ms); return -1; } @@ -942,15 +1016,15 @@ 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 (pread(fd, name, sizeof(name), name_off + xsh_name) == -1) { + if ((namesize = pread(fd, name, sizeof(name) - 1, name_off + xsh_name)) == -1) { file_badread(ms); return -1; } - name[sizeof(name) - 1] = '\0'; + name[namesize] = '\0'; if (strcmp(name, ".debug_info") == 0) stripped = 0; - if (pread(fd, xsh_addr, xsh_sizeof, off) == -1) { + if (pread(fd, xsh_addr, xsh_sizeof, off) < (ssize_t)xsh_sizeof) { file_badread(ms); return -1; } @@ -980,7 +1054,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, " for note"); return -1; } - if (pread(fd, nbuf, xsh_size, xsh_offset) == -1) { + if (pread(fd, nbuf, xsh_size, xsh_offset) < (ssize_t)xsh_size) { file_badread(ms); free(nbuf); return -1; @@ -991,7 +1065,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, if (noff >= (off_t)xsh_size) break; noff = donote(ms, nbuf, (size_t)noff, - xsh_size, clazz, swap, 4, flags); + xsh_size, clazz, swap, 4, flags, notecount); if (noff == 0) break; } @@ -1158,13 +1232,15 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, */ private int dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, - int num, size_t size, off_t fsize, int *flags, int sh_num) + int num, size_t size, off_t fsize, int sh_num, int *flags, + uint16_t *notecount) { Elf32_Phdr ph32; Elf64_Phdr ph64; const char *linking_style = "statically"; - const char *shared_libraries = ""; + const char *interp = ""; unsigned char nbuf[BUFSIZ]; + char ibuf[BUFSIZ]; ssize_t bufsize; size_t offset, align, len; @@ -1175,20 +1251,40 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, } for ( ; num; num--) { - if (pread(fd, xph_addr, xph_sizeof, off) == -1) { + if (pread(fd, xph_addr, xph_sizeof, off) < (ssize_t)xph_sizeof) { file_badread(ms); return -1; } off += size; + bufsize = 0; + align = 4; /* Things we can determine before we seek */ switch (xph_type) { case PT_DYNAMIC: linking_style = "dynamically"; break; + case PT_NOTE: + if (sh_num) /* Did this through section headers */ + continue; + if (((align = xph_align) & 0x80000000UL) != 0 || + align < 4) { + if (file_printf(ms, + ", invalid note alignment 0x%lx", + (unsigned long)align) == -1) + return -1; + align = 4; + } + /*FALLTHROUGH*/ case PT_INTERP: - shared_libraries = " (uses shared libs)"; + len = xph_filesz < sizeof(nbuf) ? xph_filesz + : sizeof(nbuf); + bufsize = pread(fd, nbuf, len, xph_offset); + if (bufsize == -1) { + file_badread(ms); + return -1; + } break; default: if (fsize != SIZE_UNKNOWN && xph_offset > fsize) { @@ -1200,35 +1296,25 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, /* Things we can determine when we seek */ switch (xph_type) { + case PT_INTERP: + if (bufsize && nbuf[0]) { + nbuf[bufsize - 1] = '\0'; + interp = (const char *)nbuf; + } else + interp = "*empty*"; + break; case PT_NOTE: - if (((align = xph_align) & 0x80000000UL) != 0 || - align < 4) { - if (file_printf(ms, - ", invalid note alignment 0x%lx", - (unsigned long)align) == -1) - return -1; - align = 4; - } - if (sh_num) - break; /* * This is a PT_NOTE section; loop through all the notes * in the section. */ - len = xph_filesz < sizeof(nbuf) ? xph_filesz - : sizeof(nbuf); - bufsize = pread(fd, nbuf, len, xph_offset); - if (bufsize == -1) { - file_badread(ms); - return -1; - } offset = 0; for (;;) { if (offset >= (size_t)bufsize) break; offset = donote(ms, nbuf, offset, (size_t)bufsize, clazz, swap, align, - flags); + flags, notecount); if (offset == 0) break; } @@ -1237,9 +1323,13 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, break; } } - if (file_printf(ms, ", %s linked%s", linking_style, shared_libraries) + if (file_printf(ms, ", %s linked", linking_style) == -1) - return -1; + return -1; + if (interp[0]) + if (file_printf(ms, ", interpreter %s", + file_printable(ibuf, sizeof(ibuf), interp)) == -1) + return -1; return 0; } @@ -1259,7 +1349,7 @@ file_tryelf(struct magic_set *ms, int fd, const unsigned char *buf, int flags = 0; Elf32_Ehdr elf32hdr; Elf64_Ehdr elf64hdr; - uint16_t type, phnum, shnum; + uint16_t type, phnum, shnum, notecount; if (ms->flags & (MAGIC_MIME|MAGIC_APPLE)) return 0; diff --git a/contrib/file/src/softmagic.c b/contrib/file/src/softmagic.c index c20ae67..5e277e3 100644 --- a/contrib/file/src/softmagic.c +++ b/contrib/file/src/softmagic.c @@ -32,7 +32,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: softmagic.c,v 1.203 2014/12/04 15:22:05 christos Exp $") +FILE_RCSID("@(#)$File: softmagic.c,v 1.206 2015/01/01 17:07:34 christos Exp $") #endif /* lint */ #include "magic.h" @@ -404,28 +404,6 @@ strndup(const char *str, size_t n) } #endif /* HAVE_STRNDUP */ -static char * -printable(char *buf, size_t bufsiz, const char *str) -{ - char *ptr, *eptr; - const unsigned char *s = (const unsigned char *)str; - - for (ptr = buf, eptr = ptr + bufsiz - 1; ptr < eptr && *s; s++) { - if (isprint(*s)) { - *ptr++ = *s; - continue; - } - if (ptr >= eptr + 4) - break; - *ptr++ = '\\'; - *ptr++ = ((*s >> 6) & 7) + '0'; - *ptr++ = ((*s >> 3) & 7) + '0'; - *ptr++ = ((*s >> 0) & 7) + '0'; - } - *ptr = '\0'; - return buf; -} - private int32_t mprint(struct magic_set *ms, struct magic *m) { @@ -433,7 +411,7 @@ mprint(struct magic_set *ms, struct magic *m) float vf; double vd; int64_t t = 0; - char buf[128], tbuf[26]; + char buf[128], tbuf[26], sbuf[512]; union VALUETYPE *p = &ms->ms_value; switch (m->type) { @@ -527,12 +505,13 @@ mprint(struct magic_set *ms, struct magic *m) case FILE_BESTRING16: case FILE_LESTRING16: if (m->reln == '=' || m->reln == '!') { - if (file_printf(ms, F(ms, m, "%s"), m->value.s) == -1) + if (file_printf(ms, F(ms, m, "%s"), + file_printable(sbuf, sizeof(sbuf), m->value.s)) + == -1) return -1; t = ms->offset + m->vallen; } else { - char sbuf[512]; char *str = p->s; /* compute t before we mangle the string? */ @@ -555,7 +534,7 @@ mprint(struct magic_set *ms, struct magic *m) } if (file_printf(ms, F(ms, m, "%s"), - printable(sbuf, sizeof(sbuf), str)) == -1) + file_printable(sbuf, sizeof(sbuf), str)) == -1) return -1; if (m->type == FILE_PSTRING) @@ -659,7 +638,8 @@ mprint(struct magic_set *ms, struct magic *m) file_oomem(ms, ms->search.rm_len); return -1; } - rval = file_printf(ms, F(ms, m, "%s"), cp); + rval = file_printf(ms, F(ms, m, "%s"), + file_printable(sbuf, sizeof(sbuf), cp)); free(cp); if (rval == -1) @@ -673,7 +653,8 @@ mprint(struct magic_set *ms, struct magic *m) } case FILE_SEARCH: - if (file_printf(ms, F(ms, m, "%s"), m->value.s) == -1) + if (file_printf(ms, F(ms, m, "%s"), + file_printable(sbuf, sizeof(sbuf), m->value.s)) == -1) return -1; if ((m->str_flags & REGEX_OFFSET_START)) t = ms->search.offset; @@ -1684,6 +1665,8 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m, break; case FILE_INDIRECT: + if (m->str_flags & INDIRECT_RELATIVE) + offset += o; if (offset == 0) return 0; |