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 | 230 | ||||
-rw-r--r-- | contrib/file/src/ascmagic.c | 5 | ||||
-rw-r--r-- | contrib/file/src/cdf.c | 115 | ||||
-rw-r--r-- | contrib/file/src/cdf.h | 23 | ||||
-rw-r--r-- | contrib/file/src/compress.c | 38 | ||||
-rw-r--r-- | contrib/file/src/elfclass.h | 8 | ||||
-rw-r--r-- | contrib/file/src/encoding.c | 3 | ||||
-rw-r--r-- | contrib/file/src/file.c | 65 | ||||
-rw-r--r-- | contrib/file/src/file.h | 29 | ||||
-rw-r--r-- | contrib/file/src/file_opts.h | 1 | ||||
-rw-r--r-- | contrib/file/src/fsmagic.c | 10 | ||||
-rw-r--r-- | contrib/file/src/funcs.c | 22 | ||||
-rw-r--r-- | contrib/file/src/getline.c | 16 | ||||
-rw-r--r-- | contrib/file/src/magic.c | 63 | ||||
-rw-r--r-- | contrib/file/src/magic.h | 12 | ||||
-rw-r--r-- | contrib/file/src/magic.h.in | 10 | ||||
-rw-r--r-- | contrib/file/src/pread.c | 15 | ||||
-rw-r--r-- | contrib/file/src/readcdf.c | 95 | ||||
-rw-r--r-- | contrib/file/src/readelf.c | 21 | ||||
-rw-r--r-- | contrib/file/src/softmagic.c | 143 | ||||
-rw-r--r-- | contrib/file/src/vasprintf.c | 12 |
22 files changed, 737 insertions, 207 deletions
diff --git a/contrib/file/src/Makefile.in b/contrib/file/src/Makefile.in index 970ff0b..f1779f9 100644 --- a/contrib/file/src/Makefile.in +++ b/contrib/file/src/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.14 from Makefile.am. +# Makefile.in generated by automake 1.14.1 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 pread.c \ - ctime_r.c getline.c vasprintf.c asprintf.c asctime_r.c \ - fmtcheck.c strlcpy.c getopt_long.c strcasestr.c strlcat.c \ +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 \ $(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 71e9af6..cfea6be 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.211 2014/06/03 19:01:34 christos Exp $") +FILE_RCSID("@(#)$File: apprentice.c,v 1.227 2014/11/28 02:46:39 christos Exp $") #endif /* lint */ #include "magic.h" @@ -86,6 +86,10 @@ FILE_RCSID("@(#)$File: apprentice.c,v 1.211 2014/06/03 19:01:34 christos Exp $") #define ALLOC_CHUNK (size_t)10 #define ALLOC_INCR (size_t)200 +#define MAP_TYPE_MMAP 0 +#define MAP_TYPE_MALLOC 1 +#define MAP_TYPE_USER 2 + struct magic_entry { struct magic *mp; uint32_t cont_count; @@ -101,6 +105,7 @@ struct magic_entry_set { struct magic_map { void *p; size_t len; + int type; struct magic *magic[MAGIC_SETS]; uint32_t nmagic[MAGIC_SETS]; }; @@ -131,7 +136,10 @@ private uint16_t swap2(uint16_t); private uint32_t swap4(uint32_t); private uint64_t swap8(uint64_t); private char *mkdbname(struct magic_set *, const char *, int); +private struct magic_map *apprentice_buf(struct magic_set *, struct magic *, + size_t); private struct magic_map *apprentice_map(struct magic_set *, const char *); +private int check_buffer(struct magic_set *, struct magic_map *, const char *); private void apprentice_unmap(struct magic_map *); private int apprentice_compile(struct magic_set *, struct magic_map *, const char *); @@ -396,10 +404,11 @@ add_mlist(struct mlist *mlp, struct magic_map *map, size_t idx) { struct mlist *ml; + mlp->map = idx == 0 ? map : NULL; if ((ml = CAST(struct mlist *, malloc(sizeof(*ml)))) == NULL) return -1; - ml->map = idx == 0 ? map : NULL; + ml->map = NULL; ml->magic = map->magic[idx]; ml->nmagic = map->nmagic[idx]; @@ -416,13 +425,11 @@ add_mlist(struct mlist *mlp, struct magic_map *map, size_t idx) private int apprentice_1(struct magic_set *ms, const char *fn, int action) { -#ifndef COMPILE_ONLY - struct mlist *ml; -#endif /* COMPILE_ONLY */ struct magic_map *map; #ifndef COMPILE_ONLY + struct mlist *ml; size_t i; -#endif /* COMPILE_ONLY */ +#endif if (magicsize != FILE_MAGICSIZE) { file_error(ms, 0, "magic element size %lu != %lu", @@ -451,22 +458,29 @@ apprentice_1(struct magic_set *ms, const char *fn, int action) for (i = 0; i < MAGIC_SETS; i++) { if (add_mlist(ms->mlist[i], map, i) == -1) { file_oomem(ms, sizeof(*ml)); - apprentice_unmap(map); - return -1; + goto fail; } } if (action == FILE_LIST) { for (i = 0; i < MAGIC_SETS; i++) { - printf("Set %zu:\nBinary patterns:\n", i); + printf("Set %" SIZE_T_FORMAT "u:\nBinary patterns:\n", + i); apprentice_list(ms->mlist[i], BINTEST); printf("Text patterns:\n"); apprentice_list(ms->mlist[i], TEXTTEST); } } -#endif /* COMPILE_ONLY */ - return 0; +fail: + for (i = 0; i < MAGIC_SETS; i++) { + mlist_free(ms->mlist[i]); + ms->mlist[i] = NULL; + } + return -1; +#else + return 0; +#endif /* COMPILE_ONLY */ } protected void @@ -510,6 +524,10 @@ file_ms_alloc(int flags) ms->mlist[i] = NULL; ms->file = "unknown"; ms->line = 0; + ms->indir_max = FILE_INDIR_MAX; + ms->name_max = FILE_NAME_MAX; + ms->elf_shnum_max = FILE_ELF_SHNUM_MAX; + ms->elf_phnum_max = FILE_ELF_PHNUM_MAX; return ms; free: free(ms); @@ -521,17 +539,21 @@ apprentice_unmap(struct magic_map *map) { if (map == NULL) return; - if (map->p != NULL) { + + switch (map->type) { #ifdef QUICK - if (map->len) + case MAP_TYPE_MMAP: + if (map->p) (void)munmap(map->p, map->len); - else + break; #endif + case MAP_TYPE_MALLOC: free(map->p); - } else { - uint32_t j; - for (j = 0; j < MAGIC_SETS; j++) - free(map->magic[j]); + break; + case MAP_TYPE_USER: + break; + default: + abort(); } free(map); } @@ -550,21 +572,70 @@ mlist_alloc(void) private void mlist_free(struct mlist *mlist) { - struct mlist *ml; + struct mlist *ml, *next; if (mlist == NULL) return; - for (ml = mlist->next; ml != mlist;) { - struct mlist *next = ml->next; + ml = mlist->next; + for (ml = mlist->next; (next = ml->next) != NULL; ml = next) { if (ml->map) apprentice_unmap(ml->map); free(ml); - ml = next; + if (ml == mlist) + break; } - free(ml); } +#ifndef COMPILE_ONLY +/* void **bufs: an array of compiled magic files */ +protected int +buffer_apprentice(struct magic_set *ms, struct magic **bufs, + size_t *sizes, size_t nbufs) +{ + size_t i, j; + struct mlist *ml; + struct magic_map *map; + + if (nbufs == 0) + return -1; + + if (ms->mlist[0] != NULL) + file_reset(ms); + + init_file_tables(); + + for (i = 0; i < MAGIC_SETS; i++) { + mlist_free(ms->mlist[i]); + if ((ms->mlist[i] = mlist_alloc()) == NULL) { + file_oomem(ms, sizeof(*ms->mlist[i])); + goto fail; + } + } + + for (i = 0; i < nbufs; i++) { + map = apprentice_buf(ms, bufs[i], sizes[i]); + if (map == NULL) + goto fail; + + for (j = 0; j < MAGIC_SETS; j++) { + if (add_mlist(ms->mlist[j], map, j) == -1) { + file_oomem(ms, sizeof(*ml)); + goto fail; + } + } + } + + return 0; +fail: + for (i = 0; i < MAGIC_SETS; i++) { + mlist_free(ms->mlist[i]); + ms->mlist[i] = NULL; + } + return -1; +} +#endif + /* const char *fn: list of magic files and directories */ protected int file_apprentice(struct magic_set *ms, const char *fn, int action) @@ -590,11 +661,9 @@ file_apprentice(struct magic_set *ms, const char *fn, int action) mlist_free(ms->mlist[i]); if ((ms->mlist[i] = mlist_alloc()) == NULL) { file_oomem(ms, sizeof(*ms->mlist[i])); - if (i != 0) { - --i; - do - mlist_free(ms->mlist[i]); - while (i != 0); + while (i-- > 0) { + mlist_free(ms->mlist[i]); + ms->mlist[i] = NULL; } free(mfn); return -1; @@ -1317,7 +1386,7 @@ file_signextend(struct magic_set *ms, struct magic *m, uint64_t v) * the sign extension must have happened. */ case FILE_BYTE: - v = (char) v; + v = (signed char) v; break; case FILE_SHORT: case FILE_BESHORT: @@ -2069,8 +2138,14 @@ out: } private int +goodchar(unsigned char x, const char *extra) +{ + return (isascii(x) && isalnum(x)) || strchr(extra, x); +} + +private int parse_extra(struct magic_set *ms, struct magic_entry *me, const char *line, - off_t off, size_t len, const char *name, int nt) + off_t off, size_t len, const char *name, const char *extra, int nt) { size_t i; const char *l = line; @@ -2091,9 +2166,7 @@ parse_extra(struct magic_set *ms, struct magic_entry *me, const char *line, } EATAB; - for (i = 0; *l && ((isascii((unsigned char)*l) && - isalnum((unsigned char)*l)) || strchr("-+/.", *l)) && - i < len; buf[i++] = *l++) + for (i = 0; *l && i < len && goodchar(*l, extra); buf[i++] = *l++) continue; if (i == len && *l) { @@ -2103,14 +2176,18 @@ parse_extra(struct magic_set *ms, struct magic_entry *me, const char *line, file_magwarn(ms, "%s type `%s' truncated %" SIZE_T_FORMAT "u", name, line, i); } else { + if (!isspace((unsigned char)*l) && !goodchar(*l, extra)) + file_magwarn(ms, "%s type `%s' has bad char '%c'", + name, line, *l); if (nt) buf[i] = '\0'; } if (i > 0) return 0; - else - return -1; + + file_magerror(ms, "Bad magic entry '%s'", line); + return -1; } /* @@ -2123,7 +2200,7 @@ parse_apple(struct magic_set *ms, struct magic_entry *me, const char *line) struct magic *m = &me->mp[0]; return parse_extra(ms, me, line, offsetof(struct magic, apple), - sizeof(m->apple), "APPLE", 0); + sizeof(m->apple), "APPLE", "!+-./", 0); } /* @@ -2136,7 +2213,7 @@ parse_mime(struct magic_set *ms, struct magic_entry *me, const char *line) struct magic *m = &me->mp[0]; return parse_extra(ms, me, line, offsetof(struct magic, mimetype), - sizeof(m->mimetype), "MIME", 1); + sizeof(m->mimetype), "MIME", "+-/.", 1); } private int @@ -2697,6 +2774,28 @@ eatsize(const char **p) } /* + * handle a buffer containing a compiled file. + */ +private struct magic_map * +apprentice_buf(struct magic_set *ms, struct magic *buf, size_t len) +{ + struct magic_map *map; + + if ((map = CAST(struct magic_map *, calloc(1, sizeof(*map)))) == NULL) { + file_oomem(ms, sizeof(*map)); + return NULL; + } + map->len = len; + map->p = buf; + map->type = MAP_TYPE_USER; + if (check_buffer(ms, map, "buffer") != 0) { + apprentice_unmap(map); + return NULL; + } + return map; +} + +/* * handle a compiled file. */ @@ -2705,12 +2804,8 @@ apprentice_map(struct magic_set *ms, const char *fn) { int fd; struct stat st; - uint32_t *ptr; - uint32_t version, entries, nentries; - int needsbyteswap; char *dbname = NULL; struct magic_map *map; - size_t i; fd = -1; if ((map = CAST(struct magic_map *, calloc(1, sizeof(*map)))) == NULL) { @@ -2742,6 +2837,7 @@ apprentice_map(struct magic_set *ms, const char *fn) file_error(ms, errno, "cannot map `%s'", dbname); goto error; } + map->type = MAP_TYPE_MMAP; #else if ((map->p = CAST(void *, malloc(map->len))) == NULL) { file_oomem(ms, map->len); @@ -2751,16 +2847,39 @@ apprentice_map(struct magic_set *ms, const char *fn) file_badread(ms); goto error; } - map->len = 0; + map->type = MAP_TYPE_MALLOC; #define RET 1 #endif (void)close(fd); fd = -1; + + if (check_buffer(ms, map, dbname) != 0) + goto error; + + free(dbname); + return map; + +error: + if (fd != -1) + (void)close(fd); + apprentice_unmap(map); + free(dbname); + return NULL; +} + +private int +check_buffer(struct magic_set *ms, struct magic_map *map, const char *dbname) +{ + uint32_t *ptr; + uint32_t entries, nentries; + uint32_t version; + int i, needsbyteswap; + ptr = CAST(uint32_t *, map->p); if (*ptr != MAGICNO) { if (swap4(*ptr) != MAGICNO) { file_error(ms, 0, "bad magic in `%s'", dbname); - goto error; + return -1; } needsbyteswap = 1; } else @@ -2773,15 +2892,14 @@ apprentice_map(struct magic_set *ms, const char *fn) file_error(ms, 0, "File %s supports only version %d magic " "files. `%s' is version %d", VERSION, VERSIONNO, dbname, version); - goto error; + return -1; } - entries = (uint32_t)(st.st_size / sizeof(struct magic)); - if ((off_t)(entries * sizeof(struct magic)) != st.st_size) { - file_error(ms, 0, "Size of `%s' %" INT64_T_FORMAT "u is not " + entries = (uint32_t)(map->len / sizeof(struct magic)); + if ((entries * sizeof(struct magic)) != map->len) { + file_error(ms, 0, "Size of `%s' %" SIZE_T_FORMAT "u is not " "a multiple of %" SIZE_T_FORMAT "u", - dbname, (unsigned long long)st.st_size, - sizeof(struct magic)); - goto error; + dbname, map->len, sizeof(struct magic)); + return -1; } map->magic[0] = CAST(struct magic *, map->p) + 1; nentries = 0; @@ -2797,20 +2915,12 @@ apprentice_map(struct magic_set *ms, const char *fn) if (entries != nentries + 1) { file_error(ms, 0, "Inconsistent entries in `%s' %u != %u", dbname, entries, nentries + 1); - goto error; + return -1; } if (needsbyteswap) for (i = 0; i < MAGIC_SETS; i++) byteswap(map->magic[i], map->nmagic[i]); - free(dbname); - return map; - -error: - if (fd != -1) - (void)close(fd); - apprentice_unmap(map); - free(dbname); - return NULL; + return 0; } /* diff --git a/contrib/file/src/ascmagic.c b/contrib/file/src/ascmagic.c index ca26665..78a6dbb 100644 --- a/contrib/file/src/ascmagic.c +++ b/contrib/file/src/ascmagic.c @@ -35,7 +35,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: ascmagic.c,v 1.88 2014/02/12 23:20:53 christos Exp $") +FILE_RCSID("@(#)$File: ascmagic.c,v 1.91 2014/11/28 02:46:39 christos Exp $") #endif /* lint */ #include "magic.h" @@ -147,7 +147,8 @@ file_ascmagic_with_encoding(struct magic_set *ms, const unsigned char *buf, == NULL) goto done; if ((rv = file_softmagic(ms, utf8_buf, - (size_t)(utf8_end - utf8_buf), 0, TEXTTEST, text)) == 0) + (size_t)(utf8_end - utf8_buf), 0, NULL, + TEXTTEST, text)) == 0) rv = -1; } diff --git a/contrib/file/src/cdf.c b/contrib/file/src/cdf.c index 106fc7a..9e3cf9f 100644 --- a/contrib/file/src/cdf.c +++ b/contrib/file/src/cdf.c @@ -35,7 +35,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: cdf.c,v 1.63 2014/06/09 13:04:37 christos Exp $") +FILE_RCSID("@(#)$File: cdf.c,v 1.69 2014/12/04 15:56:46 christos Exp $") #endif #include <assert.h> @@ -73,6 +73,8 @@ static union { #define CDF_TOLE8(x) ((uint64_t)(NEED_SWAP ? _cdf_tole8(x) : (uint64_t)(x))) #define CDF_TOLE4(x) ((uint32_t)(NEED_SWAP ? _cdf_tole4(x) : (uint32_t)(x))) #define CDF_TOLE2(x) ((uint16_t)(NEED_SWAP ? _cdf_tole2(x) : (uint16_t)(x))) +#define CDF_TOLE(x) (sizeof(x) == 2 ? CDF_TOLE2(x) : (sizeof(x) == 4 ? \ + CDF_TOLE4(x) : CDF_TOLE8(x))) #define CDF_GETUINT32(x, y) cdf_getuint32(x, y) @@ -461,6 +463,12 @@ cdf_count_chain(const cdf_sat_t *sat, cdf_secid_t sid, size_t size) / sizeof(maxsector)); DPRINTF(("Chain:")); + if (sid == CDF_SECID_END_OF_CHAIN) { + /* 0-length chain. */ + DPRINTF((" empty\n")); + return 0; + } + for (j = i = 0; sid >= 0; i++, j++) { DPRINTF((" %d", sid)); if (j >= CDF_LOOP_LIMIT) { @@ -817,13 +825,18 @@ cdf_read_property_info(const cdf_stream_t *sst, const cdf_header_t *h, goto out; for (i = 0; i < sh.sh_properties; i++) { size_t tail = (i << 1) + 1; + size_t ofs; if (cdf_check_stream_offset(sst, h, p, tail * sizeof(uint32_t), __LINE__) == -1) goto out; - size_t ofs = CDF_GETUINT32(p, tail); + ofs = CDF_GETUINT32(p, tail); q = (const uint8_t *)(const void *) ((const char *)(const void *)p + ofs - 2 * sizeof(uint32_t)); + if (q < p) { + DPRINTF(("Wrapped around %p < %p\n", q, p)); + goto out; + } if (q > e) { DPRINTF(("Ran of the end %p > %p\n", q, e)); goto out; @@ -985,6 +998,54 @@ cdf_unpack_summary_info(const cdf_stream_t *sst, const cdf_header_t *h, } +#define extract_catalog_field(f, l) \ + memcpy(&ce[i].f, b + (l), sizeof(ce[i].f)); \ + ce[i].f = CDF_TOLE(ce[i].f) + +int +cdf_unpack_catalog(const cdf_header_t *h, const cdf_stream_t *sst, + cdf_catalog_t **cat) +{ + size_t ss = sst->sst_dirlen < h->h_min_size_standard_stream ? + CDF_SHORT_SEC_SIZE(h) : CDF_SEC_SIZE(h); + const char *b = CAST(const char *, sst->sst_tab); + const char *eb = b + ss * sst->sst_len; + size_t nr, i, k; + cdf_catalog_entry_t *ce; + uint16_t reclen; + const uint16_t *np; + + for (nr = 0; b < eb; nr++) { + memcpy(&reclen, b, sizeof(reclen)); + reclen = CDF_TOLE2(reclen); + if (reclen == 0) + break; + b += reclen; + } + *cat = CAST(cdf_catalog_t *, + malloc(sizeof(cdf_catalog_t) + nr * sizeof(*ce))); + (*cat)->cat_num = nr; + ce = (*cat)->cat_e; + b = CAST(const char *, sst->sst_tab); + for (i = 0; i < nr; i++) { + extract_catalog_field(ce_namlen, 0); + extract_catalog_field(ce_num, 2); + extract_catalog_field(ce_timestamp, 6); + reclen = ce[i].ce_namlen; + ce[i].ce_namlen = + sizeof(ce[i].ce_name) / sizeof(ce[i].ce_name[0]) - 1; + if (ce[i].ce_namlen > reclen - 14) + ce[i].ce_namlen = reclen - 14; + np = CAST(const uint16_t *, (b + 16)); + for (k = 0; k < ce[i].ce_namlen; k++) { + ce[i].ce_name[k] = np[k]; + CDF_TOLE2(ce[i].ce_name[k]); + } + ce[i].ce_name[ce[i].ce_namlen] = 0; + b += reclen; + } + return 0; +} int cdf_print_classid(char *buf, size_t buflen, const cdf_classid_t *id) @@ -1068,6 +1129,15 @@ cdf_print_elapsed_time(char *buf, size_t bufsiz, cdf_timestamp_t ts) return len; } +char * +cdf_u16tos8(char *buf, size_t len, const uint16_t *p) +{ + size_t i; + for (i = 0; i < len && p[i]; i++) + buf[i] = (char)p[i]; + buf[i] = '\0'; + return buf; +} #ifdef CDF_DEBUG void @@ -1093,7 +1163,7 @@ cdf_dump_header(const cdf_header_t *h) for (i = 0; i < __arraycount(h->h_master_sat); i++) { if (h->h_master_sat[i] == CDF_SECID_FREE) break; - (void)fprintf(stderr, "%35.35s[%.3zu] = %d\n", + (void)fprintf(stderr, "%35.35s[%.3" SIZE_T_FORMAT "u] = %d\n", "master_sat", i, h->h_master_sat[i]); } } @@ -1288,7 +1358,7 @@ cdf_dump_summary_info(const cdf_header_t *h, const cdf_stream_t *sst) return; (void)fprintf(stderr, "Endian: %x\n", ssi.si_byte_order); (void)fprintf(stderr, "Os Version %d.%d\n", ssi.si_os_version & 0xff, - ssi.si_os_version >> 8); + ssi.si_os_version >> 8); (void)fprintf(stderr, "Os %d\n", ssi.si_os); cdf_print_classid(buf, sizeof(buf), &ssi.si_class); (void)fprintf(stderr, "Class %s\n", buf); @@ -1297,6 +1367,27 @@ cdf_dump_summary_info(const cdf_header_t *h, const cdf_stream_t *sst) free(info); } + +void +cdf_dump_catalog(const cdf_header_t *h, const cdf_stream_t *sst) +{ + cdf_catalog_t *cat; + cdf_unpack_catalog(h, sst, &cat); + const cdf_catalog_entry_t *ce = cat->cat_e; + struct timespec ts; + char tbuf[64], sbuf[256]; + size_t i; + + printf("Catalog:\n"); + for (i = 0; i < cat->cat_num; i++) { + cdf_timestamp_to_timespec(&ts, ce[i].ce_timestamp); + printf("\t%d %s %s", ce[i].ce_num, + cdf_u16tos8(sbuf, ce[i].ce_namlen, ce[i].ce_name), + cdf_ctime(&ts.tv_sec, tbuf)); + } + free(cat); +} + #endif #ifdef TEST @@ -1309,6 +1400,7 @@ main(int argc, char *argv[]) cdf_stream_t sst, scn; cdf_dir_t dir; cdf_info_t info; + const cdf_directory_t *root; if (argc < 2) { (void)fprintf(stderr, "Usage: %s <filename>\n", getprogname()); @@ -1342,7 +1434,8 @@ main(int argc, char *argv[]) if (cdf_read_dir(&info, &h, &sat, &dir) == -1) err(1, "Cannot read dir"); - if (cdf_read_short_stream(&info, &h, &sat, &dir, &sst) == -1) + if (cdf_read_short_stream(&info, &h, &sat, &dir, &sst, &root) + == -1) err(1, "Cannot read short stream"); #ifdef CDF_DEBUG cdf_dump_stream(&h, &sst); @@ -1355,9 +1448,17 @@ main(int argc, char *argv[]) if (cdf_read_summary_info(&info, &h, &sat, &ssat, &sst, &dir, &scn) == -1) - err(1, "Cannot read summary info"); + warn("Cannot read summary info"); +#ifdef CDF_DEBUG + else + cdf_dump_summary_info(&h, &scn); +#endif + if (cdf_read_catalog(&info, &h, &sat, &ssat, &sst, &dir, + &scn) == -1) + warn("Cannot read catalog"); #ifdef CDF_DEBUG - cdf_dump_summary_info(&h, &scn); + else + cdf_dump_catalog(&h, &scn); #endif (void)close(info.i_fd); diff --git a/contrib/file/src/cdf.h b/contrib/file/src/cdf.h index 910fb95..64e3648 100644 --- a/contrib/file/src/cdf.h +++ b/contrib/file/src/cdf.h @@ -267,6 +267,19 @@ typedef struct { size_t i_len; } cdf_info_t; + +typedef struct { + uint16_t ce_namlen; + uint32_t ce_num; + uint64_t ce_timestamp; + uint16_t ce_name[256]; +} cdf_catalog_entry_t; + +typedef struct { + size_t cat_num; + cdf_catalog_entry_t cat_e[0]; +} cdf_catalog_t; + struct timespec; int cdf_timestamp_to_timespec(struct timespec *, cdf_timestamp_t); int cdf_timespec_to_timestamp(cdf_timestamp_t *, const struct timespec *); @@ -301,11 +314,19 @@ int cdf_read_property_info(const cdf_stream_t *, const cdf_header_t *, uint32_t, int cdf_read_user_stream(const cdf_info_t *, const cdf_header_t *, const cdf_sat_t *, const cdf_sat_t *, const cdf_stream_t *, const cdf_dir_t *, const char *, cdf_stream_t *); +#define cdf_read_catalog(info, header, sat, ssat, stream, dir, scn) \ + cdf_read_user_stream(info, header, sat, ssat, stream, dir, "Catalog", \ + scn) +#define cdf_read_encrypted_package(info, header, sat, ssat, stream, dir, scn) \ + cdf_read_user_stream(info, header, sat, ssat, stream, dir, \ + "EncryptedPackage", scn) int cdf_read_summary_info(const cdf_info_t *, const cdf_header_t *, const cdf_sat_t *, const cdf_sat_t *, const cdf_stream_t *, const cdf_dir_t *, cdf_stream_t *); int cdf_unpack_summary_info(const cdf_stream_t *, const cdf_header_t *, cdf_summary_info_header_t *, cdf_property_info_t **, size_t *); +int cdf_unpack_catalog(const cdf_header_t *, const cdf_stream_t *, + cdf_catalog_t **); int cdf_print_classid(char *, size_t, const cdf_classid_t *); int cdf_print_property_name(char *, size_t, uint32_t); int cdf_print_elapsed_time(char *, size_t, cdf_timestamp_t); @@ -313,6 +334,7 @@ uint16_t cdf_tole2(uint16_t); uint32_t cdf_tole4(uint32_t); uint64_t cdf_tole8(uint64_t); char *cdf_ctime(const time_t *, char *); +char *cdf_u16tos8(char *, size_t, const uint16_t *); #ifdef CDF_DEBUG void cdf_dump_header(const cdf_header_t *); @@ -323,6 +345,7 @@ void cdf_dump_dir(const cdf_info_t *, const cdf_header_t *, const cdf_sat_t *, const cdf_sat_t *, const cdf_stream_t *, const cdf_dir_t *); void cdf_dump_property_info(const cdf_property_info_t *, size_t); void cdf_dump_summary_info(const cdf_header_t *, const cdf_stream_t *); +void cdf_dump_catalog(const cdf_header_t *, const cdf_stream_t *); #endif diff --git a/contrib/file/src/compress.c b/contrib/file/src/compress.c index 45251b1..4a6f42e 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.73 2014/01/05 15:55:21 christos Exp $") +FILE_RCSID("@(#)$File: compress.c,v 1.75 2014/12/04 15:56:46 christos Exp $") #endif #include "magic.h" @@ -45,7 +45,7 @@ FILE_RCSID("@(#)$File: compress.c,v 1.73 2014/01/05 15:55:21 christos Exp $") #endif #include <string.h> #include <errno.h> -#ifndef __MINGW32__ +#if !defined(__MINGW32__) && !defined(WIN32) #include <sys/ioctl.h> #endif #ifdef HAVE_SYS_WAIT_H @@ -377,6 +377,7 @@ uncompressbuf(struct magic_set *ms, int fd, size_t method, const unsigned char *old, unsigned char **newch, size_t n) { int fdin[2], fdout[2]; + int status; ssize_t r; pid_t pid; @@ -459,7 +460,17 @@ uncompressbuf(struct magic_set *ms, int fd, size_t method, /*NOTREACHED*/ default: /* parent */ - break; + if (wait(&status) == -1) { +#ifdef DEBUG + (void)fprintf(stderr, + "Wait failed (%s)\n", + strerror(errno)); +#endif + exit(1); + } + exit(WIFEXITED(status) ? + WEXITSTATUS(status) : 1); + /*NOTREACHED*/ } (void) close(fdin[1]); fdin[1] = -1; @@ -470,7 +481,7 @@ uncompressbuf(struct magic_set *ms, int fd, size_t method, (void)fprintf(stderr, "Malloc failed (%s)\n", strerror(errno)); #endif - n = 0; + n = NODATA; goto err; } if ((r = sread(fdout[0], *newch, HOWMANY, 0)) <= 0) { @@ -479,7 +490,7 @@ uncompressbuf(struct magic_set *ms, int fd, size_t method, strerror(errno)); #endif free(*newch); - n = 0; + n = NODATA; *newch = NULL; goto err; } else { @@ -491,12 +502,19 @@ err: if (fdin[1] != -1) (void) close(fdin[1]); (void) close(fdout[0]); -#ifdef WNOHANG - while (waitpid(pid, NULL, WNOHANG) != -1) - continue; -#else - (void)wait(NULL); + if (wait(&status) == -1) { +#ifdef DEBUG + (void)fprintf(stderr, "Wait failed (%s)\n", + strerror(errno)); #endif + n = NODATA; + } else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { +#ifdef DEBUG + (void)fprintf(stderr, "Child status (0x%x)\n", status); +#endif + n = NODATA; + } + (void) close(fdin[0]); return n; diff --git a/contrib/file/src/elfclass.h b/contrib/file/src/elfclass.h index 0826ce3..e144d11 100644 --- a/contrib/file/src/elfclass.h +++ b/contrib/file/src/elfclass.h @@ -36,7 +36,7 @@ #ifdef ELFCORE case ET_CORE: phnum = elf_getu16(swap, elfhdr.e_phnum); - if (phnum > MAX_PHNUM) + if (phnum > ms->elf_phnum_max) return toomany(ms, "program", phnum); flags |= FLAGS_IS_CORE; if (dophn_core(ms, clazz, swap, fd, @@ -49,10 +49,10 @@ case ET_EXEC: case ET_DYN: phnum = elf_getu16(swap, elfhdr.e_phnum); - if (phnum > MAX_PHNUM) + if (phnum > ms->elf_phnum_max) return toomany(ms, "program", phnum); shnum = elf_getu16(swap, elfhdr.e_shnum); - if (shnum > MAX_SHNUM) + if (shnum > ms->elf_shnum_max) return toomany(ms, "section", shnum); if (dophn_exec(ms, clazz, swap, fd, (off_t)elf_getu(swap, elfhdr.e_phoff), phnum, @@ -62,7 +62,7 @@ /*FALLTHROUGH*/ case ET_REL: shnum = elf_getu16(swap, elfhdr.e_shnum); - if (shnum > MAX_SHNUM) + if (shnum > ms->elf_shnum_max) return toomany(ms, "section", shnum); if (doshn(ms, clazz, swap, fd, (off_t)elf_getu(swap, elfhdr.e_shoff), shnum, diff --git a/contrib/file/src/encoding.c b/contrib/file/src/encoding.c index b75e0cc..c1b23cc 100644 --- a/contrib/file/src/encoding.c +++ b/contrib/file/src/encoding.c @@ -35,7 +35,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: encoding.c,v 1.9 2013/11/19 20:45:50 christos Exp $") +FILE_RCSID("@(#)$File: encoding.c,v 1.10 2014/09/11 12:08:52 christos Exp $") #endif /* lint */ #include "magic.h" @@ -97,7 +97,6 @@ file_encoding(struct magic_set *ms, const unsigned char *buf, size_t nbytes, uni *code_mime = "utf-8"; } else if (file_looks_utf8(buf, nbytes, *ubuf, ulen) > 1) { DPRINTF(("utf8 %" SIZE_T_FORMAT "u\n", *ulen)); - *code = "UTF-8 Unicode (with BOM)"; *code = "UTF-8 Unicode"; *code_mime = "utf-8"; } else if ((ucs_type = looks_ucs16(buf, nbytes, *ubuf, ulen)) != 0) { diff --git a/contrib/file/src/file.c b/contrib/file/src/file.c index 370da91..148f806 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.153 2014/02/11 15:41:04 christos Exp $") +FILE_RCSID("@(#)$File: file.c,v 1.159 2014/11/28 02:46:39 christos Exp $") #endif /* lint */ #include "magic.h" @@ -54,9 +54,6 @@ FILE_RCSID("@(#)$File: file.c,v 1.153 2014/02/11 15:41:04 christos Exp $") #ifdef HAVE_UNISTD_H #include <unistd.h> /* for read() */ #endif -#ifdef HAVE_LOCALE_H -#include <locale.h> -#endif #ifdef HAVE_WCHAR_H #include <wchar.h> #endif @@ -101,7 +98,7 @@ private const struct option long_options[] = { #undef OPT_LONGONLY {0, 0, NULL, 0} }; -#define OPTSTRING "bcCde:Ef:F:hiklLm:nNprsvz0" +#define OPTSTRING "bcCde:Ef:F:hiklLm:nNpP:rsvz0" private const struct { const char *name; @@ -119,6 +116,17 @@ private const struct { { "tokens", MAGIC_NO_CHECK_TOKENS }, /* OBSOLETE: ignored for backwards compatibility */ }; +private struct { + const char *name; + int tag; + size_t value; +} pm[] = { + { "indir", MAGIC_PARAM_INDIR_MAX, 0 }, + { "name", MAGIC_PARAM_NAME_MAX, 0 }, + { "elf_phnum", MAGIC_PARAM_ELF_PHNUM_MAX, 0 }, + { "elf_shnum", MAGIC_PARAM_ELF_SHNUM_MAX, 0 }, +}; + private char *progname; /* used throughout */ private void usage(void); @@ -128,6 +136,8 @@ private void help(void); private int unwrap(struct magic_set *, const char *); private int process(struct magic_set *ms, const char *, int); private struct magic_set *load(const char *, int); +private void setparam(const char *); +private void applyparam(magic_t); /* @@ -145,7 +155,9 @@ main(int argc, char *argv[]) const char *magicfile = NULL; /* where the magic is */ /* makes islower etc work for other langs */ +#ifdef HAVE_SETLOCALE (void)setlocale(LC_CTYPE, ""); +#endif #ifdef __EMX__ /* sh-like wildcard expansion! Shouldn't hurt at least ... */ @@ -243,9 +255,13 @@ main(int argc, char *argv[]) flags |= MAGIC_PRESERVE_ATIME; break; #endif + case 'P': + setparam(optarg); + break; case 'r': flags |= MAGIC_RAW; break; + break; case 's': flags |= MAGIC_DEVICES; break; @@ -298,6 +314,8 @@ main(int argc, char *argv[]) strerror(errno)); return 1; } + + switch(action) { case FILE_CHECK: c = magic_check(magic, magicfile); @@ -321,7 +339,7 @@ main(int argc, char *argv[]) if (magic == NULL) if ((magic = load(magicfile, flags)) == NULL) return 1; - break; + applyparam(magic); } if (optind == argc) { @@ -351,6 +369,41 @@ main(int argc, char *argv[]) return e; } +private void +applyparam(magic_t magic) +{ + size_t i; + + for (i = 0; i < __arraycount(pm); i++) { + if (pm[i].value == 0) + continue; + if (magic_setparam(magic, pm[i].tag, &pm[i].value) == -1) { + (void)fprintf(stderr, "%s: Can't set %s %s\n", progname, + pm[i].name, strerror(errno)); + exit(1); + } + } +} + +private void +setparam(const char *p) +{ + size_t i; + char *s; + + if ((s = strchr(p, '=')) == NULL) + goto badparm; + + for (i = 0; i < __arraycount(pm); i++) { + if (strncmp(p, pm[i].name, s - p) != 0) + continue; + pm[i].value = atoi(s + 1); + return; + } +badparm: + (void)fprintf(stderr, "%s: Unknown param %s\n", progname, p); + exit(1); +} private struct magic_set * /*ARGSUSED*/ diff --git a/contrib/file/src/file.h b/contrib/file/src/file.h index 1a652a8..14fa836 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.152 2014/06/03 19:01:34 christos Exp $ + * @(#)$File: file.h,v 1.161 2014/12/04 15:56:46 christos Exp $ */ #ifndef __file_h__ @@ -64,7 +64,9 @@ #include <regex.h> #include <time.h> #include <sys/types.h> +#ifndef WIN32 #include <sys/param.h> +#endif /* Do this here and now, because struct stat gets re-defined on solaris */ #include <sys/stat.h> #include <stdarg.h> @@ -401,6 +403,14 @@ struct magic_set { /* FIXME: Make the string dynamically allocated so that e.g. strings matched in files can be longer than MAXstring */ union VALUETYPE ms_value; /* either number or string */ + uint16_t indir_max; + uint16_t name_max; + uint16_t elf_shnum_max; + uint16_t elf_phnum_max; +#define FILE_INDIR_MAX 15 +#define FILE_NAME_MAX 30 +#define FILE_ELF_SHNUM_MAX 32768 +#define FILE_ELF_PHNUM_MAX 128 }; /* Type for Unicode characters */ @@ -440,8 +450,10 @@ protected int file_encoding(struct magic_set *, const unsigned char *, size_t, unichar **, size_t *, const char **, const char **, const char **); protected int file_is_tar(struct magic_set *, const unsigned char *, size_t); protected int file_softmagic(struct magic_set *, const unsigned char *, size_t, - size_t, int, int); + uint16_t, uint16_t *, int, int); protected int file_apprentice(struct magic_set *, const char *, int); +protected int buffer_apprentice(struct magic_set *, struct magic **, + size_t *, size_t); protected int file_magicfind(struct magic_set *, const char *, struct mlist *); protected uint64_t file_signextend(struct magic_set *, struct magic *, uint64_t); @@ -469,9 +481,20 @@ protected int file_os2_apptype(struct magic_set *, const char *, const void *, size_t); #endif /* __EMX__ */ +#if defined(HAVE_LOCALE_H) +#include <locale.h> +#endif +#if defined(HAVE_XLOCALE_H) +#include <xlocale.h> +#endif + typedef struct { const char *pat; - char *old_lc_ctype; +#if defined(HAVE_NEWLOCALE) && defined(HAVE_USELOCALE) && defined(HAVE_FREELOCALE) +#define USE_C_LOCALE + locale_t old_lc_ctype; + locale_t c_lc_ctype; +#endif int rc; regex_t rx; } file_regex_t; diff --git a/contrib/file/src/file_opts.h b/contrib/file/src/file_opts.h index db34eb7..9cb1d01 100644 --- a/contrib/file/src/file_opts.h +++ b/contrib/file/src/file_opts.h @@ -44,6 +44,7 @@ OPT('0', "print0", 0, " terminate filenames with ASCII NUL\n") OPT('p', "preserve-date", 0, " preserve access times on files\n") #endif 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/fsmagic.c b/contrib/file/src/fsmagic.c index ef5492f..1e8fd74 100644 --- a/contrib/file/src/fsmagic.c +++ b/contrib/file/src/fsmagic.c @@ -32,7 +32,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: fsmagic.c,v 1.73 2014/05/14 23:15:42 christos Exp $") +FILE_RCSID("@(#)$File: fsmagic.c,v 1.75 2014/12/04 15:56:46 christos Exp $") #endif /* lint */ #include "magic.h" @@ -75,10 +75,10 @@ bad_link(struct magic_set *ms, int err, char *buf) else if (!mime) { if (ms->flags & MAGIC_ERROR) { file_error(ms, err, - "broken symbolic link to `%s'", buf); + "broken symbolic link to %s", buf); return -1; } - if (file_printf(ms, "broken symbolic link to `%s'", buf) == -1) + if (file_printf(ms, "broken symbolic link to %s", buf) == -1) return -1; } return 1; @@ -129,7 +129,7 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb) #ifdef WIN32 { - HANDLE hFile = CreateFile(fn, 0, FILE_SHARE_DELETE | + HANDLE hFile = CreateFile((LPCSTR)fn, 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (hFile != INVALID_HANDLE_VALUE) { @@ -352,7 +352,7 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb) if (mime) { if (handle_mime(ms, mime, "symlink") == -1) return -1; - } else if (file_printf(ms, "%ssymbolic link to `%s'", + } else if (file_printf(ms, "%ssymbolic link to %s", COMMA, buf) == -1) return -1; } diff --git a/contrib/file/src/funcs.c b/contrib/file/src/funcs.c index 7e7d2e7..f190349 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.72 2014/05/14 23:15:42 christos Exp $") +FILE_RCSID("@(#)$File: funcs.c,v 1.77 2014/11/28 02:46:39 christos Exp $") #endif /* lint */ #include "magic.h" @@ -45,9 +45,6 @@ FILE_RCSID("@(#)$File: funcs.c,v 1.72 2014/05/14 23:15:42 christos Exp $") #if defined(HAVE_LIMITS_H) #include <limits.h> #endif -#if defined(HAVE_LOCALE_H) -#include <locale.h> -#endif #ifndef SIZE_MAX #define SIZE_MAX ((size_t)~0) @@ -230,7 +227,7 @@ file_buffer(struct magic_set *ms, int fd, const char *inname __attribute__ ((unu /* try soft magic tests */ if ((ms->flags & MAGIC_NO_CHECK_SOFT) == 0) - if ((m = file_softmagic(ms, ubuf, nb, 0, BINTEST, + if ((m = file_softmagic(ms, ubuf, nb, 0, NULL, BINTEST, looks_text)) != 0) { if ((ms->flags & MAGIC_DEBUG) != 0) (void)fprintf(stderr, "softmagic %d\n", m); @@ -455,13 +452,14 @@ out: protected int file_regcomp(file_regex_t *rx, const char *pat, int flags) { - rx->old_lc_ctype = setlocale(LC_CTYPE, NULL); - assert(rx->old_lc_ctype != NULL); - rx->old_lc_ctype = strdup(rx->old_lc_ctype); +#ifdef USE_C_LOCALE + rx->c_lc_ctype = newlocale(LC_CTYPE_MASK, "C", 0); + assert(rx->c_lc_ctype != NULL); + rx->old_lc_ctype = uselocale(rx->c_lc_ctype); assert(rx->old_lc_ctype != NULL); +#endif rx->pat = pat; - (void)setlocale(LC_CTYPE, "C"); return rx->rc = regcomp(&rx->rx, pat, flags); } @@ -478,8 +476,10 @@ file_regfree(file_regex_t *rx) { if (rx->rc == 0) regfree(&rx->rx); - (void)setlocale(LC_CTYPE, rx->old_lc_ctype); - free(rx->old_lc_ctype); +#ifdef USE_C_LOCALE + (void)uselocale(rx->old_lc_ctype); + freelocale(rx->c_lc_ctype); +#endif } protected void diff --git a/contrib/file/src/getline.c b/contrib/file/src/getline.c index 99cd150..ab5e115 100644 --- a/contrib/file/src/getline.c +++ b/contrib/file/src/getline.c @@ -1,4 +1,4 @@ -/* $NetBSD: fgetln.c,v 1.9 2008/04/29 06:53:03 martin Exp $ */ +/* $NetBSD: getline.c,v 1.2 2014/09/16 17:23:50 christos Exp $ */ /*- * Copyright (c) 2011 The NetBSD Foundation, Inc. @@ -52,10 +52,14 @@ getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp) for (ptr = *buf, eptr = *buf + *bufsiz;;) { int c = fgetc(fp); if (c == -1) { - if (feof(fp)) - return ptr == *buf ? -1 : ptr - *buf; - else - return -1; + if (feof(fp)) { + ssize_t diff = (ssize_t)(ptr - *buf); + if (diff != 0) { + *ptr = '\0'; + return diff; + } + } + return -1; } *ptr++ = c; if (c == delimiter) { @@ -93,7 +97,7 @@ main(int argc, char *argv[]) size_t n = 0; while ((len = getline(&p, &n, stdin)) != -1) - (void)printf("%zd %s", len, p); + (void)printf("%" SIZE_T_FORMAT "d %s", len, p); free(p); return 0; } diff --git a/contrib/file/src/magic.c b/contrib/file/src/magic.c index e4bd12b..b0cf11c 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.84 2014/05/14 23:15:42 christos Exp $") +FILE_RCSID("@(#)$File: magic.c,v 1.90 2014/12/04 15:56:46 christos Exp $") #endif /* lint */ #include "magic.h" @@ -128,6 +128,7 @@ out: #else char *hmagicp; char *tmppath = NULL; + LPTSTR dllpath; hmagicpath = NULL; #define APPENDPATH() \ @@ -173,7 +174,7 @@ out: } /* Third, try to get magic file relative to dll location */ - LPTSTR dllpath = malloc(sizeof(*dllpath) * (MAX_PATH + 1)); + dllpath = malloc(sizeof(*dllpath) * (MAX_PATH + 1)); dllpath[MAX_PATH] = 0; /* just in case long path gets truncated and not null terminated */ if (GetModuleFileNameA(NULL, dllpath, MAX_PATH)){ PathRemoveFileSpecA(dllpath); @@ -257,6 +258,20 @@ magic_load(struct magic_set *ms, const char *magicfile) return file_apprentice(ms, magicfile, FILE_LOAD); } +#ifndef COMPILE_ONLY +/* + * Install a set of compiled magic buffers. + */ +public int +magic_load_buffers(struct magic_set *ms, void **bufs, size_t *sizes, + size_t nbufs) +{ + if (ms == NULL) + return -1; + return buffer_apprentice(ms, (struct magic **)bufs, sizes, nbufs); +} +#endif + public int magic_compile(struct magic_set *ms, const char *magicfile) { @@ -522,3 +537,47 @@ magic_version(void) { return MAGIC_VERSION; } + +public int +magic_setparam(struct magic_set *ms, int param, const void *val) +{ + switch (param) { + case MAGIC_PARAM_INDIR_MAX: + ms->indir_max = *(const size_t *)val; + return 0; + case MAGIC_PARAM_NAME_MAX: + ms->name_max = *(const size_t *)val; + return 0; + case MAGIC_PARAM_ELF_PHNUM_MAX: + ms->elf_phnum_max = *(const size_t *)val; + return 0; + case MAGIC_PARAM_ELF_SHNUM_MAX: + ms->elf_shnum_max = *(const size_t *)val; + return 0; + default: + errno = EINVAL; + return -1; + } +} + +public int +magic_getparam(struct magic_set *ms, int param, void *val) +{ + switch (param) { + case MAGIC_PARAM_INDIR_MAX: + *(size_t *)val = ms->indir_max; + return 0; + case MAGIC_PARAM_NAME_MAX: + *(size_t *)val = ms->name_max; + return 0; + case MAGIC_PARAM_ELF_PHNUM_MAX: + *(size_t *)val = ms->elf_phnum_max; + return 0; + case MAGIC_PARAM_ELF_SHNUM_MAX: + *(size_t *)val = ms->elf_shnum_max; + return 0; + default: + errno = EINVAL; + return -1; + } +} diff --git a/contrib/file/src/magic.h b/contrib/file/src/magic.h index 38e59d7..94cb397 100644 --- a/contrib/file/src/magic.h +++ b/contrib/file/src/magic.h @@ -75,7 +75,7 @@ #define MAGIC_NO_CHECK_FORTRAN 0x000000 /* Don't check ascii/fortran */ #define MAGIC_NO_CHECK_TROFF 0x000000 /* Don't check ascii/troff */ -#define MAGIC_VERSION 518 /* This implementation */ +#define MAGIC_VERSION 521 /* This implementation */ #ifdef __cplusplus @@ -96,11 +96,21 @@ int magic_setflags(magic_t, int); int magic_version(void); int magic_load(magic_t, const char *); +int magic_load_buffers(magic_t, void **, size_t *, size_t); + int magic_compile(magic_t, const char *); int magic_check(magic_t, const char *); int magic_list(magic_t, const char *); int magic_errno(magic_t); +#define MAGIC_PARAM_INDIR_MAX 0 +#define MAGIC_PARAM_NAME_MAX 1 +#define MAGIC_PARAM_ELF_PHNUM_MAX 2 +#define MAGIC_PARAM_ELF_SHNUM_MAX 3 + +int magic_setparam(magic_t, int, const void *); +int magic_getparam(magic_t, int, void *); + #ifdef __cplusplus }; #endif diff --git a/contrib/file/src/magic.h.in b/contrib/file/src/magic.h.in index 86fc41b..856478b 100644 --- a/contrib/file/src/magic.h.in +++ b/contrib/file/src/magic.h.in @@ -96,11 +96,21 @@ int magic_setflags(magic_t, int); int magic_version(void); int magic_load(magic_t, const char *); +int magic_load_buffers(magic_t, void **, size_t *, size_t); + int magic_compile(magic_t, const char *); int magic_check(magic_t, const char *); int magic_list(magic_t, const char *); int magic_errno(magic_t); +#define MAGIC_PARAM_INDIR_MAX 0 +#define MAGIC_PARAM_NAME_MAX 1 +#define MAGIC_PARAM_ELF_PHNUM_MAX 2 +#define MAGIC_PARAM_ELF_SHNUM_MAX 3 + +int magic_setparam(magic_t, int, const void *); +int magic_getparam(magic_t, int, void *); + #ifdef __cplusplus }; #endif diff --git a/contrib/file/src/pread.c b/contrib/file/src/pread.c index 649f609..72d3a6b 100644 --- a/contrib/file/src/pread.c +++ b/contrib/file/src/pread.c @@ -1,14 +1,23 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: pread.c,v 1.2 2013/04/02 16:23:07 christos Exp $") +FILE_RCSID("@(#)$File: pread.c,v 1.3 2014/09/15 19:11:25 christos Exp $") #endif /* lint */ #include <fcntl.h> #include <unistd.h> ssize_t pread(int fd, void *buf, size_t len, off_t off) { - if (lseek(fd, off, SEEK_SET) == (off_t)-1) + off_t old; + ssize_t rv; + + if ((old = lseek(fd, off, SEEK_SET)) == -1) + return -1; + + if ((rv = read(fd, buf, len)) == -1) + return -1; + + if (lseek(fd, old, SEEK_SET) == -1) return -1; - return read(fd, buf, len); + return rv; } diff --git a/contrib/file/src/readcdf.c b/contrib/file/src/readcdf.c index 7ced9ea..635a926 100644 --- a/contrib/file/src/readcdf.c +++ b/contrib/file/src/readcdf.c @@ -26,7 +26,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: readcdf.c,v 1.44 2014/05/14 23:22:48 christos Exp $") +FILE_RCSID("@(#)$File: readcdf.c,v 1.49 2014/12/04 15:56:46 christos Exp $") #endif #include <assert.h> @@ -35,9 +35,6 @@ FILE_RCSID("@(#)$File: readcdf.c,v 1.44 2014/05/14 23:22:48 christos Exp $") #include <string.h> #include <time.h> #include <ctype.h> -#if defined(HAVE_LOCALE_H) -#include <locale.h> -#endif #include "cdf.h" #include "magic.h" @@ -75,7 +72,7 @@ static const struct cv { const char *mime; } clsid2mime[] = { { - { 0x00000000000c1084LLU, 0x46000000000000c0LLU }, + { 0x00000000000c1084ULL, 0x46000000000000c0ULL }, "x-msi", }, { { 0, 0 }, @@ -83,7 +80,7 @@ static const struct cv { }, }, clsid2desc[] = { { - { 0x00000000000c1084LLU, 0x46000000000000c0LLU }, + { 0x00000000000c1084ULL, 0x46000000000000c0ULL }, "MSI Installer", }, { { 0, 0 }, @@ -107,20 +104,23 @@ cdf_app_to_mime(const char *vbuf, const struct nv *nv) { size_t i; const char *rv = NULL; - char *old_lc_ctype; +#ifdef USE_C_LOCALE + locale_t old_lc_ctype, c_lc_ctype; - old_lc_ctype = setlocale(LC_CTYPE, NULL); - assert(old_lc_ctype != NULL); - old_lc_ctype = strdup(old_lc_ctype); + c_lc_ctype = newlocale(LC_CTYPE_MASK, "C", 0); + assert(c_lc_ctype != NULL); + old_lc_ctype = uselocale(c_lc_ctype); assert(old_lc_ctype != NULL); - (void)setlocale(LC_CTYPE, "C"); +#endif for (i = 0; nv[i].pattern != NULL; i++) if (strcasestr(vbuf, nv[i].pattern) != NULL) { rv = nv[i].mime; break; } - (void)setlocale(LC_CTYPE, old_lc_ctype); - free(old_lc_ctype); +#ifdef USE_C_LOCALE + (void)uselocale(old_lc_ctype); + freelocale(c_lc_ctype); +#endif return rv; } @@ -241,6 +241,37 @@ cdf_file_property_info(struct magic_set *ms, const cdf_property_info_t *info, } private int +cdf_file_catalog(struct magic_set *ms, const cdf_header_t *h, + const cdf_stream_t *sst) +{ + cdf_catalog_t *cat; + size_t i; + char buf[256]; + cdf_catalog_entry_t *ce; + + if (NOTMIME(ms)) { + if (file_printf(ms, "Microsoft Thumbs.db [") == -1) + return -1; + if (cdf_unpack_catalog(h, sst, &cat) == -1) + return -1; + ce = cat->cat_e; + /* skip first entry since it has a , or paren */ + for (i = 1; i < cat->cat_num; i++) + if (file_printf(ms, "%s%s", + cdf_u16tos8(buf, ce[i].ce_namlen, ce[i].ce_name), + i == cat->cat_num - 1 ? "]" : ", ") == -1) { + free(cat); + return -1; + } + free(cat); + } else { + if (file_printf(ms, "application/CDFV2") == -1) + return -1; + } + return 1; +} + +private int cdf_file_summary_info(struct magic_set *ms, const cdf_header_t *h, const cdf_stream_t *sst, const cdf_directory_t *root_storage) { @@ -285,11 +316,12 @@ cdf_file_summary_info(struct magic_set *ms, const cdf_header_t *h, if (root_storage) { str = cdf_clsid_to_mime(root_storage->d_storage_uuid, clsid2desc); - if (str) + if (str) { if (file_printf(ms, ", %s", str) == -1) return -2; } } + } m = cdf_file_property_info(ms, info, count, root_storage); free(info); @@ -302,11 +334,11 @@ private char * format_clsid(char *buf, size_t len, const uint64_t uuid[2]) { snprintf(buf, len, "%.8" PRIx64 "-%.4" PRIx64 "-%.4" PRIx64 "-%.4" PRIx64 "-%.12" PRIx64, - (uuid[0] >> 32) & (uint64_t)0x000000000ffffffffLLU, - (uuid[0] >> 16) & (uint64_t)0x0000000000000ffffLLU, - (uuid[0] >> 0) & (uint64_t)0x0000000000000ffffLLU, - (uuid[1] >> 48) & (uint64_t)0x0000000000000ffffLLU, - (uuid[1] >> 0) & (uint64_t)0x0000fffffffffffffLLU); + (uuid[0] >> 32) & (uint64_t)0x000000000ffffffffULL, + (uuid[0] >> 16) & (uint64_t)0x0000000000000ffffULL, + (uuid[0] >> 0) & (uint64_t)0x0000000000000ffffULL, + (uuid[1] >> 48) & (uint64_t)0x0000000000000ffffULL, + (uuid[1] >> 0) & (uint64_t)0x0000fffffffffffffULL); return buf; } #endif @@ -323,6 +355,7 @@ file_trycdf(struct magic_set *ms, int fd, const unsigned char *buf, int i; const char *expn = ""; const char *corrupt = "corrupt: "; + const cdf_directory_t *root_storage; info.i_fd = fd; info.i_buf = buf; @@ -356,7 +389,6 @@ file_trycdf(struct magic_set *ms, int fd, const unsigned char *buf, goto out2; } - const cdf_directory_t *root_storage; if ((i = cdf_read_short_stream(&info, &h, &sat, &dir, &sst, &root_storage)) == -1) { expn = "Cannot read short stream"; @@ -404,8 +436,24 @@ file_trycdf(struct magic_set *ms, int fd, const unsigned char *buf, if ((i = cdf_read_summary_info(&info, &h, &sat, &ssat, &sst, &dir, &scn)) == -1) { if (errno == ESRCH) { - corrupt = expn; - expn = "No summary info"; + if ((i = cdf_read_catalog(&info, &h, &sat, &ssat, &sst, + &dir, &scn)) == -1) { + corrupt = expn; + if ((i = cdf_read_encrypted_package(&info, &h, + &sat, &ssat, &sst, &dir, &scn)) == -1) + expn = "No summary info"; + else { + expn = "Encrypted"; + i = -1; + } + goto out4; + } +#ifdef CDF_DEBUG + cdf_dump_catalog(&h, &scn); +#endif + if ((i = cdf_file_catalog(ms, &h, &scn)) + < 0) + expn = "Can't expand catalog"; } else { expn = "Cannot read summary info"; } @@ -464,7 +512,8 @@ out0: if (file_printf(ms, ", %s%s", corrupt, expn) == -1) return -1; } else { - if (file_printf(ms, "application/CDFV2-corrupt") == -1) + if (file_printf(ms, "application/CDFV2-%s", + *corrupt ? "corrupt" : "encrypted") == -1) return -1; } i = 1; diff --git a/contrib/file/src/readelf.c b/contrib/file/src/readelf.c index 55b7e98..08a2afb 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.103 2014/05/02 02:25:10 christos Exp $") +FILE_RCSID("@(#)$File: readelf.c,v 1.111 2014/12/09 02:47:45 christos Exp $") #endif #ifdef BUILTIN_ELF @@ -60,8 +60,9 @@ private uint16_t getu16(int, uint16_t); private uint32_t getu32(int, uint32_t); private uint64_t getu64(int, uint64_t); -#define MAX_PHNUM 256 -#define MAX_SHNUM 1024 +#define MAX_PHNUM 128 +#define MAX_SHNUM 32768 +#define SIZE_UNKNOWN ((off_t)-1) private int toomany(struct magic_set *ms, const char *name, uint16_t num) @@ -324,7 +325,7 @@ dophn_core(struct magic_set *ms, int clazz, int swap, int fd, off_t off, } off += size; - if (xph_offset > fsize) { + if (fsize != SIZE_UNKNOWN && xph_offset > fsize) { /* Perhaps warn here */ continue; } @@ -964,7 +965,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, stripped = 0; break; default: - if (xsh_offset > fsize) { + if (fsize != SIZE_UNKNOWN && xsh_offset > fsize) { /* Perhaps warn here */ continue; } @@ -1190,7 +1191,7 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, shared_libraries = " (uses shared libs)"; break; default: - if (xph_offset > fsize) { + if (fsize != SIZE_UNKNOWN && xph_offset > fsize) { /* Maybe warn here? */ continue; } @@ -1200,7 +1201,8 @@ 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_NOTE: - if ((align = xph_align) & 0x80000000UL) { + if (((align = xph_align) & 0x80000000UL) != 0 || + align < 4) { if (file_printf(ms, ", invalid note alignment 0x%lx", (unsigned long)align) == -1) @@ -1283,7 +1285,10 @@ file_tryelf(struct magic_set *ms, int fd, const unsigned char *buf, file_badread(ms); return -1; } - fsize = st.st_size; + if (S_ISREG(st.st_mode) || st.st_size != 0) + fsize = st.st_size; + else + fsize = SIZE_UNKNOWN; clazz = buf[EI_CLASS]; diff --git a/contrib/file/src/softmagic.c b/contrib/file/src/softmagic.c index b0f193d..c20ae67 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.191 2014/06/04 17:36:34 christos Exp $") +FILE_RCSID("@(#)$File: softmagic.c,v 1.203 2014/12/04 15:22:05 christos Exp $") #endif /* lint */ #include "magic.h" @@ -41,17 +41,13 @@ FILE_RCSID("@(#)$File: softmagic.c,v 1.191 2014/06/04 17:36:34 christos Exp $") #include <ctype.h> #include <stdlib.h> #include <time.h> -#if defined(HAVE_LOCALE_H) -#include <locale.h> -#endif - private int match(struct magic_set *, struct magic *, uint32_t, - const unsigned char *, size_t, size_t, int, int, int, int, int *, int *, - int *); + const unsigned char *, size_t, size_t, int, int, int, uint16_t, + uint16_t *, int *, int *, int *); private int mget(struct magic_set *, const unsigned char *, - struct magic *, size_t, size_t, unsigned int, int, int, int, int, int *, - int *, int *); + struct magic *, size_t, size_t, unsigned int, int, int, int, uint16_t, + uint16_t *, int *, int *, int *); private int magiccheck(struct magic_set *, struct magic *); private int32_t mprint(struct magic_set *, struct magic *); private int32_t moffset(struct magic_set *, struct magic *); @@ -68,8 +64,6 @@ private void cvt_64(union VALUETYPE *, const struct magic *); #define OFFSET_OOB(n, o, i) ((n) < (o) || (i) > ((n) - (o))) -#define MAX_RECURSION_LEVEL 10 - /* * softmagic - lookup one file in parsed, in-memory copy of database * Passed the name and FILE * of one file to be typed. @@ -77,14 +71,21 @@ private void cvt_64(union VALUETYPE *, const struct magic *); /*ARGSUSED1*/ /* nbytes passed for regularity, maybe need later */ protected int file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes, - size_t level, int mode, int text) + uint16_t indir_level, uint16_t *name_count, int mode, int text) { struct mlist *ml; int rv, printed_something = 0, need_separator = 0; + uint16_t nc; + + if (name_count == NULL) { + nc = 0; + name_count = &nc; + } + for (ml = ms->mlist[0]->next; ml != ms->mlist[0]; ml = ml->next) if ((rv = match(ms, ml->magic, ml->nmagic, buf, nbytes, 0, mode, - text, 0, level, &printed_something, &need_separator, - NULL)) != 0) + text, 0, indir_level, name_count, + &printed_something, &need_separator, NULL)) != 0) return rv; return 0; @@ -101,8 +102,8 @@ file_fmtcheck(struct magic_set *ms, const struct magic *m, const char *def, const char *ptr = fmtcheck(m->desc, def); if (ptr == def) file_magerror(ms, - "%s, %zu: format `%s' does not match with `%s'", - file, line, m->desc, def); + "%s, %" SIZE_T_FORMAT "u: format `%s' does not match" + " with `%s'", file, line, m->desc, def); return ptr; } #else @@ -139,8 +140,8 @@ file_fmtcheck(struct magic_set *ms, const struct magic *m, const char *def, private int match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, const unsigned char *s, size_t nbytes, size_t offset, int mode, int text, - int flip, int recursion_level, int *printed_something, int *need_separator, - int *returnval) + int flip, uint16_t indir_level, uint16_t *name_count, + int *printed_something, int *need_separator, int *returnval) { uint32_t magindex = 0; unsigned int cont_level = 0; @@ -177,8 +178,8 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, /* if main entry matches, print it... */ switch (mget(ms, s, m, nbytes, offset, cont_level, mode, text, - flip, recursion_level + 1, printed_something, - need_separator, returnval)) { + flip, indir_level, name_count, + printed_something, need_separator, returnval)) { case -1: return -1; case 0: @@ -238,9 +239,9 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, if (file_check_mem(ms, ++cont_level) == -1) return -1; - while (++magindex < nmagic && - magic[magindex].cont_level != 0) { - m = &magic[magindex]; + while (magindex + 1 < nmagic && + magic[magindex + 1].cont_level != 0) { + m = &magic[++magindex]; ms->line = m->lineno; /* for messages */ if (cont_level < m->cont_level) @@ -266,8 +267,8 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, } #endif switch (mget(ms, s, m, nbytes, offset, cont_level, mode, - text, flip, recursion_level + 1, printed_something, - need_separator, returnval)) { + text, flip, indir_level, name_count, + printed_something, need_separator, returnval)) { case -1: return -1; case 0: @@ -403,6 +404,28 @@ 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) { @@ -509,6 +532,7 @@ mprint(struct magic_set *ms, struct magic *m) t = ms->offset + m->vallen; } else { + char sbuf[512]; char *str = p->s; /* compute t before we mangle the string? */ @@ -530,7 +554,8 @@ mprint(struct magic_set *ms, struct magic *m) *++last = '\0'; } - if (file_printf(ms, F(ms, m, "%s"), str) == -1) + if (file_printf(ms, F(ms, m, "%s"), + printable(sbuf, sizeof(sbuf), str)) == -1) return -1; if (m->type == FILE_PSTRING) @@ -946,14 +971,17 @@ mconvert(struct magic_set *ms, struct magic *m, int flip) size_t sz = file_pstring_length_size(m); char *ptr1 = p->s, *ptr2 = ptr1 + sz; size_t len = file_pstring_get_length(m, ptr1); - if (len >= sizeof(p->s)) { + sz = sizeof(p->s) - sz; /* maximum length of string */ + if (len >= sz) { /* * The size of the pascal string length (sz) * is 1, 2, or 4. We need at least 1 byte for NUL * termination, but we've already truncated the * string by p->s, so we need to deduct sz. + * Because we can use one of the bytes of the length + * after we shifted as NUL termination. */ - len = sizeof(p->s) - sz; + len = sz; } while (len--) *ptr1++ = *ptr2++; @@ -1063,7 +1091,7 @@ mconvert(struct magic_set *ms, struct magic *m, int flip) private void mdebug(uint32_t offset, const char *str, size_t len) { - (void) fprintf(stderr, "mget/%zu @%d: ", len, offset); + (void) fprintf(stderr, "mget/%" SIZE_T_FORMAT "u @%d: ", len, offset); file_showstr(stderr, str, len); (void) fputc('\n', stderr); (void) fputc('\n', stderr); @@ -1193,8 +1221,8 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir, private int mget(struct magic_set *ms, const unsigned char *s, struct magic *m, size_t nbytes, size_t o, unsigned int cont_level, int mode, int text, - int flip, int recursion_level, int *printed_something, - int *need_separator, int *returnval) + int flip, uint16_t indir_level, uint16_t *name_count, + int *printed_something, int *need_separator, int *returnval) { uint32_t offset = ms->offset; uint32_t lhs; @@ -1204,8 +1232,15 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m, union VALUETYPE *p = &ms->ms_value; struct mlist ml; - if (recursion_level >= MAX_RECURSION_LEVEL) { - file_error(ms, 0, "recursion nesting exceeded"); + if (indir_level >= ms->indir_max) { + file_error(ms, 0, "indirect recursion nesting (%hu) exceeded", + indir_level); + return -1; + } + + if (*name_count >= ms->name_max) { + file_error(ms, 0, "name use count (%hu) exceeded", + *name_count); return -1; } @@ -1214,8 +1249,11 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m, return -1; if ((ms->flags & MAGIC_DEBUG) != 0) { - fprintf(stderr, "mget(type=%d, flag=%x, offset=%u, o=%zu, " - "nbytes=%zu)\n", m->type, m->flag, offset, o, nbytes); + fprintf(stderr, "mget(type=%d, flag=%x, offset=%u, o=%" + SIZE_T_FORMAT "u, " "nbytes=%" SIZE_T_FORMAT + "u, il=%hu, nc=%hu)\n", + m->type, m->flag, offset, o, nbytes, + indir_level, *name_count); mdebug(offset, (char *)(void *)p, sizeof(union VALUETYPE)); #ifndef COMPILE_ONLY file_mdump(m); @@ -1656,7 +1694,7 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m, return -1; rv = file_softmagic(ms, s + offset, nbytes - offset, - recursion_level, BINTEST, text); + indir_level + 1, name_count, BINTEST, text); if ((ms->flags & MAGIC_DEBUG) != 0) fprintf(stderr, "indirect @offs=%u[%d]\n", offset, rv); @@ -1691,13 +1729,13 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m, file_error(ms, 0, "cannot find entry `%s'", rbuf); return -1; } - + (*name_count)++; oneed_separator = *need_separator; if (m->flag & NOSPACE) *need_separator = 0; rv = match(ms, ml.magic, ml.nmagic, s, nbytes, offset + o, - mode, text, flip, recursion_level, printed_something, - need_separator, returnval); + mode, text, flip, indir_level, name_count, + printed_something, need_separator, returnval); if (rv != 1) *need_separator = oneed_separator; return rv; @@ -1952,6 +1990,7 @@ magiccheck(struct magic_set *ms, struct magic *m) case FILE_REGEX: { int rc; file_regex_t rx; + const char *search; if (ms->search.s == NULL) return 0; @@ -1968,19 +2007,31 @@ magiccheck(struct magic_set *ms, struct magic *m) size_t slen = ms->search.s_len; #ifndef REG_STARTEND #define REG_STARTEND 0 - char c; - if (slen != 0) - slen--; - c = ms->search.s[slen]; - ((char *)(intptr_t)ms->search.s)[slen] = '\0'; + char *copy; + if (slen != 0) { + copy = malloc(slen); + if (copy == NULL) { + file_error(ms, errno, + "can't allocate %" SIZE_T_FORMAT "u bytes", + slen); + return -1; + } + memcpy(copy, ms->search.s, slen); + copy[--slen] = '\0'; + search = copy; + } else { + search = ms->search.s; + copy = NULL; + } #else + search = ms->search.s; pmatch[0].rm_so = 0; pmatch[0].rm_eo = slen; #endif - rc = file_regexec(&rx, (const char *)ms->search.s, + rc = file_regexec(&rx, (const char *)search, 1, pmatch, REG_STARTEND); #if REG_STARTEND == 0 - ((char *)(intptr_t)ms->search.s)[l] = c; + free(copy); #endif switch (rc) { case 0: diff --git a/contrib/file/src/vasprintf.c b/contrib/file/src/vasprintf.c index cc43ae3..7a18bed 100644 --- a/contrib/file/src/vasprintf.c +++ b/contrib/file/src/vasprintf.c @@ -108,7 +108,7 @@ you use strange formats. #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: vasprintf.c,v 1.12 2014/05/14 23:09:21 christos Exp $") +FILE_RCSID("@(#)$File: vasprintf.c,v 1.13 2014/12/04 15:56:46 christos Exp $") #endif /* lint */ #include <assert.h> @@ -633,11 +633,15 @@ int vasprintf(char **ptr, const char *format_string, va_list vargs) #ifdef va_copy va_copy (s.vargs, vargs); #else -#ifdef __va_copy +# ifdef __va_copy __va_copy (s.vargs, vargs); -#else +# else +# ifdef WIN32 + s.vargs = vargs; +# else memcpy (&s.vargs, &vargs, sizeof (s.va_args)); -#endif /* __va_copy */ +# endif /* WIN32 */ +# endif /* __va_copy */ #endif /* va_copy */ s.maxlen = (size_t)INT_MAX; |