diff options
author | Xin LI <delphij@FreeBSD.org> | 2019-11-10 03:44:32 +0000 |
---|---|---|
committer | Xin LI <delphij@FreeBSD.org> | 2019-11-10 03:44:32 +0000 |
commit | 4ef4bf0189e5e736a37f9ead9beaaa8e1cd1f9fb (patch) | |
tree | 0b82394b9b244b8f3a588afe3b96177c08ff98eb /src | |
parent | ad1ba6e1e032f79d03b9a6e2c714de84d1911b3a (diff) |
Notes
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/Makefile.in | 9 | ||||
-rw-r--r-- | src/apprentice.c | 294 | ||||
-rw-r--r-- | src/apptype.c | 12 | ||||
-rw-r--r-- | src/ascmagic.c | 84 | ||||
-rw-r--r-- | src/asprintf.c | 6 | ||||
-rw-r--r-- | src/buffer.c | 17 | ||||
-rw-r--r-- | src/cdf.c | 171 | ||||
-rw-r--r-- | src/cdf.h | 6 | ||||
-rw-r--r-- | src/cdf_time.c | 28 | ||||
-rw-r--r-- | src/compress.c | 298 | ||||
-rw-r--r-- | src/der.c | 37 | ||||
-rw-r--r-- | src/dprintf.c | 6 | ||||
-rw-r--r-- | src/elfclass.h | 18 | ||||
-rw-r--r-- | src/encoding.c | 79 | ||||
-rw-r--r-- | src/file.c | 47 | ||||
-rw-r--r-- | src/file.h | 41 | ||||
-rw-r--r-- | src/fmtcheck.c | 2 | ||||
-rw-r--r-- | src/fsmagic.c | 37 | ||||
-rw-r--r-- | src/funcs.c | 115 | ||||
-rw-r--r-- | src/getopt_long.c | 12 | ||||
-rw-r--r-- | src/is_json.c | 462 | ||||
-rw-r--r-- | src/is_tar.c | 15 | ||||
-rw-r--r-- | src/magic.c | 105 | ||||
-rw-r--r-- | src/magic.h.in | 4 | ||||
-rw-r--r-- | src/mygetopt.h | 2 | ||||
-rw-r--r-- | src/print.c | 42 | ||||
-rw-r--r-- | src/readcdf.c | 57 | ||||
-rw-r--r-- | src/readelf.c | 301 | ||||
-rw-r--r-- | src/readelf.h | 8 | ||||
-rw-r--r-- | src/seccomp.c | 15 | ||||
-rw-r--r-- | src/softmagic.c | 469 | ||||
-rw-r--r-- | src/vasprintf.c | 12 |
33 files changed, 1830 insertions, 985 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index bbd3f5016d5c3..2fbefdbfcb5b3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,14 +8,14 @@ AM_CPPFLAGS = -DMAGIC='"$(MAGIC)"' AM_CFLAGS = $(CFLAG_VISIBILITY) @WARNINGS@ libmagic_la_SOURCES = buffer.c magic.c apprentice.c softmagic.c ascmagic.c \ - encoding.c compress.c is_tar.c readelf.c print.c fsmagic.c \ + encoding.c compress.c is_json.c is_tar.c readelf.c print.c fsmagic.c \ funcs.c file.h readelf.h tar.h apptype.c der.c der.h \ file_opts.h elfclass.h mygetopt.h cdf.c cdf_time.c readcdf.c cdf.h libmagic_la_LDFLAGS = -no-undefined -version-info 1:0:0 if MINGW MINGWLIBS = -lgnurx -lshlwapi else -MINGWLIBS = +MINGWLIBS = endif libmagic_la_LIBADD = $(LTLIBOBJS) $(MINGWLIBS) diff --git a/src/Makefile.in b/src/Makefile.in index afa7bfa061eb3..29567c4702808 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -136,9 +136,9 @@ LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libmagic_la_DEPENDENCIES = $(LTLIBOBJS) $(am__DEPENDENCIES_1) am_libmagic_la_OBJECTS = buffer.lo magic.lo apprentice.lo softmagic.lo \ - ascmagic.lo encoding.lo compress.lo is_tar.lo readelf.lo \ - print.lo fsmagic.lo funcs.lo apptype.lo der.lo cdf.lo \ - cdf_time.lo readcdf.lo + ascmagic.lo encoding.lo compress.lo is_json.lo is_tar.lo \ + readelf.lo print.lo fsmagic.lo funcs.lo apptype.lo der.lo \ + cdf.lo cdf_time.lo readcdf.lo libmagic_la_OBJECTS = $(am_libmagic_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -343,7 +343,7 @@ nodist_include_HEADERS = magic.h AM_CPPFLAGS = -DMAGIC='"$(MAGIC)"' AM_CFLAGS = $(CFLAG_VISIBILITY) @WARNINGS@ libmagic_la_SOURCES = buffer.c magic.c apprentice.c softmagic.c ascmagic.c \ - encoding.c compress.c is_tar.c readelf.c print.c fsmagic.c \ + encoding.c compress.c is_json.c is_tar.c readelf.c print.c fsmagic.c \ funcs.c file.h readelf.h tar.h apptype.c der.c der.h \ file_opts.h elfclass.h mygetopt.h cdf.c cdf_time.c readcdf.c cdf.h @@ -515,6 +515,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsmagic.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/funcs.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/is_json.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/is_tar.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/magic.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/print.Plo@am__quote@ diff --git a/src/apprentice.c b/src/apprentice.c index ea8d0b222e0a8..eca3ae06af99e 100644 --- a/src/apprentice.c +++ b/src/apprentice.c @@ -2,7 +2,7 @@ * Copyright (c) Ian F. Darwin 1986-1995. * Software written by Ian F. Darwin and others; * maintained 1995-present by Christos Zoulas and others. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -12,7 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -32,7 +32,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: apprentice.c,v 1.272 2018/06/22 20:39:50 christos Exp $") +FILE_RCSID("@(#)$File: apprentice.c,v 1.283 2019/02/20 02:35:27 christos Exp $") #endif /* lint */ #include "magic.h" @@ -40,9 +40,7 @@ FILE_RCSID("@(#)$File: apprentice.c,v 1.272 2018/06/22 20:39:50 christos Exp $") #ifdef HAVE_UNISTD_H #include <unistd.h> #endif -#ifdef HAVE_STDDEF_H #include <stddef.h> -#endif #include <string.h> #include <assert.h> #include <ctype.h> @@ -51,20 +49,13 @@ FILE_RCSID("@(#)$File: apprentice.c,v 1.272 2018/06/22 20:39:50 christos Exp $") #include <sys/mman.h> #endif #include <dirent.h> -#if defined(HAVE_LIMITS_H) #include <limits.h> -#endif -#ifndef SSIZE_MAX -#define MAXMAGIC_SIZE ((ssize_t)0x7fffffff) -#else -#define MAXMAGIC_SIZE SSIZE_MAX -#endif -#define EATAB {while (isascii((unsigned char) *l) && \ - isspace((unsigned char) *l)) ++l;} -#define LOWCASE(l) (isupper((unsigned char) (l)) ? \ - tolower((unsigned char) (l)) : (l)) +#define EATAB {while (isascii(CAST(unsigned char, *l)) && \ + isspace(CAST(unsigned char, *l))) ++l;} +#define LOWCASE(l) (isupper(CAST(unsigned char, l)) ? \ + tolower(CAST(unsigned char, l)) : (l)) /* * Work around a bug in headers on Digital Unix. * At least confirmed for: OSF1 V4.0 878 @@ -83,15 +74,15 @@ FILE_RCSID("@(#)$File: apprentice.c,v 1.272 2018/06/22 20:39:50 christos Exp $") #define MAP_FILE 0 #endif -#define ALLOC_CHUNK (size_t)10 -#define ALLOC_INCR (size_t)200 +#define ALLOC_CHUNK CAST(size_t, 10) +#define ALLOC_INCR CAST(size_t, 200) #define MAP_TYPE_USER 0 #define MAP_TYPE_MALLOC 1 #define MAP_TYPE_MMAP 2 struct magic_entry { - struct magic *mp; + struct magic *mp; uint32_t cont_count; uint32_t max_count; }; @@ -126,7 +117,7 @@ private int apprentice_1(struct magic_set *, const char *, int); private size_t apprentice_magic_strength(const struct magic *); private int apprentice_sort(const void *, const void *); private void apprentice_list(struct mlist *, int ); -private struct magic_map *apprentice_load(struct magic_set *, +private struct magic_map *apprentice_load(struct magic_set *, const char *, int); private struct mlist *mlist_alloc(void); private void mlist_free(struct mlist *); @@ -300,12 +291,21 @@ get_type(const struct type_tbl_s *tbl, const char *l, const char **t) return p->type; } +private off_t +maxoff_t(void) { + if (/*CONSTCOND*/sizeof(off_t) == sizeof(int)) + return CAST(off_t, INT_MAX); + if (/*CONSTCOND*/sizeof(off_t) == sizeof(long)) + return CAST(off_t, LONG_MAX); + return 0x7fffffff; +} + private int get_standard_integer_type(const char *l, const char **t) { int type; - if (isalpha((unsigned char)l[1])) { + if (isalpha(CAST(unsigned char, l[1]))) { switch (l[1]) { case 'C': /* "dC" and "uC" */ @@ -340,7 +340,7 @@ get_standard_integer_type(const char *l, const char **t) return FILE_INVALID; } l += 2; - } else if (isdigit((unsigned char)l[1])) { + } else if (isdigit(CAST(unsigned char, l[1]))) { /* * "d{num}" and "u{num}"; we only support {num} values * of 1, 2, 4, and 8 - the Single UNIX Specification @@ -351,7 +351,7 @@ get_standard_integer_type(const char *l, const char **t) * neither of them support values bigger than 8 or * non-power-of-2 values. */ - if (isdigit((unsigned char)l[2])) { + if (isdigit(CAST(unsigned char, l[2]))) { /* Multi-digit, so > 9 */ return FILE_INVALID; } @@ -437,8 +437,8 @@ apprentice_1(struct magic_set *ms, const char *fn, int action) if (magicsize != FILE_MAGICSIZE) { file_error(ms, 0, "magic element size %lu != %lu", - (unsigned long)sizeof(*map->magic[0]), - (unsigned long)FILE_MAGICSIZE); + CAST(unsigned long, sizeof(*map->magic[0])), + CAST(unsigned long, FILE_MAGICSIZE)); return -1; } @@ -451,7 +451,7 @@ apprentice_1(struct magic_set *ms, const char *fn, int action) #ifndef COMPILE_ONLY map = apprentice_map(ms, fn); - if (map == (struct magic_map *)-1) + if (map == RCAST(struct magic_map *, -1)) return -1; if (map == NULL) { if (ms->flags & MAGIC_CHECK) @@ -503,7 +503,7 @@ file_ms_alloc(int flags) struct magic_set *ms; size_t i, len; - if ((ms = CAST(struct magic_set *, calloc((size_t)1, + if ((ms = CAST(struct magic_set *, calloc(CAST(size_t, 1u), sizeof(struct magic_set)))) == NULL) return NULL; @@ -582,6 +582,14 @@ mlist_alloc(void) } private void +mlist_free_one(struct mlist *ml) +{ + if (ml->map) + apprentice_unmap(CAST(struct magic_map *, ml->map)); + free(ml); +} + +private void mlist_free(struct mlist *mlist) { struct mlist *ml, *next; @@ -589,14 +597,11 @@ mlist_free(struct mlist *mlist) if (mlist == NULL) return; - ml = mlist->next; - for (ml = mlist->next; (next = ml->next) != NULL; ml = next) { - if (ml->map) - apprentice_unmap(CAST(struct magic_map *, ml->map)); - free(ml); - if (ml == mlist) - break; + for (ml = mlist->next; ml != mlist; ml = next) { + next = ml->next; + mlist_free_one(ml); } + mlist_free_one(mlist); } #ifndef COMPILE_ONLY @@ -826,7 +831,7 @@ typesize(int type) case FILE_LEDOUBLE: return 8; default: - return (size_t)~0; + return CAST(size_t, ~0); } } @@ -836,8 +841,9 @@ typesize(int type) private size_t apprentice_magic_strength(const struct magic *m) { -#define MULT 10 - size_t ts, v, val = 2 * MULT; /* baseline strength */ +#define MULT 10U + size_t ts, v; + ssize_t val = 2 * MULT; /* baseline strength */ switch (m->type) { case FILE_DEFAULT: /* make sure this sorts last */ @@ -880,7 +886,7 @@ apprentice_magic_strength(const struct magic *m) case FILE_BEDOUBLE: case FILE_LEDOUBLE: ts = typesize(m->type); - if (ts == (size_t)~0) + if (ts == CAST(size_t, ~0)) abort(); val += ts * MULT; break; @@ -896,6 +902,8 @@ apprentice_magic_strength(const struct magic *m) break; case FILE_SEARCH: + if (m->vallen == 0) + break; val += m->vallen * MAX(MULT / m->vallen, 1); break; @@ -943,9 +951,6 @@ apprentice_magic_strength(const struct magic *m) abort(); } - if (val == 0) /* ensure we only return 0 for FILE_DEFAULT */ - val = 1; - switch (m->factor_op) { case FILE_FACTOR_OP_NONE: break; @@ -965,6 +970,9 @@ apprentice_magic_strength(const struct magic *m) abort(); } + if (val <= 0) /* ensure we only return 0 for FILE_DEFAULT */ + val = 1; + /* * Magic entries with no description get a bonus because they depend * on subsequent magic entries to print something. @@ -974,7 +982,7 @@ apprentice_magic_strength(const struct magic *m) return val; } -/* +/* * Sort callback for sorting entries by "strength" (basically length) */ private int @@ -992,7 +1000,7 @@ apprentice_sort(const void *a, const void *b) return 1; } -/* +/* * Shows sorted patterns list in the order which is used for the matching */ private void @@ -1088,12 +1096,12 @@ set_test_type(struct magic *mstart, struct magic *m) mstart->flag |= BINTEST; if (mstart->str_flags & STRING_TEXTTEST) mstart->flag |= TEXTTEST; - + if (mstart->flag & (TEXTTEST|BINTEST)) break; /* binary test if pattern is not text */ - if (file_looks_utf8(m->value.us, (size_t)m->vallen, NULL, + if (file_looks_utf8(m->value.us, CAST(size_t, m->vallen), NULL, NULL) <= 0) mstart->flag |= BINTEST; else @@ -1174,7 +1182,7 @@ load_1(struct magic_set *ms, int action, const char *fn, int *errs, size_t i; for (i = 0; bang[i].name != NULL; i++) { - if ((size_t)(len - 2) > bang[i].len && + if (CAST(size_t, len - 2) > bang[i].len && memcmp(bang[i].name, line + 2, bang[i].len) == 0) break; @@ -1227,7 +1235,7 @@ load_1(struct magic_set *ms, int action, const char *fn, int *errs, private int cmpstrp(const void *p1, const void *p2) { - return strcmp(*(char *const *)p1, *(char *const *)p2); + return strcmp(*RCAST(char *const *, p1), *RCAST(char *const *, p2)); } @@ -1253,10 +1261,10 @@ set_text_binary(struct magic_set *ms, struct magic_entry *me, uint32_t nme, if (me[i].mp->flag & BINTEST) { char *p = strstr(me[i].mp->desc, text); if (p && (p == me[i].mp->desc || - isspace((unsigned char)p[-1])) && + isspace(CAST(unsigned char, p[-1]))) && (p + len - me[i].mp->desc == MAXstring || (p[len] == '\0' || - isspace((unsigned char)p[len])))) + isspace(CAST(unsigned char, p[len]))))) (void)fprintf(stderr, "*** Possible " "binary test for text type\n"); } @@ -1280,7 +1288,7 @@ set_last_default(struct magic_set *ms, struct magic_entry *me, uint32_t nme) file_magwarn(ms, "level 0 \"default\" did not sort last"); } - return; + return; } } } @@ -1387,12 +1395,14 @@ apprentice_load(struct magic_set *ms, const char *fn, int action) filearr[files++] = mfn; } closedir(dir); - qsort(filearr, files, sizeof(*filearr), cmpstrp); - for (i = 0; i < files; i++) { - load_1(ms, action, filearr[i], &errs, mset); - free(filearr[i]); + if (filearr) { + qsort(filearr, files, sizeof(*filearr), cmpstrp); + for (i = 0; i < files; i++) { + load_1(ms, action, filearr[i], &errs, mset); + free(filearr[i]); + } + free(filearr); } - free(filearr); } else load_1(ms, action, fn, &errs, mset); if (errs) @@ -1450,12 +1460,12 @@ file_signextend(struct magic_set *ms, struct magic *m, uint64_t v) * the sign extension must have happened. */ case FILE_BYTE: - v = (signed char) v; + v = CAST(signed char, v); break; case FILE_SHORT: case FILE_BESHORT: case FILE_LESHORT: - v = (short) v; + v = CAST(short, v); break; case FILE_DATE: case FILE_BEDATE: @@ -1472,7 +1482,7 @@ file_signextend(struct magic_set *ms, struct magic *m, uint64_t v) case FILE_FLOAT: case FILE_BEFLOAT: case FILE_LEFLOAT: - v = (int32_t) v; + v = CAST(int32_t, v); break; case FILE_QUAD: case FILE_BEQUAD: @@ -1489,7 +1499,7 @@ file_signextend(struct magic_set *ms, struct magic *m, uint64_t v) case FILE_DOUBLE: case FILE_BEDOUBLE: case FILE_LEDOUBLE: - v = (int64_t) v; + v = CAST(int64_t, v); break; case FILE_STRING: case FILE_PSTRING: @@ -1616,7 +1626,7 @@ get_cond(const char *l, const char **t) for (p = cond_tbl; p->len; p++) { if (strncmp(l, p->name, p->len) == 0 && - isspace((unsigned char)l[p->len])) { + isspace(CAST(unsigned char, l[p->len]))) { if (t) *t = l + p->len; break; @@ -1674,7 +1684,7 @@ parse_indirect_modifier(struct magic_set *ms, struct magic *m, const char **lp) { const char *l = *lp; - while (!isspace((unsigned char)*++l)) + while (!isspace(CAST(unsigned char, *++l))) switch (*l) { case CHAR_INDIRECT_RELATIVE: m->str_flags |= INDIRECT_RELATIVE; @@ -1700,7 +1710,7 @@ parse_op_modifier(struct magic_set *ms, struct magic *m, const char **lp, ++l; m->mask_op |= op; - val = (uint64_t)strtoull(l, &t, 0); + val = CAST(uint64_t, strtoull(l, &t, 0)); l = t; m->num_mask = file_signextend(ms, m, val); eatsize(&l); @@ -1714,7 +1724,7 @@ parse_string_modifier(struct magic_set *ms, struct magic *m, const char **lp) char *t; int have_range = 0; - while (!isspace((unsigned char)*++l)) { + while (!isspace(CAST(unsigned char, *++l))) { switch (*l) { case '0': case '1': case '2': case '3': case '4': case '5': @@ -1796,7 +1806,7 @@ parse_string_modifier(struct magic_set *ms, struct magic *m, const char **lp) goto out; } /* allow multiple '/' for readability */ - if (l[1] == '/' && !isspace((unsigned char)l[2])) + if (l[1] == '/' && !isspace(CAST(unsigned char, l[2]))) l++; } if (string_modifier_check(ms, m) == -1) @@ -1833,7 +1843,7 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line, */ while (*l == '>') { ++l; /* step over */ - cont_level++; + cont_level++; } #ifdef ENABLE_CONDITIONALS if (cont_level == 0 || cont_level > last_cont_level) @@ -1851,7 +1861,7 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line, return -1; } m = &me->mp[me->cont_count - 1]; - diff = (int32_t)cont_level - (int32_t)m->cont_level; + diff = CAST(int32_t, cont_level) - CAST(int32_t, m->cont_level); if (diff > 1) file_magwarn(ms, "New continuation level %u is more " "than one larger than current level %u", cont_level, @@ -1864,7 +1874,7 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line, file_oomem(ms, sizeof(*nm) * cnt); return -1; } - me->mp = m = nm; + me->mp = nm; me->max_count = CAST(uint32_t, cnt); } m = &me->mp[me->cont_count++]; @@ -1910,7 +1920,7 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line, } /* get offset, then skip over it */ - m->offset = (int32_t)strtol(l, &t, 0); + m->offset = CAST(int32_t, strtol(l, &t, 0)); if (l == t) { if (ms->flags & MAGIC_CHECK) file_magwarn(ms, "offset `%s' invalid", l); @@ -2008,8 +2018,8 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line, m->in_op |= FILE_OPINDIRECT; l++; } - if (isdigit((unsigned char)*l) || *l == '-') { - m->in_offset = (int32_t)strtol(l, &t, 0); + if (isdigit(CAST(unsigned char, *l)) || *l == '-') { + m->in_offset = CAST(int32_t, strtol(l, &t, 0)); if (l == t) { if (ms->flags & MAGIC_CHECK) file_magwarn(ms, @@ -2018,7 +2028,7 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line, } l = t; } - if (*l++ != ')' || + if (*l++ != ')' || ((m->in_op & FILE_OPINDIRECT) && *l++ != ')')) { if (ms->flags & MAGIC_CHECK) file_magwarn(ms, @@ -2043,7 +2053,7 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line, /* * Try it as a keyword type prefixed by "u"; match what * follows the "u". If that fails, try it as an SUS - * integer type. + * integer type. */ m->type = get_type(type_tbl, l + 1, &l); if (m->type == FILE_INVALID) { @@ -2072,7 +2082,8 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line, */ if (*l == 'd') m->type = get_standard_integer_type(l, &l); - else if (*l == 's' && !isalpha((unsigned char)l[1])) { + else if (*l == 's' + && !isalpha(CAST(unsigned char, l[1]))) { m->type = FILE_STRING; ++l; } @@ -2083,7 +2094,7 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line, /* Not found - try it as a special keyword. */ m->type = get_type(special_tbl, l, &l); } - + if (m->type == FILE_INVALID) { if (ms->flags & MAGIC_CHECK) file_magwarn(ms, "type `%s' invalid", l); @@ -2130,7 +2141,7 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line, * anything if mask = 0 (unless you have a better idea) */ EATAB; - + switch (*l) { case '>': case '<': @@ -2162,8 +2173,8 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line, break; default: m->reln = '='; /* the default relation */ - if (*l == 'x' && ((isascii((unsigned char)l[1]) && - isspace((unsigned char)l[1])) || !l[1])) { + if (*l == 'x' && ((isascii(CAST(unsigned char, l[1])) && + isspace(CAST(unsigned char, l[1]))) || !l[1])) { m->reln = *l; ++l; } @@ -2177,7 +2188,7 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line, /* * TODO finish this macro and start using it! - * #define offsetcheck {if (offset > ms->bytes_max -1) + * #define offsetcheck {if (offset > ms->bytes_max -1) * magwarn("offset too big"); } */ @@ -2260,11 +2271,11 @@ parse_strength(struct magic_set *ms, struct magic_entry *me, const char *line) file_magwarn(ms, "Too large factor `%lu'", factor); goto out; } - if (*el && !isspace((unsigned char)*el)) { + if (*el && !isspace(CAST(unsigned char, *el))) { file_magwarn(ms, "Bad factor `%s'", l); goto out; } - m->factor = (uint8_t)factor; + m->factor = CAST(uint8_t, factor); if (m->factor == 0 && m->factor_op == FILE_FACTOR_OP_DIV) { file_magwarn(ms, "Cannot have factor op `%c' and factor %u", m->factor_op, m->factor); @@ -2295,9 +2306,9 @@ parse_extra(struct magic_set *ms, struct magic_entry *me, const char *line, if (buf[0] != '\0') { len = nt ? strlen(buf) : len; file_magwarn(ms, "Current entry already has a %s type " - "`%.*s', new type `%s'", name, (int)len, buf, l); + "`%.*s', new type `%s'", name, CAST(int, len), buf, l); return -1; - } + } if (*m->desc == '\0') { file_magwarn(ms, "Current entry does not yet have a " @@ -2316,7 +2327,7 @@ 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)) + if (!isspace(CAST(unsigned char, *l)) && !goodchar(*l, extra)) file_magwarn(ms, "%s type `%s' has bad char '%c'", name, line, *l); if (nt) @@ -2418,7 +2429,7 @@ check_format_type(const char *ptr, int type, const char **estr) if (*ptr == '#') ptr++; #define CHECKLEN() do { \ - for (len = cnt = 0; isdigit((unsigned char)*ptr); ptr++, cnt++) \ + for (len = cnt = 0; isdigit(CAST(unsigned char, *ptr)); ptr++, cnt++) \ len = len * 10 + (*ptr - '0'); \ if (cnt > 5 || len > 1024) \ goto toolong; \ @@ -2434,7 +2445,7 @@ check_format_type(const char *ptr, int type, const char **estr) if (*ptr++ != 'l') goto invalid; } - + switch (*ptr++) { #ifdef STRICT_FORMAT /* "long" formats are int formats for us */ /* so don't accept the 'l' modifier */ @@ -2452,7 +2463,7 @@ check_format_type(const char *ptr, int type, const char **estr) default: goto invalid; } - + /* * Don't accept h and hh modifiers. They make writing * magic entries more complicated, for very little benefit @@ -2508,7 +2519,7 @@ check_format_type(const char *ptr, int type, const char **estr) default: goto invalid; } - + case FILE_FMT_FLOAT: case FILE_FMT_DOUBLE: if (*ptr == '-') @@ -2527,30 +2538,30 @@ check_format_type(const char *ptr, int type, const char **estr) case 'g': case 'G': return 0; - + default: goto invalid; } - + case FILE_FMT_STR: if (*ptr == '-') ptr++; - while (isdigit((unsigned char )*ptr)) + while (isdigit(CAST(unsigned char, *ptr))) ptr++; if (*ptr == '.') { ptr++; - while (isdigit((unsigned char )*ptr)) + while (isdigit(CAST(unsigned char , *ptr))) ptr++; } - + switch (*ptr++) { case 's': return 0; default: goto invalid; } - + default: /* internal error */ abort(); @@ -2561,7 +2572,7 @@ toolong: *estr = "too long"; return -1; } - + /* * Check that the optional printf format in description matches * the type of the magic. @@ -2584,7 +2595,7 @@ check_format(struct magic_set *ms, struct magic *m) if (m->type >= file_nformats) { file_magwarn(ms, "Internal error inconsistency between " - "m->type and format strings"); + "m->type and format strings"); return -1; } if (file_formats[m->type] == FILE_FMT_NONE) { @@ -2604,7 +2615,7 @@ check_format(struct magic_set *ms, struct magic *m) file_names[m->type], m->desc); return -1; } - + for (; *ptr; ptr++) { if (*ptr == '%') { file_magwarn(ms, @@ -2617,9 +2628,9 @@ check_format(struct magic_set *ms, struct magic *m) return 0; } -/* - * Read a numeric value from a pointer, into the value union of a magic - * pointer, according to the magic type. Update the string pointer to point +/* + * Read a numeric value from a pointer, into the value union of a magic + * pointer, according to the magic type. Update the string pointer to point * just after the number read. Return 0 for success, non-zero for failure. */ private int @@ -2685,7 +2696,7 @@ getvalue(struct magic_set *ms, struct magic *m, const char **p, int action) return 0; default: errno = 0; - ull = (uint64_t)strtoull(*p, &ep, 0); + ull = CAST(uint64_t, strtoull(*p, &ep, 0)); m->value.q = file_signextend(ms, m, ull); if (*p == ep) { file_magwarn(ms, "Unparseable number `%s'", *p); @@ -2694,24 +2705,24 @@ getvalue(struct magic_set *ms, struct magic *m, const char **p, int action) uint64_t x; const char *q; - if (ts == (size_t)~0) { + if (ts == CAST(size_t, ~0)) { file_magwarn(ms, "Expected numeric type got `%s'", type_tbl[m->type].name); } - for (q = *p; isspace((unsigned char)*q); q++) + for (q = *p; isspace(CAST(unsigned char, *q)); q++) continue; if (*q == '-') - ull = -(int64_t)ull; + ull = -CAST(int64_t, ull); switch (ts) { case 1: - x = (uint64_t)(ull & ~0xffULL); + x = CAST(uint64_t, ull & ~0xffULL); break; case 2: - x = (uint64_t)(ull & ~0xffffULL); + x = CAST(uint64_t, ull & ~0xffffULL); break; case 4: - x = (uint64_t)(ull & ~0xffffffffULL); + x = CAST(uint64_t, ull & ~0xffffffffULL); break; case 8: x = 0; @@ -2751,7 +2762,7 @@ getstr(struct magic_set *ms, struct magic *m, const char *s, int warn) int val; while ((c = *s++) != '\0') { - if (isspace((unsigned char) c)) + if (isspace(CAST(unsigned char, c))) break; if (p >= pmax) { file_error(ms, 0, "string too long: `%s'", origs); @@ -2775,8 +2786,8 @@ getstr(struct magic_set *ms, struct magic *m, const char *s, int warn) /*FALLTHROUGH*/ default: if (warn) { - if (isprint((unsigned char)c)) { - /* Allow escaping of + if (isprint(CAST(unsigned char, c))) { + /* Allow escaping of * ``relations'' */ if (strchr("<>&^=!", c) == NULL && (m->type != FILE_REGEX || @@ -2813,7 +2824,7 @@ getstr(struct magic_set *ms, struct magic *m, const char *s, int warn) case '!': /* and baskslash itself */ case '\\': - *p++ = (char) c; + *p++ = CAST(char, c); break; case 'a': @@ -2865,7 +2876,7 @@ getstr(struct magic_set *ms, struct magic *m, const char *s, int warn) } else --s; - *p++ = (char)val; + *p++ = CAST(char, val); break; /* \x and up to 2 hex digits */ @@ -2881,18 +2892,18 @@ getstr(struct magic_set *ms, struct magic *m, const char *s, int warn) --s; } else --s; - *p++ = (char)val; + *p++ = CAST(char, val); break; } } else - *p++ = (char)c; + *p++ = CAST(char, c); } --s; out: *p = '\0'; m->vallen = CAST(unsigned char, (p - origp)); if (m->type == FILE_PSTRING) - m->vallen += (unsigned char)file_pstring_length_size(m); + m->vallen += CAST(unsigned char, file_pstring_length_size(m)); return s; } @@ -2901,9 +2912,9 @@ out: private int hextoint(int c) { - if (!isascii((unsigned char) c)) + if (!isascii(CAST(unsigned char, c))) return -1; - if (isdigit((unsigned char) c)) + if (isdigit(CAST(unsigned char, c))) return c - '0'; if ((c >= 'a') && (c <= 'f')) return c + 10 - 'a'; @@ -2981,7 +2992,7 @@ eatsize(const char **p) { const char *l = *p; - if (LOWCASE(*l) == 'u') + if (LOWCASE(*l) == 'u') l++; switch (LOWCASE(*l)) { @@ -3052,17 +3063,17 @@ apprentice_map(struct magic_set *ms, const char *fn) file_error(ms, errno, "cannot stat `%s'", dbname); goto error; } - if (st.st_size < 8 || st.st_size > MAXMAGIC_SIZE) { + if (st.st_size < 8 || st.st_size > maxoff_t()) { file_error(ms, 0, "file `%s' is too %s", dbname, st.st_size < 8 ? "small" : "large"); goto error; } - map->len = (size_t)st.st_size; + map->len = CAST(size_t, st.st_size); #ifdef QUICK map->type = MAP_TYPE_MMAP; - if ((map->p = mmap(0, (size_t)st.st_size, PROT_READ|PROT_WRITE, - MAP_PRIVATE|MAP_FILE, fd, (off_t)0)) == MAP_FAILED) { + if ((map->p = mmap(0, CAST(size_t, st.st_size), PROT_READ|PROT_WRITE, + MAP_PRIVATE|MAP_FILE, fd, CAST(off_t, 0))) == MAP_FAILED) { file_error(ms, errno, "cannot map `%s'", dbname); goto error; } @@ -3082,11 +3093,11 @@ apprentice_map(struct magic_set *ms, const char *fn) fd = -1; if (check_buffer(ms, map, dbname) != 0) { - rv = (struct magic_map *)-1; + rv = RCAST(struct magic_map *, -1); goto error; } #ifdef QUICK - if (mprotect(map->p, (size_t)st.st_size, PROT_READ) == -1) { + if (mprotect(map->p, CAST(size_t, st.st_size), PROT_READ) == -1) { file_error(ms, errno, "cannot mprotect `%s'", dbname); goto error; } @@ -3130,7 +3141,7 @@ check_buffer(struct magic_set *ms, struct magic_map *map, const char *dbname) VERSIONNO, dbname, version); return -1; } - entries = (uint32_t)(map->len / sizeof(struct magic)); + entries = CAST(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", @@ -3179,10 +3190,10 @@ apprentice_compile(struct magic_set *ms, struct magic_map *map, const char *fn) dbname = mkdbname(ms, fn, 1); - if (dbname == NULL) + if (dbname == NULL) goto out; - if ((fd = open(dbname, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0644)) == -1) + if ((fd = open(dbname, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0644)) == -1) { file_error(ms, errno, "cannot open `%s'", dbname); goto out; @@ -3192,14 +3203,14 @@ apprentice_compile(struct magic_set *ms, struct magic_map *map, const char *fn) hdr.h[1] = VERSIONNO; memcpy(hdr.h + 2, map->nmagic, nm); - if (write(fd, &hdr, sizeof(hdr)) != (ssize_t)sizeof(hdr)) { + if (write(fd, &hdr, sizeof(hdr)) != CAST(ssize_t, sizeof(hdr))) { file_error(ms, errno, "error writing `%s'", dbname); goto out2; } for (i = 0; i < MAGIC_SETS; i++) { len = m * map->nmagic[i]; - if (write(fd, map->magic[i], len) != (ssize_t)len) { + if (write(fd, map->magic[i], len) != CAST(ssize_t, len)) { file_error(ms, errno, "error writing `%s'", dbname); goto out2; } @@ -3245,7 +3256,8 @@ mkdbname(struct magic_set *ms, const char *fn, int strip) q++; /* Compatibility with old code that looked in .mime */ if (ms->flags & MAGIC_MIME) { - if (asprintf(&buf, "%.*s.mime%s", (int)(q - fn), fn, ext) < 0) + if (asprintf(&buf, "%.*s.mime%s", CAST(int, q - fn), fn, ext) + < 0) return NULL; if (access(buf, R_OK) != -1) { ms->flags &= MAGIC_MIME_TYPE; @@ -3253,7 +3265,7 @@ mkdbname(struct magic_set *ms, const char *fn, int strip) } free(buf); } - if (asprintf(&buf, "%.*s%s", (int)(q - fn), fn, ext) < 0) + if (asprintf(&buf, "%.*s%s", CAST(int, q - fn), fn, ext) < 0) return NULL; /* Compatibility with old code that looked in .mime */ @@ -3280,8 +3292,8 @@ private uint16_t swap2(uint16_t sv) { uint16_t rv; - uint8_t *s = (uint8_t *)(void *)&sv; - uint8_t *d = (uint8_t *)(void *)&rv; + uint8_t *s = RCAST(uint8_t *, RCAST(void *, &sv)); + uint8_t *d = RCAST(uint8_t *, RCAST(void *, &rv)); d[0] = s[1]; d[1] = s[0]; return rv; @@ -3294,8 +3306,8 @@ private uint32_t swap4(uint32_t sv) { uint32_t rv; - uint8_t *s = (uint8_t *)(void *)&sv; - uint8_t *d = (uint8_t *)(void *)&rv; + uint8_t *s = RCAST(uint8_t *, RCAST(void *, &sv)); + uint8_t *d = RCAST(uint8_t *, RCAST(void *, &rv)); d[0] = s[3]; d[1] = s[2]; d[2] = s[1]; @@ -3310,8 +3322,8 @@ private uint64_t swap8(uint64_t sv) { uint64_t rv; - uint8_t *s = (uint8_t *)(void *)&sv; - uint8_t *d = (uint8_t *)(void *)&rv; + uint8_t *s = RCAST(uint8_t *, RCAST(void *, &sv)); + uint8_t *d = RCAST(uint8_t *, RCAST(void *, &rv)); #if 0 d[0] = s[3]; d[1] = s[2]; @@ -3341,9 +3353,9 @@ private void bs1(struct magic *m) { m->cont_level = swap2(m->cont_level); - m->offset = swap4((uint32_t)m->offset); - m->in_offset = swap4((uint32_t)m->in_offset); - m->lineno = swap4((uint32_t)m->lineno); + m->offset = swap4(CAST(uint32_t, m->offset)); + m->in_offset = swap4(CAST(uint32_t, m->in_offset)); + m->lineno = swap4(CAST(uint32_t, m->lineno)); if (IS_STRING(m->type)) { m->str_range = swap4(m->str_range); m->str_flags = swap4(m->str_flags); @@ -3354,7 +3366,7 @@ bs1(struct magic *m) } } -protected size_t +protected size_t file_pstring_length_size(const struct magic *m) { switch (m->str_flags & PSTRING_LEN) { @@ -3375,7 +3387,7 @@ protected size_t file_pstring_get_length(const struct magic *m, const char *ss) { size_t len = 0; - const unsigned char *s = (const unsigned char *)ss; + const unsigned char *s = RCAST(const unsigned char *, ss); unsigned int s3, s2, s1, s0; switch (m->str_flags & PSTRING_LEN) { diff --git a/src/apptype.c b/src/apptype.c index fcd764e49a441..1bb33e41c27a9 100644 --- a/src/apptype.c +++ b/src/apptype.c @@ -1,15 +1,15 @@ /* * Adapted from: apptype.c, Written by Eberhard Mattes and put into the * public domain - * + * * Notes: 1. Qualify the filename so that DosQueryAppType does not do extraneous * searches. - * + * * 2. DosQueryAppType will return FAPPTYP_DOS on a file ending with ".com" * (other than an OS/2 exe or Win exe with this name). Eberhard Mattes * remarks Tue, 6 Apr 93: Moreover, it reports the type of the (new and very * bug ridden) Win Emacs as "OS/2 executable". - * + * * 3. apptype() uses the filename if given, otherwise a tmp file is created with * the contents of buf. If buf is not the complete file, apptype can * incorrectly identify the exe type. The "-z" option of "file" is the reason @@ -18,16 +18,16 @@ /* * amai: Darrel Hankerson did the changes described here. - * + * * It remains to check the validity of comments (2.) since it's referred to an * "old" OS/2 version. - * + * */ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: apptype.c,v 1.13 2011/09/07 21:57:15 christos Exp $") +FILE_RCSID("@(#)$File: apptype.c,v 1.14 2018/09/09 20:33:28 christos Exp $") #endif /* lint */ #include <stdlib.h> diff --git a/src/ascmagic.c b/src/ascmagic.c index 2d1abe543e603..624ac90b1f1c2 100644 --- a/src/ascmagic.c +++ b/src/ascmagic.c @@ -35,7 +35,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: ascmagic.c,v 1.98 2017/11/02 20:25:39 christos Exp $") +FILE_RCSID("@(#)$File: ascmagic.c,v 1.104 2019/05/07 02:27:11 christos Exp $") #endif /* lint */ #include "magic.h" @@ -80,7 +80,13 @@ file_ascmagic(struct magic_set *ms, const struct buffer *b, int text) const char *type = NULL; bb = *b; - bb.flen = trim_nuls(b->fbuf, b->flen); + bb.flen = trim_nuls(CAST(const unsigned char *, b->fbuf), b->flen); + /* + * Avoid trimming at an odd byte if the original buffer was evenly + * sized; this avoids losing the last character on UTF-16 LE text + */ + if ((bb.flen & 1) && !(b->flen & 1)) + bb.flen++; /* If file doesn't look like any sort of text, give up. */ if (file_encoding(ms, &bb, &ubuf, &ulen, &code, &code_mime, @@ -96,17 +102,18 @@ file_ascmagic(struct magic_set *ms, const struct buffer *b, int text) } protected int -file_ascmagic_with_encoding(struct magic_set *ms, +file_ascmagic_with_encoding(struct magic_set *ms, const struct buffer *b, unichar *ubuf, size_t ulen, const char *code, const char *type, int text) { struct buffer bb; - const unsigned char *buf = b->fbuf; + const unsigned char *buf = CAST(const unsigned char *, b->fbuf); size_t nbytes = b->flen; unsigned char *utf8_buf = NULL, *utf8_end; - size_t mlen, i; + size_t mlen, i, len; int rv = -1; int mime = ms->flags & MAGIC_MIME; + int need_separator = 0; const char *subtype = NULL; const char *subtype_mime = NULL; @@ -121,7 +128,7 @@ file_ascmagic_with_encoding(struct magic_set *ms, int n_nel = 0; int executable = 0; - size_t last_line_end = (size_t)-1; + size_t last_line_end = CAST(size_t, -1); int has_long_lines = 0; nbytes = trim_nuls(buf, nbytes); @@ -144,12 +151,14 @@ file_ascmagic_with_encoding(struct magic_set *ms, if ((utf8_end = encode_utf8(utf8_buf, mlen, ubuf, ulen)) == NULL) goto done; - buffer_init(&bb, b->fd, utf8_buf, - (size_t)(utf8_end - utf8_buf)); + buffer_init(&bb, b->fd, &b->st, utf8_buf, + CAST(size_t, utf8_end - utf8_buf)); if ((rv = file_softmagic(ms, &bb, NULL, NULL, TEXTTEST, text)) == 0) rv = -1; + else + need_separator = 1; buffer_fini(&bb); if ((ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION))) { rv = rv == -1 ? 0 : 1; @@ -200,8 +209,21 @@ file_ascmagic_with_encoding(struct magic_set *ms, rv = 0; goto done; } + len = file_printedlen(ms); if (mime) { - if (!file_printedlen(ms) && (mime & MAGIC_MIME_TYPE) != 0) { + if ((mime & MAGIC_MIME_TYPE) != 0) { + if (len) { + /* + * Softmagic printed something, we + * are either done, or we need a separator + */ + if ((ms->flags & MAGIC_CONTINUE) == 0) { + rv = 1; + goto done; + } + if (need_separator && file_separator(ms) == -1) + goto done; + } if (subtype_mime) { if (file_printf(ms, "%s", subtype_mime) == -1) goto done; @@ -211,7 +233,7 @@ file_ascmagic_with_encoding(struct magic_set *ms, } } } else { - if (file_printedlen(ms)) { + if (len) { switch (file_replace(ms, " text$", ", ")) { case 0: switch (file_replace(ms, " text executable$", @@ -324,42 +346,42 @@ encode_utf8(unsigned char *buf, size_t len, unichar *ubuf, size_t ulen) if (ubuf[i] <= 0x7f) { if (end - buf < 1) return NULL; - *buf++ = (unsigned char)ubuf[i]; + *buf++ = CAST(unsigned char, ubuf[i]); } else if (ubuf[i] <= 0x7ff) { if (end - buf < 2) return NULL; - *buf++ = (unsigned char)((ubuf[i] >> 6) + 0xc0); - *buf++ = (unsigned char)((ubuf[i] & 0x3f) + 0x80); + *buf++ = CAST(unsigned char, (ubuf[i] >> 6) + 0xc0); + *buf++ = CAST(unsigned char, (ubuf[i] & 0x3f) + 0x80); } else if (ubuf[i] <= 0xffff) { if (end - buf < 3) return NULL; - *buf++ = (unsigned char)((ubuf[i] >> 12) + 0xe0); - *buf++ = (unsigned char)(((ubuf[i] >> 6) & 0x3f) + 0x80); - *buf++ = (unsigned char)((ubuf[i] & 0x3f) + 0x80); + *buf++ = CAST(unsigned char, (ubuf[i] >> 12) + 0xe0); + *buf++ = CAST(unsigned char, ((ubuf[i] >> 6) & 0x3f) + 0x80); + *buf++ = CAST(unsigned char, (ubuf[i] & 0x3f) + 0x80); } else if (ubuf[i] <= 0x1fffff) { if (end - buf < 4) return NULL; - *buf++ = (unsigned char)((ubuf[i] >> 18) + 0xf0); - *buf++ = (unsigned char)(((ubuf[i] >> 12) & 0x3f) + 0x80); - *buf++ = (unsigned char)(((ubuf[i] >> 6) & 0x3f) + 0x80); - *buf++ = (unsigned char)((ubuf[i] & 0x3f) + 0x80); + *buf++ = CAST(unsigned char, (ubuf[i] >> 18) + 0xf0); + *buf++ = CAST(unsigned char, ((ubuf[i] >> 12) & 0x3f) + 0x80); + *buf++ = CAST(unsigned char, ((ubuf[i] >> 6) & 0x3f) + 0x80); + *buf++ = CAST(unsigned char, (ubuf[i] & 0x3f) + 0x80); } else if (ubuf[i] <= 0x3ffffff) { if (end - buf < 5) return NULL; - *buf++ = (unsigned char)((ubuf[i] >> 24) + 0xf8); - *buf++ = (unsigned char)(((ubuf[i] >> 18) & 0x3f) + 0x80); - *buf++ = (unsigned char)(((ubuf[i] >> 12) & 0x3f) + 0x80); - *buf++ = (unsigned char)(((ubuf[i] >> 6) & 0x3f) + 0x80); - *buf++ = (unsigned char)((ubuf[i] & 0x3f) + 0x80); + *buf++ = CAST(unsigned char, (ubuf[i] >> 24) + 0xf8); + *buf++ = CAST(unsigned char, ((ubuf[i] >> 18) & 0x3f) + 0x80); + *buf++ = CAST(unsigned char, ((ubuf[i] >> 12) & 0x3f) + 0x80); + *buf++ = CAST(unsigned char, ((ubuf[i] >> 6) & 0x3f) + 0x80); + *buf++ = CAST(unsigned char, (ubuf[i] & 0x3f) + 0x80); } else if (ubuf[i] <= 0x7fffffff) { if (end - buf < 6) return NULL; - *buf++ = (unsigned char)((ubuf[i] >> 30) + 0xfc); - *buf++ = (unsigned char)(((ubuf[i] >> 24) & 0x3f) + 0x80); - *buf++ = (unsigned char)(((ubuf[i] >> 18) & 0x3f) + 0x80); - *buf++ = (unsigned char)(((ubuf[i] >> 12) & 0x3f) + 0x80); - *buf++ = (unsigned char)(((ubuf[i] >> 6) & 0x3f) + 0x80); - *buf++ = (unsigned char)((ubuf[i] & 0x3f) + 0x80); + *buf++ = CAST(unsigned char, (ubuf[i] >> 30) + 0xfc); + *buf++ = CAST(unsigned char, ((ubuf[i] >> 24) & 0x3f) + 0x80); + *buf++ = CAST(unsigned char, ((ubuf[i] >> 18) & 0x3f) + 0x80); + *buf++ = CAST(unsigned char, ((ubuf[i] >> 12) & 0x3f) + 0x80); + *buf++ = CAST(unsigned char, ((ubuf[i] >> 6) & 0x3f) + 0x80); + *buf++ = CAST(unsigned char, (ubuf[i] & 0x3f) + 0x80); } else /* Invalid character */ return NULL; } diff --git a/src/asprintf.c b/src/asprintf.c index 30852d2b3b007..2d14e8074f23d 100644 --- a/src/asprintf.c +++ b/src/asprintf.c @@ -2,7 +2,7 @@ * Copyright (c) Ian F. Darwin 1986-1995. * Software written by Ian F. Darwin and others; * maintained 1995-present by Christos Zoulas and others. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -12,7 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -29,7 +29,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: asprintf.c,v 1.4 2010/07/21 16:47:17 christos Exp $") +FILE_RCSID("@(#)$File: asprintf.c,v 1.5 2018/09/09 20:33:28 christos Exp $") #endif int asprintf(char **ptr, const char *fmt, ...) diff --git a/src/buffer.c b/src/buffer.c index 5f76b80d282cb..6d8967d2fa73d 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -27,7 +27,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: buffer.c,v 1.4 2018/02/21 21:26:00 christos Exp $") +FILE_RCSID("@(#)$File: buffer.c,v 1.6 2019/05/07 02:27:11 christos Exp $") #endif /* lint */ #include "magic.h" @@ -37,10 +37,13 @@ FILE_RCSID("@(#)$File: buffer.c,v 1.4 2018/02/21 21:26:00 christos Exp $") #include <sys/stat.h> void -buffer_init(struct buffer *b, int fd, const void *data, size_t len) +buffer_init(struct buffer *b, int fd, const struct stat *st, const void *data, + size_t len) { b->fd = fd; - if (b->fd == -1 || fstat(b->fd, &b->st) == -1) + if (st) + memcpy(&b->st, st, sizeof(b->st)); + else if (b->fd == -1 || fstat(b->fd, &b->st) == -1) memset(&b->st, 0, sizeof(b->st)); b->fbuf = data; b->flen = len; @@ -61,13 +64,13 @@ buffer_fill(const struct buffer *bb) struct buffer *b = CCAST(struct buffer *, bb); if (b->elen != 0) - return b->elen == (size_t)~0 ? -1 : 0; + return b->elen == CAST(size_t, ~0) ? -1 : 0; if (!S_ISREG(b->st.st_mode)) goto out; - b->elen = (size_t)b->st.st_size < b->flen ? - (size_t)b->st.st_size : b->flen; + b->elen = CAST(size_t, b->st.st_size) < b->flen ? + CAST(size_t, b->st.st_size) : b->flen; if ((b->ebuf = malloc(b->elen)) == NULL) goto out; @@ -79,6 +82,6 @@ buffer_fill(const struct buffer *bb) return 0; out: - b->elen = (size_t)~0; + b->elen = CAST(size_t, ~0); return -1; } diff --git a/src/cdf.c b/src/cdf.c index aad68cd0a33cb..556a3ff868098 100644 --- a/src/cdf.c +++ b/src/cdf.c @@ -35,7 +35,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: cdf.c,v 1.110 2017/12/19 00:21:21 christos Exp $") +FILE_RCSID("@(#)$File: cdf.c,v 1.114 2019/02/20 02:35:27 christos Exp $") #endif #include <assert.h> @@ -47,9 +47,7 @@ FILE_RCSID("@(#)$File: cdf.c,v 1.110 2017/12/19 00:21:21 christos Exp $") #include <string.h> #include <time.h> #include <ctype.h> -#ifdef HAVE_LIMITS_H #include <limits.h> -#endif #ifndef EFTYPE #define EFTYPE EINVAL @@ -68,11 +66,14 @@ static union { uint32_t u; } cdf_bo; -#define NEED_SWAP (cdf_bo.u == (uint32_t)0x01020304) +#define NEED_SWAP (cdf_bo.u == CAST(uint32_t, 0x01020304)) -#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_TOLE8(x) \ + (CAST(uint64_t, NEED_SWAP ? _cdf_tole8(x) : CAST(uint64_t, x))) +#define CDF_TOLE4(x) \ + (CAST(uint32_t, NEED_SWAP ? _cdf_tole4(x) : CAST(uint32_t, x))) +#define CDF_TOLE2(x) \ + (CAST(uint16_t, NEED_SWAP ? _cdf_tole2(x) : CAST(uint16_t, x))) #define CDF_TOLE(x) (/*CONSTCOND*/sizeof(x) == 2 ? \ CDF_TOLE2(CAST(uint16_t, x)) : \ (/*CONSTCOND*/sizeof(x) == 4 ? \ @@ -90,7 +91,8 @@ static void * cdf_malloc(const char *file __attribute__((__unused__)), size_t line __attribute__((__unused__)), size_t n) { - DPRINTF(("%s,%zu: %s %zu\n", file, line, __func__, n)); + DPRINTF(("%s,%" SIZE_T_FORMAT "u: %s %" SIZE_T_FORMAT "u\n", + file, line, __func__, n)); return malloc(n); } @@ -99,7 +101,8 @@ static void * cdf_realloc(const char *file __attribute__((__unused__)), size_t line __attribute__((__unused__)), void *p, size_t n) { - DPRINTF(("%s,%zu: %s %zu\n", file, line, __func__, n)); + DPRINTF(("%s,%" SIZE_T_FORMAT "u: %s %" SIZE_T_FORMAT "u\n", + file, line, __func__, n)); return realloc(p, n); } @@ -108,7 +111,8 @@ static void * cdf_calloc(const char *file __attribute__((__unused__)), size_t line __attribute__((__unused__)), size_t n, size_t u) { - DPRINTF(("%s,%zu: %s %zu %zu\n", file, line, __func__, n, u)); + DPRINTF(("%s,%" SIZE_T_FORMAT "u: %s %" SIZE_T_FORMAT "u %" + SIZE_T_FORMAT "u\n", file, line, __func__, n, u)); return calloc(n, u); } @@ -119,8 +123,8 @@ static uint16_t _cdf_tole2(uint16_t sv) { uint16_t rv; - uint8_t *s = (uint8_t *)(void *)&sv; - uint8_t *d = (uint8_t *)(void *)&rv; + uint8_t *s = RCAST(uint8_t *, RCAST(void *, &sv)); + uint8_t *d = RCAST(uint8_t *, RCAST(void *, &rv)); d[0] = s[1]; d[1] = s[0]; return rv; @@ -133,8 +137,8 @@ static uint32_t _cdf_tole4(uint32_t sv) { uint32_t rv; - uint8_t *s = (uint8_t *)(void *)&sv; - uint8_t *d = (uint8_t *)(void *)&rv; + uint8_t *s = RCAST(uint8_t *, RCAST(void *, &sv)); + uint8_t *d = RCAST(uint8_t *, RCAST(void *, &rv)); d[0] = s[3]; d[1] = s[2]; d[2] = s[1]; @@ -149,8 +153,8 @@ static uint64_t _cdf_tole8(uint64_t sv) { uint64_t rv; - uint8_t *s = (uint8_t *)(void *)&sv; - uint8_t *d = (uint8_t *)(void *)&rv; + uint8_t *s = RCAST(uint8_t *, RCAST(void *, &sv)); + uint8_t *d = RCAST(uint8_t *, RCAST(void *, &rv)); d[0] = s[7]; d[1] = s[6]; d[2] = s[5]; @@ -215,15 +219,17 @@ cdf_swap_header(cdf_header_t *h) h->h_min_size_standard_stream = CDF_TOLE4(h->h_min_size_standard_stream); h->h_secid_first_sector_in_short_sat = - CDF_TOLE4((uint32_t)h->h_secid_first_sector_in_short_sat); + CDF_TOLE4(CAST(uint32_t, h->h_secid_first_sector_in_short_sat)); h->h_num_sectors_in_short_sat = CDF_TOLE4(h->h_num_sectors_in_short_sat); h->h_secid_first_sector_in_master_sat = - CDF_TOLE4((uint32_t)h->h_secid_first_sector_in_master_sat); + CDF_TOLE4(CAST(uint32_t, h->h_secid_first_sector_in_master_sat)); h->h_num_sectors_in_master_sat = CDF_TOLE4(h->h_num_sectors_in_master_sat); - for (i = 0; i < __arraycount(h->h_master_sat); i++) - h->h_master_sat[i] = CDF_TOLE4((uint32_t)h->h_master_sat[i]); + for (i = 0; i < __arraycount(h->h_master_sat); i++) { + h->h_master_sat[i] = + CDF_TOLE4(CAST(uint32_t, h->h_master_sat[i])); + } } void @@ -256,15 +262,16 @@ void cdf_swap_dir(cdf_directory_t *d) { d->d_namelen = CDF_TOLE2(d->d_namelen); - d->d_left_child = CDF_TOLE4((uint32_t)d->d_left_child); - d->d_right_child = CDF_TOLE4((uint32_t)d->d_right_child); - d->d_storage = CDF_TOLE4((uint32_t)d->d_storage); + d->d_left_child = CDF_TOLE4(CAST(uint32_t, d->d_left_child)); + d->d_right_child = CDF_TOLE4(CAST(uint32_t, d->d_right_child)); + d->d_storage = CDF_TOLE4(CAST(uint32_t, d->d_storage)); d->d_storage_uuid[0] = CDF_TOLE8(d->d_storage_uuid[0]); d->d_storage_uuid[1] = CDF_TOLE8(d->d_storage_uuid[1]); d->d_flags = CDF_TOLE4(d->d_flags); - d->d_created = CDF_TOLE8((uint64_t)d->d_created); - d->d_modified = CDF_TOLE8((uint64_t)d->d_modified); - d->d_stream_first_sector = CDF_TOLE4((uint32_t)d->d_stream_first_sector); + d->d_created = CDF_TOLE8(CAST(uint64_t, d->d_created)); + d->d_modified = CDF_TOLE8(CAST(uint64_t, d->d_modified)); + d->d_stream_first_sector = CDF_TOLE4( + CAST(uint32_t, d->d_stream_first_sector)); d->d_size = CDF_TOLE4(d->d_size); } @@ -321,11 +328,11 @@ static int cdf_check_stream_offset(const cdf_stream_t *sst, const cdf_header_t *h, const void *p, size_t tail, int line) { - const char *b = (const char *)sst->sst_tab; - const char *e = ((const char *)p) + tail; + const char *b = RCAST(const char *, sst->sst_tab); + const char *e = RCAST(const char *, p) + tail; size_t ss = cdf_check_stream(sst, h); /*LINTED*/(void)&line; - if (e >= b && (size_t)(e - b) <= ss * sst->sst_len) + if (e >= b && CAST(size_t, e - b) <= ss * sst->sst_len) return 0; DPRINTF(("%d: offset begin %p < end %p || %" SIZE_T_FORMAT "u" " > %" SIZE_T_FORMAT "u [%" SIZE_T_FORMAT "u %" @@ -338,23 +345,23 @@ cdf_check_stream_offset(const cdf_stream_t *sst, const cdf_header_t *h, static ssize_t cdf_read(const cdf_info_t *info, off_t off, void *buf, size_t len) { - size_t siz = (size_t)off + len; + size_t siz = CAST(size_t, off + len); - if ((off_t)(off + len) != (off_t)siz) + if (CAST(off_t, off + len) != CAST(off_t, siz)) goto out; if (info->i_buf != NULL && info->i_len >= siz) { (void)memcpy(buf, &info->i_buf[off], len); - return (ssize_t)len; + return CAST(ssize_t, len); } if (info->i_fd == -1) goto out; - if (pread(info->i_fd, buf, len, off) != (ssize_t)len) + if (pread(info->i_fd, buf, len, off) != CAST(ssize_t, len)) return -1; - return (ssize_t)len; + return CAST(ssize_t, len); out: errno = EINVAL; return -1; @@ -366,7 +373,7 @@ cdf_read_header(const cdf_info_t *info, cdf_header_t *h) char buf[512]; (void)memcpy(cdf_bo.s, "\01\02\03\04", 4); - if (cdf_read(info, (off_t)0, buf, sizeof(buf)) == -1) + if (cdf_read(info, CAST(off_t, 0), buf, sizeof(buf)) == -1) return -1; cdf_unpack_header(h, buf); cdf_swap_header(h); @@ -400,7 +407,7 @@ cdf_read_sector(const cdf_info_t *info, void *buf, size_t offs, size_t len, size_t ss = CDF_SEC_SIZE(h); size_t pos = CDF_SEC_POS(h, id); assert(ss == len); - return cdf_read(info, (off_t)pos, ((char *)buf) + offs, len); + return cdf_read(info, CAST(off_t, pos), RCAST(char *, buf) + offs, len); } ssize_t @@ -416,8 +423,8 @@ cdf_read_short_sector(const cdf_stream_t *sst, void *buf, size_t offs, pos + len, CDF_SEC_SIZE(h) * sst->sst_len)); goto out; } - (void)memcpy(((char *)buf) + offs, - ((const char *)sst->sst_tab) + pos, len); + (void)memcpy(RCAST(char *, buf) + offs, + RCAST(const char *, sst->sst_tab) + pos, len); return len; out: errno = EFTYPE; @@ -460,7 +467,7 @@ cdf_read_sat(const cdf_info_t *info, cdf_header_t *h, cdf_sat_t *sat) if (h->h_master_sat[i] < 0) break; if (cdf_read_sector(info, sat->sat_tab, ss * i, ss, h, - h->h_master_sat[i]) != (ssize_t)ss) { + h->h_master_sat[i]) != CAST(ssize_t, ss)) { DPRINTF(("Reading sector %d", h->h_master_sat[i])); goto out1; } @@ -477,27 +484,29 @@ cdf_read_sat(const cdf_info_t *info, cdf_header_t *h, cdf_sat_t *sat) DPRINTF(("Reading master sector loop limit")); goto out3; } - if (cdf_read_sector(info, msa, 0, ss, h, mid) != (ssize_t)ss) { + if (cdf_read_sector(info, msa, 0, ss, h, mid) != + CAST(ssize_t, ss)) { DPRINTF(("Reading master sector %d", mid)); goto out2; } for (k = 0; k < nsatpersec; k++, i++) { - sec = CDF_TOLE4((uint32_t)msa[k]); + sec = CDF_TOLE4(CAST(uint32_t, msa[k])); if (sec < 0) goto out; if (i >= sat->sat_len) { - DPRINTF(("Out of bounds reading MSA %" SIZE_T_FORMAT - "u >= %" SIZE_T_FORMAT "u", i, sat->sat_len)); + DPRINTF(("Out of bounds reading MSA %" + SIZE_T_FORMAT "u >= %" SIZE_T_FORMAT "u", + i, sat->sat_len)); goto out3; } if (cdf_read_sector(info, sat->sat_tab, ss * i, ss, h, - sec) != (ssize_t)ss) { + sec) != CAST(ssize_t, ss)) { DPRINTF(("Reading sector %d", CDF_TOLE4(msa[k]))); goto out2; } } - mid = CDF_TOLE4((uint32_t)msa[nsatpersec]); + mid = CDF_TOLE4(CAST(uint32_t, msa[nsatpersec])); } out: sat->sat_len = i; @@ -516,7 +525,7 @@ size_t cdf_count_chain(const cdf_sat_t *sat, cdf_secid_t sid, size_t size) { size_t i, j; - cdf_secid_t maxsector = (cdf_secid_t)((sat->sat_len * size) + cdf_secid_t maxsector = CAST(cdf_secid_t, (sat->sat_len * size) / sizeof(maxsector)); DPRINTF(("Chain:")); @@ -536,7 +545,7 @@ cdf_count_chain(const cdf_sat_t *sat, cdf_secid_t sid, size_t size) DPRINTF(("Sector %d >= %d\n", sid, maxsector)); goto out; } - sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]); + sid = CDF_TOLE4(CAST(uint32_t, sat->sat_tab[sid])); } if (i == 0) { DPRINTF((" none, sid: %d\n", sid)); @@ -547,7 +556,7 @@ cdf_count_chain(const cdf_sat_t *sat, cdf_secid_t sid, size_t size) return i; out: errno = EFTYPE; - return (size_t)-1; + return CAST(size_t, -1); } int @@ -564,7 +573,7 @@ cdf_read_long_sector_chain(const cdf_info_t *info, const cdf_header_t *h, if (sid == CDF_SECID_END_OF_CHAIN || len == 0) return cdf_zero_stream(scn); - if (scn->sst_len == (size_t)-1) + if (scn->sst_len == CAST(size_t, -1)) goto out; scn->sst_tab = CDF_CALLOC(scn->sst_len, ss); @@ -583,7 +592,7 @@ cdf_read_long_sector_chain(const cdf_info_t *info, const cdf_header_t *h, goto out; } if ((nr = cdf_read_sector(info, scn->sst_tab, i * ss, ss, h, - sid)) != (ssize_t)ss) { + sid)) != CAST(ssize_t, ss)) { if (i == scn->sst_len - 1 && nr > 0) { /* Last sector might be truncated */ return 0; @@ -591,7 +600,7 @@ cdf_read_long_sector_chain(const cdf_info_t *info, const cdf_header_t *h, DPRINTF(("Reading long sector chain %d", sid)); goto out; } - sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]); + sid = CDF_TOLE4(CAST(uint32_t, sat->sat_tab[sid])); } return 0; out: @@ -610,7 +619,7 @@ cdf_read_short_sector_chain(const cdf_header_t *h, scn->sst_dirlen = len; scn->sst_ss = ss; - if (scn->sst_len == (size_t)-1) + if (scn->sst_len == CAST(size_t, -1)) goto out; scn->sst_tab = CDF_CALLOC(scn->sst_len, ss); @@ -629,11 +638,11 @@ cdf_read_short_sector_chain(const cdf_header_t *h, goto out; } if (cdf_read_short_sector(sst, scn->sst_tab, i * ss, ss, h, - sid) != (ssize_t)ss) { + sid) != CAST(ssize_t, ss)) { DPRINTF(("Reading short sector chain %d", sid)); goto out; } - sid = CDF_TOLE4((uint32_t)ssat->sat_tab[sid]); + sid = CDF_TOLE4(CAST(uint32_t, ssat->sat_tab[sid])); } return 0; out: @@ -664,7 +673,7 @@ cdf_read_dir(const cdf_info_t *info, const cdf_header_t *h, cdf_secid_t sid = h->h_secid_first_directory; ns = cdf_count_chain(sat, sid, ss); - if (ns == (size_t)-1) + if (ns == CAST(size_t, -1)) return -1; nd = ss / CDF_DIRECTORY_SIZE; @@ -685,7 +694,8 @@ cdf_read_dir(const cdf_info_t *info, const cdf_header_t *h, DPRINTF(("Read dir loop limit")); goto out; } - if (cdf_read_sector(info, buf, 0, ss, h, sid) != (ssize_t)ss) { + if (cdf_read_sector(info, buf, 0, ss, h, sid) != + CAST(ssize_t, ss)) { DPRINTF(("Reading directory sector %d", sid)); goto out; } @@ -693,7 +703,7 @@ cdf_read_dir(const cdf_info_t *info, const cdf_header_t *h, cdf_unpack_dir(&dir->dir_tab[i * nd + j], &buf[j * CDF_DIRECTORY_SIZE]); } - sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]); + sid = CDF_TOLE4(CAST(uint32_t, sat->sat_tab[sid])); } if (NEED_SWAP) for (i = 0; i < dir->dir_len; i++) @@ -718,7 +728,7 @@ cdf_read_ssat(const cdf_info_t *info, const cdf_header_t *h, ssat->sat_tab = NULL; ssat->sat_len = cdf_count_chain(sat, sid, ss); - if (ssat->sat_len == (size_t)-1) + if (ssat->sat_len == CAST(size_t, -1)) goto out; ssat->sat_tab = CAST(cdf_secid_t *, CDF_CALLOC(ssat->sat_len, ss)); @@ -737,11 +747,11 @@ cdf_read_ssat(const cdf_info_t *info, const cdf_header_t *h, goto out; } if (cdf_read_sector(info, ssat->sat_tab, i * ss, ss, h, sid) != - (ssize_t)ss) { + CAST(ssize_t, ss)) { DPRINTF(("Reading short sat sector %d", sid)); goto out1; } - sid = CDF_TOLE4((uint32_t)sat->sat_tab[sid]); + sid = CDF_TOLE4(CAST(uint32_t, sat->sat_tab[sid])); } return 0; out: @@ -791,7 +801,7 @@ cdf_namecmp(const char *d, const uint16_t *s, size_t l) { for (; l--; d++, s++) if (*d != CDF_TOLE2(*s)) - return (unsigned char)*d - CDF_TOLE2(*s); + return CAST(unsigned char, *d) - CDF_TOLE2(*s); return 0; } @@ -859,7 +869,7 @@ cdf_offset(const void *p, size_t l) } static const uint8_t * -cdf_get_property_info_pos(const cdf_stream_t *sst, const cdf_header_t *h, +cdf_get_property_info_pos(const cdf_stream_t *sst, const cdf_header_t *h, const uint8_t *p, const uint8_t *e, size_t i) { size_t tail = (i << 1) + 1; @@ -874,7 +884,7 @@ cdf_get_property_info_pos(const cdf_stream_t *sst, const cdf_header_t *h, __LINE__) == -1) return NULL; ofs = CDF_GETUINT32(p, tail); - q = CAST(const uint8_t *, cdf_offset(CAST(const void *, p), + q = CAST(const uint8_t *, cdf_offset(CAST(const void *, p), ofs - 2 * sizeof(uint32_t))); if (q < p) { @@ -896,8 +906,8 @@ cdf_grow_info(cdf_property_info_t **info, size_t *maxcount, size_t incr) size_t newcount = *maxcount + incr; if (newcount > CDF_PROP_LIMIT) { - DPRINTF(("exceeded property limit %zu > %zu\n", - newcount, CDF_PROP_LIMIT)); + DPRINTF(("exceeded property limit %" SIZE_T_FORMAT "u > %" + SIZE_T_FORMAT "u\n", newcount, CDF_PROP_LIMIT)); goto out; } inp = CAST(cdf_property_info_t *, @@ -922,7 +932,7 @@ cdf_copy_info(cdf_property_info_t *inp, const void *p, const void *e, if (inp->pi_type & CDF_VECTOR) return 0; - if ((size_t)(CAST(const char *, e) - CAST(const char *, p)) < len) + if (CAST(size_t, CAST(const char *, e) - CAST(const char *, p)) < len) return 0; (void)memcpy(&inp->pi_val, p, len); @@ -1065,10 +1075,10 @@ cdf_read_property_info(const cdf_stream_t *sst, const cdf_header_t *h, inp[i].pi_str.s_buf = CAST(const char *, CAST(const void *, &q[o4])); - DPRINTF(("o=%zu l=%d(%" SIZE_T_FORMAT - "u), t=%zu s=%s\n", o4, l, - CDF_ROUND(l, sizeof(l)), left, - inp[i].pi_str.s_buf)); + DPRINTF(("o=%" SIZE_T_FORMAT "u l=%d(%" + SIZE_T_FORMAT "u), t=%" SIZE_T_FORMAT + "u s=%s\n", o4, l, CDF_ROUND(l, sizeof(l)), + left, inp[i].pi_str.s_buf)); if (l & 1) l++; @@ -1108,8 +1118,9 @@ cdf_unpack_summary_info(const cdf_stream_t *sst, const cdf_header_t *h, const cdf_summary_info_header_t *si = CAST(const cdf_summary_info_header_t *, sst->sst_tab); const cdf_section_declaration_t *sd = - CAST(const cdf_section_declaration_t *, (const void *) - ((const char *)sst->sst_tab + CDF_SECTION_DECLARATION_OFFSET)); + CAST(const cdf_section_declaration_t *, RCAST(const void *, + RCAST(const char *, sst->sst_tab) + + CDF_SECTION_DECLARATION_OFFSET)); if (cdf_check_stream_offset(sst, h, si, sizeof(*si), __LINE__) == -1 || cdf_check_stream_offset(sst, h, sd, sizeof(*sd), __LINE__) == -1) @@ -1260,28 +1271,28 @@ cdf_print_elapsed_time(char *buf, size_t bufsiz, cdf_timestamp_t ts) int days, hours, mins, secs; ts /= CDF_TIME_PREC; - secs = (int)(ts % 60); + secs = CAST(int, ts % 60); ts /= 60; - mins = (int)(ts % 60); + mins = CAST(int, ts % 60); ts /= 60; - hours = (int)(ts % 24); + hours = CAST(int, ts % 24); ts /= 24; - days = (int)ts; + days = CAST(int, ts); if (days) { len += snprintf(buf + len, bufsiz - len, "%dd+", days); - if ((size_t)len >= bufsiz) + if (CAST(size_t, len) >= bufsiz) return len; } if (days || hours) { len += snprintf(buf + len, bufsiz - len, "%.2d:", hours); - if ((size_t)len >= bufsiz) + if (CAST(size_t, len) >= bufsiz) return len; } len += snprintf(buf + len, bufsiz - len, "%.2d:", mins); - if ((size_t)len >= bufsiz) + if (CAST(size_t, len) >= bufsiz) return len; len += snprintf(buf + len, bufsiz - len, "%.2d", secs); @@ -1293,7 +1304,7 @@ 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] = CAST(char, p[i]); buf[i] = '\0'; return buf; } diff --git a/src/cdf.h b/src/cdf.h index f2df8306b17d3..2f7e554b71809 100644 --- a/src/cdf.h +++ b/src/cdf.h @@ -76,9 +76,9 @@ typedef struct { cdf_secid_t h_master_sat[436/4]; } cdf_header_t; -#define CDF_SEC_SIZE(h) ((size_t)(1 << (h)->h_sec_size_p2)) +#define CDF_SEC_SIZE(h) CAST(size_t, 1 << (h)->h_sec_size_p2) #define CDF_SEC_POS(h, secid) (CDF_SEC_SIZE(h) + (secid) * CDF_SEC_SIZE(h)) -#define CDF_SHORT_SEC_SIZE(h) ((size_t)(1 << (h)->h_short_sec_size_p2)) +#define CDF_SHORT_SEC_SIZE(h) CAST(size_t, 1 << (h)->h_short_sec_size_p2) #define CDF_SHORT_SEC_POS(h, secid) ((secid) * CDF_SHORT_SEC_SIZE(h)) typedef int32_t cdf_dirid_t; @@ -272,7 +272,7 @@ typedef struct { typedef struct { uint16_t ce_namlen; uint32_t ce_num; - uint64_t ce_timestamp; + uint64_t ce_timestamp; uint16_t ce_name[256]; } cdf_catalog_entry_t; diff --git a/src/cdf_time.c b/src/cdf_time.c index 2bdcd2a7f7a8a..e4eea4c737f39 100644 --- a/src/cdf_time.c +++ b/src/cdf_time.c @@ -27,7 +27,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: cdf_time.c,v 1.16 2017/03/29 15:57:48 christos Exp $") +FILE_RCSID("@(#)$File: cdf_time.c,v 1.19 2019/03/12 20:43:05 christos Exp $") #endif #include <time.h> @@ -56,7 +56,7 @@ cdf_getdays(int year) for (y = CDF_BASE_YEAR; y < year; y++) days += isleap(y) + 365; - + return days; } @@ -68,7 +68,7 @@ cdf_getday(int year, int days) { size_t m; - for (m = 0; m < sizeof(mdays) / sizeof(mdays[0]); m++) { + for (m = 0; m < __arraycount(mdays); m++) { int sub = mdays[m] + (m == 1 && isleap(year)); if (days < sub) return days; @@ -77,7 +77,7 @@ cdf_getday(int year, int days) return days; } -/* +/* * Return the 0...11 month number. */ static int @@ -85,14 +85,14 @@ cdf_getmonth(int year, int days) { size_t m; - for (m = 0; m < sizeof(mdays) / sizeof(mdays[0]); m++) { + for (m = 0; m < __arraycount(mdays); m++) { days -= mdays[m]; if (m == 1 && isleap(year)) days--; if (days <= 0) - return (int)m; + return CAST(int, m); } - return (int)m; + return CAST(int, m); } int @@ -108,22 +108,22 @@ cdf_timestamp_to_timespec(struct timespec *ts, cdf_timestamp_t t) ts->tv_nsec = (t % CDF_TIME_PREC) * 100; t /= CDF_TIME_PREC; - tm.tm_sec = (int)(t % 60); + tm.tm_sec = CAST(int, t % 60); t /= 60; - tm.tm_min = (int)(t % 60); + tm.tm_min = CAST(int, t % 60); t /= 60; - tm.tm_hour = (int)(t % 24); + tm.tm_hour = CAST(int, t % 24); t /= 24; /* XXX: Approx */ - tm.tm_year = (int)(CDF_BASE_YEAR + (t / 365)); + tm.tm_year = CAST(int, CDF_BASE_YEAR + (t / 365)); rdays = cdf_getdays(tm.tm_year); t -= rdays - 1; - tm.tm_mday = cdf_getday(tm.tm_year, (int)t); - tm.tm_mon = cdf_getmonth(tm.tm_year, (int)t); + tm.tm_mday = cdf_getday(tm.tm_year, CAST(int, t)); + tm.tm_mon = cdf_getmonth(tm.tm_year, CAST(int, t)); tm.tm_wday = 0; tm.tm_yday = 0; tm.tm_isdst = 0; @@ -172,7 +172,7 @@ cdf_ctime(const time_t *sec, char *buf) if (ptr != NULL) return buf; (void)snprintf(buf, 26, "*Bad* %#16.16" INT64_T_FORMAT "x\n", - (long long)*sec); + CAST(long long, *sec)); return buf; } diff --git a/src/compress.c b/src/compress.c index 5d565d56089ec..95e42a24dd522 100644 --- a/src/compress.c +++ b/src/compress.c @@ -2,7 +2,7 @@ * Copyright (c) Ian F. Darwin 1986-1995. * Software written by Ian F. Darwin and others; * maintained 1995-present by Christos Zoulas and others. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -12,7 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -29,13 +29,13 @@ * compress routines: * zmagic() - returns 0 if not recognized, uncompresses and prints * information if recognized - * uncompress(method, old, n, newch) - uncompress old into new, + * uncompress(method, old, n, newch) - uncompress old into new, * using method, return sizeof new */ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: compress.c,v 1.107 2018/04/28 18:48:22 christos Exp $") +FILE_RCSID("@(#)$File: compress.c,v 1.121 2019/05/07 02:27:11 christos Exp $") #endif #include "magic.h" @@ -47,12 +47,10 @@ FILE_RCSID("@(#)$File: compress.c,v 1.107 2018/04/28 18:48:22 christos Exp $") #include <errno.h> #include <ctype.h> #include <stdarg.h> -#ifdef HAVE_SIGNAL_H #include <signal.h> -# ifndef HAVE_SIG_T +#ifndef HAVE_SIG_T typedef void (*sig_t)(int); -# endif /* HAVE_SIG_T */ -#endif +#endif /* HAVE_SIG_T */ #if !defined(__MINGW32__) && !defined(WIN32) #include <sys/ioctl.h> #endif @@ -62,10 +60,17 @@ typedef void (*sig_t)(int); #if defined(HAVE_SYS_TIME_H) #include <sys/time.h> #endif + #if defined(HAVE_ZLIB_H) && defined(ZLIBSUPPORT) #define BUILTIN_DECOMPRESS #include <zlib.h> #endif + +#if defined(HAVE_BZLIB_H) +#define BUILTIN_BZLIB +#include <bzlib.h> +#endif + #ifdef DEBUG int tty = -1; #define DPRINTF(...) do { \ @@ -137,30 +142,34 @@ static const char *zstd_args[] = { "zstd", "-cd", NULL }; +#define do_zlib NULL +#define do_bzlib NULL + private const struct { const void *magic; size_t maglen; const char **argv; + void *unused; } compr[] = { - { "\037\235", 2, gzip_args }, /* compressed */ + { "\037\235", 2, gzip_args, NULL }, /* compressed */ /* Uncompress can get stuck; so use gzip first if we have it * Idea from Damien Clark, thanks! */ - { "\037\235", 2, uncompress_args }, /* compressed */ - { "\037\213", 2, gzip_args }, /* gzipped */ - { "\037\236", 2, gzip_args }, /* frozen */ - { "\037\240", 2, gzip_args }, /* SCO LZH */ + { "\037\235", 2, uncompress_args, NULL }, /* compressed */ + { "\037\213", 2, gzip_args, do_zlib }, /* gzipped */ + { "\037\236", 2, gzip_args, NULL }, /* frozen */ + { "\037\240", 2, gzip_args, NULL }, /* SCO LZH */ /* the standard pack utilities do not accept standard input */ - { "\037\036", 2, gzip_args }, /* packed */ - { "PK\3\4", 4, gzip_args }, /* pkzipped, */ + { "\037\036", 2, gzip_args, NULL }, /* packed */ + { "PK\3\4", 4, gzip_args, NULL }, /* pkzipped, */ /* ...only first file examined */ - { "BZh", 3, bzip2_args }, /* bzip2-ed */ - { "LZIP", 4, lzip_args }, /* lzip-ed */ - { "\3757zXZ\0", 6, xz_args }, /* XZ Utils */ - { "LRZI", 4, lrzip_args }, /* LRZIP */ - { "\004\"M\030",4, lz4_args }, /* LZ4 */ - { "\x28\xB5\x2F\xFD", 4, zstd_args }, /* zstd */ + { "BZh", 3, bzip2_args, do_bzlib }, /* bzip2-ed */ + { "LZIP", 4, lzip_args, NULL }, /* lzip-ed */ + { "\3757zXZ\0", 6, xz_args, NULL }, /* XZ Utils */ + { "LRZI", 4, lrzip_args, NULL }, /* LRZIP */ + { "\004\"M\030",4, lz4_args, NULL }, /* LZ4 */ + { "\x28\xB5\x2F\xFD", 4, zstd_args, NULL }, /* zstd */ #ifdef ZLIBSUPPORT - { RCAST(const void *, zlibcmp), 0, zlib_args }, /* zlib */ + { RCAST(const void *, zlibcmp), 0, zlib_args, NULL }, /* zlib */ #endif }; @@ -170,7 +179,7 @@ private const struct { private ssize_t swrite(int, const void *, size_t); #if HAVE_FORK -private size_t ncompr = sizeof(compr) / sizeof(compr[0]); +private size_t ncompr = __arraycount(compr); private int uncompressbuf(int, size_t, size_t, const unsigned char *, unsigned char **, size_t *); #ifdef BUILTIN_DECOMPRESS @@ -179,6 +188,11 @@ private int uncompresszlib(const unsigned char *, unsigned char **, size_t, private int uncompressgzipped(const unsigned char *, unsigned char **, size_t, size_t *); #endif +#ifdef BUILTIN_BZLIB +private int uncompressbzlib(const unsigned char *, unsigned char **, size_t, + size_t *, int); +#endif + static int makeerror(unsigned char **, size_t *, const char *, ...) __attribute__((__format__(__printf__, 3, 4))); private const char *methodname(size_t); @@ -210,18 +224,14 @@ file_zmagic(struct magic_set *ms, const struct buffer *b, const char *name) int urv, prv, rv = 0; int mime = ms->flags & MAGIC_MIME; int fd = b->fd; - const unsigned char *buf = b->fbuf; + const unsigned char *buf = CAST(const unsigned char *, b->fbuf); size_t nbytes = b->flen; -#ifdef HAVE_SIGNAL_H - sig_t osigpipe; -#endif + int sa_saved = 0; + struct sigaction sig_act; if ((ms->flags & MAGIC_COMPRESS) == 0) return 0; -#ifdef HAVE_SIGNAL_H - osigpipe = signal(SIGPIPE, SIG_IGN); -#endif for (i = 0; i < ncompr; i++) { int zm; if (nbytes < compr[i].maglen) @@ -236,10 +246,20 @@ file_zmagic(struct magic_set *ms, const struct buffer *b, const char *name) if (!zm) continue; + + /* Prevent SIGPIPE death if child dies unexpectedly */ + if (!sa_saved) { + //We can use sig_act for both new and old, but + struct sigaction new_act; + memset(&new_act, 0, sizeof(new_act)); + new_act.sa_handler = SIG_IGN; + sa_saved = sigaction(SIGPIPE, &new_act, &sig_act) != -1; + } + nsz = nbytes; urv = uncompressbuf(fd, ms->bytes_max, i, buf, &newbuf, &nsz); - DPRINTF("uncompressbuf = %d, %s, %zu\n", urv, (char *)newbuf, - nsz); + DPRINTF("uncompressbuf = %d, %s, %" SIZE_T_FORMAT "u\n", urv, + (char *)newbuf, nsz); switch (urv) { case OKDATA: case ERRDATA: @@ -247,7 +267,7 @@ file_zmagic(struct magic_set *ms, const struct buffer *b, const char *name) if (urv == ERRDATA) prv = format_decompression_error(ms, i, newbuf); else - prv = file_buffer(ms, -1, name, newbuf, nsz); + prv = file_buffer(ms, -1, NULL, name, newbuf, nsz); if (prv == -1) goto error; rv = 1; @@ -264,8 +284,11 @@ file_zmagic(struct magic_set *ms, const struct buffer *b, const char *name) * XXX: If file_buffer fails here, we overwrite * the compressed text. FIXME. */ - if (file_buffer(ms, -1, NULL, buf, nbytes) == -1) + if (file_buffer(ms, -1, NULL, NULL, buf, nbytes) == -1) { + if (file_pop_buffer(ms, pb) != NULL) + abort(); goto error; + } if ((rbuf = file_pop_buffer(ms, pb)) != NULL) { if (file_printf(ms, "%s", rbuf) == -1) { free(rbuf); @@ -289,9 +312,9 @@ file_zmagic(struct magic_set *ms, const struct buffer *b, const char *name) out: DPRINTF("rv = %d\n", rv); -#ifdef HAVE_SIGNAL_H - (void)signal(SIGPIPE, osigpipe); -#endif + if (sa_saved && sig_act.sa_handler != SIG_IGN) + (void)sigaction(SIGPIPE, &sig_act, NULL); + free(newbuf); ms->flags |= MAGIC_COMPRESS; DPRINTF("Zmagic returns %d\n", rv); @@ -367,7 +390,7 @@ sread(int fd, void *buf, size_t n, int canbepipe __attribute__((__unused__))) (void)ioctl(fd, FIONREAD, &t); } - if (t > 0 && (size_t)t < n) { + if (t > 0 && CAST(size_t, t) < n) { n = t; rn = n; } @@ -411,7 +434,9 @@ file_pipe2file(struct magic_set *ms, int fd, const void *startbuf, #else { int te; + mode_t ou = umask(0); tfd = mkstemp(buf); + (void)umask(ou); te = errno; (void)unlink(buf); errno = te; @@ -423,11 +448,11 @@ file_pipe2file(struct magic_set *ms, int fd, const void *startbuf, return -1; } - if (swrite(tfd, startbuf, nbytes) != (ssize_t)nbytes) + if (swrite(tfd, startbuf, nbytes) != CAST(ssize_t, nbytes)) r = 1; else { while ((r = sread(fd, buf, sizeof(buf), 1)) > 0) - if (swrite(tfd, buf, (size_t)r) != r) + if (swrite(tfd, buf, CAST(size_t, r)) != r) break; } @@ -452,7 +477,7 @@ file_pipe2file(struct magic_set *ms, int fd, const void *startbuf, return -1; } (void)close(tfd); - if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) { + if (lseek(fd, CAST(off_t, 0), SEEK_SET) == CAST(off_t, -1)) { file_badseek(ms); return -1; } @@ -509,7 +534,7 @@ uncompresszlib(const unsigned char *old, unsigned char **newch, int rc; z_stream z; - if ((*newch = CAST(unsigned char *, malloc(bytes_max + 1))) == NULL) + if ((*newch = CAST(unsigned char *, malloc(bytes_max + 1))) == NULL) return makeerror(newch, n, "No buffer, %s", strerror(errno)); z.next_in = CCAST(Bytef *, old); @@ -529,18 +554,18 @@ uncompresszlib(const unsigned char *old, unsigned char **newch, if (rc != Z_OK && rc != Z_STREAM_END) goto err; - *n = (size_t)z.total_out; + *n = CAST(size_t, z.total_out); rc = inflateEnd(&z); if (rc != Z_OK) goto err; - + /* let's keep the nul-terminate tradition */ (*newch)[*n] = '\0'; return OKDATA; err: - strlcpy((char *)*newch, z.msg ? z.msg : zError(rc), bytes_max); - *n = strlen((char *)*newch); + strlcpy(RCAST(char *, *newch), z.msg ? z.msg : zError(rc), bytes_max); + *n = strlen(RCAST(char *, *newch)); return ERRDATA; } #endif @@ -560,7 +585,7 @@ makeerror(unsigned char **buf, size_t *len, const char *fmt, ...) *len = 0; return NODATA; } - *buf = (unsigned char *)msg; + *buf = RCAST(unsigned char *, msg); *len = strlen(msg); return ERRDATA; } @@ -582,52 +607,42 @@ closep(int *fd) closefd(fd, i); } -static void -copydesc(int i, int *fd) +static int +copydesc(int i, int fd) { - int j = fd[i == STDIN_FILENO ? 0 : 1]; - if (j == i) - return; - if (dup2(j, i) == -1) { - DPRINTF("dup(%d, %d) failed (%s)\n", j, i, strerror(errno)); + if (fd == i) + return 0; /* "no dup was necessary" */ + if (dup2(fd, i) == -1) { + DPRINTF("dup(%d, %d) failed (%s)\n", fd, i, strerror(errno)); exit(1); } - closep(fd); + return 1; } -static void -writechild(int fdp[3][2], const void *old, size_t n) +static pid_t +writechild(int fd, const void *old, size_t n) { - int status; + pid_t pid; - closefd(fdp[STDIN_FILENO], 0); - /* + /* * fork again, to avoid blocking because both * pipes filled */ - switch (fork()) { - case 0: /* child */ - closefd(fdp[STDOUT_FILENO], 0); - if (swrite(fdp[STDIN_FILENO][1], old, n) != (ssize_t)n) { - DPRINTF("Write failed (%s)\n", strerror(errno)); - exit(1); - } - exit(0); - /*NOTREACHED*/ - - case -1: + pid = fork(); + if (pid == -1) { DPRINTF("Fork failed (%s)\n", strerror(errno)); exit(1); - /*NOTREACHED*/ - - default: /* parent */ - if (wait(&status) == -1) { - DPRINTF("Wait failed (%s)\n", strerror(errno)); + } + if (pid == 0) { + /* child */ + if (swrite(fd, old, n) != CAST(ssize_t, n)) { + DPRINTF("Write failed (%s)\n", strerror(errno)); exit(1); } - DPRINTF("Grandchild wait return %#x\n", status); + exit(0); } - closefd(fdp[STDIN_FILENO], 1); + /* parent */ + return pid; } static ssize_t @@ -637,17 +652,17 @@ filter_error(unsigned char *ubuf, ssize_t n) char *buf; ubuf[n] = '\0'; - buf = (char *)ubuf; - while (isspace((unsigned char)*buf)) + buf = RCAST(char *, ubuf); + while (isspace(CAST(unsigned char, *buf))) buf++; DPRINTF("Filter error[[[%s]]]\n", buf); - if ((p = strchr((char *)buf, '\n')) != NULL) + if ((p = strchr(CAST(char *, buf), '\n')) != NULL) *p = '\0'; - if ((p = strchr((char *)buf, ';')) != NULL) + if ((p = strchr(CAST(char *, buf), ';')) != NULL) *p = '\0'; - if ((p = strrchr((char *)buf, ':')) != NULL) { + if ((p = strrchr(CAST(char *, buf), ':')) != NULL) { ++p; - while (isspace((unsigned char)*p)) + while (isspace(CAST(unsigned char, *p))) p++; n = strlen(p); memmove(ubuf, p, CAST(size_t, n + 1)); @@ -674,7 +689,9 @@ uncompressbuf(int fd, size_t bytes_max, size_t method, const unsigned char *old, unsigned char **newch, size_t* n) { int fdp[3][2]; - int status, rv; + int status, rv, w; + pid_t pid; + pid_t writepid = -1; size_t i; ssize_t r; @@ -698,43 +715,68 @@ uncompressbuf(int fd, size_t bytes_max, size_t method, const unsigned char *old, return makeerror(newch, n, "Cannot create pipe, %s", strerror(errno)); } - switch (fork()) { - case 0: /* child */ + + /* For processes with large mapped virtual sizes, vfork + * may be _much_ faster (10-100 times) than fork. + */ + pid = vfork(); + if (pid == -1) { + return makeerror(newch, n, "Cannot vfork, %s", + strerror(errno)); + } + if (pid == 0) { + /* child */ + /* Note: we are after vfork, do not modify memory + * in a way which confuses parent. In particular, + * do not modify fdp[i][j]. + */ if (fd != -1) { - fdp[STDIN_FILENO][0] = fd; - (void) lseek(fd, (off_t)0, SEEK_SET); + (void) lseek(fd, CAST(off_t, 0), SEEK_SET); + if (copydesc(STDIN_FILENO, fd)) + (void) close(fd); + } else { + if (copydesc(STDIN_FILENO, fdp[STDIN_FILENO][0])) + (void) close(fdp[STDIN_FILENO][0]); + if (fdp[STDIN_FILENO][1] > 2) + (void) close(fdp[STDIN_FILENO][1]); } - - for (i = 0; i < __arraycount(fdp); i++) - copydesc(CAST(int, i), fdp[i]); +///FIXME: if one of the fdp[i][j] is 0 or 1, this can bomb spectacularly + if (copydesc(STDOUT_FILENO, fdp[STDOUT_FILENO][1])) + (void) close(fdp[STDOUT_FILENO][1]); + if (fdp[STDOUT_FILENO][0] > 2) + (void) close(fdp[STDOUT_FILENO][0]); + + if (copydesc(STDERR_FILENO, fdp[STDERR_FILENO][1])) + (void) close(fdp[STDERR_FILENO][1]); + if (fdp[STDERR_FILENO][0] > 2) + (void) close(fdp[STDERR_FILENO][0]); (void)execvp(compr[method].argv[0], - (char *const *)(intptr_t)compr[method].argv); - dprintf(STDERR_FILENO, "exec `%s' failed, %s", + RCAST(char *const *, RCAST(intptr_t, compr[method].argv))); + dprintf(STDERR_FILENO, "exec `%s' failed, %s", compr[method].argv[0], strerror(errno)); - exit(1); - /*NOTREACHED*/ - case -1: - return makeerror(newch, n, "Cannot fork, %s", - strerror(errno)); - - default: /* parent */ - for (i = 1; i < __arraycount(fdp); i++) - closefd(fdp[i], 1); - - /* Write the buffer data to the child, if we don't have fd */ - if (fd == -1) - writechild(fdp, old, *n); + _exit(1); /* _exit(), not exit(), because of vfork */ + } + /* parent */ + /* Close write sides of child stdout/err pipes */ + for (i = 1; i < __arraycount(fdp); i++) + closefd(fdp[i], 1); + /* Write the buffer data to child stdin, if we don't have fd */ + if (fd == -1) { + closefd(fdp[STDIN_FILENO], 0); + writepid = writechild(fdp[STDIN_FILENO][1], old, *n); + closefd(fdp[STDIN_FILENO], 1); + } - *newch = CAST(unsigned char *, malloc(bytes_max + 1)); - if (*newch == NULL) { - rv = makeerror(newch, n, "No buffer, %s", - strerror(errno)); - goto err; - } - rv = OKDATA; - if ((r = sread(fdp[STDOUT_FILENO][0], *newch, bytes_max, 0)) > 0) - break; + *newch = CAST(unsigned char *, malloc(bytes_max + 1)); + if (*newch == NULL) { + rv = makeerror(newch, n, "No buffer, %s", + strerror(errno)); + goto err; + } + rv = OKDATA; + r = sread(fdp[STDOUT_FILENO][0], *newch, bytes_max, 0); + if (r <= 0) { DPRINTF("Read stdout failed %d (%s)\n", fdp[STDOUT_FILENO][0], r != -1 ? strerror(errno) : "no data"); @@ -743,7 +785,7 @@ uncompressbuf(int fd, size_t bytes_max, size_t method, const unsigned char *old, (r = sread(fdp[STDERR_FILENO][0], *newch, bytes_max, 0)) > 0) { r = filter_error(*newch, r); - break; + goto ok; } free(*newch); if (r == 0) @@ -753,7 +795,7 @@ uncompressbuf(int fd, size_t bytes_max, size_t method, const unsigned char *old, rv = makeerror(newch, n, "No data"); goto err; } - +ok: *n = r; /* NUL terminate, as every buffer is handled here. */ (*newch)[*n] = '\0'; @@ -761,7 +803,10 @@ err: closefd(fdp[STDIN_FILENO], 1); closefd(fdp[STDOUT_FILENO], 0); closefd(fdp[STDERR_FILENO], 0); - if (wait(&status) == -1) { + + w = waitpid(pid, &status, 0); +wait_err: + if (w == -1) { free(*newch); rv = makeerror(newch, n, "Wait failed, %s", strerror(errno)); DPRINTF("Child wait return %#x\n", status); @@ -770,10 +815,19 @@ err: } else if (WEXITSTATUS(status) != 0) { DPRINTF("Child exited (%#x)\n", WEXITSTATUS(status)); } + if (writepid > 0) { + /* _After_ we know decompressor has exited, our input writer + * definitely will exit now (at worst, writing fails in it, + * since output fd is closed now on the reading size). + */ + w = waitpid(writepid, &status, 0); + writepid = -1; + goto wait_err; + } + + closefd(fdp[STDIN_FILENO], 0); //why? it is already closed here! + DPRINTF("Returning %p n=%" SIZE_T_FORMAT "u rv=%d\n", *newch, *n, rv); - closefd(fdp[STDIN_FILENO], 0); - DPRINTF("Returning %p n=%zu rv=%d\n", *newch, *n, rv); - return rv; } #endif diff --git a/src/der.c b/src/der.c index d017b63983f09..8867c568034dd 100644 --- a/src/der.c +++ b/src/der.c @@ -35,7 +35,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: der.c,v 1.13 2018/06/23 15:15:26 christos Exp $") +FILE_RCSID("@(#)$File: der.c,v 1.16 2019/02/20 02:35:27 christos Exp $") #endif #endif @@ -56,7 +56,7 @@ FILE_RCSID("@(#)$File: der.c,v 1.13 2018/06/23 15:15:26 christos Exp $") #include <err.h> #endif -#define DER_BAD ((uint32_t)-1) +#define DER_BAD CAST(uint32_t, -1) #define DER_CLASS_UNIVERSAL 0 #define DER_CLASS_APPLICATION 1 @@ -207,7 +207,7 @@ getlength(const uint8_t *c, size_t *p, size_t l) static const char * der_tag(char *buf, size_t len, uint32_t tag) { - if (tag < DER_TAG_LONG) + if (tag < DER_TAG_LONG) strlcpy(buf, der__tag[tag], len); else snprintf(buf, len, "%#x", tag); @@ -224,11 +224,11 @@ der_data(char *buf, size_t blen, uint32_t tag, const void *q, uint32_t len) case DER_TAG_UTF8_STRING: case DER_TAG_IA5_STRING: case DER_TAG_UTCTIME: - return snprintf(buf, blen, "%.*s", len, (const char *)q); + return snprintf(buf, blen, "%.*s", len, RCAST(const char *, q)); default: break; } - + for (uint32_t i = 0; i < len; i++) { uint32_t z = i << 1; if (z < blen - 2) @@ -245,18 +245,21 @@ der_offs(struct magic_set *ms, struct magic *m, size_t nbytes) if (gettag(b, &offs, len) == DER_BAD) return -1; - DPRINTF(("%s1: %d %zu %u\n", __func__, ms->offset, offs, m->offset)); + DPRINTF(("%s1: %d %" SIZE_T_FORMAT "u %u\n", __func__, ms->offset, + offs, m->offset)); uint32_t tlen = getlength(b, &offs, len); if (tlen == DER_BAD) return -1; - DPRINTF(("%s2: %d %zu %u\n", __func__, ms->offset, offs, tlen)); + DPRINTF(("%s2: %d %" SIZE_T_FORMAT "u %u\n", __func__, ms->offset, + offs, tlen)); offs += ms->offset + m->offset; DPRINTF(("cont_level = %d\n", m->cont_level)); #ifdef DEBUG_DER for (size_t i = 0; i < m->cont_level; i++) - printf("cont_level[%zu] = %u\n", i, ms->c.li[i].off); + printf("cont_level[%" SIZE_T_FORMAT "u] = %u\n", i, + ms->c.li[i].off); #endif if (m->cont_level != 0) { if (offs + tlen > nbytes) @@ -304,22 +307,23 @@ again: s++; goto val; default: - if (!isdigit((unsigned char)*s)) + if (!isdigit(CAST(unsigned char, *s))) return 0; slen = 0; do slen = slen * 10 + *s - '0'; - while (isdigit((unsigned char)*++s)); + while (isdigit(CAST(unsigned char, *++s))); if ((ms->flags & MAGIC_DEBUG) != 0) - fprintf(stderr, "%s: len %zu %u\n", __func__, - slen, tlen); + fprintf(stderr, "%s: len %" SIZE_T_FORMAT "u %u\n", + __func__, slen, tlen); if (tlen != slen) return 0; goto again; } val: - DPRINTF(("%s: before data %zu %u\n", __func__, offs, tlen)); + DPRINTF(("%s: before data %" SIZE_T_FORMAT "u %u\n", __func__, offs, + tlen)); der_data(buf, sizeof(buf), tag, b + offs, tlen); if ((ms->flags & MAGIC_DEBUG) != 0) fprintf(stderr, "%s: data %s %s\n", __func__, buf, s); @@ -343,7 +347,7 @@ printtag(uint32_t tag, const void *q, uint32_t len) default: break; } - + for (uint32_t i = 0; i < len; i++) printf("%.2x", d[i]); printf("\n"); @@ -367,8 +371,9 @@ printdata(size_t level, const void *v, size_t x, size_t l) if (p + x >= ep) break; uint32_t len = getlength(p, &x, ep - p + x); - - printf("%zu %zu-%zu %c,%c,%s,%u:", level, ox, x, + + printf("%" SIZE_T_FORMAT "u %" SIZE_T_FORMAT "u-%" + SIZE_T_FORMAT "u %c,%c,%s,%u:", level, ox, x, der_class[c], der_type[t], der_tag(buf, sizeof(buf), tag), len); q = p + x; diff --git a/src/dprintf.c b/src/dprintf.c index 3ae1581b16e86..027a64f39e29d 100644 --- a/src/dprintf.c +++ b/src/dprintf.c @@ -2,7 +2,7 @@ * Copyright (c) Ian F. Darwin 1986-1995. * Software written by Ian F. Darwin and others; * maintained 1995-present by Christos Zoulas and others. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -12,7 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -28,7 +28,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: dprintf.c,v 1.1 2015/11/13 15:36:14 christos Exp $") +FILE_RCSID("@(#)$File: dprintf.c,v 1.2 2018/09/09 20:33:28 christos Exp $") #endif /* lint */ #include <assert.h> diff --git a/src/elfclass.h b/src/elfclass.h index 5360b0b55a7e8..936d8dc912e07 100644 --- a/src/elfclass.h +++ b/src/elfclass.h @@ -1,7 +1,7 @@ /* * Copyright (c) Christos Zoulas 2008. * All Rights Reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -11,7 +11,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -41,8 +41,8 @@ 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), + CAST(off_t, elf_getu(swap, elfhdr.e_phoff)), phnum, + CAST(size_t, elf_getu16(swap, elfhdr.e_phentsize)), fsize, &flags, ¬ecount) == -1) return -1; break; @@ -56,8 +56,8 @@ 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, - (size_t)elf_getu16(swap, elfhdr.e_phentsize), + CAST(off_t, elf_getu(swap, elfhdr.e_phoff)), phnum, + CAST(size_t, elf_getu16(swap, elfhdr.e_phentsize)), fsize, shnum, &flags, ¬ecount) == -1) return -1; /*FALLTHROUGH*/ @@ -66,10 +66,10 @@ if (shnum > ms->elf_shnum_max) 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), + CAST(off_t, elf_getu(swap, elfhdr.e_shoff)), shnum, + CAST(size_t, elf_getu16(swap, elfhdr.e_shentsize)), fsize, elf_getu16(swap, elfhdr.e_machine), - (int)elf_getu16(swap, elfhdr.e_shstrndx), + CAST(int, elf_getu16(swap, elfhdr.e_shstrndx)), &flags, ¬ecount) == -1) return -1; break; diff --git a/src/encoding.c b/src/encoding.c index 3e7b9e584b08e..76244f87f95b0 100644 --- a/src/encoding.c +++ b/src/encoding.c @@ -35,7 +35,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: encoding.c,v 1.14 2017/11/02 20:25:39 christos Exp $") +FILE_RCSID("@(#)$File: encoding.c,v 1.20 2019/04/15 16:48:41 christos Exp $") #endif /* lint */ #include "magic.h" @@ -49,6 +49,7 @@ private int looks_utf8_with_BOM(const unsigned char *, size_t, unichar *, size_t *); private int looks_utf7(const unsigned char *, size_t, unichar *, size_t *); private int looks_ucs16(const unsigned char *, size_t, unichar *, size_t *); +private int looks_ucs32(const unsigned char *, size_t, unichar *, size_t *); private int looks_latin1(const unsigned char *, size_t, unichar *, size_t *); private int looks_extended(const unsigned char *, size_t, unichar *, size_t *); private void from_ebcdic(const unsigned char *, size_t, unsigned char *); @@ -69,7 +70,7 @@ protected int file_encoding(struct magic_set *ms, const struct buffer *b, unichar **ubuf, size_t *ulen, const char **code, const char **code_mime, const char **type) { - const unsigned char *buf = b->fbuf; + const unsigned char *buf = CAST(const unsigned char *, b->fbuf); size_t nbytes = b->flen; size_t mlen; int rv = 1, ucs_type; @@ -88,12 +89,13 @@ file_encoding(struct magic_set *ms, const struct buffer *b, unichar **ubuf, *code_mime = "binary"; mlen = (nbytes + 1) * sizeof((*ubuf)[0]); - if ((*ubuf = CAST(unichar *, calloc((size_t)1, mlen))) == NULL) { + if ((*ubuf = CAST(unichar *, calloc(CAST(size_t, 1), mlen))) == NULL) { file_oomem(ms, mlen); goto done; } mlen = (nbytes + 1) * sizeof(nbuf[0]); - if ((nbuf = CAST(unsigned char *, calloc((size_t)1, mlen))) == NULL) { + if ((nbuf = CAST(unsigned char *, + calloc(CAST(size_t, 1), mlen))) == NULL) { file_oomem(ms, mlen); goto done; } @@ -116,6 +118,15 @@ file_encoding(struct magic_set *ms, const struct buffer *b, unichar **ubuf, DPRINTF(("utf8 %" SIZE_T_FORMAT "u\n", *ulen)); *code = "UTF-8 Unicode"; *code_mime = "utf-8"; + } else if ((ucs_type = looks_ucs32(buf, nbytes, *ubuf, ulen)) != 0) { + if (ucs_type == 1) { + *code = "Little-endian UTF-32 Unicode"; + *code_mime = "utf-32le"; + } else { + *code = "Big-endian UTF-32 Unicode"; + *code_mime = "utf-32be"; + } + DPRINTF(("ucs32 %" SIZE_T_FORMAT "u\n", *ulen)); } else if ((ucs_type = looks_ucs16(buf, nbytes, *ubuf, ulen)) != 0) { if (ucs_type == 1) { *code = "Little-endian UTF-16 Unicode"; @@ -410,7 +421,7 @@ looks_utf7(const unsigned char *buf, size_t nbytes, unichar *ubuf, size_t *ulen) } private int -looks_ucs16(const unsigned char *buf, size_t nbytes, unichar *ubuf, +looks_ucs16(const unsigned char *bf, size_t nbytes, unichar *ubf, size_t *ulen) { int bigend; @@ -419,9 +430,9 @@ looks_ucs16(const unsigned char *buf, size_t nbytes, unichar *ubuf, if (nbytes < 2) return 0; - if (buf[0] == 0xff && buf[1] == 0xfe) + if (bf[0] == 0xff && bf[1] == 0xfe) bigend = 0; - else if (buf[0] == 0xfe && buf[1] == 0xff) + else if (bf[0] == 0xfe && bf[1] == 0xff) bigend = 1; else return 0; @@ -432,20 +443,64 @@ looks_ucs16(const unsigned char *buf, size_t nbytes, unichar *ubuf, /* XXX fix to properly handle chars > 65536 */ if (bigend) - ubuf[(*ulen)++] = buf[i + 1] + 256 * buf[i]; + ubf[(*ulen)++] = bf[i + 1] + | (CAST(unichar, bf[i]) << 8); else - ubuf[(*ulen)++] = buf[i] + 256 * buf[i + 1]; + ubf[(*ulen)++] = bf[i] + | (CAST(unichar, bf[i + 1]) << 8); - if (ubuf[*ulen - 1] == 0xfffe) + if (ubf[*ulen - 1] == 0xfffe) return 0; - if (ubuf[*ulen - 1] < 128 && - text_chars[(size_t)ubuf[*ulen - 1]] != T) + if (ubf[*ulen - 1] < 128 && + text_chars[CAST(size_t, ubf[*ulen - 1])] != T) return 0; } return 1 + bigend; } +private int +looks_ucs32(const unsigned char *bf, size_t nbytes, unichar *ubf, + size_t *ulen) +{ + int bigend; + size_t i; + + if (nbytes < 4) + return 0; + + if (bf[0] == 0xff && bf[1] == 0xfe && bf[2] == 0 && bf[3] == 0) + bigend = 0; + else if (bf[0] == 0 && bf[1] == 0 && bf[2] == 0xfe && bf[3] == 0xff) + bigend = 1; + else + return 0; + + *ulen = 0; + + for (i = 4; i + 3 < nbytes; i += 4) { + /* XXX fix to properly handle chars > 65536 */ + + if (bigend) + ubf[(*ulen)++] = CAST(unichar, bf[i + 3]) + | (CAST(unichar, bf[i + 2]) << 8) + | (CAST(unichar, bf[i + 1]) << 16) + | (CAST(unichar, bf[i]) << 24); + else + ubf[(*ulen)++] = CAST(unichar, bf[i + 0]) + | (CAST(unichar, bf[i + 1]) << 8) + | (CAST(unichar, bf[i + 2]) << 16) + | (CAST(unichar, bf[i + 3]) << 24); + + if (ubf[*ulen - 1] == 0xfffe) + return 0; + if (ubf[*ulen - 1] < 128 && + text_chars[CAST(size_t, ubf[*ulen - 1])] != T) + return 0; + } + + return 1 + bigend; +} #undef F #undef T #undef I diff --git a/src/file.c b/src/file.c index 87dd1bb60f4c4..5b60b95f42401 100644 --- a/src/file.c +++ b/src/file.c @@ -32,7 +32,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: file.c,v 1.175 2018/03/02 16:11:37 christos Exp $") +FILE_RCSID("@(#)$File: file.c,v 1.181 2019/03/28 20:54:03 christos Exp $") #endif /* lint */ #include "magic.h" @@ -128,6 +128,7 @@ private const struct { { "encoding", MAGIC_NO_CHECK_ENCODING }, { "soft", MAGIC_NO_CHECK_SOFT }, { "tar", MAGIC_NO_CHECK_TAR }, + { "json", MAGIC_NO_CHECK_JSON }, { "text", MAGIC_NO_CHECK_TEXT }, /* synonym for ascii */ { "tokens", MAGIC_NO_CHECK_TOKENS }, /* OBSOLETE: ignored for backwards compatibility */ }; @@ -136,14 +137,15 @@ private struct { const char *name; int tag; size_t value; + int set; } 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 }, - { "elf_notes", MAGIC_PARAM_ELF_NOTES_MAX, 0 }, - { "regex", MAGIC_PARAM_REGEX_MAX, 0 }, - { "bytes", MAGIC_PARAM_BYTES_MAX, 0 }, + { "indir", MAGIC_PARAM_INDIR_MAX, 0, 0 }, + { "name", MAGIC_PARAM_NAME_MAX, 0, 0 }, + { "elf_phnum", MAGIC_PARAM_ELF_PHNUM_MAX, 0, 0 }, + { "elf_shnum", MAGIC_PARAM_ELF_SHNUM_MAX, 0, 0 }, + { "elf_notes", MAGIC_PARAM_ELF_NOTES_MAX, 0, 0 }, + { "regex", MAGIC_PARAM_REGEX_MAX, 0, 0 }, + { "bytes", MAGIC_PARAM_BYTES_MAX, 0, 0 }, }; private int posixly; @@ -184,9 +186,7 @@ main(int argc, char *argv[]) char *progname; /* 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 ... */ @@ -242,11 +242,11 @@ main(int argc, char *argv[]) flags |= MAGIC_ERROR; break; case 'e': - for (i = 0; i < sizeof(nv) / sizeof(nv[0]); i++) + for (i = 0; i < __arraycount(nv); i++) if (strcmp(nv[i].name, optarg) == 0) break; - if (i == sizeof(nv) / sizeof(nv[0])) + if (i == __arraycount(nv)) errflg++; else flags |= nv[i].value; @@ -398,7 +398,8 @@ main(int argc, char *argv[]) } else { size_t j, wid, nw; - for (wid = 0, j = (size_t)optind; j < (size_t)argc; j++) { + for (wid = 0, j = CAST(size_t, optind); j < CAST(size_t, argc); + j++) { nw = file_mbswidth(argv[j]); if (nw > wid) wid = nw; @@ -426,7 +427,7 @@ applyparam(magic_t magic) size_t i; for (i = 0; i < __arraycount(pm); i++) { - if (pm[i].value == 0) + if (!pm[i].set) continue; if (magic_setparam(magic, pm[i].tag, &pm[i].value) == -1) file_err(EXIT_FAILURE, "Can't set %s", pm[i].name); @@ -446,6 +447,7 @@ setparam(const char *p) if (strncmp(p, pm[i].name, s - p) != 0) continue; pm[i].value = atoi(s + 1); + pm[i].set = 1; return; } badparm: @@ -534,9 +536,8 @@ process(struct magic_set *ms, const char *inname, int wid) (void)putc('\0', stdout); if (nulsep < 2) { (void)printf("%s", separator); - (void)printf("%*s ", - (int) (nopad ? 0 : (wid - file_mbswidth(inname))), - ""); + (void)printf("%*s ", CAST(int, nopad ? 0 + : (wid - file_mbswidth(inname))), ""); } } @@ -563,8 +564,8 @@ file_mbswidth(const char *s) while (n > 0) { bytesconsumed = mbrtowc(&nextchar, s, n, &state); - if (bytesconsumed == (size_t)(-1) || - bytesconsumed == (size_t)(-2)) { + if (bytesconsumed == CAST(size_t, -1) || + bytesconsumed == CAST(size_t, -2)) { /* Something went wrong, return something reasonable */ return old_n; } @@ -623,13 +624,13 @@ docprint(const char *opts, int def) for (sp = p - 1; sp > opts && *sp == ' '; sp--) continue; - fprintf(stdout, "%.*s", (int)(p - opts), opts); + fprintf(stdout, "%.*s", CAST(int, p - opts), opts); comma = 0; for (i = 0; i < __arraycount(nv); i++) { fprintf(stdout, "%s%s", comma++ ? ", " : "", nv[i].name); - if (i && i % 5 == 0) { - fprintf(stdout, ",\n%*s", (int)(p - sp - 1), ""); + if (i && i % 5 == 0 && i != __arraycount(nv) - 1) { + fprintf(stdout, ",\n%*s", CAST(int, p - sp - 1), ""); comma = 0; } } @@ -653,7 +654,7 @@ help(void) #include "file_opts.h" #undef OPT #undef OPT_LONGONLY - fprintf(stdout, "\nReport bugs to http://bugs.gw.com/\n"); + fprintf(stdout, "\nReport bugs to https://bugs.astron.com/\n"); exit(EXIT_SUCCESS); } diff --git a/src/file.h b/src/file.h index 57a84a80c0d5e..69a586ab73238 100644 --- a/src/file.h +++ b/src/file.h @@ -27,7 +27,7 @@ */ /* * file.h - definitions for file(1) program - * @(#)$File: file.h,v 1.193 2018/05/24 18:09:17 christos Exp $ + * @(#)$File: file.h,v 1.206 2019/05/07 02:27:11 christos Exp $ */ #ifndef __file_h__ @@ -40,6 +40,9 @@ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS #endif +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS +#endif #ifdef WIN32 #ifdef _WIN64 @@ -379,7 +382,7 @@ struct mlist { #define CCAST(T, b) const_cast<T>(b) #else #define CAST(T, b) ((T)(b)) -#define RCAST(T, b) ((T)(b)) +#define RCAST(T, b) ((T)(uintptr_t)(b)) #define CCAST(T, b) ((T)(uintptr_t)(b)) #endif @@ -450,12 +453,14 @@ struct stat; protected const char *file_fmttime(uint64_t, int, char *); protected struct magic_set *file_ms_alloc(int); protected void file_ms_free(struct magic_set *); -protected int file_buffer(struct magic_set *, int, const char *, const void *, - size_t); +protected int file_default(struct magic_set *, size_t); +protected int file_buffer(struct magic_set *, int, struct stat *, const char *, + const void *, size_t); protected int file_fsmagic(struct magic_set *, const char *, struct stat *); protected int file_pipe2file(struct magic_set *, int, const void *, size_t); protected int file_vprintf(struct magic_set *, const char *, va_list) __attribute__((__format__(__printf__, 2, 0))); +protected int file_separator(struct magic_set *); protected size_t file_printedlen(const struct magic_set *); protected int file_replace(struct magic_set *, const char *, const char *); protected int file_printf(struct magic_set *, const char *, ...) @@ -473,6 +478,7 @@ protected int file_ascmagic_with_encoding(struct magic_set *, const struct buffer *, unichar *, size_t, const char *, const char *, int); protected int file_encoding(struct magic_set *, const struct buffer *, unichar **, size_t *, const char **, const char **, const char **); +protected int file_is_json(struct magic_set *, const struct buffer *); protected int file_is_tar(struct magic_set *, const struct buffer *); protected int file_softmagic(struct magic_set *, const struct buffer *, uint16_t *, uint16_t *, int, int); @@ -501,19 +507,18 @@ 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 *); +protected char * file_printable(char *, size_t, const char *, size_t); #ifdef __EMX__ protected int file_os2_apptype(struct magic_set *, const char *, const void *, size_t); #endif /* __EMX__ */ -protected void buffer_init(struct buffer *, int, const void *, size_t); +protected void buffer_init(struct buffer *, int, const struct stat *, + const void *, size_t); protected void buffer_fini(struct buffer *); protected int buffer_fill(const struct buffer *); -#if defined(HAVE_LOCALE_H) #include <locale.h> -#endif #if defined(HAVE_XLOCALE_H) #include <xlocale.h> #endif @@ -550,17 +555,6 @@ extern const char *file_names[]; extern const size_t file_nnames; #endif -#ifndef HAVE_STRERROR -extern int sys_nerr; -extern char *sys_errlist[]; -#define strerror(e) \ - (((e) >= 0 && (e) < sys_nerr) ? sys_errlist[(e)] : "Unknown error") -#endif - -#ifndef HAVE_STRTOUL -#define strtoul(a, b, c) strtol(a, b, c) -#endif - #ifndef HAVE_PREAD ssize_t pread(int, void *, size_t, off_t); #endif @@ -600,17 +594,17 @@ struct tm *gmtime_r(const time_t *, struct tm *); struct tm *localtime_r(const time_t *, struct tm *); #endif #ifndef HAVE_FMTCHECK -const char *fmtcheck(const char *, const char *) +const char *fmtcheck(const char *, const char *) __attribute__((__format_arg__(2))); #endif #ifdef HAVE_LIBSECCOMP -// basic filter +// basic filter // this mode should not interfere with normal operations // only some dangerous syscalls are blacklisted int enable_sandbox_basic(void); -// enhanced filter +// enhanced filter // this mode allows only the necessary syscalls used during normal operation // extensive testing required !!! int enable_sandbox_full(void); @@ -634,6 +628,9 @@ protected void file_warnx(const char *, ...) #ifndef O_BINARY #define O_BINARY 0 #endif +#ifndef O_NONBLOCK +#define O_NONBLOCK 0 +#endif #ifndef __cplusplus #if defined(__GNUC__) && (__GNUC__ >= 3) diff --git a/src/fmtcheck.c b/src/fmtcheck.c index 486aa08681d37..fcad436b8eba7 100644 --- a/src/fmtcheck.c +++ b/src/fmtcheck.c @@ -235,7 +235,7 @@ fmtcheck(const char *f1, const char *f2) EFT f1t, f2t; if (!f1) return f2; - + f1p = f1; f1t = FMTCHECK_START; f2p = f2; diff --git a/src/fsmagic.c b/src/fsmagic.c index c0a437a8f6d0e..25c4f811567f4 100644 --- a/src/fsmagic.c +++ b/src/fsmagic.c @@ -2,7 +2,7 @@ * Copyright (c) Ian F. Darwin 1986-1995. * Software written by Ian F. Darwin and others; * maintained 1995-present by Christos Zoulas and others. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -12,7 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -32,7 +32,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: fsmagic.c,v 1.77 2017/05/24 19:17:50 christos Exp $") +FILE_RCSID("@(#)$File: fsmagic.c,v 1.80 2019/04/23 18:59:27 christos Exp $") #endif /* lint */ #include "magic.h" @@ -46,11 +46,14 @@ FILE_RCSID("@(#)$File: fsmagic.c,v 1.77 2017/05/24 19:17:50 christos Exp $") # include <sys/mkdev.h> # define HAVE_MAJOR #endif -#ifdef MAJOR_IN_SYSMACROS +#ifdef HAVE_SYS_SYSMACROS_H # include <sys/sysmacros.h> +#endif +#ifdef MAJOR_IN_SYSMACROS # define HAVE_MAJOR #endif -#ifdef major /* Might be defined in sys/types.h. */ +#if defined(major) && !defined(HAVE_MAJOR) +/* Might be defined in sys/types.h. */ # define HAVE_MAJOR #endif #ifdef WIN32 @@ -77,7 +80,7 @@ bad_link(struct magic_set *ms, int err, char *buf) file_error(ms, err, "broken symbolic link to %s", buf); return -1; - } + } if (file_printf(ms, "broken symbolic link to %s", buf) == -1) return -1; } @@ -174,17 +177,17 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb) return -1; #endif #ifdef S_ISGID - if (sb->st_mode & S_ISGID) + if (sb->st_mode & S_ISGID) if (file_printf(ms, "%ssetgid", COMMA) == -1) return -1; #endif #ifdef S_ISVTX - if (sb->st_mode & S_ISVTX) + if (sb->st_mode & S_ISVTX) if (file_printf(ms, "%ssticky", COMMA) == -1) return -1; #endif } - + switch (sb->st_mode & S_IFMT) { case S_IFDIR: if (mime) { @@ -196,7 +199,7 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb) break; #ifdef S_IFCHR case S_IFCHR: - /* + /* * If -s has been specified, treat character special files * like ordinary files. Otherwise, just report that they * are block special files and go on to the next file. @@ -231,7 +234,7 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb) #endif #ifdef S_IFBLK case S_IFBLK: - /* + /* * If -s has been specified, treat block special files * like ordinary files. Otherwise, just report that they * are block special files and go on to the next file. @@ -308,6 +311,15 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb) buf[nch] = '\0'; /* readlink(2) does not do this */ /* If broken symlink, say so and quit early. */ +#ifdef __linux__ + /* + * linux procfs/devfs makes symlinks like pipe:[3515864880] + * that we can't stat their readlink output, so stat the + * original filename instead. + */ + if (stat(fn, &tstatbuf) < 0) + return bad_link(ms, errno, buf); +#else if (*buf == '/') { if (stat(buf, &tstatbuf) < 0) return bad_link(ms, errno, buf); @@ -320,7 +332,7 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb) } else { if (tmp - fn + 1 > BUFSIZ) { if (ms->flags & MAGIC_ERROR) { - file_error(ms, 0, + file_error(ms, 0, "path too long: `%s'", buf); return -1; } @@ -345,6 +357,7 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb) if (stat(tmp, &tstatbuf) < 0) return bad_link(ms, errno, buf); } +#endif /* Otherwise, handle it. */ if ((ms->flags & MAGIC_SYMLINK) != 0) { diff --git a/src/funcs.c b/src/funcs.c index 0bf92fe1c2509..23e7f32e63d26 100644 --- a/src/funcs.c +++ b/src/funcs.c @@ -27,7 +27,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: funcs.c,v 1.95 2018/05/24 18:09:17 christos Exp $") +FILE_RCSID("@(#)$File: funcs.c,v 1.104 2019/05/07 02:27:11 christos Exp $") #endif /* lint */ #include "magic.h" @@ -42,9 +42,7 @@ FILE_RCSID("@(#)$File: funcs.c,v 1.95 2018/05/24 18:09:17 christos Exp $") #if defined(HAVE_WCTYPE_H) #include <wctype.h> #endif -#if defined(HAVE_LIMITS_H) #include <limits.h> -#endif #ifndef SIZE_MAX #define SIZE_MAX ((size_t)~0) @@ -107,13 +105,13 @@ file_error_core(struct magic_set *ms, int error, const char *f, va_list va, if (lineno != 0) { free(ms->o.buf); ms->o.buf = NULL; - file_printf(ms, "line %" SIZE_T_FORMAT "u:", lineno); + (void)file_printf(ms, "line %" SIZE_T_FORMAT "u:", lineno); } if (ms->o.buf && *ms->o.buf) - file_printf(ms, " "); - file_vprintf(ms, f, va); + (void)file_printf(ms, " "); + (void)file_vprintf(ms, f, va); if (error > 0) - file_printf(ms, " (%s)", strerror(error)); + (void)file_printf(ms, " (%s)", strerror(error)); ms->event_flags |= EVENT_HAD_ERR; ms->error = error; } @@ -162,36 +160,70 @@ file_badread(struct magic_set *ms) #ifndef COMPILE_ONLY +protected int +file_separator(struct magic_set *ms) +{ + return file_printf(ms, "\n- "); +} + static int checkdone(struct magic_set *ms, int *rv) { if ((ms->flags & MAGIC_CONTINUE) == 0) return 1; - if (file_printf(ms, "\n- ") == -1) + if (file_separator(ms) == -1) *rv = -1; return 0; } +protected int +file_default(struct magic_set *ms, size_t nb) +{ + if (ms->flags & MAGIC_MIME) { + if ((ms->flags & MAGIC_MIME_TYPE) && + file_printf(ms, "application/%s", + nb ? "octet-stream" : "x-empty") == -1) + return -1; + return 1; + } + if (ms->flags & MAGIC_APPLE) { + if (file_printf(ms, "UNKNUNKN") == -1) + return -1; + return 1; + } + if (ms->flags & MAGIC_EXTENSION) { + if (file_printf(ms, "???") == -1) + return -1; + return 1; + } + return 0; +} + +/* + * The magic detection functions return: + * 1: found + * 0: not found + * -1: error + */ /*ARGSUSED*/ protected int -file_buffer(struct magic_set *ms, int fd, const char *inname __attribute__ ((__unused__)), +file_buffer(struct magic_set *ms, int fd, struct stat *st, + const char *inname __attribute__ ((__unused__)), const void *buf, size_t nb) { int m = 0, rv = 0, looks_text = 0; const char *code = NULL; const char *code_mime = "binary"; - const char *type = "application/octet-stream"; const char *def = "data"; const char *ftype = NULL; char *rbuf = NULL; struct buffer b; - buffer_init(&b, fd, buf, nb); + buffer_init(&b, fd, st, buf, nb); ms->mode = b.st.st_mode; if (nb == 0) { def = "empty"; - type = "application/x-empty"; goto simple; } else if (nb == 1) { def = "very short file (no magic)"; @@ -240,6 +272,17 @@ file_buffer(struct magic_set *ms, int fd, const char *inname __attribute__ ((__u } } + /* Check if we have a JSON file */ + if ((ms->flags & MAGIC_NO_CHECK_JSON) == 0) { + m = file_is_json(ms, &b); + if ((ms->flags & MAGIC_DEBUG) != 0) + (void)fprintf(stderr, "[try json %d]\n", m); + if (m) { + if (checkdone(ms, &rv)) + goto done; + } + } + /* Check if we have a CDF file */ if ((ms->flags & MAGIC_NO_CHECK_CDF) == 0) { m = file_trycdf(ms, &b); @@ -268,7 +311,7 @@ file_buffer(struct magic_set *ms, int fd, const char *inname __attribute__ ((__u rv = file_tryelf(ms, &b); rbuf = file_pop_buffer(ms, pb); - if (rv != 1) { + if (rv == -1) { free(rbuf); rbuf = NULL; } @@ -299,27 +342,18 @@ file_buffer(struct magic_set *ms, int fd, const char *inname __attribute__ ((__u if ((ms->flags & MAGIC_DEBUG) != 0) (void)fprintf(stderr, "[try ascmagic %d]\n", m); if (m) { - if (checkdone(ms, &rv)) - goto done; + goto done; } } simple: /* give up */ - m = 1; - if (ms->flags & MAGIC_MIME) { - if ((ms->flags & MAGIC_MIME_TYPE) && - file_printf(ms, "%s", type) == -1) - rv = -1; - } else if (ms->flags & MAGIC_APPLE) { - if (file_printf(ms, "UNKNUNKN") == -1) - rv = -1; - } else if (ms->flags & MAGIC_EXTENSION) { - if (file_printf(ms, "???") == -1) - rv = -1; - } else { - if (file_printf(ms, "%s", def) == -1) - rv = -1; + if (m == 0) { + m = 1; + rv = file_default(ms, nb); + if (rv == 0) + if (file_printf(ms, "%s", def) == -1) + rv = -1; } done: if ((ms->flags & MAGIC_MIME_ENCODING) != 0) { @@ -364,9 +398,9 @@ file_reset(struct magic_set *ms, int checkloaded) #define OCTALIFY(n, o) \ /*LINTED*/ \ (void)(*(n)++ = '\\', \ - *(n)++ = (((uint32_t)*(o) >> 6) & 3) + '0', \ - *(n)++ = (((uint32_t)*(o) >> 3) & 7) + '0', \ - *(n)++ = (((uint32_t)*(o) >> 0) & 7) + '0', \ + *(n)++ = ((CAST(uint32_t, *(o)) >> 6) & 3) + '0', \ + *(n)++ = ((CAST(uint32_t, *(o)) >> 3) & 7) + '0', \ + *(n)++ = ((CAST(uint32_t, *(o)) >> 0) & 7) + '0', \ (o)++) protected const char * @@ -412,9 +446,9 @@ file_getbuffer(struct magic_set *ms) while (op < eop) { bytesconsumed = mbrtowc(&nextchar, op, - (size_t)(eop - op), &state); - if (bytesconsumed == (size_t)(-1) || - bytesconsumed == (size_t)(-2)) { + CAST(size_t, eop - op), &state); + if (bytesconsumed == CAST(size_t, -1) || + bytesconsumed == CAST(size_t, -2)) { mb_conv = 0; break; } @@ -437,7 +471,7 @@ file_getbuffer(struct magic_set *ms) #endif for (np = ms->o.pbuf, op = ms->o.buf; *op;) { - if (isprint((unsigned char)*op)) { + if (isprint(CAST(unsigned char, *op))) { *np++ = *op++; } else { OCTALIFY(np, op); @@ -595,12 +629,13 @@ file_pop_buffer(struct magic_set *ms, file_pushbuf_t *pb) * convert string to ascii printable format. */ protected char * -file_printable(char *buf, size_t bufsiz, const char *str) +file_printable(char *buf, size_t bufsiz, const char *str, size_t slen) { - char *ptr, *eptr; - const unsigned char *s = (const unsigned char *)str; + char *ptr, *eptr = buf + bufsiz - 1; + const unsigned char *s = RCAST(const unsigned char *, str); + const unsigned char *es = s + slen; - for (ptr = buf, eptr = ptr + bufsiz - 1; ptr < eptr && *s; s++) { + for (ptr = buf; ptr < eptr && s < es && *s; s++) { if (isprint(*s)) { *ptr++ = *s; continue; diff --git a/src/getopt_long.c b/src/getopt_long.c index d357dc30f444a..43c4245619efa 100644 --- a/src/getopt_long.c +++ b/src/getopt_long.c @@ -32,7 +32,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: getopt_long.c,v 1.6 2009/02/13 18:48:05 christos Exp $") +FILE_RCSID("@(#)$File: getopt_long.c,v 1.7 2018/09/09 20:33:28 christos Exp $") #endif /* lint */ #include <assert.h> @@ -124,7 +124,7 @@ gcd(a, b) b = c; c = a % b; } - + return b; } @@ -223,7 +223,7 @@ start: place = EMSG; if (IN_ORDER) { /* - * GNU extension: + * GNU extension: * return non-option as argument to option 1 */ optarg = nargv[optind++]; @@ -269,7 +269,7 @@ start: } if (optchar == 'W' && oli[1] == ';') { /* -W long-option */ /* XXX: what if no long options provided (called by getopt)? */ - if (*place) + if (*place) return -2; if (++optind >= nargc) { /* no arg */ @@ -404,7 +404,7 @@ getopt_long(nargc, nargv, options, long_options, idx) has_equal++; } else current_argv_len = strlen(current_argv); - + for (i = 0; long_options[i].name; i++) { /* find matching long option */ if (strncmp(current_argv, long_options[i].name, @@ -488,7 +488,7 @@ getopt_long(nargc, nargv, options, long_options, idx) if (long_options[match].flag) { *long_options[match].flag = long_options[match].val; retval = 0; - } else + } else retval = long_options[match].val; if (idx) *idx = match; diff --git a/src/is_json.c b/src/is_json.c new file mode 100644 index 0000000000000..206ec3795e54e --- /dev/null +++ b/src/is_json.c @@ -0,0 +1,462 @@ +/*- + * Copyright (c) 2018 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Parse JSON object serialization format (RFC-7159) + */ + +#ifndef TEST +#include "file.h" + +#ifndef lint +FILE_RCSID("@(#)$File: is_json.c,v 1.13 2019/03/02 01:08:10 christos Exp $") +#endif + +#include <string.h> +#include "magic.h" +#endif + +#ifdef DEBUG +#include <stdio.h> +#define DPRINTF(a, b, c) \ + printf("%s [%.2x/%c] %.20s\n", (a), *(b), *(b), (const char *)(c)) +#else +#define DPRINTF(a, b, c) do { } while (/*CONSTCOND*/0) +#endif + +#define JSON_ARRAY 0 +#define JSON_CONSTANT 1 +#define JSON_NUMBER 2 +#define JSON_OBJECT 3 +#define JSON_STRING 4 +#define JSON_ARRAYN 5 +#define JSON_MAX 6 + +/* + * if JSON_COUNT != 0: + * count all the objects, require that we have the whole data file + * otherwise: + * stop if we find an object or an array + */ +#ifndef JSON_COUNT +#define JSON_COUNT 0 +#endif + +static int json_parse(const unsigned char **, const unsigned char *, size_t *, + size_t); + +static int +json_isspace(const unsigned char uc) +{ + switch (uc) { + case ' ': + case '\n': + case '\r': + case '\t': + return 1; + default: + return 0; + } +} + +static int +json_isdigit(unsigned char uc) +{ + switch (uc) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + return 1; + default: + return 0; + } +} + +static int +json_isxdigit(unsigned char uc) +{ + if (json_isdigit(uc)) + return 1; + switch (uc) { + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + return 1; + default: + return 0; + } +} + +static const unsigned char * +json_skip_space(const unsigned char *uc, const unsigned char *ue) +{ + while (uc < ue && json_isspace(*uc)) + uc++; + return uc; +} + +static int +json_parse_string(const unsigned char **ucp, const unsigned char *ue) +{ + const unsigned char *uc = *ucp; + size_t i; + + DPRINTF("Parse string: ", uc, *ucp); + while (uc < ue) { + switch (*uc++) { + case '\0': + goto out; + case '\\': + if (uc == ue) + goto out; + switch (*uc++) { + case '\0': + goto out; + case '"': + case '\\': + case '/': + case 'b': + case 'f': + case 'n': + case 'r': + case 't': + continue; + case 'u': + if (ue - uc < 4) { + uc = ue; + goto out; + } + for (i = 0; i < 4; i++) + if (!json_isxdigit(*uc++)) + goto out; + continue; + default: + goto out; + } + case '"': + *ucp = uc; + return 1; + default: + continue; + } + } +out: + DPRINTF("Bad string: ", uc, *ucp); + *ucp = uc; + return 0; +} + +static int +json_parse_array(const unsigned char **ucp, const unsigned char *ue, + size_t *st, size_t lvl) +{ + const unsigned char *uc = *ucp; + int more = 0; /* Array has more than 1 element */ + + DPRINTF("Parse array: ", uc, *ucp); + while (uc < ue) { + if (!json_parse(&uc, ue, st, lvl + 1)) + goto out; + if (uc == ue) + goto out; + switch (*uc) { + case ',': + more++; + uc++; + continue; + case ']': + if (more) + st[JSON_ARRAYN]++; + *ucp = uc + 1; + return 1; + default: + goto out; + } + } +out: + DPRINTF("Bad array: ", uc, *ucp); + *ucp = uc; + return 0; +} + +static int +json_parse_object(const unsigned char **ucp, const unsigned char *ue, + size_t *st, size_t lvl) +{ + const unsigned char *uc = *ucp; + DPRINTF("Parse object: ", uc, *ucp); + while (uc < ue) { + uc = json_skip_space(uc, ue); + if (uc == ue) + goto out; + if (*uc++ != '"') { + DPRINTF("not string", uc, *ucp); + goto out; + } + DPRINTF("next field", uc, *ucp); + if (!json_parse_string(&uc, ue)) { + DPRINTF("not string", uc, *ucp); + goto out; + } + uc = json_skip_space(uc, ue); + if (uc == ue) + goto out; + if (*uc++ != ':') { + DPRINTF("not colon", uc, *ucp); + goto out; + } + if (!json_parse(&uc, ue, st, lvl + 1)) { + DPRINTF("not json", uc, *ucp); + goto out; + } + if (uc == ue) + goto out; + switch (*uc++) { + case ',': + continue; + case '}': /* { */ + *ucp = uc; + DPRINTF("Good object: ", uc, *ucp); + return 1; + default: + *ucp = uc - 1; + DPRINTF("not more", uc, *ucp); + goto out; + } + } +out: + DPRINTF("Bad object: ", uc, *ucp); + *ucp = uc; + return 0; +} + +static int +json_parse_number(const unsigned char **ucp, const unsigned char *ue) +{ + const unsigned char *uc = *ucp; + int got = 0; + + DPRINTF("Parse number: ", uc, *ucp); + if (uc == ue) + return 0; + if (*uc == '-') + uc++; + + for (; uc < ue; uc++) { + if (!json_isdigit(*uc)) + break; + got = 1; + } + if (uc == ue) + goto out; + if (*uc == '.') + uc++; + for (; uc < ue; uc++) { + if (!json_isdigit(*uc)) + break; + got = 1; + } + if (uc == ue) + goto out; + if (got && (*uc == 'e' || *uc == 'E')) { + uc++; + got = 0; + if (uc == ue) + goto out; + if (*uc == '+' || *uc == '-') + uc++; + for (; uc < ue; uc++) { + if (!json_isdigit(*uc)) + break; + got = 1; + } + } +out: + if (!got) + DPRINTF("Bad number: ", uc, *ucp); + else + DPRINTF("Good number: ", uc, *ucp); + *ucp = uc; + return got; +} + +static int +json_parse_const(const unsigned char **ucp, const unsigned char *ue, + const char *str, size_t len) +{ + const unsigned char *uc = *ucp; + + DPRINTF("Parse const: ", uc, *ucp); + for (len--; uc < ue && --len;) { + if (*uc++ == *++str) + continue; + } + if (len) + DPRINTF("Bad const: ", uc, *ucp); + *ucp = uc; + return len == 0; +} + +static int +json_parse(const unsigned char **ucp, const unsigned char *ue, + size_t *st, size_t lvl) +{ + const unsigned char *uc; + int rv = 0; + int t; + + uc = json_skip_space(*ucp, ue); + if (uc == ue) + goto out; + + // Avoid recursion + if (lvl > 20) + return 0; +#if JSON_COUNT + /* bail quickly if not counting */ + if (lvl > 1 && (st[JSON_OBJECT] || st[JSON_ARRAYN])) + return 1; +#endif + + DPRINTF("Parse general: ", uc, *ucp); + switch (*uc++) { + case '"': + rv = json_parse_string(&uc, ue); + t = JSON_STRING; + break; + case '[': + rv = json_parse_array(&uc, ue, st, lvl + 1); + t = JSON_ARRAY; + break; + case '{': /* '}' */ + rv = json_parse_object(&uc, ue, st, lvl + 1); + t = JSON_OBJECT; + break; + case 't': + rv = json_parse_const(&uc, ue, "true", sizeof("true")); + t = JSON_CONSTANT; + break; + case 'f': + rv = json_parse_const(&uc, ue, "false", sizeof("false")); + t = JSON_CONSTANT; + break; + case 'n': + rv = json_parse_const(&uc, ue, "null", sizeof("null")); + t = JSON_CONSTANT; + break; + default: + --uc; + rv = json_parse_number(&uc, ue); + t = JSON_NUMBER; + break; + } + if (rv) + st[t]++; + uc = json_skip_space(uc, ue); +out: + *ucp = uc; + DPRINTF("End general: ", uc, *ucp); + if (lvl == 0) + return rv && (st[JSON_ARRAYN] || st[JSON_OBJECT]); + return rv; +} + +#ifndef TEST +int +file_is_json(struct magic_set *ms, const struct buffer *b) +{ + const unsigned char *uc = CAST(const unsigned char *, b->fbuf); + const unsigned char *ue = uc + b->flen; + size_t st[JSON_MAX]; + int mime = ms->flags & MAGIC_MIME; + + + if ((ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION)) != 0) + return 0; + + memset(st, 0, sizeof(st)); + + if (!json_parse(&uc, ue, st, 0)) + return 0; + + if (mime == MAGIC_MIME_ENCODING) + return 1; + if (mime) { + if (file_printf(ms, "application/json") == -1) + return -1; + return 1; + } + if (file_printf(ms, "JSON data") == -1) + return -1; +#if JSON_COUNT +#define P(n) st[n], st[n] > 1 ? "s" : "" + if (file_printf(ms, " (%" SIZE_T_FORMAT "u object%s, %" SIZE_T_FORMAT + "u array%s, %" SIZE_T_FORMAT "u string%s, %" SIZE_T_FORMAT + "u constant%s, %" SIZE_T_FORMAT "u number%s, %" SIZE_T_FORMAT + "u >1array%s)", + P(JSON_OBJECT), P(JSON_ARRAY), P(JSON_STRING), P(JSON_CONSTANT), + P(JSON_NUMBER), P(JSON_ARRAYN)) + == -1) + return -1; +#endif + return 1; +} + +#else + +#include <sys/types.h> +#include <sys/stat.h> +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdint.h> +#include <err.h> + +int +main(int argc, char *argv[]) +{ + int fd, rv; + struct stat st; + unsigned char *p; + size_t stats[JSON_MAX]; + + if ((fd = open(argv[1], O_RDONLY)) == -1) + err(EXIT_FAILURE, "Can't open `%s'", argv[1]); + + if (fstat(fd, &st) == -1) + err(EXIT_FAILURE, "Can't stat `%s'", argv[1]); + + if ((p = malloc(st.st_size)) == NULL) + err(EXIT_FAILURE, "Can't allocate %jd bytes", + (intmax_t)st.st_size); + if (read(fd, p, st.st_size) != st.st_size) + err(EXIT_FAILURE, "Can't read %jd bytes", + (intmax_t)st.st_size); + memset(stats, 0, sizeof(stats)); + printf("is json %d\n", json_parse((const unsigned char **)&p, + p + st.st_size, stats, 0)); + return 0; +} +#endif diff --git a/src/is_tar.c b/src/is_tar.c index 7110604f9e81b..82b08051fbdda 100644 --- a/src/is_tar.c +++ b/src/is_tar.c @@ -40,7 +40,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: is_tar.c,v 1.41 2017/11/02 20:25:39 christos Exp $") +FILE_RCSID("@(#)$File: is_tar.c,v 1.44 2019/02/20 02:35:27 christos Exp $") #endif #include "magic.h" @@ -62,7 +62,7 @@ static const char tartype[][32] = { /* should be equal to messages */ protected int file_is_tar(struct magic_set *ms, const struct buffer *b) { - const unsigned char *buf = b->fbuf; + const unsigned char *buf = CAST(const unsigned char *, b->fbuf); size_t nbytes = b->flen; /* * Do the tar test first, because if the first file in the tar @@ -78,9 +78,13 @@ file_is_tar(struct magic_set *ms, const struct buffer *b) if (tar < 1 || tar > 3) return 0; + if (mime == MAGIC_MIME_ENCODING) + return 1; + if (file_printf(ms, "%s", mime ? "application/x-tar" : tartype[tar - 1]) == -1) return -1; + return 1; } @@ -94,7 +98,8 @@ file_is_tar(struct magic_set *ms, const struct buffer *b) private int is_tar(const unsigned char *buf, size_t nbytes) { - const union record *header = (const union record *)(const void *)buf; + const union record *header = RCAST(const union record *, + RCAST(const void *, buf)); size_t i; int sum, recsum; const unsigned char *p, *ep; @@ -143,7 +148,7 @@ from_oct(const char *where, size_t digs) if (digs == 0) return -1; - while (isspace((unsigned char)*where)) { /* Skip spaces */ + while (isspace(CAST(unsigned char, *where))) { /* Skip spaces */ where++; if (digs-- == 0) return -1; /* All blank field */ @@ -154,7 +159,7 @@ from_oct(const char *where, size_t digs) digs--; } - if (digs > 0 && *where && !isspace((unsigned char)*where)) + if (digs > 0 && *where && !isspace(CAST(unsigned char, *where))) return -1; /* Ended on non-(space/NUL) */ return value; diff --git a/src/magic.c b/src/magic.c index 1448a69bcad52..da5baf108e5d9 100644 --- a/src/magic.c +++ b/src/magic.c @@ -33,7 +33,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: magic.c,v 1.102 2017/08/28 13:39:18 christos Exp $") +FILE_RCSID("@(#)$File: magic.c,v 1.111 2019/05/07 02:27:11 christos Exp $") #endif /* lint */ #include "magic.h" @@ -44,9 +44,7 @@ FILE_RCSID("@(#)$File: magic.c,v 1.102 2017/08/28 13:39:18 christos Exp $") #ifdef QUICK #include <sys/mman.h> #endif -#ifdef HAVE_LIMITS_H #include <limits.h> /* for PIPE_BUF */ -#endif #if defined(HAVE_UTIMES) # include <sys/time.h> @@ -314,7 +312,8 @@ magic_load_buffers(struct magic_set *ms, void **bufs, size_t *sizes, { if (ms == NULL) return -1; - return buffer_apprentice(ms, (struct magic **)bufs, sizes, nbufs); + return buffer_apprentice(ms, RCAST(struct magic **, bufs), + sizes, nbufs); } #endif @@ -407,7 +406,8 @@ file_or_fd(struct magic_set *ms, const char *inname, int fd) struct stat sb; ssize_t nbytes = 0; /* number of bytes read from a datafile */ int ispipe = 0; - off_t pos = (off_t)-1; + int okstat = 0; + off_t pos = CAST(off_t, -1); if (file_reset(ms, 1) == -1) goto out; @@ -435,25 +435,13 @@ file_or_fd(struct magic_set *ms, const char *inname, int fd) if (fd == STDIN_FILENO) _setmode(STDIN_FILENO, O_BINARY); #endif - - if (inname == NULL) { - if (fstat(fd, &sb) == 0 && S_ISFIFO(sb.st_mode)) - ispipe = 1; - else - pos = lseek(fd, (off_t)0, SEEK_CUR); - } else { - int flags = O_RDONLY|O_BINARY; - int okstat = stat(inname, &sb) == 0; - - if (okstat && S_ISFIFO(sb.st_mode)) { -#ifdef O_NONBLOCK - flags |= O_NONBLOCK; -#endif - ispipe = 1; - } - + if (inname != NULL) { + int flags = O_RDONLY|O_BINARY|O_NONBLOCK; errno = 0; if ((fd = open(inname, flags)) < 0) { + okstat = stat(inname, &sb) == 0; + if (okstat && S_ISFIFO(sb.st_mode)) + ispipe = 1; #ifdef WIN32 /* * Can't stat, can't open. It may have been opened in @@ -472,24 +460,29 @@ file_or_fd(struct magic_set *ms, const char *inname, int fd) rv = 0; goto done; } -#ifdef O_NONBLOCK - if ((flags = fcntl(fd, F_GETFL)) != -1) { - flags &= ~O_NONBLOCK; - (void)fcntl(fd, F_SETFL, flags); - } -#endif + } + + if (fd != -1) { + if (!okstat) + okstat = fstat(fd, &sb) == 0; + if (okstat && S_ISFIFO(sb.st_mode)) + ispipe = 1; + if (inname == NULL) + pos = lseek(fd, CAST(off_t, 0), SEEK_CUR); } /* * try looking at the first ms->bytes_max bytes */ if (ispipe) { - ssize_t r = 0; + if (fd != -1) { + ssize_t r = 0; - while ((r = sread(fd, (void *)&buf[nbytes], - (size_t)(ms->bytes_max - nbytes), 1)) > 0) { - nbytes += r; - if (r < PIPE_BUF) break; + while ((r = sread(fd, RCAST(void *, &buf[nbytes]), + CAST(size_t, ms->bytes_max - nbytes), 1)) > 0) { + nbytes += r; + if (r < PIPE_BUF) break; + } } if (nbytes == 0 && inname) { @@ -500,14 +493,14 @@ file_or_fd(struct magic_set *ms, const char *inname, int fd) goto done; } - } else { + } else if (fd != -1) { /* Windows refuses to read from a big console buffer. */ size_t howmany = #if defined(WIN32) - _isatty(fd) ? 8 * 1024 : + _isatty(fd) ? 8 * 1024 : #endif - ms->bytes_max; - if ((nbytes = read(fd, (char *)buf, howmany)) == -1) { + ms->bytes_max; + if ((nbytes = read(fd, RCAST(void *, buf), howmany)) == -1) { if (inname == NULL && fd != STDIN_FILENO) file_error(ms, errno, "cannot read fd %d", fd); else @@ -518,13 +511,13 @@ file_or_fd(struct magic_set *ms, const char *inname, int fd) } (void)memset(buf + nbytes, 0, SLOP); /* NUL terminate */ - if (file_buffer(ms, fd, inname, buf, (size_t)nbytes) == -1) + if (file_buffer(ms, fd, okstat ? &sb : NULL, inname, buf, CAST(size_t, nbytes)) == -1) goto done; rv = 0; done: free(buf); if (fd != -1) { - if (pos != (off_t)-1) + if (pos != CAST(off_t, -1)) (void)lseek(fd, pos, SEEK_SET); close_and_restore(ms, inname, fd, &sb); } @@ -544,7 +537,7 @@ magic_buffer(struct magic_set *ms, const void *buf, size_t nb) * The main work is done here! * We have the file name and/or the data buffer to be identified. */ - if (file_buffer(ms, -1, NULL, buf, nb) == -1) { + if (file_buffer(ms, -1, NULL, NULL, buf, nb) == -1) { return NULL; } return file_getbuffer(ms); @@ -598,27 +591,29 @@ magic_version(void) public int magic_setparam(struct magic_set *ms, int param, const void *val) { + if (ms == NULL) + return -1; switch (param) { case MAGIC_PARAM_INDIR_MAX: - ms->indir_max = (uint16_t)*(const size_t *)val; + ms->indir_max = CAST(uint16_t, *CAST(const size_t *, val)); return 0; case MAGIC_PARAM_NAME_MAX: - ms->name_max = (uint16_t)*(const size_t *)val; + ms->name_max = CAST(uint16_t, *CAST(const size_t *, val)); return 0; case MAGIC_PARAM_ELF_PHNUM_MAX: - ms->elf_phnum_max = (uint16_t)*(const size_t *)val; + ms->elf_phnum_max = CAST(uint16_t, *CAST(const size_t *, val)); return 0; case MAGIC_PARAM_ELF_SHNUM_MAX: - ms->elf_shnum_max = (uint16_t)*(const size_t *)val; + ms->elf_shnum_max = CAST(uint16_t, *CAST(const size_t *, val)); return 0; case MAGIC_PARAM_ELF_NOTES_MAX: - ms->elf_notes_max = (uint16_t)*(const size_t *)val; + ms->elf_notes_max = CAST(uint16_t, *CAST(const size_t *, val)); return 0; case MAGIC_PARAM_REGEX_MAX: - ms->elf_notes_max = (uint16_t)*(const size_t *)val; + ms->regex_max = CAST(uint16_t, *CAST(const size_t *, val)); return 0; case MAGIC_PARAM_BYTES_MAX: - ms->bytes_max = *(const size_t *)val; + ms->bytes_max = *CAST(const size_t *, val); return 0; default: errno = EINVAL; @@ -629,27 +624,29 @@ magic_setparam(struct magic_set *ms, int param, const void *val) public int magic_getparam(struct magic_set *ms, int param, void *val) { + if (ms == NULL) + return -1; switch (param) { case MAGIC_PARAM_INDIR_MAX: - *(size_t *)val = ms->indir_max; + *CAST(size_t *, val) = ms->indir_max; return 0; case MAGIC_PARAM_NAME_MAX: - *(size_t *)val = ms->name_max; + *CAST(size_t *, val) = ms->name_max; return 0; case MAGIC_PARAM_ELF_PHNUM_MAX: - *(size_t *)val = ms->elf_phnum_max; + *CAST(size_t *, val) = ms->elf_phnum_max; return 0; case MAGIC_PARAM_ELF_SHNUM_MAX: - *(size_t *)val = ms->elf_shnum_max; + *CAST(size_t *, val) = ms->elf_shnum_max; return 0; case MAGIC_PARAM_ELF_NOTES_MAX: - *(size_t *)val = ms->elf_notes_max; + *CAST(size_t *, val) = ms->elf_notes_max; return 0; case MAGIC_PARAM_REGEX_MAX: - *(size_t *)val = ms->regex_max; + *CAST(size_t *, val) = ms->regex_max; return 0; case MAGIC_PARAM_BYTES_MAX: - *(size_t *)val = ms->bytes_max; + *CAST(size_t *, val) = ms->bytes_max; return 0; default: errno = EINVAL; diff --git a/src/magic.h.in b/src/magic.h.in index 1134bdc886d41..0580fa21cceac 100644 --- a/src/magic.h.in +++ b/src/magic.h.in @@ -58,6 +58,7 @@ #define MAGIC_NO_CHECK_CDF 0x0040000 /* Don't check for cdf files */ #define MAGIC_NO_CHECK_TOKENS 0x0100000 /* Don't check tokens */ #define MAGIC_NO_CHECK_ENCODING 0x0200000 /* Don't check text encodings */ +#define MAGIC_NO_CHECK_JSON 0x0400000 /* Don't check for JSON files */ /* No built-in tests; only consult the magic file */ #define MAGIC_NO_CHECK_BUILTIN ( \ @@ -70,6 +71,7 @@ MAGIC_NO_CHECK_CDF | \ MAGIC_NO_CHECK_TOKENS | \ MAGIC_NO_CHECK_ENCODING | \ + MAGIC_NO_CHECK_JSON | \ 0 \ ) @@ -96,7 +98,7 @@ b\22no_check_cdf\0\ b\23no_check_reserved0\0\ b\24no_check_tokens\0\ b\25no_check_encoding\0\ -b\26no_check_reserved1\0\ +b\26no_check_json\0\ b\27no_check_reserved2\0\ b\30extension\0\ b\31transp_compression\0\ diff --git a/src/mygetopt.h b/src/mygetopt.h index ef87525eaf5bb..d766762631d13 100644 --- a/src/mygetopt.h +++ b/src/mygetopt.h @@ -64,5 +64,5 @@ struct option { int getopt_long(int, char * const *, const char *, const struct option *, int *); - + #endif /* !_GETOPT_H_ */ diff --git a/src/print.c b/src/print.c index 0b918636bc5e5..391a7fbe15621 100644 --- a/src/print.c +++ b/src/print.c @@ -2,7 +2,7 @@ * Copyright (c) Ian F. Darwin 1986-1995. * Software written by Ian F. Darwin and others; * maintained 1995-present by Christos Zoulas and others. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -12,7 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -32,7 +32,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: print.c,v 1.82 2017/02/10 18:14:01 christos Exp $") +FILE_RCSID("@(#)$File: print.c,v 1.85 2019/03/12 20:43:05 christos Exp $") #endif /* lint */ #include <string.h> @@ -43,8 +43,6 @@ FILE_RCSID("@(#)$File: print.c,v 1.82 2017/02/10 18:14:01 christos Exp $") #endif #include <time.h> -#define SZOF(a) (sizeof(a) / sizeof(a[0])) - #include "cdf.h" #ifndef COMPILE_ONLY @@ -65,9 +63,9 @@ file_mdump(struct magic *m) if (m->in_op & FILE_OPINVERSE) (void) fputc('~', stderr); (void) fprintf(stderr, "%c%u),", - ((size_t)(m->in_op & FILE_OPS_MASK) < - SZOF(optyp)) ? optyp[m->in_op & FILE_OPS_MASK] : '?', - m->in_offset); + (CAST(size_t, m->in_op & FILE_OPS_MASK) < + __arraycount(optyp)) ? + optyp[m->in_op & FILE_OPS_MASK] : '?', m->in_offset); } (void) fprintf(stderr, " %s%s", (m->flag & UNSIGNED) ? "u" : "", /* Note: type is unsigned */ @@ -78,16 +76,16 @@ file_mdump(struct magic *m) if (IS_STRING(m->type)) { if (m->str_flags) { (void) fputc('/', stderr); - if (m->str_flags & STRING_COMPACT_WHITESPACE) + if (m->str_flags & STRING_COMPACT_WHITESPACE) (void) fputc(CHAR_COMPACT_WHITESPACE, stderr); - if (m->str_flags & STRING_COMPACT_OPTIONAL_WHITESPACE) + if (m->str_flags & STRING_COMPACT_OPTIONAL_WHITESPACE) (void) fputc(CHAR_COMPACT_OPTIONAL_WHITESPACE, stderr); - if (m->str_flags & STRING_IGNORE_LOWERCASE) + if (m->str_flags & STRING_IGNORE_LOWERCASE) (void) fputc(CHAR_IGNORE_LOWERCASE, stderr); - if (m->str_flags & STRING_IGNORE_UPPERCASE) + if (m->str_flags & STRING_IGNORE_UPPERCASE) (void) fputc(CHAR_IGNORE_UPPERCASE, stderr); - if (m->str_flags & REGEX_OFFSET_START) + if (m->str_flags & REGEX_OFFSET_START) (void) fputc(CHAR_REGEX_OFFSET_START, stderr); if (m->str_flags & STRING_TEXTTEST) (void) fputc(CHAR_TEXTTEST, stderr); @@ -112,14 +110,15 @@ file_mdump(struct magic *m) (void) fprintf(stderr, "/%u", m->str_range); } else { - if ((size_t)(m->mask_op & FILE_OPS_MASK) < SZOF(optyp)) + if (CAST(size_t, m->mask_op & FILE_OPS_MASK) < + __arraycount(optyp)) (void) fputc(optyp[m->mask_op & FILE_OPS_MASK], stderr); else (void) fputc('?', stderr); - + if (m->num_mask) { (void) fprintf(stderr, "%.8llx", - (unsigned long long)m->num_mask); + CAST(unsigned long long, m->num_mask)); } } (void) fprintf(stderr, ",%c", m->reln); @@ -141,7 +140,7 @@ file_mdump(struct magic *m) case FILE_LEQUAD: case FILE_QUAD: (void) fprintf(stderr, "%" INT64_T_FORMAT "d", - (unsigned long long)m->value.q); + CAST(long long, m->value.q)); break; case FILE_PSTRING: case FILE_STRING: @@ -149,7 +148,8 @@ file_mdump(struct magic *m) case FILE_BESTRING16: case FILE_LESTRING16: case FILE_SEARCH: - file_showstr(stderr, m->value.s, (size_t)m->vallen); + file_showstr(stderr, m->value.s, + CAST(size_t, m->vallen)); break; case FILE_DATE: case FILE_LEDATE: @@ -217,11 +217,11 @@ file_magwarn(struct magic_set *ms, const char *f, ...) va_list va; /* cuz we use stdout for most, stderr here */ - (void) fflush(stdout); + (void) fflush(stdout); if (ms->file) (void) fprintf(stderr, "%s, %lu: ", ms->file, - (unsigned long)ms->line); + CAST(unsigned long, ms->line)); (void) fprintf(stderr, "Warning: "); va_start(va, f); (void) vfprintf(stderr, f, va); @@ -243,7 +243,7 @@ file_fmttime(uint64_t v, int flags, char *buf) } else { // XXX: perhaps detect and print something if overflow // on 32 bit time_t? - t = (time_t)v; + t = CAST(time_t, v); } if (flags & FILE_T_LOCAL) { diff --git a/src/readcdf.c b/src/readcdf.c index 4b86e6fed08d6..e6ea8e47fb6b4 100644 --- a/src/readcdf.c +++ b/src/readcdf.c @@ -26,7 +26,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: readcdf.c,v 1.67 2018/04/15 19:57:07 christos Exp $") +FILE_RCSID("@(#)$File: readcdf.c,v 1.73 2019/03/12 20:43:05 christos Exp $") #endif #include <assert.h> @@ -39,10 +39,6 @@ FILE_RCSID("@(#)$File: readcdf.c,v 1.67 2018/04/15 19:57:07 christos Exp $") #include "cdf.h" #include "magic.h" -#ifndef __arraycount -#define __arraycount(a) (sizeof(a) / sizeof(a[0])) -#endif - #define NOTMIME(ms) (((ms)->flags & MAGIC_MIME) == 0) static const struct nv { @@ -204,7 +200,7 @@ cdf_file_property_info(struct magic_set *ms, const cdf_property_info_t *info, && len--; s += k) { if (*s == '\0') break; - if (isprint((unsigned char)*s)) + if (isprint(CAST(unsigned char, *s))) vbuf[j++] = *s; } if (j == sizeof(vbuf)) @@ -252,7 +248,7 @@ cdf_file_property_info(struct magic_set *ms, const cdf_property_info_t *info, return -1; } } - if (!NOTMIME(ms)) { + if (ms->flags & MAGIC_MIME_TYPE) { if (str == NULL) return 0; if (file_printf(ms, "application/%s", str) == -1) @@ -285,7 +281,7 @@ cdf_file_catalog(struct magic_set *ms, const cdf_header_t *h, return -1; } free(cat); - } else { + } else if (ms->flags & MAGIC_MIME_TYPE) { if (file_printf(ms, "application/CDFV2") == -1) return -1; } @@ -318,19 +314,19 @@ cdf_file_summary_info(struct magic_set *ms, const cdf_header_t *h, case 2: if (file_printf(ms, ", Os: Windows, Version %d.%d", si.si_os_version & 0xff, - (uint32_t)si.si_os_version >> 8) == -1) + CAST(uint32_t, si.si_os_version) >> 8) == -1) return -2; break; case 1: if (file_printf(ms, ", Os: MacOS, Version %d.%d", - (uint32_t)si.si_os_version >> 8, + CAST(uint32_t, si.si_os_version) >> 8, si.si_os_version & 0xff) == -1) return -2; break; default: if (file_printf(ms, ", Os %d, Version: %d.%d", si.si_os, si.si_os_version & 0xff, - (uint32_t)si.si_os_version >> 8) == -1) + CAST(uint32_t, si.si_os_version) >> 8) == -1) return -2; break; } @@ -353,11 +349,11 @@ cdf_file_summary_info(struct magic_set *ms, const cdf_header_t *h, #ifdef notdef private char * format_clsid(char *buf, size_t len, const uint64_t uuid[2]) { - snprintf(buf, len, "%.8" PRIx64 "-%.4" PRIx64 "-%.4" PRIx64 "-%.4" + snprintf(buf, len, "%.8" PRIx64 "-%.4" PRIx64 "-%.4" PRIx64 "-%.4" PRIx64 "-%.12" PRIx64, (uuid[0] >> 32) & (uint64_t)0x000000000ffffffffULL, (uuid[0] >> 16) & (uint64_t)0x0000000000000ffffULL, - (uuid[0] >> 0) & (uint64_t)0x0000000000000ffffULL, + (uuid[0] >> 0) & (uint64_t)0x0000000000000ffffULL, (uuid[1] >> 48) & (uint64_t)0x0000000000000ffffULL, (uuid[1] >> 0) & (uint64_t)0x0000fffffffffffffULL); return buf; @@ -406,7 +402,7 @@ cdf_check_summary_info(struct magic_set *ms, const cdf_info_t *info, for (j = 0; str == NULL && j < dir->dir_len; j++) { d = &dir->dir_tab[j]; for (k = 0; k < sizeof(name); k++) - name[k] = (char)cdf_tole2(d->d_name[k]); + name[k] = CAST(char, cdf_tole2(d->d_name[k])); str = cdf_app_to_mime(name, NOTMIME(ms) ? name2desc : name2mime); } @@ -416,7 +412,7 @@ cdf_check_summary_info(struct magic_set *ms, const cdf_info_t *info, return -1; i = 1; } - } else { + } else if (ms->flags & MAGIC_MIME_TYPE) { if (str == NULL) str = "vnd.ms-office"; if (file_printf(ms, "application/%s", str) == -1) @@ -436,7 +432,7 @@ private struct sinfo { const char *sections[5]; const int types[5]; } sectioninfo[] = { - { "Encrypted", "encrypted", + { "Encrypted", "encrypted", { "EncryptedPackage", "EncryptedSummary", NULL, NULL, NULL, @@ -448,7 +444,7 @@ private struct sinfo { }, }, - { "QuickBooks", "quickbooks", + { "QuickBooks", "quickbooks", { #if 0 "TaxForms", "PDFTaxForms", "modulesInBackup", @@ -527,7 +523,7 @@ cdf_file_dir_info(struct magic_set *ms, const cdf_dir_t *dir) if (NOTMIME(ms)) { if (file_printf(ms, "CDFV2 %s", si->name) == -1) return -1; - } else { + } else if (ms->flags & MAGIC_MIME_TYPE) { if (file_printf(ms, "application/%s", si->mime) == -1) return -1; } @@ -540,7 +536,7 @@ protected int file_trycdf(struct magic_set *ms, const struct buffer *b) { int fd = b->fd; - const unsigned char *buf = b->fbuf; + const unsigned char *buf = CAST(const unsigned char *, b->fbuf); size_t nbytes = b->flen; cdf_info_t info; cdf_header_t h; @@ -614,7 +610,7 @@ file_trycdf(struct magic_set *ms, const struct buffer *b) if (file_printf(ms, "Hangul (Korean) Word Processor File 5.x") == -1) return -1; - } else { + } else if (ms->flags & MAGIC_MIME_TYPE) { if (file_printf(ms, "application/x-hwp") == -1) return -1; } @@ -661,19 +657,20 @@ out2: out1: free(sat.sat_tab); out0: - if (i == -1) { - if (NOTMIME(ms)) { + /* If we handled it already, return */ + if (i != -1) + return i; + /* Provide a default handler */ + if (NOTMIME(ms)) { if (file_printf(ms, "Composite Document File V2 Document") == -1) - return -1; - if (*expn) - if (file_printf(ms, ", %s", expn) == -1) return -1; - } else { + if (*expn) + if (file_printf(ms, ", %s", expn) == -1) + return -1; + } else if (ms->flags & MAGIC_MIME_TYPE) { if (file_printf(ms, "application/CDFV2") == -1) - return -1; - } - i = 1; + return -1; } - return i; + return 1; } diff --git a/src/readelf.c b/src/readelf.c index db0b35a506a71..ef61d4cd600fe 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -1,7 +1,7 @@ /* * Copyright (c) Christos Zoulas 2003. * All Rights Reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -11,7 +11,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -27,7 +27,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: readelf.c,v 1.144 2018/07/08 23:37:33 christos Exp $") +FILE_RCSID("@(#)$File: readelf.c,v 1.165 2019/05/07 02:27:11 christos Exp $") #endif #ifdef BUILTIN_ELF @@ -69,7 +69,7 @@ toomany(struct magic_set *ms, const char *name, uint16_t num) { if (file_printf(ms, ", too many %s (%u)", name, num) == -1) return -1; - return 0; + return 1; } private uint16_t @@ -85,7 +85,7 @@ getu16(int swap, uint16_t value) retval.c[0] = tmpval.c[1]; retval.c[1] = tmpval.c[0]; - + return retval.ui; } else return value; @@ -106,7 +106,7 @@ getu32(int swap, uint32_t value) retval.c[1] = tmpval.c[2]; retval.c[2] = tmpval.c[1]; retval.c[3] = tmpval.c[0]; - + return retval.ui; } else return value; @@ -131,7 +131,7 @@ getu64(int swap, uint64_t value) retval.c[5] = tmpval.c[2]; retval.c[6] = tmpval.c[1]; retval.c[7] = tmpval.c[0]; - + return retval.ui; } else return value; @@ -262,7 +262,10 @@ static const size_t prpsoffsets32[] = { 84, /* SunOS 5.x (short name) */ 44, /* Linux (command line) */ - 28, /* Linux 2.0.36 (short name) */ + 28, /* Linux (short name) */ + + 48, /* Linux PowerPC (command line) */ + 32, /* Linux PowerPC (short name) */ 8, /* FreeBSD */ }; @@ -282,8 +285,8 @@ static const size_t prpsoffsets64[] = { 16, /* FreeBSD, 64-bit */ }; -#define NOFFSETS32 (sizeof(prpsoffsets32) / sizeof(prpsoffsets32[0])) -#define NOFFSETS64 (sizeof(prpsoffsets64) / sizeof(prpsoffsets64[0])) +#define NOFFSETS32 __arraycount(prpsoffsets32) +#define NOFFSETS64 __arraycount(prpsoffsets64) #define NOFFSETS (clazz == ELFCLASS32 ? NOFFSETS32 : NOFFSETS64) @@ -352,6 +355,11 @@ dophn_core(struct magic_set *ms, int clazz, int swap, int fd, off_t off, off_t ph_off = off; int ph_num = num; + if (num == 0) { + if (file_printf(ms, ", no program header") == -1) + return -1; + return 0; + } if (size != xph_sizeof) { if (file_printf(ms, ", corrupted program header size") == -1) return -1; @@ -388,9 +396,9 @@ dophn_core(struct magic_set *ms, int clazz, int swap, int fd, off_t off, } offset = 0; for (;;) { - if (offset >= (size_t)bufsize) + if (offset >= CAST(size_t, bufsize)) break; - offset = donote(ms, nbuf, offset, (size_t)bufsize, + offset = donote(ms, nbuf, offset, CAST(size_t, bufsize), clazz, swap, 4, flags, notecount, fd, ph_off, ph_num, fsize); if (offset == 0) @@ -402,7 +410,7 @@ dophn_core(struct magic_set *ms, int clazz, int swap, int fd, off_t off, } #endif -static void +static int do_note_netbsd_version(struct magic_set *ms, int swap, void *v) { uint32_t desc; @@ -410,7 +418,7 @@ do_note_netbsd_version(struct magic_set *ms, int swap, void *v) desc = elf_getu32(swap, desc); if (file_printf(ms, ", for NetBSD") == -1) - return; + return -1; /* * The version number used to be stuck as 199905, and was thus * basically content-free. Newer versions of NetBSD have fixed @@ -430,24 +438,25 @@ do_note_netbsd_version(struct magic_set *ms, int swap, void *v) uint32_t ver_maj = desc / 100000000; if (file_printf(ms, " %u.%u", ver_maj, ver_min) == -1) - return; + return -1; if (ver_rel == 0 && ver_patch != 0) { if (file_printf(ms, ".%u", ver_patch) == -1) - return; + return -1; } else if (ver_rel != 0) { while (ver_rel > 26) { if (file_printf(ms, "Z") == -1) - return; + return -1; ver_rel -= 26; } if (file_printf(ms, "%c", 'A' + ver_rel - 1) == -1) - return; + return -1; } } + return 0; } -static void +static int do_note_freebsd_version(struct magic_set *ms, int swap, void *v) { uint32_t desc; @@ -455,71 +464,72 @@ do_note_freebsd_version(struct magic_set *ms, int swap, void *v) memcpy(&desc, v, sizeof(desc)); desc = elf_getu32(swap, desc); if (file_printf(ms, ", for FreeBSD") == -1) - return; + return -1; /* * Contents is __FreeBSD_version, whose relation to OS * versions is defined by a huge table in the Porter's * Handbook. This is the general scheme: - * + * * Releases: * Mmp000 (before 4.10) * Mmi0p0 (before 5.0) * Mmm0p0 - * + * * Development branches: * Mmpxxx (before 4.6) * Mmp1xx (before 4.10) * Mmi1xx (before 5.0) * M000xx (pre-M.0) * Mmm1xx - * + * * M = major version * m = minor version * i = minor version increment (491000 -> 4.10) * p = patchlevel * x = revision - * + * * The first release of FreeBSD to use ELF by default * was version 3.0. */ if (desc == 460002) { if (file_printf(ms, " 4.6.2") == -1) - return; + return -1; } else if (desc < 460100) { if (file_printf(ms, " %d.%d", desc / 100000, desc / 10000 % 10) == -1) - return; + return -1; if (desc / 1000 % 10 > 0) if (file_printf(ms, ".%d", desc / 1000 % 10) == -1) - return; + return -1; if ((desc % 1000 > 0) || (desc % 100000 == 0)) if (file_printf(ms, " (%d)", desc) == -1) - return; + return -1; } else if (desc < 500000) { if (file_printf(ms, " %d.%d", desc / 100000, desc / 10000 % 10 + desc / 1000 % 10) == -1) - return; + return -1; if (desc / 100 % 10 > 0) { if (file_printf(ms, " (%d)", desc) == -1) - return; + return -1; } else if (desc / 10 % 10 > 0) { if (file_printf(ms, ".%d", desc / 10 % 10) == -1) - return; + return -1; } } else { if (file_printf(ms, " %d.%d", desc / 100000, desc / 1000 % 100) == -1) - return; + return -1; if ((desc / 100 % 10 > 0) || (desc % 100000 / 100 == 0)) { if (file_printf(ms, " (%d)", desc) == -1) - return; + return -1; } else if (desc / 10 % 10 > 0) { if (file_printf(ms, ".%d", desc / 10 % 10) == -1) - return; + return -1; } } + return 0; } private int @@ -528,7 +538,7 @@ 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) { - if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 && + if (namesz == 4 && strcmp(RCAST(char *, &nbuf[noff]), "GNU") == 0 && type == NT_GNU_BUILD_ID && (descsz >= 4 && descsz <= 20)) { uint8_t desc[20]; const char *btype; @@ -549,18 +559,18 @@ do_bid_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, break; } if (file_printf(ms, ", BuildID[%s]=", btype) == -1) - return 1; + return -1; memcpy(desc, &nbuf[doff], descsz); for (i = 0; i < descsz; i++) if (file_printf(ms, "%02x", desc[i]) == -1) - return 1; + return -1; return 1; } - if (namesz == 4 && strcmp((char *)&nbuf[noff], "Go") == 0 && + if (namesz == 4 && strcmp(RCAST(char *, &nbuf[noff]), "Go") == 0 && type == NT_GO_BUILD_ID && descsz < 128) { - if (file_printf(ms, ", Go BuildID=%s", - (char *)&nbuf[doff]) == -1) - return 1; + if (file_printf(ms, ", Go BuildID=%.*s", + CAST(int, descsz), RCAST(char *, &nbuf[doff])) == -1) + return -1; return 1; } return 0; @@ -571,88 +581,95 @@ 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 && - type == NT_GNU_VERSION && descsz == 2) { - *flags |= FLAGS_DID_OS_NOTE; - file_printf(ms, ", for SuSE %d.%d", nbuf[doff], nbuf[doff + 1]); + const char *name = RCAST(const char *, &nbuf[noff]); + + if (namesz == 5 && strcmp(name, "SuSE") == 0 && + type == NT_GNU_VERSION && descsz == 2) { + *flags |= FLAGS_DID_OS_NOTE; + if (file_printf(ms, ", for SuSE %d.%d", nbuf[doff], + nbuf[doff + 1]) == -1) + return -1; return 1; } - if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 && + if (namesz == 4 && strcmp(name, "GNU") == 0 && type == NT_GNU_VERSION && descsz == 16) { uint32_t desc[4]; memcpy(desc, &nbuf[doff], sizeof(desc)); *flags |= FLAGS_DID_OS_NOTE; if (file_printf(ms, ", for GNU/") == -1) - return 1; + return -1; switch (elf_getu32(swap, desc[0])) { case GNU_OS_LINUX: if (file_printf(ms, "Linux") == -1) - return 1; + return -1; break; case GNU_OS_HURD: if (file_printf(ms, "Hurd") == -1) - return 1; + return -1; break; case GNU_OS_SOLARIS: if (file_printf(ms, "Solaris") == -1) - return 1; + return -1; break; case GNU_OS_KFREEBSD: if (file_printf(ms, "kFreeBSD") == -1) - return 1; + return -1; break; case GNU_OS_KNETBSD: if (file_printf(ms, "kNetBSD") == -1) - return 1; + return -1; break; default: if (file_printf(ms, "<unknown>") == -1) - return 1; + 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 1; + return -1; return 1; } - if (namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0) { + if (namesz == 7 && strcmp(name, "NetBSD") == 0) { if (type == NT_NETBSD_VERSION && descsz == 4) { *flags |= FLAGS_DID_OS_NOTE; - do_note_netbsd_version(ms, swap, &nbuf[doff]); + if (do_note_netbsd_version(ms, swap, &nbuf[doff]) == -1) + return -1; return 1; } } - if (namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0) { + if (namesz == 8 && strcmp(name, "FreeBSD") == 0) { if (type == NT_FREEBSD_VERSION && descsz == 4) { *flags |= FLAGS_DID_OS_NOTE; - do_note_freebsd_version(ms, swap, &nbuf[doff]); + if (do_note_freebsd_version(ms, swap, &nbuf[doff]) + == -1) + return -1; return 1; } } - if (namesz == 8 && strcmp((char *)&nbuf[noff], "OpenBSD") == 0 && + if (namesz == 8 && strcmp(name, "OpenBSD") == 0 && type == NT_OPENBSD_VERSION && descsz == 4) { *flags |= FLAGS_DID_OS_NOTE; if (file_printf(ms, ", for OpenBSD") == -1) - return 1; + return -1; /* Content of note is always 0 */ return 1; } - if (namesz == 10 && strcmp((char *)&nbuf[noff], "DragonFly") == 0 && + if (namesz == 10 && strcmp(name, "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; + return -1; 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 1; } return 0; @@ -663,7 +680,9 @@ 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 && + const char *name = RCAST(const char *, &nbuf[noff]); + + if (namesz == 4 && strcmp(name, "PaX") == 0 && type == NT_NETBSD_PAX && descsz == 4) { static const char *pax[] = { "+mprotect", @@ -682,14 +701,14 @@ do_pax_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, desc = elf_getu32(swap, desc); if (desc && file_printf(ms, ", PaX: ") == -1) - return 1; + return -1; for (i = 0; i < __arraycount(pax); i++) { - if (((1 << (int)i) & desc) == 0) + if (((1 << CAST(int, i)) & desc) == 0) continue; if (file_printf(ms, "%s%s", did++ ? "," : "", pax[i]) == -1) - return 1; + return -1; } return 1; } @@ -702,6 +721,8 @@ do_core_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, size_t noff, size_t doff, int *flags, size_t size, int clazz) { #ifdef ELFCORE + const char *name = RCAST(const char *, &nbuf[noff]); + int os_style = -1; /* * Sigh. The 2.0.36 kernel in Debian 2.1, at @@ -717,16 +738,16 @@ do_core_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, * doesn't include the terminating null in the * name.... */ - if ((namesz == 4 && strncmp((char *)&nbuf[noff], "CORE", 4) == 0) || - (namesz == 5 && strcmp((char *)&nbuf[noff], "CORE") == 0)) { + if ((namesz == 4 && strncmp(name, "CORE", 4) == 0) || + (namesz == 5 && strcmp(name, "CORE") == 0)) { os_style = OS_STYLE_SVR4; - } + } - if ((namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0)) { + if ((namesz == 8 && strcmp(name, "FreeBSD") == 0)) { os_style = OS_STYLE_FREEBSD; } - if ((namesz >= 11 && strncmp((char *)&nbuf[noff], "NetBSD-CORE", 11) + if ((namesz >= 11 && strncmp(name, "NetBSD-CORE", 11) == 0)) { os_style = OS_STYLE_NETBSD; } @@ -734,7 +755,7 @@ do_core_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, if (os_style != -1 && (*flags & FLAGS_DID_CORE_STYLE) == 0) { if (file_printf(ms, ", %s-style", os_style_names[os_style]) == -1) - return 1; + return -1; *flags |= FLAGS_DID_CORE_STYLE; *flags |= os_style; } @@ -745,26 +766,48 @@ do_core_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, char sbuf[512]; struct NetBSD_elfcore_procinfo pi; memset(&pi, 0, sizeof(pi)); - memcpy(&pi, nbuf + doff, descsz); + memcpy(&pi, nbuf + doff, MIN(descsz, sizeof(pi))); if (file_printf(ms, ", from '%.31s', pid=%u, uid=%u, " "gid=%u, nlwps=%u, lwp=%u (signal %u/code %u)", file_printable(sbuf, sizeof(sbuf), - CAST(char *, pi.cpi_name)), - elf_getu32(swap, (uint32_t)pi.cpi_pid), + RCAST(char *, pi.cpi_name), sizeof(pi.cpi_name)), + elf_getu32(swap, CAST(uint32_t, pi.cpi_pid)), elf_getu32(swap, pi.cpi_euid), elf_getu32(swap, pi.cpi_egid), elf_getu32(swap, pi.cpi_nlwps), - elf_getu32(swap, (uint32_t)pi.cpi_siglwp), + elf_getu32(swap, CAST(uint32_t, pi.cpi_siglwp)), elf_getu32(swap, pi.cpi_signo), elf_getu32(swap, pi.cpi_sigcode)) == -1) - return 1; + return -1; *flags |= FLAGS_DID_CORE; return 1; } break; + case OS_STYLE_FREEBSD: + if (type == NT_PRPSINFO && *flags & FLAGS_IS_CORE) { + size_t argoff, pidoff; + + if (clazz == ELFCLASS32) + argoff = 4 + 4 + 17; + else + argoff = 4 + 4 + 8 + 17; + if (file_printf(ms, ", from '%.80s'", nbuf + doff + + argoff) == -1) + return -1; + pidoff = argoff + 81 + 2; + if (doff + pidoff + 4 <= size) { + if (file_printf(ms, ", pid=%u", + elf_getu32(swap, *RCAST(uint32_t *, (nbuf + + doff + pidoff)))) == -1) + return -1; + } + *flags |= FLAGS_DID_CORE; + } + break; + default: if (type == NT_PRPSINFO && *flags & FLAGS_IS_CORE) { size_t i, j; @@ -847,8 +890,8 @@ do_core_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, i = k; } - cname = (unsigned char *) - &nbuf[doff + prpsoffsets(i)]; + cname = CAST(unsigned char *, + &nbuf[doff + prpsoffsets(i)]); for (cp = cname; cp < nbuf + size && *cp && isprint(*cp); cp++) continue; @@ -859,8 +902,8 @@ do_core_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, while (cp > cname && isspace(cp[-1])) cp--; if (file_printf(ms, ", from '%.*s'", - (int)(cp - cname), cname) == -1) - return 1; + CAST(int, cp - cname), cname) == -1) + return -1; *flags |= FLAGS_DID_CORE; return 1; @@ -886,7 +929,8 @@ get_offset_from_virtaddr(struct magic_set *ms, int swap, int clazz, int fd, * virtual address in which the "virtaddr" belongs to. */ for ( ; num; num--) { - if (pread(fd, xph_addr, xph_sizeof, off) < (ssize_t)xph_sizeof) { + if (pread(fd, xph_addr, xph_sizeof, off) < + CAST(ssize_t, xph_sizeof)) { file_badread(ms); return -1; } @@ -916,7 +960,8 @@ get_string_on_virtaddr(struct magic_set *ms, offset = get_offset_from_virtaddr(ms, swap, clazz, fd, ph_off, ph_num, fsize, virtaddr); - if ((buflen = pread(fd, buf, CAST(size_t, buflen), offset)) <= 0) { + if (offset < 0 || + (buflen = pread(fd, buf, CAST(size_t, buflen), offset)) <= 0) { file_badread(ms); return 0; } @@ -925,7 +970,7 @@ get_string_on_virtaddr(struct magic_set *ms, /* We expect only printable characters, so return if buffer contains * non-printable character before the '\0' or just '\0'. */ - for (bptr = buf; *bptr && isprint((unsigned char)*bptr); bptr++) + for (bptr = buf; *bptr && isprint(CAST(unsigned char, *bptr)); bptr++) continue; if (*bptr != '\0') return 0; @@ -1027,13 +1072,13 @@ do_auxv_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, if (buflen == 0) continue; - + if (file_printf(ms, ", %s: '%s'", tag, buf) == -1) - return 0; + return -1; } else { - if (file_printf(ms, ", %s: %d", tag, (int) xauxv_val) - == -1) - return 0; + if (file_printf(ms, ", %s: %d", tag, + CAST(int, xauxv_val)) == -1) + return -1; } } return 1; @@ -1062,7 +1107,7 @@ dodynamic(struct magic_set *ms, void *vbuf, size_t offset, size_t size, switch (xdh_tag) { case DT_FLAGS_1: - if (xdh_val == DF_1_PIE) + if (xdh_val & DF_1_PIE) ms->mode |= 0111; else ms->mode &= ~0111; @@ -1110,14 +1155,16 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size, } if (namesz & 0x80000000) { - file_printf(ms, ", bad note name size %#lx", - CAST(unsigned long, namesz)); + if (file_printf(ms, ", bad note name size %#lx", + CAST(unsigned long, namesz)) == -1) + return -1; return 0; } if (descsz & 0x80000000) { - file_printf(ms, ", bad note description size %#lx", - CAST(unsigned long, descsz)); + if (file_printf(ms, ", bad note description size %#lx", + CAST(unsigned long, descsz)) == -1) + return -1; return 0; } @@ -1151,7 +1198,7 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size, namesz, descsz, noff, doff, flags)) return offset; } - + if ((*flags & FLAGS_DID_NETBSD_PAX) == 0) { if (do_pax_note(ms, nbuf, xnh_type, swap, namesz, descsz, noff, doff, flags)) @@ -1171,7 +1218,7 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size, return offset; } - if (namesz == 7 && strcmp(CAST(char *, &nbuf[noff]), "NetBSD") == 0) { + if (namesz == 7 && strcmp(RCAST(char *, &nbuf[noff]), "NetBSD") == 0) { int descw, flag; const char *str, *tag; if (descsz > 100) @@ -1202,7 +1249,7 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size, if (*flags & flag) return offset; - str = CAST(const char *, &nbuf[doff]); + str = RCAST(const char *, &nbuf[doff]); descw = CAST(int, descsz); *flags |= flag; file_printf(ms, ", %s: %.*s", tag, descw, str); @@ -1278,6 +1325,11 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, char name[50]; ssize_t namesize; + if (num == 0) { + if (file_printf(ms, ", no section header") == -1) + return -1; + return 0; + } if (size != xsh_sizeof) { if (file_printf(ms, ", corrupted section header size") == -1) return -1; @@ -1343,7 +1395,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, CAST(uintmax_t, xsh_size), CAST(uintmax_t, fsize)) == -1) return -1; - return 0; + return 0; } if ((nbuf = malloc(xsh_size)) == NULL) { file_error(ms, errno, "Cannot allocate memory" @@ -1428,7 +1480,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, return -1; break; } - // gnu attributes + // gnu attributes #endif break; } @@ -1548,7 +1600,12 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, char interp[BUFSIZ]; ssize_t bufsize; size_t offset, align, len; - + + if (num == 0) { + if (file_printf(ms, ", no program header") == -1) + return -1; + return 0; + } if (size != xph_sizeof) { if (file_printf(ms, ", corrupted program header size") == -1) return -1; @@ -1558,7 +1615,7 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, interp[0] = '\0'; for ( ; num; num--) { int doread; - if (pread(fd, xph_addr, xph_sizeof, off) < + if (pread(fd, xph_addr, xph_sizeof, off) < CAST(ssize_t, xph_sizeof)) { file_badread(ms); return -1; @@ -1579,7 +1636,7 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, continue; if (((align = xph_align) & 0x80000000UL) != 0 || align < 4) { - if (file_printf(ms, + if (file_printf(ms, ", invalid note alignment %#lx", CAST(unsigned long, align)) == -1) return -1; @@ -1613,8 +1670,10 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, switch (xph_type) { case PT_DYNAMIC: offset = 0; + // Let DF_1 determine if we are PIE or not. + ms->mode &= ~0111; for (;;) { - if (offset >= (size_t)bufsize) + if (offset >= CAST(size_t, bufsize)) break; offset = dodynamic(ms, nbuf, offset, CAST(size_t, bufsize), clazz, swap); @@ -1626,7 +1685,7 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, case PT_INTERP: if (bufsize && nbuf[0]) { nbuf[bufsize - 1] = '\0'; - memcpy(interp, nbuf, bufsize); + memcpy(interp, nbuf, CAST(size_t, bufsize)); } else strlcpy(interp, "*empty*", sizeof(interp)); break; @@ -1637,7 +1696,7 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, */ offset = 0; for (;;) { - if (offset >= (size_t)bufsize) + if (offset >= CAST(size_t, bufsize)) break; offset = donote(ms, nbuf, offset, CAST(size_t, bufsize), clazz, swap, align, @@ -1655,7 +1714,8 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, return -1; if (interp[0]) if (file_printf(ms, ", interpreter %s", - file_printable(ibuf, sizeof(ibuf), interp)) == -1) + file_printable(ibuf, sizeof(ibuf), interp, sizeof(interp))) + == -1) return -1; return 0; } @@ -1665,7 +1725,7 @@ protected int file_tryelf(struct magic_set *ms, const struct buffer *b) { int fd = b->fd; - const unsigned char *buf = b->fbuf; + const unsigned char *buf = CAST(const unsigned char *, b->fbuf); size_t nbytes = b->flen; union { int32_t l; @@ -1674,6 +1734,7 @@ file_tryelf(struct magic_set *ms, const struct buffer *b) int clazz; int swap; struct stat st; + const struct stat *stp; off_t fsize; int flags = 0; Elf32_Ehdr elf32hdr; @@ -1687,7 +1748,8 @@ file_tryelf(struct magic_set *ms, const struct buffer *b) * file locations and thus file(1) cannot determine it from easily. * Instead we traverse thru all section headers until a symbol table * one is found or else the binary is stripped. - * Return immediately if it's not ELF (so we avoid pipe2file unless needed). + * Return immediately if it's not ELF (so we avoid pipe2file unless + * needed). */ if (buf[EI_MAG0] != ELFMAG0 || (buf[EI_MAG1] != ELFMAG1 && buf[EI_MAG1] != OLFMAG1) @@ -1701,12 +1763,25 @@ file_tryelf(struct magic_set *ms, const struct buffer *b) && (errno == ESPIPE)) fd = file_pipe2file(ms, fd, buf, nbytes); - if (fstat(fd, &st) == -1) { - file_badread(ms); + if (fd == -1) { + file_badread(ms); return -1; } - if (S_ISREG(st.st_mode) || st.st_size != 0) - fsize = st.st_size; + + stp = &b->st; + /* + * b->st.st_size != 0 if previous fstat() succeeded, + * which is likely, we can avoid extra stat() call. + */ + if (b->st.st_size == 0) { + stp = &st; + if (fstat(fd, &st) == -1) { + file_badread(ms); + return -1; + } + } + if (S_ISREG(stp->st_mode) || stp->st_size != 0) + fsize = stp->st_size; else fsize = SIZE_UNKNOWN; diff --git a/src/readelf.h b/src/readelf.h index 6ae63f2d950da..809d3f7573bd1 100644 --- a/src/readelf.h +++ b/src/readelf.h @@ -1,7 +1,7 @@ /* * Copyright (c) Christos Zoulas 2003. * All Rights Reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -11,7 +11,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -304,7 +304,7 @@ typedef struct { #define GNU_OS_KNETBSD 4 /* - * GNU Hardware capability information + * GNU Hardware capability information * word[0]: Number of entries * word[1]: Bitmask of enabled entries * Followed by a byte id, and a NUL terminated string per entry @@ -313,7 +313,7 @@ typedef struct { /* * GNU Build ID generated by ld - * 160 bit SHA1 [default] + * 160 bit SHA1 [default] * 128 bit md5 or uuid */ #define NT_GNU_BUILD_ID 3 diff --git a/src/seccomp.c b/src/seccomp.c index a5abb4a159f98..1b9d9b8559377 100644 --- a/src/seccomp.c +++ b/src/seccomp.c @@ -27,7 +27,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: seccomp.c,v 1.6 2018/06/26 20:29:29 christos Exp $") +FILE_RCSID("@(#)$File: seccomp.c,v 1.8 2019/02/24 18:12:04 christos Exp $") #endif /* lint */ #if HAVE_LIBSECCOMP @@ -126,14 +126,14 @@ enable_sandbox_basic(void) DENY_RULE (socket); // ... - + // applying filter... if (seccomp_load (ctx) == -1) goto out; // free ctx after the filter has been loaded into the kernel seccomp_release(ctx); return 0; - + out: seccomp_release(ctx); return -1; @@ -151,7 +151,7 @@ enable_sandbox_full(void) if (prctl(PR_SET_DUMPABLE, 0, 0, 0, 0) == -1) return -1; - + // initialize the filter ctx = seccomp_init(SCMP_ACT_KILL); if (ctx == NULL) @@ -163,10 +163,10 @@ enable_sandbox_full(void) ALLOW_RULE(dup2); ALLOW_RULE(exit); ALLOW_RULE(exit_group); - ALLOW_RULE(fcntl); - ALLOW_RULE(fcntl64); + ALLOW_RULE(fcntl); + ALLOW_RULE(fcntl64); ALLOW_RULE(fstat); - ALLOW_RULE(fstat64); + ALLOW_RULE(fstat64); ALLOW_RULE(getdents); #ifdef __NR_getdents64 ALLOW_RULE(getdents64); @@ -176,6 +176,7 @@ enable_sandbox_full(void) ALLOW_RULE(_llseek); ALLOW_RULE(lstat); ALLOW_RULE(lstat64); + ALLOW_RULE(madvise); ALLOW_RULE(mmap); ALLOW_RULE(mmap2); ALLOW_RULE(mprotect); diff --git a/src/softmagic.c b/src/softmagic.c index 9a5db9d3e2b3d..2edae41df4da3 100644 --- a/src/softmagic.c +++ b/src/softmagic.c @@ -32,7 +32,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: softmagic.c,v 1.262 2018/06/22 20:39:50 christos Exp $") +FILE_RCSID("@(#)$File: softmagic.c,v 1.286 2019/05/17 02:24:59 christos Exp $") #endif /* lint */ #include "magic.h" @@ -45,11 +45,11 @@ FILE_RCSID("@(#)$File: softmagic.c,v 1.262 2018/06/22 20:39:50 christos Exp $") private int match(struct magic_set *, struct magic *, uint32_t, const struct buffer *, size_t, int, int, int, uint16_t *, - uint16_t *, int *, int *, int *); + uint16_t *, int *, int *, int *, int *); private int mget(struct magic_set *, struct magic *, const struct buffer *, - const unsigned char *, size_t, + const unsigned char *, size_t, size_t, unsigned int, int, int, int, uint16_t *, - uint16_t *, int *, int *, int *); + uint16_t *, int *, int *, int *, int *); private int msetoffset(struct magic_set *, struct magic *, struct buffer *, const struct buffer *, size_t, unsigned int); private int magiccheck(struct magic_set *, struct magic *); @@ -67,24 +67,46 @@ private int cvt_16(union VALUETYPE *, const struct magic *); private int cvt_32(union VALUETYPE *, const struct magic *); private int cvt_64(union VALUETYPE *, const struct magic *); -#define OFFSET_OOB(n, o, i) ((n) < (uint32_t)(o) || (i) > ((n) - (o))) -#define BE64(p) (((uint64_t)(p)->hq[0]<<56)|((uint64_t)(p)->hq[1]<<48)| \ - ((uint64_t)(p)->hq[2]<<40)|((uint64_t)(p)->hq[3]<<32)| \ - ((uint64_t)(p)->hq[4]<<24)|((uint64_t)(p)->hq[5]<<16)| \ - ((uint64_t)(p)->hq[6]<<8)|((uint64_t)(p)->hq[7])) -#define LE64(p) (((uint64_t)(p)->hq[7]<<56)|((uint64_t)(p)->hq[6]<<48)| \ - ((uint64_t)(p)->hq[5]<<40)|((uint64_t)(p)->hq[4]<<32)| \ - ((uint64_t)(p)->hq[3]<<24)|((uint64_t)(p)->hq[2]<<16)| \ - ((uint64_t)(p)->hq[1]<<8)|((uint64_t)(p)->hq[0])) -#define LE32(p) (((uint32_t)(p)->hl[3]<<24)|((uint32_t)(p)->hl[2]<<16)| \ - ((uint32_t)(p)->hl[1]<<8)|((uint32_t)(p)->hl[0])) -#define BE32(p) (((uint32_t)(p)->hl[0]<<24)|((uint32_t)(p)->hl[1]<<16)| \ - ((uint32_t)(p)->hl[2]<<8)|((uint32_t)(p)->hl[3])) -#define ME32(p) (((uint32_t)(p)->hl[1]<<24)|((uint32_t)(p)->hl[0]<<16)| \ - ((uint32_t)(p)->hl[3]<<8)|((uint32_t)(p)->hl[2])) -#define BE16(p) (((uint16_t)(p)->hs[0]<<8)|((uint16_t)(p)->hs[1])) -#define LE16(p) (((uint16_t)(p)->hs[1]<<8)|((uint16_t)(p)->hs[0])) -#define SEXT(s,v,p) ((s)?(intmax_t)(int##v##_t)(p):(intmax_t)(uint##v##_t)(p)) +#define OFFSET_OOB(n, o, i) ((n) < CAST(uint32_t, (o)) || (i) > ((n) - (o))) +#define BE64(p) ( \ + (CAST(uint64_t, (p)->hq[0])<<56)| \ + (CAST(uint64_t, (p)->hq[1])<<48)| \ + (CAST(uint64_t, (p)->hq[2])<<40)| \ + (CAST(uint64_t, (p)->hq[3])<<32)| \ + (CAST(uint64_t, (p)->hq[4])<<24)| \ + (CAST(uint64_t, (p)->hq[5])<<16)| \ + (CAST(uint64_t, (p)->hq[6])<<8)| \ + (CAST(uint64_t, (p)->hq[7]))) +#define LE64(p) ( \ + (CAST(uint64_t, (p)->hq[7])<<56)| \ + (CAST(uint64_t, (p)->hq[6])<<48)| \ + (CAST(uint64_t, (p)->hq[5])<<40)| \ + (CAST(uint64_t, (p)->hq[4])<<32)| \ + (CAST(uint64_t, (p)->hq[3])<<24)| \ + (CAST(uint64_t, (p)->hq[2])<<16)| \ + (CAST(uint64_t, (p)->hq[1])<<8)| \ + (CAST(uint64_t, (p)->hq[0]))) +#define LE32(p) ( \ + (CAST(uint32_t, (p)->hl[3])<<24)| \ + (CAST(uint32_t, (p)->hl[2])<<16)| \ + (CAST(uint32_t, (p)->hl[1])<<8)| \ + (CAST(uint32_t, (p)->hl[0]))) +#define BE32(p) ( \ + (CAST(uint32_t, (p)->hl[0])<<24)| \ + (CAST(uint32_t, (p)->hl[1])<<16)| \ + (CAST(uint32_t, (p)->hl[2])<<8)| \ + (CAST(uint32_t, (p)->hl[3]))) +#define ME32(p) ( \ + (CAST(uint32_t, (p)->hl[1])<<24)| \ + (CAST(uint32_t, (p)->hl[0])<<16)| \ + (CAST(uint32_t, (p)->hl[3])<<8)| \ + (CAST(uint32_t, (p)->hl[2]))) + +#define BE16(p) ((CAST(uint16_t, (p)->hs[0])<<8)|(CAST(uint16_t, (p)->hs[1]))) +#define LE16(p) ((CAST(uint16_t, (p)->hs[1])<<8)|(CAST(uint16_t, (p)->hs[0]))) +#define SEXT(s,v,p) ((s) ? \ + CAST(intmax_t, CAST(int##v##_t, p)) : \ + CAST(intmax_t, CAST(uint##v##_t, p))) /* * softmagic - lookup one file in parsed, in-memory copy of database @@ -111,7 +133,7 @@ file_softmagic(struct magic_set *ms, const struct buffer *b, for (ml = ms->mlist[0]->next; ml != ms->mlist[0]; ml = ml->next) if ((rv = match(ms, ml->magic, ml->nmagic, b, 0, mode, text, 0, indir_count, name_count, - &printed_something, &need_separator, NULL)) != 0) + &printed_something, &need_separator, NULL, NULL)) != 0) return rv; return 0; @@ -125,7 +147,12 @@ private const char * __attribute__((__format_arg__(3))) file_fmtcheck(struct magic_set *ms, const char *desc, const char *def, const char *file, size_t line) { - const char *ptr = fmtcheck(desc, def); + const char *ptr; + + if (strchr(desc, '%') == NULL) + return desc; + + ptr = fmtcheck(desc, def); if (ptr == def) file_magerror(ms, "%s, %" SIZE_T_FORMAT "u: format `%s' does not match" @@ -167,17 +194,25 @@ private int match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, const struct buffer *b, size_t offset, int mode, int text, int flip, uint16_t *indir_count, uint16_t *name_count, - int *printed_something, int *need_separator, int *returnval) + int *printed_something, int *need_separator, int *returnval, + int *found_match) { uint32_t magindex = 0; unsigned int cont_level = 0; - int returnvalv = 0, e; /* if a match is found it is set to 1*/ + int found_matchv = 0; /* if a match is found it is set to 1*/ + int returnvalv = 0, e; int firstline = 1; /* a flag to print X\n X\n- X */ struct buffer bb; int print = (ms->flags & MAGIC_NODESC) == 0; + /* + * returnval can be 0 if a match is found, but there was no + * annotation to be printed. + */ if (returnval == NULL) returnval = &returnvalv; + if (found_match == NULL) + found_match = &found_matchv; if (file_check_mem(ms, cont_level) == -1) return -1; @@ -206,17 +241,21 @@ flush: ms->line = m->lineno; /* if main entry matches, print it... */ - switch (mget(ms, m, b, bb.fbuf, bb.flen, offset, cont_level, + switch (mget(ms, m, b, CAST(const unsigned char *, bb.fbuf), + bb.flen, offset, cont_level, mode, text, flip, indir_count, name_count, - printed_something, need_separator, returnval)) { + printed_something, need_separator, returnval, found_match)) + { case -1: return -1; case 0: flush = m->reln != '!'; break; default: - if (m->type == FILE_INDIRECT) + if (m->type == FILE_INDIRECT) { + *found_match = 1; *returnval = 1; + } switch (magiccheck(ms, m)) { case -1: @@ -238,7 +277,11 @@ flush: goto flush; } - if ((e = handle_annotation(ms, m, firstline)) != 0) { + if (*m->desc) + *found_match = 1; + + if ((e = handle_annotation(ms, m, firstline)) != 0) + { *need_separator = 1; *printed_something = 1; *returnval = 1; @@ -249,16 +292,16 @@ flush: * If we are going to print something, we'll need to print * a blank before we print something else. */ - if (*m->desc) { + if (print && *m->desc) { *need_separator = 1; *printed_something = 1; + *returnval = 1; if (print_sep(ms, firstline) == -1) return -1; + if (mprint(ms, m) == -1) + return -1; } - if (print && mprint(ms, m) == -1) - return -1; - switch (moffset(ms, m, &bb, &ms->c.li[cont_level].off)) { case -1: case 0: @@ -299,10 +342,11 @@ flush: continue; } #endif - switch (mget(ms, m, b, bb.fbuf, bb.flen, offset, + switch (mget(ms, m, b, CAST(const unsigned char *, + bb.fbuf), bb.flen, offset, cont_level, mode, text, flip, indir_count, name_count, printed_something, need_separator, - returnval)) { + returnval, found_match)) { case -1: return -1; case 0: @@ -311,8 +355,10 @@ flush: flush = 1; break; default: - if (m->type == FILE_INDIRECT) + if (m->type == FILE_INDIRECT) { + *found_match = 1; *returnval = 1; + } flush = 0; break; } @@ -337,6 +383,9 @@ flush: } else ms->c.li[cont_level].got_match = 1; + if (*m->desc) + *found_match = 1; + if ((e = handle_annotation(ms, m, firstline)) != 0) { *need_separator = 1; @@ -344,35 +393,36 @@ flush: *returnval = 1; return e; } - /* - * If we are going to print something, - * make sure that we have a separator first. - */ - if (*m->desc) { + if (print && *m->desc) { + /* + * This continuation matched. Print + * its message, with a blank before it + * if the previous item printed and + * this item isn't empty. + */ + /* + * If we are going to print something, + * make sure that we have a separator + * first. + */ if (!*printed_something) { *printed_something = 1; if (print_sep(ms, firstline) == -1) return -1; } - } - /* - * This continuation matched. Print - * its message, with a blank before it - * if the previous item printed and - * this item isn't empty. - */ - /* space if previous printed */ - if (*need_separator - && ((m->flag & NOSPACE) == 0) - && *m->desc) { - if (print && - file_printf(ms, " ") == -1) - return -1; + /* space if previous printed */ + if (*need_separator + && (m->flag & NOSPACE) == 0) { + if (file_printf(ms, " ") == -1) + return -1; + } + *returnval = 1; *need_separator = 0; + if (mprint(ms, m) == -1) + return -1; + *need_separator = 1; } - if (print && mprint(ms, m) == -1) - return -1; switch (moffset(ms, m, &bb, &ms->c.li[cont_level].off)) { @@ -385,9 +435,6 @@ flush: break; } - if (*m->desc) - *need_separator = 1; - /* * If we see any continuations * at a higher level, @@ -400,11 +447,13 @@ flush: } if (*printed_something) { firstline = 0; - if (print) - *returnval = 1; } - if ((ms->flags & MAGIC_CONTINUE) == 0 && *printed_something) { + if (*found_match) { + if ((ms->flags & MAGIC_CONTINUE) == 0) return *returnval; /* don't keep searching */ + // So that we print a separator + *printed_something = 0; + firstline = 0; } cont_level = 0; } @@ -460,7 +509,7 @@ varexpand(struct magic_set *ms, char *buf, size_t len, const char *str) size_t l; for (sptr = str; (ptr = strstr(sptr, "${")) != NULL;) { - l = (size_t)(ptr - sptr); + l = CAST(size_t, ptr - sptr); if (l >= len) return -1; memcpy(buf, sptr, l); @@ -526,19 +575,19 @@ mprint(struct magic_set *ms, struct magic *m) switch (m->type) { case FILE_BYTE: - v = file_signextend(ms, m, (uint64_t)p->b); + v = file_signextend(ms, m, CAST(uint64_t, p->b)); switch (check_fmt(ms, desc)) { case -1: return -1; case 1: (void)snprintf(buf, sizeof(buf), "%d", - (unsigned char)v); + CAST(unsigned char, v)); if (file_printf(ms, F(ms, desc, "%s"), buf) == -1) return -1; break; default: if (file_printf(ms, F(ms, desc, "%d"), - (unsigned char) v) == -1) + CAST(unsigned char, v)) == -1) return -1; break; } @@ -548,19 +597,19 @@ mprint(struct magic_set *ms, struct magic *m) case FILE_SHORT: case FILE_BESHORT: case FILE_LESHORT: - v = file_signextend(ms, m, (uint64_t)p->h); + v = file_signextend(ms, m, CAST(uint64_t, p->h)); switch (check_fmt(ms, desc)) { case -1: return -1; case 1: (void)snprintf(buf, sizeof(buf), "%u", - (unsigned short)v); + CAST(unsigned short, v)); if (file_printf(ms, F(ms, desc, "%s"), buf) == -1) return -1; break; default: if (file_printf(ms, F(ms, desc, "%u"), - (unsigned short) v) == -1) + CAST(unsigned short, v)) == -1) return -1; break; } @@ -571,17 +620,19 @@ mprint(struct magic_set *ms, struct magic *m) case FILE_BELONG: case FILE_LELONG: case FILE_MELONG: - v = file_signextend(ms, m, (uint64_t)p->l); + v = file_signextend(ms, m, CAST(uint64_t, p->l)); switch (check_fmt(ms, desc)) { case -1: return -1; case 1: - (void)snprintf(buf, sizeof(buf), "%u", (uint32_t) v); + (void)snprintf(buf, sizeof(buf), "%u", + CAST(uint32_t, v)); if (file_printf(ms, F(ms, desc, "%s"), buf) == -1) return -1; break; default: - if (file_printf(ms, F(ms, desc, "%u"), (uint32_t) v) == -1) + if (file_printf(ms, F(ms, desc, "%u"), + CAST(uint32_t, v)) == -1) return -1; break; } @@ -597,13 +648,13 @@ mprint(struct magic_set *ms, struct magic *m) return -1; case 1: (void)snprintf(buf, sizeof(buf), "%" INT64_T_FORMAT "u", - (unsigned long long)v); + CAST(unsigned long long, v)); if (file_printf(ms, F(ms, desc, "%s"), buf) == -1) return -1; break; default: if (file_printf(ms, F(ms, desc, "%" INT64_T_FORMAT "u"), - (unsigned long long) v) == -1) + CAST(unsigned long long, v)) == -1) return -1; break; } @@ -615,9 +666,9 @@ 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, desc, "%s"), - file_printable(sbuf, sizeof(sbuf), m->value.s)) - == -1) + if (file_printf(ms, F(ms, desc, "%s"), + file_printable(sbuf, sizeof(sbuf), m->value.s, + sizeof(m->value.s))) == -1) return -1; t = ms->offset + m->vallen; } @@ -632,19 +683,20 @@ mprint(struct magic_set *ms, struct magic *m) if (m->str_flags & STRING_TRIM) { char *last; - while (isspace((unsigned char)*str)) + while (isspace(CAST(unsigned char, *str))) str++; last = str; while (*last) last++; --last; - while (isspace((unsigned char)*last)) + while (isspace(CAST(unsigned char, *last))) last--; *++last = '\0'; } if (file_printf(ms, F(ms, desc, "%s"), - file_printable(sbuf, sizeof(sbuf), str)) == -1) + file_printable(sbuf, sizeof(sbuf), str, + sizeof(p->s) - (str - p->s))) == -1) return -1; if (m->type == FILE_PSTRING) @@ -744,13 +796,14 @@ mprint(struct magic_set *ms, struct magic *m) char *cp; int rval; - cp = strndup((const char *)ms->search.s, ms->search.rm_len); + cp = strndup(RCAST(const char *, ms->search.s), + ms->search.rm_len); if (cp == NULL) { file_oomem(ms, ms->search.rm_len); return -1; } rval = file_printf(ms, F(ms, desc, "%s"), - file_printable(sbuf, sizeof(sbuf), cp)); + file_printable(sbuf, sizeof(sbuf), cp, ms->search.rm_len)); free(cp); if (rval == -1) @@ -776,8 +829,9 @@ mprint(struct magic_set *ms, struct magic *m) t = ms->offset; break; case FILE_DER: - if (file_printf(ms, F(ms, desc, "%s"), - file_printable(sbuf, sizeof(sbuf), ms->ms_value.s)) == -1) + if (file_printf(ms, F(ms, desc, "%s"), + file_printable(sbuf, sizeof(sbuf), ms->ms_value.s, + sizeof(ms->ms_value.s))) == -1) return -1; t = ms->offset; break; @@ -785,7 +839,7 @@ mprint(struct magic_set *ms, struct magic *m) file_magerror(ms, "invalid m->type (%d) in mprint()", m->type); return -1; } - return (int32_t)t; + return CAST(int32_t, t); } private int @@ -832,7 +886,8 @@ moffset(struct magic_set *ms, struct magic *m, const struct buffer *b, p->s[strcspn(p->s, "\r\n")] = '\0'; o = CAST(uint32_t, (ms->offset + strlen(p->s))); if (m->type == FILE_PSTRING) - o += (uint32_t)file_pstring_length_size(m); + o += CAST(uint32_t, + file_pstring_length_size(m)); } break; @@ -898,11 +953,11 @@ moffset(struct magic_set *ms, struct magic *m, const struct buffer *b, case FILE_DER: { o = der_offs(ms, m, nbytes); - if (o == -1 || (size_t)o > nbytes) { + if (o == -1 || CAST(size_t, o) > nbytes) { if ((ms->flags & MAGIC_DEBUG) != 0) { (void)fprintf(stderr, - "Bad DER offset %d nbytes=%zu", - o, nbytes); + "Bad DER offset %d nbytes=%" + SIZE_T_FORMAT "u", o, nbytes); } *op = 0; return 0; @@ -915,10 +970,10 @@ moffset(struct magic_set *ms, struct magic *m, const struct buffer *b, break; } - if ((size_t)o > nbytes) { + if (CAST(size_t, o) > nbytes) { #if 0 - file_error(ms, 0, "Offset out of range %zu > %zu", - (size_t)o, nbytes); + file_error(ms, 0, "Offset out of range %" SIZE_T_FORMAT + "u > %" SIZE_T_FORMAT "u", (size_t)o, nbytes); #endif return -1; } @@ -988,36 +1043,36 @@ cvt_flip(int type, int flip) return type; } } -#define DO_CVT(fld, cast) \ +#define DO_CVT(fld, type) \ if (m->num_mask) \ switch (m->mask_op & FILE_OPS_MASK) { \ case FILE_OPAND: \ - p->fld &= cast m->num_mask; \ + p->fld &= CAST(type, m->num_mask); \ break; \ case FILE_OPOR: \ - p->fld |= cast m->num_mask; \ + p->fld |= CAST(type, m->num_mask); \ break; \ case FILE_OPXOR: \ - p->fld ^= cast m->num_mask; \ + p->fld ^= CAST(type, m->num_mask); \ break; \ case FILE_OPADD: \ - p->fld += cast m->num_mask; \ + p->fld += CAST(type, m->num_mask); \ break; \ case FILE_OPMINUS: \ - p->fld -= cast m->num_mask; \ + p->fld -= CAST(type, m->num_mask); \ break; \ case FILE_OPMULTIPLY: \ - p->fld *= cast m->num_mask; \ + p->fld *= CAST(type, m->num_mask); \ break; \ case FILE_OPDIVIDE: \ - if (cast m->num_mask == 0) \ + if (CAST(type, m->num_mask) == 0) \ return -1; \ - p->fld /= cast m->num_mask; \ + p->fld /= CAST(type, m->num_mask); \ break; \ case FILE_OPMODULO: \ - if (cast m->num_mask == 0) \ + if (CAST(type, m->num_mask) == 0) \ return -1; \ - p->fld %= cast m->num_mask; \ + p->fld %= CAST(type, m->num_mask); \ break; \ } \ if (m->mask_op & FILE_OPINVERSE) \ @@ -1026,61 +1081,61 @@ cvt_flip(int type, int flip) private int cvt_8(union VALUETYPE *p, const struct magic *m) { - DO_CVT(b, (uint8_t)); + DO_CVT(b, uint8_t); return 0; } private int cvt_16(union VALUETYPE *p, const struct magic *m) { - DO_CVT(h, (uint16_t)); + DO_CVT(h, uint16_t); return 0; } private int cvt_32(union VALUETYPE *p, const struct magic *m) { - DO_CVT(l, (uint32_t)); + DO_CVT(l, uint32_t); return 0; } private int cvt_64(union VALUETYPE *p, const struct magic *m) { - DO_CVT(q, (uint64_t)); + DO_CVT(q, uint64_t); return 0; } -#define DO_CVT2(fld, cast) \ +#define DO_CVT2(fld, type) \ if (m->num_mask) \ switch (m->mask_op & FILE_OPS_MASK) { \ case FILE_OPADD: \ - p->fld += cast m->num_mask; \ + p->fld += CAST(type, m->num_mask); \ break; \ case FILE_OPMINUS: \ - p->fld -= cast m->num_mask; \ + p->fld -= CAST(type, m->num_mask); \ break; \ case FILE_OPMULTIPLY: \ - p->fld *= cast m->num_mask; \ + p->fld *= CAST(type, m->num_mask); \ break; \ case FILE_OPDIVIDE: \ - if (cast m->num_mask == 0) \ + if (CAST(type, m->num_mask) == 0) \ return -1; \ - p->fld /= cast m->num_mask; \ + p->fld /= CAST(type, m->num_mask); \ break; \ } \ private int cvt_float(union VALUETYPE *p, const struct magic *m) { - DO_CVT2(f, (float)); + DO_CVT2(f, float); return 0; } private int cvt_double(union VALUETYPE *p, const struct magic *m) { - DO_CVT2(d, (double)); + DO_CVT2(d, double); return 0; } @@ -1136,7 +1191,7 @@ mconvert(struct magic_set *ms, struct magic *m, int flip) * 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 = sz; } while (len--) @@ -1145,14 +1200,14 @@ mconvert(struct magic_set *ms, struct magic *m, int flip) return 1; } case FILE_BESHORT: - p->h = (short)BE16(p); + p->h = CAST(short, BE16(p)); if (cvt_16(p, m) == -1) goto out; return 1; case FILE_BELONG: case FILE_BEDATE: case FILE_BELDATE: - p->l = (int32_t)BE32(p); + p->l = CAST(int32_t, BE32(p)); if (cvt_32(p, m) == -1) goto out; return 1; @@ -1160,19 +1215,19 @@ mconvert(struct magic_set *ms, struct magic *m, int flip) case FILE_BEQDATE: case FILE_BEQLDATE: case FILE_BEQWDATE: - p->q = (uint64_t)BE64(p); + p->q = CAST(uint64_t, BE64(p)); if (cvt_64(p, m) == -1) goto out; return 1; case FILE_LESHORT: - p->h = (short)LE16(p); + p->h = CAST(short, LE16(p)); if (cvt_16(p, m) == -1) goto out; return 1; case FILE_LELONG: case FILE_LEDATE: case FILE_LELDATE: - p->l = (int32_t)LE32(p); + p->l = CAST(int32_t, LE32(p)); if (cvt_32(p, m) == -1) goto out; return 1; @@ -1180,14 +1235,14 @@ mconvert(struct magic_set *ms, struct magic *m, int flip) case FILE_LEQDATE: case FILE_LEQLDATE: case FILE_LEQWDATE: - p->q = (uint64_t)LE64(p); + p->q = CAST(uint64_t, LE64(p)); if (cvt_64(p, m) == -1) goto out; return 1; case FILE_MELONG: case FILE_MEDATE: case FILE_MELDATE: - p->l = (int32_t)ME32(p); + p->l = CAST(int32_t, ME32(p)); if (cvt_32(p, m) == -1) goto out; return 1; @@ -1210,7 +1265,7 @@ mconvert(struct magic_set *ms, struct magic *m, int flip) goto out; return 1; case FILE_BEDOUBLE: - p->q = BE64(p); + p->q = BE64(p); if (cvt_double(p, m) == -1) goto out; return 1; @@ -1301,9 +1356,11 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir, || (b = CAST(const char *, memchr(c, '\r', CAST(size_t, (end - c)))))); lines--, b++) { - last = b; if (b < end - 1 && b[0] == '\r' && b[1] == '\n') b++; + if (b < end - 1 && b[0] == '\n') + b++; + last = b; } if (lines) last = end; @@ -1366,7 +1423,7 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir, * might even cause problems */ if (nbytes < sizeof(*p)) - (void)memset(((char *)(void *)p) + nbytes, '\0', + (void)memset(RCAST(char *, RCAST(void *, p)) + nbytes, '\0', sizeof(*p) - nbytes); return 0; } @@ -1407,7 +1464,7 @@ do_ops(struct magic *m, intmax_t lhs, intmax_t off) if (m->in_op & FILE_OPINVERSE) offset = ~offset; - return (uint32_t)offset; + return CAST(uint32_t, offset); } private int @@ -1428,19 +1485,19 @@ msetoffset(struct magic_set *ms, struct magic *m, struct buffer *bb, return -1; if (o != 0) { // Not yet! - file_magerror(ms, "non zero offset %zu at" - " level %u", o, cont_level); + file_magerror(ms, "non zero offset %" SIZE_T_FORMAT + "u at level %u", o, cont_level); return -1; } - if ((size_t)-m->offset > b->elen) + if (CAST(size_t, -m->offset) > b->elen) return -1; - buffer_init(bb, -1, b->ebuf, b->elen); - ms->eoffset = ms->offset = b->elen + m->offset; + buffer_init(bb, -1, NULL, b->ebuf, b->elen); + ms->eoffset = ms->offset = CAST(int32_t, b->elen + m->offset); } else { if (cont_level == 0) { normal: // XXX: Pass real fd, then who frees bb? - buffer_init(bb, -1, b->fbuf, b->flen); + buffer_init(bb, -1, NULL, b->fbuf, b->flen); ms->offset = m->offset; ms->eoffset = 0; } else { @@ -1448,7 +1505,8 @@ normal: } } if ((ms->flags & MAGIC_DEBUG) != 0) { - fprintf(stderr, "bb=[%p,%zu], %d [b=%p,%zu], [o=%#x, c=%d]\n", + fprintf(stderr, "bb=[%p,%" SIZE_T_FORMAT "u], %d [b=%p,%" + SIZE_T_FORMAT "u], [o=%#x, c=%d]\n", bb->fbuf, bb->flen, ms->offset, b->fbuf, b->flen, m->offset, cont_level); } @@ -1459,7 +1517,8 @@ private int mget(struct magic_set *ms, struct magic *m, const struct buffer *b, const unsigned char *s, size_t nbytes, size_t o, unsigned int cont_level, int mode, int text, int flip, uint16_t *indir_count, uint16_t *name_count, - int *printed_something, int *need_separator, int *returnval) + int *printed_something, int *need_separator, int *returnval, + int *found_match) { uint32_t offset = ms->offset; struct buffer bb; @@ -1484,8 +1543,8 @@ mget(struct magic_set *ms, struct magic *m, const struct buffer *b, - if (mcopy(ms, p, m->type, m->flag & INDIR, s, (uint32_t)(offset + o), - (uint32_t)nbytes, m) == -1) + if (mcopy(ms, p, m->type, m->flag & INDIR, s, + CAST(uint32_t, offset + o), CAST(uint32_t, nbytes), m) == -1) return -1; if ((ms->flags & MAGIC_DEBUG) != 0) { @@ -1494,7 +1553,8 @@ mget(struct magic_set *ms, struct magic *m, const struct buffer *b, "u, il=%hu, nc=%hu)\n", m->type, m->flag, offset, o, nbytes, *indir_count, *name_count); - mdebug(offset, (char *)(void *)p, sizeof(union VALUETYPE)); + mdebug(offset, RCAST(char *, RCAST(void *, p)), + sizeof(union VALUETYPE)); #ifndef COMPILE_ONLY file_mdump(m); #endif @@ -1505,40 +1565,58 @@ mget(struct magic_set *ms, struct magic *m, const struct buffer *b, const int sgn = m->in_op & FILE_OPSIGNED; if (m->in_op & FILE_OPINDIRECT) { const union VALUETYPE *q = CAST(const union VALUETYPE *, - ((const void *)(s + offset + off))); - if (OFFSET_OOB(nbytes, offset + off, sizeof(*q))) - return 0; + RCAST(const void *, s + offset + off)); switch (cvt_flip(m->in_type, flip)) { case FILE_BYTE: + if (OFFSET_OOB(nbytes, offset + off, 1)) + return 0; off = SEXT(sgn,8,q->b); break; case FILE_SHORT: + if (OFFSET_OOB(nbytes, offset + off, 2)) + return 0; off = SEXT(sgn,16,q->h); break; case FILE_BESHORT: + if (OFFSET_OOB(nbytes, offset + off, 2)) + return 0; off = SEXT(sgn,16,BE16(q)); break; case FILE_LESHORT: + if (OFFSET_OOB(nbytes, offset + off, 2)) + return 0; off = SEXT(sgn,16,LE16(q)); break; case FILE_LONG: + if (OFFSET_OOB(nbytes, offset + off, 4)) + return 0; off = SEXT(sgn,32,q->l); break; case FILE_BELONG: case FILE_BEID3: + if (OFFSET_OOB(nbytes, offset + off, 4)) + return 0; off = SEXT(sgn,32,BE32(q)); break; case FILE_LEID3: case FILE_LELONG: + if (OFFSET_OOB(nbytes, offset + off, 4)) + return 0; off = SEXT(sgn,32,LE32(q)); break; case FILE_MELONG: + if (OFFSET_OOB(nbytes, offset + off, 4)) + return 0; off = SEXT(sgn,32,ME32(q)); break; case FILE_BEQUAD: + if (OFFSET_OOB(nbytes, offset + off, 8)) + return 0; off = SEXT(sgn,64,BE64(q)); break; case FILE_LEQUAD: + if (OFFSET_OOB(nbytes, offset + off, 8)) + return 0; off = SEXT(sgn,64,LE64(q)); break; default: @@ -1574,7 +1652,7 @@ mget(struct magic_set *ms, struct magic *m, const struct buffer *b, return 0; lhs = BE32(p); if (in_type == FILE_BEID3) - lhs = cvt_id3(ms, (uint32_t)lhs); + lhs = cvt_id3(ms, CAST(uint32_t, lhs)); offset = do_ops(m, SEXT(sgn,32,lhs), off); break; case FILE_LELONG: @@ -1583,7 +1661,7 @@ mget(struct magic_set *ms, struct magic *m, const struct buffer *b, return 0; lhs = LE32(p); if (in_type == FILE_LEID3) - lhs = cvt_id3(ms, (uint32_t)lhs); + lhs = cvt_id3(ms, CAST(uint32_t, lhs)); offset = do_ops(m, SEXT(sgn,32,lhs), off); break; case FILE_MELONG: @@ -1626,7 +1704,7 @@ mget(struct magic_set *ms, struct magic *m, const struct buffer *b, ms->offset = offset; if ((ms->flags & MAGIC_DEBUG) != 0) { - mdebug(offset, (char *)(void *)p, + mdebug(offset, RCAST(char *, RCAST(void *, p)), sizeof(union VALUETYPE)); #ifndef COMPILE_ONLY file_mdump(m); @@ -1714,7 +1792,8 @@ mget(struct magic_set *ms, struct magic *m, const struct buffer *b, if (rv == 1) { if ((ms->flags & MAGIC_NODESC) == 0 && - file_printf(ms, F(ms, m->desc, "%u"), offset) == -1) { + file_printf(ms, F(ms, m->desc, "%u"), offset) == -1) + { free(rbuf); return -1; } @@ -1744,7 +1823,8 @@ mget(struct magic_set *ms, struct magic *m, const struct buffer *b, *need_separator = 0; rv = match(ms, ml.magic, ml.nmagic, b, offset + o, mode, text, flip, indir_count, name_count, - printed_something, need_separator, returnval); + printed_something, need_separator, returnval, found_match); + (*name_count)--; if (rv != 1) *need_separator = oneed_separator; return rv; @@ -1775,8 +1855,8 @@ file_strncmp(const char *s1, const char *s2, size_t len, uint32_t flags) * the ctype functions will work correctly without extra * casting. */ - const unsigned char *a = (const unsigned char *)s1; - const unsigned char *b = (const unsigned char *)s2; + const unsigned char *a = RCAST(const unsigned char *, s1); + const unsigned char *b = RCAST(const unsigned char *, s2); const unsigned char *eb = b + len; uint64_t v; @@ -1971,13 +2051,15 @@ magiccheck(struct magic_set *ms, struct magic *m) case FILE_STRING: case FILE_PSTRING: l = 0; - v = file_strncmp(m->value.s, p->s, (size_t)m->vallen, m->str_flags); + v = file_strncmp(m->value.s, p->s, CAST(size_t, m->vallen), + m->str_flags); break; case FILE_BESTRING16: case FILE_LESTRING16: l = 0; - v = file_strncmp16(m->value.s, p->s, (size_t)m->vallen, m->str_flags); + v = file_strncmp16(m->value.s, p->s, CAST(size_t, m->vallen), + m->str_flags); break; case FILE_SEARCH: { /* search ms->search.s for the string m->value.s */ @@ -1990,6 +2072,22 @@ magiccheck(struct magic_set *ms, struct magic *m) slen = MIN(m->vallen, sizeof(m->value.s)); l = 0; v = 0; +#ifdef HAVE_MEMMEM + if (slen > 0 && m->str_flags == 0) { + const char *found; + idx = m->str_range + slen; + if (m->str_range == 0 || ms->search.s_len < idx) + idx = ms->search.s_len; + found = CAST(const char *, memmem(ms->search.s, idx, + m->value.s, slen)); + if (!found) + return 0; + idx = found - ms->search.s; + ms->search.offset += idx; + ms->search.rm_len = ms->search.s_len - idx; + break; + } +#endif for (idx = 0; m->str_range == 0 || idx < m->str_range; idx++) { if (slen + idx > ms->search.s_len) @@ -2019,7 +2117,7 @@ magiccheck(struct magic_set *ms, struct magic *m) ((m->str_flags & STRING_IGNORE_CASE) ? REG_ICASE : 0)); if (rc) { file_regerror(&rx, rc, ms); - v = (uint64_t)-1; + v = CAST(uint64_t, -1); } else { regmatch_t pmatch; size_t slen = ms->search.s_len; @@ -2040,15 +2138,15 @@ magiccheck(struct magic_set *ms, struct magic *m) search = CCAST(char *, ""); copy = NULL; } - rc = file_regexec(&rx, (const char *)search, + rc = file_regexec(&rx, RCAST(const char *, search), 1, &pmatch, 0); free(copy); switch (rc) { case 0: - ms->search.s += (int)pmatch.rm_so; - ms->search.offset += (size_t)pmatch.rm_so; - ms->search.rm_len = - (size_t)(pmatch.rm_eo - pmatch.rm_so); + ms->search.s += CAST(int, pmatch.rm_so); + ms->search.offset += CAST(size_t, pmatch.rm_so); + ms->search.rm_len = CAST(size_t, + pmatch.rm_eo - pmatch.rm_so); v = 0; break; @@ -2058,12 +2156,12 @@ magiccheck(struct magic_set *ms, struct magic *m) default: file_regerror(&rx, rc, ms); - v = (uint64_t)-1; + v = CAST(uint64_t, -1); break; } } file_regfree(&rx); - if (v == (uint64_t)-1) + if (v == CAST(uint64_t, -1)) return -1; break; } @@ -2092,7 +2190,7 @@ magiccheck(struct magic_set *ms, struct magic *m) case 'x': if ((ms->flags & MAGIC_DEBUG) != 0) (void) fprintf(stderr, "%" INT64_T_FORMAT - "u == *any* = 1\n", (unsigned long long)v); + "u == *any* = 1\n", CAST(unsigned long long, v)); matched = 1; break; @@ -2100,16 +2198,18 @@ magiccheck(struct magic_set *ms, struct magic *m) matched = v != l; if ((ms->flags & MAGIC_DEBUG) != 0) (void) fprintf(stderr, "%" INT64_T_FORMAT "u != %" - INT64_T_FORMAT "u = %d\n", (unsigned long long)v, - (unsigned long long)l, matched); + INT64_T_FORMAT "u = %d\n", + CAST(unsigned long long, v), + CAST(unsigned long long, l), matched); break; case '=': matched = v == l; if ((ms->flags & MAGIC_DEBUG) != 0) (void) fprintf(stderr, "%" INT64_T_FORMAT "u == %" - INT64_T_FORMAT "u = %d\n", (unsigned long long)v, - (unsigned long long)l, matched); + INT64_T_FORMAT "u = %d\n", + CAST(unsigned long long, v), + CAST(unsigned long long, l), matched); break; case '>': @@ -2118,15 +2218,16 @@ magiccheck(struct magic_set *ms, struct magic *m) if ((ms->flags & MAGIC_DEBUG) != 0) (void) fprintf(stderr, "%" INT64_T_FORMAT "u > %" INT64_T_FORMAT "u = %d\n", - (unsigned long long)v, - (unsigned long long)l, matched); + CAST(unsigned long long, v), + CAST(unsigned long long, l), matched); } else { - matched = (int64_t) v > (int64_t) l; + matched = CAST(int64_t, v) > CAST(int64_t, l); if ((ms->flags & MAGIC_DEBUG) != 0) (void) fprintf(stderr, "%" INT64_T_FORMAT "d > %" INT64_T_FORMAT "d = %d\n", - (long long)v, (long long)l, matched); + CAST(long long, v), + CAST(long long, l), matched); } break; @@ -2136,15 +2237,16 @@ magiccheck(struct magic_set *ms, struct magic *m) if ((ms->flags & MAGIC_DEBUG) != 0) (void) fprintf(stderr, "%" INT64_T_FORMAT "u < %" INT64_T_FORMAT "u = %d\n", - (unsigned long long)v, - (unsigned long long)l, matched); + CAST(unsigned long long, v), + CAST(unsigned long long, l), matched); } else { - matched = (int64_t) v < (int64_t) l; + matched = CAST(int64_t, v) < CAST(int64_t, l); if ((ms->flags & MAGIC_DEBUG) != 0) (void) fprintf(stderr, "%" INT64_T_FORMAT "d < %" INT64_T_FORMAT "d = %d\n", - (long long)v, (long long)l, matched); + CAST(long long, v), + CAST(long long, l), matched); } break; @@ -2153,8 +2255,9 @@ magiccheck(struct magic_set *ms, struct magic *m) if ((ms->flags & MAGIC_DEBUG) != 0) (void) fprintf(stderr, "((%" INT64_T_FORMAT "x & %" INT64_T_FORMAT "x) == %" INT64_T_FORMAT - "x) = %d\n", (unsigned long long)v, - (unsigned long long)l, (unsigned long long)l, + "x) = %d\n", CAST(unsigned long long, v), + CAST(unsigned long long, l), + CAST(unsigned long long, l), matched); break; @@ -2163,9 +2266,9 @@ magiccheck(struct magic_set *ms, struct magic *m) if ((ms->flags & MAGIC_DEBUG) != 0) (void) fprintf(stderr, "((%" INT64_T_FORMAT "x & %" INT64_T_FORMAT "x) != %" INT64_T_FORMAT - "x) = %d\n", (unsigned long long)v, - (unsigned long long)l, (unsigned long long)l, - matched); + "x) = %d\n", CAST(unsigned long long, v), + CAST(unsigned long long, l), + CAST(unsigned long long, l), matched); break; default: @@ -2181,14 +2284,14 @@ private int handle_annotation(struct magic_set *ms, struct magic *m, int firstline) { if ((ms->flags & MAGIC_APPLE) && m->apple[0]) { - if (!firstline && file_printf(ms, "\n- ") == -1) + if (print_sep(ms, firstline) == -1) return -1; if (file_printf(ms, "%.8s", m->apple) == -1) return -1; return 1; } if ((ms->flags & MAGIC_EXTENSION) && m->ext[0]) { - if (!firstline && file_printf(ms, "\n- ") == -1) + if (print_sep(ms, firstline) == -1) return -1; if (file_printf(ms, "%s", m->ext) == -1) return -1; @@ -2197,7 +2300,7 @@ handle_annotation(struct magic_set *ms, struct magic *m, int firstline) if ((ms->flags & MAGIC_MIME_TYPE) && m->mimetype[0]) { char buf[1024]; const char *p; - if (!firstline && file_printf(ms, "\n- ") == -1) + if (print_sep(ms, firstline) == -1) return -1; if (varexpand(ms, buf, sizeof(buf), m->mimetype) == -1) p = m->mimetype; @@ -2213,13 +2316,11 @@ handle_annotation(struct magic_set *ms, struct magic *m, int firstline) private int print_sep(struct magic_set *ms, int firstline) { -// if (ms->flags & MAGIC_NODESC) -// return 0; if (firstline) return 0; /* * we found another match * put a newline and '-' to do some simple formatting */ - return file_printf(ms, "\n- "); + return file_separator(ms); } diff --git a/src/vasprintf.c b/src/vasprintf.c index ad1d3165534de..c87465bd53488 100644 --- a/src/vasprintf.c +++ b/src/vasprintf.c @@ -2,7 +2,7 @@ * Copyright (c) Ian F. Darwin 1986-1995. * Software written by Ian F. Darwin and others; * maintained 1995-present by Christos Zoulas and others. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -12,7 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -51,7 +51,7 @@ form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. The name of the author may not be used to endorse or promote products derived from this software without specific -prior written permission. +prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF @@ -108,7 +108,7 @@ you use strange formats. #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: vasprintf.c,v 1.14 2017/08/13 00:21:47 christos Exp $") +FILE_RCSID("@(#)$File: vasprintf.c,v 1.16 2018/10/01 18:45:39 christos Exp $") #endif /* lint */ #include <assert.h> @@ -116,12 +116,8 @@ FILE_RCSID("@(#)$File: vasprintf.c,v 1.14 2017/08/13 00:21:47 christos Exp $") #include <stdlib.h> #include <stdarg.h> #include <ctype.h> -#ifdef HAVE_LIMITS_H #include <limits.h> -#endif -#ifdef HAVE_STDDEF_H #include <stddef.h> -#endif #define ALLOC_CHUNK 2048 #define ALLOC_SECURITY_MARGIN 1024 /* big value because some platforms have very big 'G' exponent */ |