1b6cee71dSXin LI /*
2b6cee71dSXin LI * Copyright (c) Ian F. Darwin 1986-1995.
3b6cee71dSXin LI * Software written by Ian F. Darwin and others;
4b6cee71dSXin LI * maintained 1995-present by Christos Zoulas and others.
5b6cee71dSXin LI *
6b6cee71dSXin LI * Redistribution and use in source and binary forms, with or without
7b6cee71dSXin LI * modification, are permitted provided that the following conditions
8b6cee71dSXin LI * are met:
9b6cee71dSXin LI * 1. Redistributions of source code must retain the above copyright
10b6cee71dSXin LI * notice immediately at the beginning of the file, without modification,
11b6cee71dSXin LI * this list of conditions, and the following disclaimer.
12b6cee71dSXin LI * 2. Redistributions in binary form must reproduce the above copyright
13b6cee71dSXin LI * notice, this list of conditions and the following disclaimer in the
14b6cee71dSXin LI * documentation and/or other materials provided with the distribution.
15b6cee71dSXin LI *
16b6cee71dSXin LI * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17b6cee71dSXin LI * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18b6cee71dSXin LI * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19b6cee71dSXin LI * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20b6cee71dSXin LI * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21b6cee71dSXin LI * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22b6cee71dSXin LI * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23b6cee71dSXin LI * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24b6cee71dSXin LI * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25b6cee71dSXin LI * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26b6cee71dSXin LI * SUCH DAMAGE.
27b6cee71dSXin LI */
28b6cee71dSXin LI /*
29b6cee71dSXin LI * softmagic - interpret variable magic from MAGIC
30b6cee71dSXin LI */
31b6cee71dSXin LI
32b6cee71dSXin LI #include "file.h"
33b6cee71dSXin LI
34b6cee71dSXin LI #ifndef lint
35*ae316d1dSXin LI FILE_RCSID("@(#)$File: softmagic.c,v 1.350 2024/11/27 15:37:00 christos Exp $")
36b6cee71dSXin LI #endif /* lint */
37b6cee71dSXin LI
38b6cee71dSXin LI #include "magic.h"
39b6cee71dSXin LI #include <assert.h>
40898496eeSXin LI #include <math.h>
41b6cee71dSXin LI #include <string.h>
42b6cee71dSXin LI #include <ctype.h>
43b6cee71dSXin LI #include <stdlib.h>
44898496eeSXin LI #include <limits.h>
45b6cee71dSXin LI #include <time.h>
463e41d09dSXin LI #include "der.h"
47b6cee71dSXin LI
48898496eeSXin LI file_private int match(struct magic_set *, struct magic *, file_regex_t **, size_t,
4958a0f0d0SEitan Adler const struct buffer *, size_t, int, int, int, uint16_t *,
50898496eeSXin LI uint16_t *, int *, int *, int *, int *, int *);
51898496eeSXin LI file_private int mget(struct magic_set *, struct magic *, const struct buffer *,
5258a0f0d0SEitan Adler const unsigned char *, size_t,
5358a0f0d0SEitan Adler size_t, unsigned int, int, int, int, uint16_t *,
54898496eeSXin LI uint16_t *, int *, int *, int *, int *, int *);
55898496eeSXin LI file_private int msetoffset(struct magic_set *, struct magic *, struct buffer *,
5658a0f0d0SEitan Adler const struct buffer *, size_t, unsigned int);
57898496eeSXin LI file_private int magiccheck(struct magic_set *, struct magic *, file_regex_t **);
58898496eeSXin LI file_private int mprint(struct magic_set *, struct magic *);
59*ae316d1dSXin LI file_private int moffset(struct magic_set *, struct magic *,
60*ae316d1dSXin LI const struct buffer *, size_t, int32_t *);
61898496eeSXin LI file_private void mdebug(uint32_t, const char *, size_t);
62898496eeSXin LI file_private int mcopy(struct magic_set *, union VALUETYPE *, int, int,
63b6cee71dSXin LI const unsigned char *, uint32_t, size_t, struct magic *);
64898496eeSXin LI file_private int mconvert(struct magic_set *, struct magic *, int);
65898496eeSXin LI file_private int print_sep(struct magic_set *, int);
66898496eeSXin LI file_private int handle_annotation(struct magic_set *, struct magic *, int);
67898496eeSXin LI file_private int cvt_8(union VALUETYPE *, const struct magic *);
68898496eeSXin LI file_private int cvt_16(union VALUETYPE *, const struct magic *);
69898496eeSXin LI file_private int cvt_32(union VALUETYPE *, const struct magic *);
70898496eeSXin LI file_private int cvt_64(union VALUETYPE *, const struct magic *);
71b6cee71dSXin LI
7248c779cdSXin LI #define OFFSET_OOB(n, o, i) ((n) < CAST(uint32_t, (o)) || (i) > ((n) - (o)))
7348c779cdSXin LI #define BE64(p) ( \
74*ae316d1dSXin LI (CAST(uint64_t, (p)[0])<<56)| \
75*ae316d1dSXin LI (CAST(uint64_t, (p)[1])<<48)| \
76*ae316d1dSXin LI (CAST(uint64_t, (p)[2])<<40)| \
77*ae316d1dSXin LI (CAST(uint64_t, (p)[3])<<32)| \
78*ae316d1dSXin LI (CAST(uint64_t, (p)[4])<<24)| \
79*ae316d1dSXin LI (CAST(uint64_t, (p)[5])<<16)| \
80*ae316d1dSXin LI (CAST(uint64_t, (p)[6])<<8)| \
81*ae316d1dSXin LI (CAST(uint64_t, (p)[7])))
8248c779cdSXin LI #define LE64(p) ( \
83*ae316d1dSXin LI (CAST(uint64_t, (p)[7])<<56)| \
84*ae316d1dSXin LI (CAST(uint64_t, (p)[6])<<48)| \
85*ae316d1dSXin LI (CAST(uint64_t, (p)[5])<<40)| \
86*ae316d1dSXin LI (CAST(uint64_t, (p)[4])<<32)| \
87*ae316d1dSXin LI (CAST(uint64_t, (p)[3])<<24)| \
88*ae316d1dSXin LI (CAST(uint64_t, (p)[2])<<16)| \
89*ae316d1dSXin LI (CAST(uint64_t, (p)[1])<<8)| \
90*ae316d1dSXin LI (CAST(uint64_t, (p)[0])))
9148c779cdSXin LI #define LE32(p) ( \
92*ae316d1dSXin LI (CAST(uint32_t, (p)[3])<<24)| \
93*ae316d1dSXin LI (CAST(uint32_t, (p)[2])<<16)| \
94*ae316d1dSXin LI (CAST(uint32_t, (p)[1])<<8)| \
95*ae316d1dSXin LI (CAST(uint32_t, (p)[0])))
9648c779cdSXin LI #define BE32(p) ( \
97*ae316d1dSXin LI (CAST(uint32_t, (p)[0])<<24)| \
98*ae316d1dSXin LI (CAST(uint32_t, (p)[1])<<16)| \
99*ae316d1dSXin LI (CAST(uint32_t, (p)[2])<<8)| \
100*ae316d1dSXin LI (CAST(uint32_t, (p)[3])))
10148c779cdSXin LI #define ME32(p) ( \
102*ae316d1dSXin LI (CAST(uint32_t, (p)[1])<<24)| \
103*ae316d1dSXin LI (CAST(uint32_t, (p)[0])<<16)| \
104*ae316d1dSXin LI (CAST(uint32_t, (p)[3])<<8)| \
105*ae316d1dSXin LI (CAST(uint32_t, (p)[2])))
10648c779cdSXin LI
107*ae316d1dSXin LI #define BE16(p) ((CAST(uint16_t, (p)[0])<<8)|(CAST(uint16_t, (p)[1])))
108*ae316d1dSXin LI #define LE16(p) ((CAST(uint16_t, (p)[1])<<8)|(CAST(uint16_t, (p)[0])))
10948c779cdSXin LI #define SEXT(s,v,p) ((s) ? \
11048c779cdSXin LI CAST(intmax_t, CAST(int##v##_t, p)) : \
11148c779cdSXin LI CAST(intmax_t, CAST(uint##v##_t, p)))
1122c4f1647SXin LI
113b6cee71dSXin LI /*
114b6cee71dSXin LI * softmagic - lookup one file in parsed, in-memory copy of database
115b6cee71dSXin LI * Passed the name and FILE * of one file to be typed.
116b6cee71dSXin LI */
117b6cee71dSXin LI /*ARGSUSED1*/ /* nbytes passed for regularity, maybe need later */
118898496eeSXin LI file_protected int
file_softmagic(struct magic_set * ms,const struct buffer * b,uint16_t * indir_count,uint16_t * name_count,int mode,int text)11958a0f0d0SEitan Adler file_softmagic(struct magic_set *ms, const struct buffer *b,
1203e41d09dSXin LI uint16_t *indir_count, uint16_t *name_count, int mode, int text)
121b6cee71dSXin LI {
122b6cee71dSXin LI struct mlist *ml;
123898496eeSXin LI int rv = 0, printed_something = 0, need_separator = 0, firstline = 1;
1243e41d09dSXin LI uint16_t nc, ic;
125c2931133SXin LI
126c2931133SXin LI if (name_count == NULL) {
127c2931133SXin LI nc = 0;
128c2931133SXin LI name_count = &nc;
129c2931133SXin LI }
1303e41d09dSXin LI if (indir_count == NULL) {
1313e41d09dSXin LI ic = 0;
1323e41d09dSXin LI indir_count = ⁣
1333e41d09dSXin LI }
134c2931133SXin LI
135a2dfb722SXin LI for (ml = ms->mlist[0]->next; ml != ms->mlist[0]; ml = ml->next) {
136a2dfb722SXin LI int ret = match(ms, ml->magic, ml->magic_rxcomp, ml->nmagic, b,
137a4d6d3b8SXin LI 0, mode, text, 0, indir_count, name_count,
138898496eeSXin LI &printed_something, &need_separator, &firstline,
139898496eeSXin LI NULL, NULL);
140a2dfb722SXin LI switch (ret) {
141a2dfb722SXin LI case -1:
142a2dfb722SXin LI return ret;
143a2dfb722SXin LI case 0:
144a2dfb722SXin LI continue;
145a2dfb722SXin LI default:
146a2dfb722SXin LI if ((ms->flags & MAGIC_CONTINUE) == 0)
147a2dfb722SXin LI return ret;
148a2dfb722SXin LI rv = ret;
149a2dfb722SXin LI break;
150a2dfb722SXin LI }
151a2dfb722SXin LI }
152b6cee71dSXin LI
153a2dfb722SXin LI return rv;
154b6cee71dSXin LI }
155b6cee71dSXin LI
156b6cee71dSXin LI #define FILE_FMTDEBUG
157b6cee71dSXin LI #ifdef FILE_FMTDEBUG
158b6cee71dSXin LI #define F(a, b, c) file_fmtcheck((a), (b), (c), __FILE__, __LINE__)
159b6cee71dSXin LI
160898496eeSXin LI file_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)16158a0f0d0SEitan Adler file_fmtcheck(struct magic_set *ms, const char *desc, const char *def,
162b6cee71dSXin LI const char *file, size_t line)
163b6cee71dSXin LI {
16448c779cdSXin LI const char *ptr;
16548c779cdSXin LI
16648c779cdSXin LI if (strchr(desc, '%') == NULL)
16748c779cdSXin LI return desc;
16848c779cdSXin LI
16948c779cdSXin LI ptr = fmtcheck(desc, def);
170b6cee71dSXin LI if (ptr == def)
171b6cee71dSXin LI file_magerror(ms,
172c2931133SXin LI "%s, %" SIZE_T_FORMAT "u: format `%s' does not match"
17358a0f0d0SEitan Adler " with `%s'", file, line, desc, def);
174b6cee71dSXin LI return ptr;
175b6cee71dSXin LI }
176b6cee71dSXin LI #else
17758a0f0d0SEitan Adler #define F(a, b, c) fmtcheck((b), (c))
178b6cee71dSXin LI #endif
179b6cee71dSXin LI
180b6cee71dSXin LI /*
181b6cee71dSXin LI * Go through the whole list, stopping if you find a match. Process all
182b6cee71dSXin LI * the continuations of that match before returning.
183b6cee71dSXin LI *
184b6cee71dSXin LI * We support multi-level continuations:
185b6cee71dSXin LI *
186b6cee71dSXin LI * At any time when processing a successful top-level match, there is a
187b6cee71dSXin LI * current continuation level; it represents the level of the last
188b6cee71dSXin LI * successfully matched continuation.
189b6cee71dSXin LI *
190b6cee71dSXin LI * Continuations above that level are skipped as, if we see one, it
191b6cee71dSXin LI * means that the continuation that controls them - i.e, the
192b6cee71dSXin LI * lower-level continuation preceding them - failed to match.
193b6cee71dSXin LI *
194b6cee71dSXin LI * Continuations below that level are processed as, if we see one,
195b6cee71dSXin LI * it means we've finished processing or skipping higher-level
196b6cee71dSXin LI * continuations under the control of a successful or unsuccessful
197b6cee71dSXin LI * lower-level continuation, and are now seeing the next lower-level
198b6cee71dSXin LI * continuation and should process it. The current continuation
199b6cee71dSXin LI * level reverts to the level of the one we're seeing.
200b6cee71dSXin LI *
201b6cee71dSXin LI * Continuations at the current level are processed as, if we see
202b6cee71dSXin LI * one, there's no lower-level continuation that may have failed.
203b6cee71dSXin LI *
204b6cee71dSXin LI * If a continuation matches, we bump the current continuation level
205b6cee71dSXin LI * so that higher-level continuations are processed.
206b6cee71dSXin LI */
207898496eeSXin LI file_private int
match(struct magic_set * ms,struct magic * magic,file_regex_t ** magic_rxcomp,size_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 * firstline,int * returnval,int * found_match)208a4d6d3b8SXin LI match(struct magic_set *ms, struct magic *magic, file_regex_t **magic_rxcomp,
209a2dfb722SXin LI size_t nmagic, const struct buffer *b, size_t offset, int mode, int text,
2103e41d09dSXin LI int flip, uint16_t *indir_count, uint16_t *name_count,
211898496eeSXin LI int *printed_something, int *need_separator, int *firstline,
212898496eeSXin LI int *returnval, int *found_match)
213b6cee71dSXin LI {
214b6cee71dSXin LI uint32_t magindex = 0;
215b6cee71dSXin LI unsigned int cont_level = 0;
21648c779cdSXin LI int found_matchv = 0; /* if a match is found it is set to 1*/
21748c779cdSXin LI int returnvalv = 0, e;
21858a0f0d0SEitan Adler struct buffer bb;
2195f0216bdSXin LI int print = (ms->flags & MAGIC_NODESC) == 0;
220b6cee71dSXin LI
22148c779cdSXin LI /*
22248c779cdSXin LI * returnval can be 0 if a match is found, but there was no
22348c779cdSXin LI * annotation to be printed.
22448c779cdSXin LI */
225b6cee71dSXin LI if (returnval == NULL)
226b6cee71dSXin LI returnval = &returnvalv;
22748c779cdSXin LI if (found_match == NULL)
22848c779cdSXin LI found_match = &found_matchv;
229b6cee71dSXin LI
230b6cee71dSXin LI if (file_check_mem(ms, cont_level) == -1)
231b6cee71dSXin LI return -1;
232b6cee71dSXin LI
233b6cee71dSXin LI for (magindex = 0; magindex < nmagic; magindex++) {
234b6cee71dSXin LI int flush = 0;
235b6cee71dSXin LI struct magic *m = &magic[magindex];
236a4d6d3b8SXin LI file_regex_t **m_rxcomp = &magic_rxcomp[magindex];
237b6cee71dSXin LI
238b6cee71dSXin LI if (m->type != FILE_NAME)
239b6cee71dSXin LI if ((IS_STRING(m->type) &&
240b6cee71dSXin LI #define FLT (STRING_BINTEST | STRING_TEXTTEST)
241b6cee71dSXin LI ((text && (m->str_flags & FLT) == STRING_BINTEST) ||
242b6cee71dSXin LI (!text && (m->str_flags & FLT) == STRING_TEXTTEST))) ||
243b6cee71dSXin LI (m->flag & mode) != mode) {
24453021c7eSXin LI flush:
245b6cee71dSXin LI /* Skip sub-tests */
24653021c7eSXin LI while (magindex < nmagic - 1 &&
24753021c7eSXin LI magic[magindex + 1].cont_level != 0)
24853021c7eSXin LI magindex++;
24940427ccaSGordon Tetlow cont_level = 0;
250b6cee71dSXin LI continue; /* Skip to next top-level test*/
251b6cee71dSXin LI }
252b6cee71dSXin LI
25358a0f0d0SEitan Adler if (msetoffset(ms, m, &bb, b, offset, cont_level) == -1)
25458a0f0d0SEitan Adler goto flush;
255b6cee71dSXin LI ms->line = m->lineno;
256b6cee71dSXin LI
257b6cee71dSXin LI /* if main entry matches, print it... */
25848c779cdSXin LI switch (mget(ms, m, b, CAST(const unsigned char *, bb.fbuf),
25948c779cdSXin LI bb.flen, offset, cont_level,
26058a0f0d0SEitan Adler mode, text, flip, indir_count, name_count,
261898496eeSXin LI printed_something, need_separator, firstline, returnval,
262898496eeSXin LI found_match))
26348c779cdSXin LI {
264b6cee71dSXin LI case -1:
265b6cee71dSXin LI return -1;
266b6cee71dSXin LI case 0:
267b6cee71dSXin LI flush = m->reln != '!';
268b6cee71dSXin LI break;
269b6cee71dSXin LI default:
27048c779cdSXin LI if (m->type == FILE_INDIRECT) {
27148c779cdSXin LI *found_match = 1;
272b6cee71dSXin LI *returnval = 1;
27348c779cdSXin LI }
274b6cee71dSXin LI
275a4d6d3b8SXin LI switch (magiccheck(ms, m, m_rxcomp)) {
276b6cee71dSXin LI case -1:
277b6cee71dSXin LI return -1;
278b6cee71dSXin LI case 0:
279b6cee71dSXin LI flush++;
280b6cee71dSXin LI break;
281b6cee71dSXin LI default:
282b6cee71dSXin LI flush = 0;
283b6cee71dSXin LI break;
284b6cee71dSXin LI }
285b6cee71dSXin LI break;
286b6cee71dSXin LI }
287b6cee71dSXin LI if (flush) {
288b6cee71dSXin LI /*
289b6cee71dSXin LI * main entry didn't match,
290b6cee71dSXin LI * flush its continuations
291b6cee71dSXin LI */
29253021c7eSXin LI goto flush;
293b6cee71dSXin LI }
294b6cee71dSXin LI
295898496eeSXin LI if ((e = handle_annotation(ms, m, *firstline)) != 0)
29648c779cdSXin LI {
29743a5ec4eSXin LI *found_match = 1;
298b6cee71dSXin LI *need_separator = 1;
299b6cee71dSXin LI *printed_something = 1;
300b6cee71dSXin LI *returnval = 1;
301898496eeSXin LI *firstline = 0;
302b6cee71dSXin LI return e;
303b6cee71dSXin LI }
3043e41d09dSXin LI
305b6cee71dSXin LI /*
306b6cee71dSXin LI * If we are going to print something, we'll need to print
307b6cee71dSXin LI * a blank before we print something else.
308b6cee71dSXin LI */
30943a5ec4eSXin LI if (*m->desc) {
31043a5ec4eSXin LI *found_match = 1;
31143a5ec4eSXin LI if (print) {
31243a5ec4eSXin LI *returnval = 1;
313b6cee71dSXin LI *need_separator = 1;
314b6cee71dSXin LI *printed_something = 1;
315898496eeSXin LI if (print_sep(ms, *firstline) == -1)
316b6cee71dSXin LI return -1;
31748c779cdSXin LI if (mprint(ms, m) == -1)
318b6cee71dSXin LI return -1;
31948c779cdSXin LI }
32043a5ec4eSXin LI }
321b6cee71dSXin LI
322*ae316d1dSXin LI switch (moffset(ms, m, &bb, offset, &ms->c.li[cont_level].off)) {
32353021c7eSXin LI case -1:
32453021c7eSXin LI case 0:
32553021c7eSXin LI goto flush;
32653021c7eSXin LI default:
32753021c7eSXin LI break;
32853021c7eSXin LI }
329b6cee71dSXin LI
330b6cee71dSXin LI /* and any continuations that match */
331b6cee71dSXin LI if (file_check_mem(ms, ++cont_level) == -1)
332b6cee71dSXin LI return -1;
333b6cee71dSXin LI
334c2931133SXin LI while (magindex + 1 < nmagic &&
335c2931133SXin LI magic[magindex + 1].cont_level != 0) {
336c2931133SXin LI m = &magic[++magindex];
337a4d6d3b8SXin LI m_rxcomp = &magic_rxcomp[magindex];
338b6cee71dSXin LI ms->line = m->lineno; /* for messages */
339b6cee71dSXin LI
340b6cee71dSXin LI if (cont_level < m->cont_level)
341b6cee71dSXin LI continue;
342b6cee71dSXin LI if (cont_level > m->cont_level) {
343b6cee71dSXin LI /*
344b6cee71dSXin LI * We're at the end of the level
345b6cee71dSXin LI * "cont_level" continuations.
346b6cee71dSXin LI */
347b6cee71dSXin LI cont_level = m->cont_level;
348b6cee71dSXin LI }
34958a0f0d0SEitan Adler if (msetoffset(ms, m, &bb, b, offset, cont_level) == -1)
35058a0f0d0SEitan Adler goto flush;
351b6cee71dSXin LI if (m->flag & OFFADD) {
3522726a701SXin LI if (cont_level == 0) {
3532726a701SXin LI if ((ms->flags & MAGIC_DEBUG) != 0)
3542726a701SXin LI fprintf(stderr,
3552726a701SXin LI "direct *zero*"
3562726a701SXin LI " cont_level\n");
3572726a701SXin LI return 0;
3582726a701SXin LI }
359b6cee71dSXin LI ms->offset +=
360b6cee71dSXin LI ms->c.li[cont_level - 1].off;
361b6cee71dSXin LI }
362b6cee71dSXin LI
363b6cee71dSXin LI #ifdef ENABLE_CONDITIONALS
364b6cee71dSXin LI if (m->cond == COND_ELSE ||
365b6cee71dSXin LI m->cond == COND_ELIF) {
366b6cee71dSXin LI if (ms->c.li[cont_level].last_match == 1)
367b6cee71dSXin LI continue;
368b6cee71dSXin LI }
369b6cee71dSXin LI #endif
37048c779cdSXin LI switch (mget(ms, m, b, CAST(const unsigned char *,
37148c779cdSXin LI bb.fbuf), bb.flen, offset,
37258a0f0d0SEitan Adler cont_level, mode, text, flip, indir_count,
37358a0f0d0SEitan Adler name_count, printed_something, need_separator,
374898496eeSXin LI firstline, returnval, found_match)) {
375b6cee71dSXin LI case -1:
376b6cee71dSXin LI return -1;
377b6cee71dSXin LI case 0:
378b6cee71dSXin LI if (m->reln != '!')
379b6cee71dSXin LI continue;
380b6cee71dSXin LI flush = 1;
381b6cee71dSXin LI break;
382b6cee71dSXin LI default:
38348c779cdSXin LI if (m->type == FILE_INDIRECT) {
38448c779cdSXin LI *found_match = 1;
385b6cee71dSXin LI *returnval = 1;
38648c779cdSXin LI }
387b6cee71dSXin LI flush = 0;
388b6cee71dSXin LI break;
389b6cee71dSXin LI }
390b6cee71dSXin LI
391a4d6d3b8SXin LI switch (flush ? 1 : magiccheck(ms, m, m_rxcomp)) {
392b6cee71dSXin LI case -1:
393b6cee71dSXin LI return -1;
394b6cee71dSXin LI case 0:
395b6cee71dSXin LI #ifdef ENABLE_CONDITIONALS
396b6cee71dSXin LI ms->c.li[cont_level].last_match = 0;
397b6cee71dSXin LI #endif
398b6cee71dSXin LI break;
399b6cee71dSXin LI default:
400b6cee71dSXin LI #ifdef ENABLE_CONDITIONALS
401b6cee71dSXin LI ms->c.li[cont_level].last_match = 1;
402b6cee71dSXin LI #endif
403b6cee71dSXin LI if (m->type == FILE_CLEAR)
404b6cee71dSXin LI ms->c.li[cont_level].got_match = 0;
405b6cee71dSXin LI else if (ms->c.li[cont_level].got_match) {
406b6cee71dSXin LI if (m->type == FILE_DEFAULT)
407b6cee71dSXin LI break;
408b6cee71dSXin LI } else
409b6cee71dSXin LI ms->c.li[cont_level].got_match = 1;
4103e41d09dSXin LI
411898496eeSXin LI if ((e = handle_annotation(ms, m, *firstline))
41258a0f0d0SEitan Adler != 0) {
41343a5ec4eSXin LI *found_match = 1;
414b6cee71dSXin LI *need_separator = 1;
415b6cee71dSXin LI *printed_something = 1;
416b6cee71dSXin LI *returnval = 1;
417b6cee71dSXin LI return e;
418b6cee71dSXin LI }
41943a5ec4eSXin LI if (*m->desc) {
42043a5ec4eSXin LI *found_match = 1;
42143a5ec4eSXin LI }
42248c779cdSXin LI if (print && *m->desc) {
42343a5ec4eSXin LI *returnval = 1;
424b6cee71dSXin LI /*
425b6cee71dSXin LI * This continuation matched. Print
426b6cee71dSXin LI * its message, with a blank before it
427b6cee71dSXin LI * if the previous item printed and
428b6cee71dSXin LI * this item isn't empty.
429b6cee71dSXin LI */
43048c779cdSXin LI /*
43148c779cdSXin LI * If we are going to print something,
43248c779cdSXin LI * make sure that we have a separator
43348c779cdSXin LI * first.
43448c779cdSXin LI */
43548c779cdSXin LI if (!*printed_something) {
43648c779cdSXin LI *printed_something = 1;
437898496eeSXin LI if (print_sep(ms, *firstline)
43848c779cdSXin LI == -1)
43948c779cdSXin LI return -1;
44048c779cdSXin LI }
441b6cee71dSXin LI /* space if previous printed */
442b6cee71dSXin LI if (*need_separator
44348c779cdSXin LI && (m->flag & NOSPACE) == 0) {
44448c779cdSXin LI if (file_printf(ms, " ") == -1)
445b6cee71dSXin LI return -1;
446b6cee71dSXin LI }
44748c779cdSXin LI if (mprint(ms, m) == -1)
448b6cee71dSXin LI return -1;
44948c779cdSXin LI *need_separator = 1;
45048c779cdSXin LI }
451b6cee71dSXin LI
452*ae316d1dSXin LI switch (moffset(ms, m, &bb, offset,
45353021c7eSXin LI &ms->c.li[cont_level].off)) {
45453021c7eSXin LI case -1:
45553021c7eSXin LI case 0:
45640427ccaSGordon Tetlow cont_level--;
45753021c7eSXin LI break;
45853021c7eSXin LI default:
45953021c7eSXin LI break;
46053021c7eSXin LI }
461b6cee71dSXin LI
462b6cee71dSXin LI /*
463b6cee71dSXin LI * If we see any continuations
464b6cee71dSXin LI * at a higher level,
465b6cee71dSXin LI * process them.
466b6cee71dSXin LI */
467b6cee71dSXin LI if (file_check_mem(ms, ++cont_level) == -1)
468b6cee71dSXin LI return -1;
469b6cee71dSXin LI break;
470b6cee71dSXin LI }
471b6cee71dSXin LI }
472b6cee71dSXin LI if (*printed_something) {
473898496eeSXin LI *firstline = 0;
474b6cee71dSXin LI }
47548c779cdSXin LI if (*found_match) {
47648c779cdSXin LI if ((ms->flags & MAGIC_CONTINUE) == 0)
47743a5ec4eSXin LI return *returnval;
47848c779cdSXin LI // So that we print a separator
47948c779cdSXin LI *printed_something = 0;
480898496eeSXin LI *firstline = 0;
481b6cee71dSXin LI }
4825f0216bdSXin LI cont_level = 0;
483b6cee71dSXin LI }
48443a5ec4eSXin LI return *returnval;
485b6cee71dSXin LI }
486b6cee71dSXin LI
487898496eeSXin LI file_private int
check_fmt(struct magic_set * ms,const char * fmt)48858a0f0d0SEitan Adler check_fmt(struct magic_set *ms, const char *fmt)
489b6cee71dSXin LI {
490b6cee71dSXin LI file_regex_t rx;
491b6cee71dSXin LI int rc, rv = -1;
492a4d6d3b8SXin LI const char* pat = "%[-0-9\\.]*s";
493b6cee71dSXin LI
49458a0f0d0SEitan Adler if (strchr(fmt, '%') == NULL)
495b6cee71dSXin LI return 0;
496b6cee71dSXin LI
497a4d6d3b8SXin LI rc = file_regcomp(ms, &rx, pat, REG_EXTENDED|REG_NOSUB);
498a4d6d3b8SXin LI if (rc == 0) {
499a4d6d3b8SXin LI rc = file_regexec(ms, &rx, fmt, 0, 0, 0);
500b6cee71dSXin LI rv = !rc;
501b6cee71dSXin LI }
502b6cee71dSXin LI file_regfree(&rx);
503b6cee71dSXin LI return rv;
504b6cee71dSXin LI }
505b6cee71dSXin LI
50643a5ec4eSXin LI #if !defined(HAVE_STRNDUP) || defined(__aiws__) || defined(_AIX)
50743a5ec4eSXin LI # if defined(__aiws__) || defined(_AIX)
5082dc4dbb9SEitan Adler # define strndup aix_strndup /* aix is broken */
5092dc4dbb9SEitan Adler # endif
510b6cee71dSXin LI char *strndup(const char *, size_t);
511b6cee71dSXin LI
512b6cee71dSXin LI char *
strndup(const char * str,size_t n)513b6cee71dSXin LI strndup(const char *str, size_t n)
514b6cee71dSXin LI {
515b6cee71dSXin LI size_t len;
516b6cee71dSXin LI char *copy;
517b6cee71dSXin LI
518b6cee71dSXin LI for (len = 0; len < n && str[len]; len++)
519b6cee71dSXin LI continue;
520a4d6d3b8SXin LI if ((copy = CAST(char *, malloc(len + 1))) == NULL)
521b6cee71dSXin LI return NULL;
522b6cee71dSXin LI (void)memcpy(copy, str, len);
523b6cee71dSXin LI copy[len] = '\0';
524b6cee71dSXin LI return copy;
525b6cee71dSXin LI }
526b6cee71dSXin LI #endif /* HAVE_STRNDUP */
527b6cee71dSXin LI
52858a0f0d0SEitan Adler static int
varexpand(struct magic_set * ms,char * buf,size_t len,const char * str)5292dc4dbb9SEitan Adler varexpand(struct magic_set *ms, char *buf, size_t len, const char *str)
53058a0f0d0SEitan Adler {
53158a0f0d0SEitan Adler const char *ptr, *sptr, *e, *t, *ee, *et;
53258a0f0d0SEitan Adler size_t l;
53358a0f0d0SEitan Adler
53458a0f0d0SEitan Adler for (sptr = str; (ptr = strstr(sptr, "${")) != NULL;) {
53548c779cdSXin LI l = CAST(size_t, ptr - sptr);
53658a0f0d0SEitan Adler if (l >= len)
53758a0f0d0SEitan Adler return -1;
53858a0f0d0SEitan Adler memcpy(buf, sptr, l);
53958a0f0d0SEitan Adler buf += l;
54058a0f0d0SEitan Adler len -= l;
54158a0f0d0SEitan Adler ptr += 2;
54258a0f0d0SEitan Adler if (!*ptr || ptr[1] != '?')
54358a0f0d0SEitan Adler return -1;
54458a0f0d0SEitan Adler for (et = t = ptr + 2; *et && *et != ':'; et++)
54558a0f0d0SEitan Adler continue;
54658a0f0d0SEitan Adler if (*et != ':')
54758a0f0d0SEitan Adler return -1;
54858a0f0d0SEitan Adler for (ee = e = et + 1; *ee && *ee != '}'; ee++)
54958a0f0d0SEitan Adler continue;
55058a0f0d0SEitan Adler if (*ee != '}')
55158a0f0d0SEitan Adler return -1;
55258a0f0d0SEitan Adler switch (*ptr) {
55358a0f0d0SEitan Adler case 'x':
5542dc4dbb9SEitan Adler if (ms->mode & 0111) {
55558a0f0d0SEitan Adler ptr = t;
55658a0f0d0SEitan Adler l = et - t;
55758a0f0d0SEitan Adler } else {
55858a0f0d0SEitan Adler ptr = e;
55958a0f0d0SEitan Adler l = ee - e;
56058a0f0d0SEitan Adler }
56158a0f0d0SEitan Adler break;
56258a0f0d0SEitan Adler default:
56358a0f0d0SEitan Adler return -1;
56458a0f0d0SEitan Adler }
56558a0f0d0SEitan Adler if (l >= len)
56658a0f0d0SEitan Adler return -1;
56758a0f0d0SEitan Adler memcpy(buf, ptr, l);
56858a0f0d0SEitan Adler buf += l;
56958a0f0d0SEitan Adler len -= l;
57058a0f0d0SEitan Adler sptr = ee + 1;
57158a0f0d0SEitan Adler }
57258a0f0d0SEitan Adler
57358a0f0d0SEitan Adler l = strlen(sptr);
57458a0f0d0SEitan Adler if (l >= len)
57558a0f0d0SEitan Adler return -1;
57658a0f0d0SEitan Adler
57758a0f0d0SEitan Adler memcpy(buf, sptr, l);
57858a0f0d0SEitan Adler buf[l] = '\0';
57958a0f0d0SEitan Adler return 0;
58058a0f0d0SEitan Adler }
58158a0f0d0SEitan Adler
58258a0f0d0SEitan Adler
583898496eeSXin LI file_private int
mprint(struct magic_set * ms,struct magic * m)5842dc4dbb9SEitan Adler mprint(struct magic_set *ms, struct magic *m)
585b6cee71dSXin LI {
586b6cee71dSXin LI uint64_t v;
587b6cee71dSXin LI float vf;
588b6cee71dSXin LI double vd;
58958a0f0d0SEitan Adler char buf[128], tbuf[26], sbuf[512], ebuf[512];
59058a0f0d0SEitan Adler const char *desc;
591b6cee71dSXin LI union VALUETYPE *p = &ms->ms_value;
592b6cee71dSXin LI
5932dc4dbb9SEitan Adler if (varexpand(ms, ebuf, sizeof(ebuf), m->desc) == -1)
59458a0f0d0SEitan Adler desc = m->desc;
59558a0f0d0SEitan Adler else
59658a0f0d0SEitan Adler desc = ebuf;
59758a0f0d0SEitan Adler
59843a5ec4eSXin LI #define PRINTER(value, format, stype, utype) \
59943a5ec4eSXin LI v = file_signextend(ms, m, CAST(uint64_t, value)); \
60043a5ec4eSXin LI switch (check_fmt(ms, desc)) { \
60143a5ec4eSXin LI case -1: \
60243a5ec4eSXin LI return -1; \
60343a5ec4eSXin LI case 1: \
60443a5ec4eSXin LI if (m->flag & UNSIGNED) { \
60543a5ec4eSXin LI (void)snprintf(buf, sizeof(buf), "%" format "u", \
60643a5ec4eSXin LI CAST(utype, v)); \
60743a5ec4eSXin LI } else { \
60843a5ec4eSXin LI (void)snprintf(buf, sizeof(buf), "%" format "d", \
60943a5ec4eSXin LI CAST(stype, v)); \
61043a5ec4eSXin LI } \
61143a5ec4eSXin LI if (file_printf(ms, F(ms, desc, "%s"), buf) == -1) \
61243a5ec4eSXin LI return -1; \
61343a5ec4eSXin LI break; \
61443a5ec4eSXin LI default: \
61543a5ec4eSXin LI if (m->flag & UNSIGNED) { \
61643a5ec4eSXin LI if (file_printf(ms, F(ms, desc, "%" format "u"), \
61743a5ec4eSXin LI CAST(utype, v)) == -1) \
61843a5ec4eSXin LI return -1; \
61943a5ec4eSXin LI } else { \
62043a5ec4eSXin LI if (file_printf(ms, F(ms, desc, "%" format "d"), \
62143a5ec4eSXin LI CAST(stype, v)) == -1) \
62243a5ec4eSXin LI return -1; \
62343a5ec4eSXin LI } \
62443a5ec4eSXin LI break; \
62543a5ec4eSXin LI } \
62643a5ec4eSXin LI break
62743a5ec4eSXin LI
628b6cee71dSXin LI switch (m->type) {
629b6cee71dSXin LI case FILE_BYTE:
63043a5ec4eSXin LI PRINTER(p->b, "", int8_t, uint8_t);
631b6cee71dSXin LI
632b6cee71dSXin LI case FILE_SHORT:
633b6cee71dSXin LI case FILE_BESHORT:
634b6cee71dSXin LI case FILE_LESHORT:
63543a5ec4eSXin LI PRINTER(p->h, "", int16_t, uint16_t);
636b6cee71dSXin LI
637b6cee71dSXin LI case FILE_LONG:
638b6cee71dSXin LI case FILE_BELONG:
639b6cee71dSXin LI case FILE_LELONG:
640b6cee71dSXin LI case FILE_MELONG:
64143a5ec4eSXin LI PRINTER(p->l, "", int32_t, uint32_t);
642b6cee71dSXin LI
643b6cee71dSXin LI case FILE_QUAD:
644b6cee71dSXin LI case FILE_BEQUAD:
645b6cee71dSXin LI case FILE_LEQUAD:
6462726a701SXin LI case FILE_OFFSET:
64743a5ec4eSXin LI PRINTER(p->q, INT64_T_FORMAT, long long, unsigned long long);
648b6cee71dSXin LI
649b6cee71dSXin LI case FILE_STRING:
650b6cee71dSXin LI case FILE_PSTRING:
651b6cee71dSXin LI case FILE_BESTRING16:
652b6cee71dSXin LI case FILE_LESTRING16:
653b6cee71dSXin LI if (m->reln == '=' || m->reln == '!') {
65458a0f0d0SEitan Adler if (file_printf(ms, F(ms, desc, "%s"),
65543a5ec4eSXin LI file_printable(ms, sbuf, sizeof(sbuf), m->value.s,
65648c779cdSXin LI sizeof(m->value.s))) == -1)
657b6cee71dSXin LI return -1;
658b6cee71dSXin LI }
659b6cee71dSXin LI else {
660b6cee71dSXin LI char *str = p->s;
661b6cee71dSXin LI
662b6cee71dSXin LI /* compute t before we mangle the string? */
663b6cee71dSXin LI
664b6cee71dSXin LI if (*m->value.s == '\0')
6655f0216bdSXin LI str[strcspn(str, "\r\n")] = '\0';
666b6cee71dSXin LI
66743a5ec4eSXin LI if (m->str_flags & STRING_TRIM)
66843a5ec4eSXin LI str = file_strtrim(str);
669b6cee71dSXin LI
67058a0f0d0SEitan Adler if (file_printf(ms, F(ms, desc, "%s"),
67143a5ec4eSXin LI file_printable(ms, sbuf, sizeof(sbuf), str,
67248c779cdSXin LI sizeof(p->s) - (str - p->s))) == -1)
673b6cee71dSXin LI return -1;
674b6cee71dSXin LI
6752726a701SXin LI if (m->type == FILE_PSTRING) {
6762726a701SXin LI size_t l = file_pstring_length_size(ms, m);
6772726a701SXin LI if (l == FILE_BADSIZE)
6782726a701SXin LI return -1;
6792726a701SXin LI }
680b6cee71dSXin LI }
681b6cee71dSXin LI break;
682b6cee71dSXin LI
683b6cee71dSXin LI case FILE_DATE:
684b6cee71dSXin LI case FILE_BEDATE:
685b6cee71dSXin LI case FILE_LEDATE:
686b6cee71dSXin LI case FILE_MEDATE:
68758a0f0d0SEitan Adler if (file_printf(ms, F(ms, desc, "%s"),
688a4d6d3b8SXin LI file_fmtdatetime(tbuf, sizeof(tbuf), p->l, 0)) == -1)
689b6cee71dSXin LI return -1;
690b6cee71dSXin LI break;
691b6cee71dSXin LI
692b6cee71dSXin LI case FILE_LDATE:
693b6cee71dSXin LI case FILE_BELDATE:
694b6cee71dSXin LI case FILE_LELDATE:
695b6cee71dSXin LI case FILE_MELDATE:
69658a0f0d0SEitan Adler if (file_printf(ms, F(ms, desc, "%s"),
697a4d6d3b8SXin LI file_fmtdatetime(tbuf, sizeof(tbuf), p->l, FILE_T_LOCAL))
698a4d6d3b8SXin LI == -1)
699b6cee71dSXin LI return -1;
700b6cee71dSXin LI break;
701b6cee71dSXin LI
702b6cee71dSXin LI case FILE_QDATE:
703b6cee71dSXin LI case FILE_BEQDATE:
704b6cee71dSXin LI case FILE_LEQDATE:
70558a0f0d0SEitan Adler if (file_printf(ms, F(ms, desc, "%s"),
706a4d6d3b8SXin LI file_fmtdatetime(tbuf, sizeof(tbuf), p->q, 0)) == -1)
707b6cee71dSXin LI return -1;
708b6cee71dSXin LI break;
709b6cee71dSXin LI
710b6cee71dSXin LI case FILE_QLDATE:
711b6cee71dSXin LI case FILE_BEQLDATE:
712b6cee71dSXin LI case FILE_LEQLDATE:
71358a0f0d0SEitan Adler if (file_printf(ms, F(ms, desc, "%s"),
714a4d6d3b8SXin LI file_fmtdatetime(tbuf, sizeof(tbuf), p->q, FILE_T_LOCAL)) == -1)
715b6cee71dSXin LI return -1;
716b6cee71dSXin LI break;
717b6cee71dSXin LI
718b6cee71dSXin LI case FILE_QWDATE:
719b6cee71dSXin LI case FILE_BEQWDATE:
720b6cee71dSXin LI case FILE_LEQWDATE:
72158a0f0d0SEitan Adler if (file_printf(ms, F(ms, desc, "%s"),
722a4d6d3b8SXin LI file_fmtdatetime(tbuf, sizeof(tbuf), p->q, FILE_T_WINDOWS))
7232726a701SXin LI == -1)
724b6cee71dSXin LI return -1;
725b6cee71dSXin LI break;
726b6cee71dSXin LI
727b6cee71dSXin LI case FILE_FLOAT:
728b6cee71dSXin LI case FILE_BEFLOAT:
729b6cee71dSXin LI case FILE_LEFLOAT:
730b6cee71dSXin LI vf = p->f;
73158a0f0d0SEitan Adler switch (check_fmt(ms, desc)) {
732b6cee71dSXin LI case -1:
733b6cee71dSXin LI return -1;
734b6cee71dSXin LI case 1:
735b6cee71dSXin LI (void)snprintf(buf, sizeof(buf), "%g", vf);
73658a0f0d0SEitan Adler if (file_printf(ms, F(ms, desc, "%s"), buf) == -1)
737b6cee71dSXin LI return -1;
738b6cee71dSXin LI break;
739b6cee71dSXin LI default:
74058a0f0d0SEitan Adler if (file_printf(ms, F(ms, desc, "%g"), vf) == -1)
741b6cee71dSXin LI return -1;
742b6cee71dSXin LI break;
743b6cee71dSXin LI }
744b6cee71dSXin LI break;
745b6cee71dSXin LI
746b6cee71dSXin LI case FILE_DOUBLE:
747b6cee71dSXin LI case FILE_BEDOUBLE:
748b6cee71dSXin LI case FILE_LEDOUBLE:
749b6cee71dSXin LI vd = p->d;
75058a0f0d0SEitan Adler switch (check_fmt(ms, desc)) {
751b6cee71dSXin LI case -1:
752b6cee71dSXin LI return -1;
753b6cee71dSXin LI case 1:
754b6cee71dSXin LI (void)snprintf(buf, sizeof(buf), "%g", vd);
75558a0f0d0SEitan Adler if (file_printf(ms, F(ms, desc, "%s"), buf) == -1)
756b6cee71dSXin LI return -1;
757b6cee71dSXin LI break;
758b6cee71dSXin LI default:
75958a0f0d0SEitan Adler if (file_printf(ms, F(ms, desc, "%g"), vd) == -1)
760b6cee71dSXin LI return -1;
761b6cee71dSXin LI break;
762b6cee71dSXin LI }
763b6cee71dSXin LI break;
764b6cee71dSXin LI
7655f0216bdSXin LI case FILE_SEARCH:
766b6cee71dSXin LI case FILE_REGEX: {
76743a5ec4eSXin LI char *cp, *scp;
768b6cee71dSXin LI int rval;
769b6cee71dSXin LI
77048c779cdSXin LI cp = strndup(RCAST(const char *, ms->search.s),
77148c779cdSXin LI ms->search.rm_len);
772b6cee71dSXin LI if (cp == NULL) {
773b6cee71dSXin LI file_oomem(ms, ms->search.rm_len);
774b6cee71dSXin LI return -1;
775b6cee71dSXin LI }
77643a5ec4eSXin LI scp = (m->str_flags & STRING_TRIM) ? file_strtrim(cp) : cp;
77743a5ec4eSXin LI
77843a5ec4eSXin LI rval = file_printf(ms, F(ms, desc, "%s"), file_printable(ms,
77943a5ec4eSXin LI sbuf, sizeof(sbuf), scp, ms->search.rm_len));
780b6cee71dSXin LI free(cp);
781b6cee71dSXin LI
782b6cee71dSXin LI if (rval == -1)
783b6cee71dSXin LI return -1;
784b6cee71dSXin LI break;
785b6cee71dSXin LI }
786b6cee71dSXin LI
787b6cee71dSXin LI case FILE_DEFAULT:
788b6cee71dSXin LI case FILE_CLEAR:
789b6cee71dSXin LI if (file_printf(ms, "%s", m->desc) == -1)
790b6cee71dSXin LI return -1;
791b6cee71dSXin LI break;
792b6cee71dSXin LI
793b6cee71dSXin LI case FILE_INDIRECT:
794b6cee71dSXin LI case FILE_USE:
795b6cee71dSXin LI case FILE_NAME:
796b6cee71dSXin LI break;
7973e41d09dSXin LI case FILE_DER:
79858a0f0d0SEitan Adler if (file_printf(ms, F(ms, desc, "%s"),
79943a5ec4eSXin LI file_printable(ms, sbuf, sizeof(sbuf), ms->ms_value.s,
80048c779cdSXin LI sizeof(ms->ms_value.s))) == -1)
8013e41d09dSXin LI return -1;
8023e41d09dSXin LI break;
8032726a701SXin LI case FILE_GUID:
8042726a701SXin LI (void) file_print_guid(buf, sizeof(buf), ms->ms_value.guid);
8052726a701SXin LI if (file_printf(ms, F(ms, desc, "%s"), buf) == -1)
8062726a701SXin LI return -1;
807a4d6d3b8SXin LI break;
808a4d6d3b8SXin LI case FILE_MSDOSDATE:
809a4d6d3b8SXin LI case FILE_BEMSDOSDATE:
810a4d6d3b8SXin LI case FILE_LEMSDOSDATE:
811a4d6d3b8SXin LI if (file_printf(ms, F(ms, desc, "%s"),
812a4d6d3b8SXin LI file_fmtdate(tbuf, sizeof(tbuf), p->h)) == -1)
813a4d6d3b8SXin LI return -1;
814a4d6d3b8SXin LI break;
815a4d6d3b8SXin LI case FILE_MSDOSTIME:
816a4d6d3b8SXin LI case FILE_BEMSDOSTIME:
817a4d6d3b8SXin LI case FILE_LEMSDOSTIME:
818a4d6d3b8SXin LI if (file_printf(ms, F(ms, desc, "%s"),
819a4d6d3b8SXin LI file_fmttime(tbuf, sizeof(tbuf), p->h)) == -1)
820a4d6d3b8SXin LI return -1;
8212726a701SXin LI break;
822a2dfb722SXin LI case FILE_OCTAL:
823a2dfb722SXin LI file_fmtnum(buf, sizeof(buf), m->value.s, 8);
824a2dfb722SXin LI if (file_printf(ms, F(ms, desc, "%s"), buf) == -1)
825a2dfb722SXin LI return -1;
826a2dfb722SXin LI break;
827b6cee71dSXin LI default:
828b6cee71dSXin LI file_magerror(ms, "invalid m->type (%d) in mprint()", m->type);
829b6cee71dSXin LI return -1;
830b6cee71dSXin LI }
831a4d6d3b8SXin LI return 0;
832b6cee71dSXin LI }
833b6cee71dSXin LI
834898496eeSXin LI file_private int
moffset(struct magic_set * ms,struct magic * m,const struct buffer * b,size_t offset,int32_t * op)83558a0f0d0SEitan Adler moffset(struct magic_set *ms, struct magic *m, const struct buffer *b,
836*ae316d1dSXin LI size_t offset, int32_t *op)
837b6cee71dSXin LI {
83858a0f0d0SEitan Adler size_t nbytes = b->flen;
8393e41d09dSXin LI int32_t o;
8403e41d09dSXin LI
841b6cee71dSXin LI switch (m->type) {
842b6cee71dSXin LI case FILE_BYTE:
8433e41d09dSXin LI o = CAST(int32_t, (ms->offset + sizeof(char)));
8443e41d09dSXin LI break;
845b6cee71dSXin LI
846b6cee71dSXin LI case FILE_SHORT:
847b6cee71dSXin LI case FILE_BESHORT:
848b6cee71dSXin LI case FILE_LESHORT:
849a4d6d3b8SXin LI case FILE_MSDOSDATE:
850a4d6d3b8SXin LI case FILE_LEMSDOSDATE:
851a4d6d3b8SXin LI case FILE_BEMSDOSDATE:
852a4d6d3b8SXin LI case FILE_MSDOSTIME:
853a4d6d3b8SXin LI case FILE_LEMSDOSTIME:
854a4d6d3b8SXin LI case FILE_BEMSDOSTIME:
8553e41d09dSXin LI o = CAST(int32_t, (ms->offset + sizeof(short)));
8563e41d09dSXin LI break;
857b6cee71dSXin LI
858b6cee71dSXin LI case FILE_LONG:
859b6cee71dSXin LI case FILE_BELONG:
860b6cee71dSXin LI case FILE_LELONG:
861b6cee71dSXin LI case FILE_MELONG:
8623e41d09dSXin LI o = CAST(int32_t, (ms->offset + sizeof(int32_t)));
8633e41d09dSXin LI break;
864b6cee71dSXin LI
865b6cee71dSXin LI case FILE_QUAD:
866b6cee71dSXin LI case FILE_BEQUAD:
867b6cee71dSXin LI case FILE_LEQUAD:
8683e41d09dSXin LI o = CAST(int32_t, (ms->offset + sizeof(int64_t)));
8693e41d09dSXin LI break;
870b6cee71dSXin LI
871b6cee71dSXin LI case FILE_STRING:
872b6cee71dSXin LI case FILE_PSTRING:
873b6cee71dSXin LI case FILE_BESTRING16:
874b6cee71dSXin LI case FILE_LESTRING16:
875a2dfb722SXin LI case FILE_OCTAL:
8763e41d09dSXin LI if (m->reln == '=' || m->reln == '!') {
8773e41d09dSXin LI o = ms->offset + m->vallen;
8783e41d09dSXin LI } else {
879b6cee71dSXin LI union VALUETYPE *p = &ms->ms_value;
880b6cee71dSXin LI
881b6cee71dSXin LI if (*m->value.s == '\0')
8825f0216bdSXin LI p->s[strcspn(p->s, "\r\n")] = '\0';
8833e41d09dSXin LI o = CAST(uint32_t, (ms->offset + strlen(p->s)));
8842726a701SXin LI if (m->type == FILE_PSTRING) {
8852726a701SXin LI size_t l = file_pstring_length_size(ms, m);
8862726a701SXin LI if (l == FILE_BADSIZE)
8872726a701SXin LI return -1;
8882726a701SXin LI o += CAST(uint32_t, l);
8892726a701SXin LI }
890b6cee71dSXin LI }
8913e41d09dSXin LI break;
892b6cee71dSXin LI
893b6cee71dSXin LI case FILE_DATE:
894b6cee71dSXin LI case FILE_BEDATE:
895b6cee71dSXin LI case FILE_LEDATE:
896b6cee71dSXin LI case FILE_MEDATE:
8973e41d09dSXin LI o = CAST(int32_t, (ms->offset + sizeof(uint32_t)));
8983e41d09dSXin LI break;
899b6cee71dSXin LI
900b6cee71dSXin LI case FILE_LDATE:
901b6cee71dSXin LI case FILE_BELDATE:
902b6cee71dSXin LI case FILE_LELDATE:
903b6cee71dSXin LI case FILE_MELDATE:
9043e41d09dSXin LI o = CAST(int32_t, (ms->offset + sizeof(uint32_t)));
9053e41d09dSXin LI break;
906b6cee71dSXin LI
907b6cee71dSXin LI case FILE_QDATE:
908b6cee71dSXin LI case FILE_BEQDATE:
909b6cee71dSXin LI case FILE_LEQDATE:
9103e41d09dSXin LI o = CAST(int32_t, (ms->offset + sizeof(uint64_t)));
9113e41d09dSXin LI break;
912b6cee71dSXin LI
913b6cee71dSXin LI case FILE_QLDATE:
914b6cee71dSXin LI case FILE_BEQLDATE:
915b6cee71dSXin LI case FILE_LEQLDATE:
9163e41d09dSXin LI o = CAST(int32_t, (ms->offset + sizeof(uint64_t)));
9173e41d09dSXin LI break;
918b6cee71dSXin LI
919b6cee71dSXin LI case FILE_FLOAT:
920b6cee71dSXin LI case FILE_BEFLOAT:
921b6cee71dSXin LI case FILE_LEFLOAT:
9223e41d09dSXin LI o = CAST(int32_t, (ms->offset + sizeof(float)));
9233e41d09dSXin LI break;
924b6cee71dSXin LI
925b6cee71dSXin LI case FILE_DOUBLE:
926b6cee71dSXin LI case FILE_BEDOUBLE:
927b6cee71dSXin LI case FILE_LEDOUBLE:
9283e41d09dSXin LI o = CAST(int32_t, (ms->offset + sizeof(double)));
9293e41d09dSXin LI break;
930b6cee71dSXin LI
931b6cee71dSXin LI case FILE_REGEX:
932b6cee71dSXin LI if ((m->str_flags & REGEX_OFFSET_START) != 0)
933*ae316d1dSXin LI o = CAST(int32_t, ms->search.offset - offset);
934b6cee71dSXin LI else
9353e41d09dSXin LI o = CAST(int32_t,
936*ae316d1dSXin LI (ms->search.offset + ms->search.rm_len - offset));
9373e41d09dSXin LI break;
938b6cee71dSXin LI
939b6cee71dSXin LI case FILE_SEARCH:
940b6cee71dSXin LI if ((m->str_flags & REGEX_OFFSET_START) != 0)
941*ae316d1dSXin LI o = CAST(int32_t, ms->search.offset - offset);
942b6cee71dSXin LI else
943*ae316d1dSXin LI o = CAST(int32_t, (ms->search.offset + m->vallen - offset));
9443e41d09dSXin LI break;
945b6cee71dSXin LI
946b6cee71dSXin LI case FILE_CLEAR:
947b6cee71dSXin LI case FILE_DEFAULT:
948b6cee71dSXin LI case FILE_INDIRECT:
9492726a701SXin LI case FILE_OFFSET:
95043a5ec4eSXin LI case FILE_USE:
9513e41d09dSXin LI o = ms->offset;
9523e41d09dSXin LI break;
9533e41d09dSXin LI
9543e41d09dSXin LI case FILE_DER:
9553e41d09dSXin LI o = der_offs(ms, m, nbytes);
95648c779cdSXin LI if (o == -1 || CAST(size_t, o) > nbytes) {
95753021c7eSXin LI if ((ms->flags & MAGIC_DEBUG) != 0) {
95853021c7eSXin LI (void)fprintf(stderr,
95948c779cdSXin LI "Bad DER offset %d nbytes=%"
96048c779cdSXin LI SIZE_T_FORMAT "u", o, nbytes);
96153021c7eSXin LI }
962282e23f0SXin LI *op = 0;
96353021c7eSXin LI return 0;
9643e41d09dSXin LI }
9653e41d09dSXin LI break;
9662726a701SXin LI
9672726a701SXin LI case FILE_GUID:
9682726a701SXin LI o = CAST(int32_t, (ms->offset + 2 * sizeof(uint64_t)));
9692726a701SXin LI break;
970b6cee71dSXin LI
971b6cee71dSXin LI default:
9723e41d09dSXin LI o = 0;
9733e41d09dSXin LI break;
9743e41d09dSXin LI }
9753e41d09dSXin LI
97648c779cdSXin LI if (CAST(size_t, o) > nbytes) {
97753021c7eSXin LI #if 0
97848c779cdSXin LI file_error(ms, 0, "Offset out of range %" SIZE_T_FORMAT
97948c779cdSXin LI "u > %" SIZE_T_FORMAT "u", (size_t)o, nbytes);
98053021c7eSXin LI #endif
9813e41d09dSXin LI return -1;
9823e41d09dSXin LI }
9833e41d09dSXin LI *op = o;
98453021c7eSXin LI return 1;
985b6cee71dSXin LI }
9863e41d09dSXin LI
987898496eeSXin LI file_private uint32_t
cvt_id3(struct magic_set * ms,uint32_t v)9883e41d09dSXin LI cvt_id3(struct magic_set *ms, uint32_t v)
9893e41d09dSXin LI {
9903e41d09dSXin LI v = ((((v >> 0) & 0x7f) << 0) |
9913e41d09dSXin LI (((v >> 8) & 0x7f) << 7) |
9923e41d09dSXin LI (((v >> 16) & 0x7f) << 14) |
9933e41d09dSXin LI (((v >> 24) & 0x7f) << 21));
9943e41d09dSXin LI if ((ms->flags & MAGIC_DEBUG) != 0)
9953e41d09dSXin LI fprintf(stderr, "id3 offs=%u\n", v);
9963e41d09dSXin LI return v;
997b6cee71dSXin LI }
998b6cee71dSXin LI
999898496eeSXin LI file_private int
cvt_flip(int type,int flip)1000b6cee71dSXin LI cvt_flip(int type, int flip)
1001b6cee71dSXin LI {
1002b6cee71dSXin LI if (flip == 0)
1003b6cee71dSXin LI return type;
1004b6cee71dSXin LI switch (type) {
1005b6cee71dSXin LI case FILE_BESHORT:
1006b6cee71dSXin LI return FILE_LESHORT;
1007b6cee71dSXin LI case FILE_BELONG:
1008b6cee71dSXin LI return FILE_LELONG;
1009b6cee71dSXin LI case FILE_BEDATE:
1010b6cee71dSXin LI return FILE_LEDATE;
1011b6cee71dSXin LI case FILE_BELDATE:
1012b6cee71dSXin LI return FILE_LELDATE;
1013b6cee71dSXin LI case FILE_BEQUAD:
1014b6cee71dSXin LI return FILE_LEQUAD;
1015b6cee71dSXin LI case FILE_BEQDATE:
1016b6cee71dSXin LI return FILE_LEQDATE;
1017b6cee71dSXin LI case FILE_BEQLDATE:
1018b6cee71dSXin LI return FILE_LEQLDATE;
1019b6cee71dSXin LI case FILE_BEQWDATE:
1020b6cee71dSXin LI return FILE_LEQWDATE;
1021b6cee71dSXin LI case FILE_LESHORT:
1022b6cee71dSXin LI return FILE_BESHORT;
1023b6cee71dSXin LI case FILE_LELONG:
1024b6cee71dSXin LI return FILE_BELONG;
1025b6cee71dSXin LI case FILE_LEDATE:
1026b6cee71dSXin LI return FILE_BEDATE;
1027b6cee71dSXin LI case FILE_LELDATE:
1028b6cee71dSXin LI return FILE_BELDATE;
1029b6cee71dSXin LI case FILE_LEQUAD:
1030b6cee71dSXin LI return FILE_BEQUAD;
1031b6cee71dSXin LI case FILE_LEQDATE:
1032b6cee71dSXin LI return FILE_BEQDATE;
1033b6cee71dSXin LI case FILE_LEQLDATE:
1034b6cee71dSXin LI return FILE_BEQLDATE;
1035b6cee71dSXin LI case FILE_LEQWDATE:
1036b6cee71dSXin LI return FILE_BEQWDATE;
1037b6cee71dSXin LI case FILE_BEFLOAT:
1038b6cee71dSXin LI return FILE_LEFLOAT;
1039b6cee71dSXin LI case FILE_LEFLOAT:
1040b6cee71dSXin LI return FILE_BEFLOAT;
1041b6cee71dSXin LI case FILE_BEDOUBLE:
1042b6cee71dSXin LI return FILE_LEDOUBLE;
1043b6cee71dSXin LI case FILE_LEDOUBLE:
1044b6cee71dSXin LI return FILE_BEDOUBLE;
1045b6cee71dSXin LI default:
1046b6cee71dSXin LI return type;
1047b6cee71dSXin LI }
1048b6cee71dSXin LI }
104948c779cdSXin LI #define DO_CVT(fld, type) \
1050b6cee71dSXin LI if (m->num_mask) \
1051b6cee71dSXin LI switch (m->mask_op & FILE_OPS_MASK) { \
1052b6cee71dSXin LI case FILE_OPAND: \
105348c779cdSXin LI p->fld &= CAST(type, m->num_mask); \
1054b6cee71dSXin LI break; \
1055b6cee71dSXin LI case FILE_OPOR: \
105648c779cdSXin LI p->fld |= CAST(type, m->num_mask); \
1057b6cee71dSXin LI break; \
1058b6cee71dSXin LI case FILE_OPXOR: \
105948c779cdSXin LI p->fld ^= CAST(type, m->num_mask); \
1060b6cee71dSXin LI break; \
1061b6cee71dSXin LI case FILE_OPADD: \
106248c779cdSXin LI p->fld += CAST(type, m->num_mask); \
1063b6cee71dSXin LI break; \
1064b6cee71dSXin LI case FILE_OPMINUS: \
106548c779cdSXin LI p->fld -= CAST(type, m->num_mask); \
1066b6cee71dSXin LI break; \
1067b6cee71dSXin LI case FILE_OPMULTIPLY: \
106848c779cdSXin LI p->fld *= CAST(type, m->num_mask); \
1069b6cee71dSXin LI break; \
1070b6cee71dSXin LI case FILE_OPDIVIDE: \
107148c779cdSXin LI if (CAST(type, m->num_mask) == 0) \
10723e41d09dSXin LI return -1; \
107348c779cdSXin LI p->fld /= CAST(type, m->num_mask); \
1074b6cee71dSXin LI break; \
1075b6cee71dSXin LI case FILE_OPMODULO: \
107648c779cdSXin LI if (CAST(type, m->num_mask) == 0) \
10773e41d09dSXin LI return -1; \
107848c779cdSXin LI p->fld %= CAST(type, m->num_mask); \
1079b6cee71dSXin LI break; \
1080b6cee71dSXin LI } \
1081b6cee71dSXin LI if (m->mask_op & FILE_OPINVERSE) \
1082b6cee71dSXin LI p->fld = ~p->fld \
1083b6cee71dSXin LI
1084898496eeSXin LI file_private int
cvt_8(union VALUETYPE * p,const struct magic * m)1085b6cee71dSXin LI cvt_8(union VALUETYPE *p, const struct magic *m)
1086b6cee71dSXin LI {
108748c779cdSXin LI DO_CVT(b, uint8_t);
10883e41d09dSXin LI return 0;
1089b6cee71dSXin LI }
1090b6cee71dSXin LI
1091898496eeSXin LI file_private int
cvt_16(union VALUETYPE * p,const struct magic * m)1092b6cee71dSXin LI cvt_16(union VALUETYPE *p, const struct magic *m)
1093b6cee71dSXin LI {
109448c779cdSXin LI DO_CVT(h, uint16_t);
10953e41d09dSXin LI return 0;
1096b6cee71dSXin LI }
1097b6cee71dSXin LI
1098898496eeSXin LI file_private int
cvt_32(union VALUETYPE * p,const struct magic * m)1099b6cee71dSXin LI cvt_32(union VALUETYPE *p, const struct magic *m)
1100b6cee71dSXin LI {
110148c779cdSXin LI DO_CVT(l, uint32_t);
11023e41d09dSXin LI return 0;
1103b6cee71dSXin LI }
1104b6cee71dSXin LI
1105898496eeSXin LI file_private int
cvt_64(union VALUETYPE * p,const struct magic * m)1106b6cee71dSXin LI cvt_64(union VALUETYPE *p, const struct magic *m)
1107b6cee71dSXin LI {
110848c779cdSXin LI DO_CVT(q, uint64_t);
11093e41d09dSXin LI return 0;
1110b6cee71dSXin LI }
1111b6cee71dSXin LI
111248c779cdSXin LI #define DO_CVT2(fld, type) \
1113b6cee71dSXin LI if (m->num_mask) \
1114b6cee71dSXin LI switch (m->mask_op & FILE_OPS_MASK) { \
1115b6cee71dSXin LI case FILE_OPADD: \
111648c779cdSXin LI p->fld += CAST(type, m->num_mask); \
1117b6cee71dSXin LI break; \
1118b6cee71dSXin LI case FILE_OPMINUS: \
111948c779cdSXin LI p->fld -= CAST(type, m->num_mask); \
1120b6cee71dSXin LI break; \
1121b6cee71dSXin LI case FILE_OPMULTIPLY: \
112248c779cdSXin LI p->fld *= CAST(type, m->num_mask); \
1123b6cee71dSXin LI break; \
1124b6cee71dSXin LI case FILE_OPDIVIDE: \
112548c779cdSXin LI if (CAST(type, m->num_mask) == 0) \
11263e41d09dSXin LI return -1; \
112748c779cdSXin LI p->fld /= CAST(type, m->num_mask); \
1128b6cee71dSXin LI break; \
1129b6cee71dSXin LI } \
1130b6cee71dSXin LI
1131898496eeSXin LI file_private int
cvt_float(union VALUETYPE * p,const struct magic * m)1132b6cee71dSXin LI cvt_float(union VALUETYPE *p, const struct magic *m)
1133b6cee71dSXin LI {
113448c779cdSXin LI DO_CVT2(f, float);
11353e41d09dSXin LI return 0;
1136b6cee71dSXin LI }
1137b6cee71dSXin LI
1138898496eeSXin LI file_private int
cvt_double(union VALUETYPE * p,const struct magic * m)1139b6cee71dSXin LI cvt_double(union VALUETYPE *p, const struct magic *m)
1140b6cee71dSXin LI {
114148c779cdSXin LI DO_CVT2(d, double);
11423e41d09dSXin LI return 0;
1143b6cee71dSXin LI }
1144b6cee71dSXin LI
1145b6cee71dSXin LI /*
1146b6cee71dSXin LI * Convert the byte order of the data we are looking at
1147b6cee71dSXin LI * While we're here, let's apply the mask operation
1148b6cee71dSXin LI * (unless you have a better idea)
1149b6cee71dSXin LI */
1150898496eeSXin LI file_private int
mconvert(struct magic_set * ms,struct magic * m,int flip)1151b6cee71dSXin LI mconvert(struct magic_set *ms, struct magic *m, int flip)
1152b6cee71dSXin LI {
1153b6cee71dSXin LI union VALUETYPE *p = &ms->ms_value;
1154b6cee71dSXin LI
115540427ccaSGordon Tetlow switch (cvt_flip(m->type, flip)) {
1156b6cee71dSXin LI case FILE_BYTE:
11573e41d09dSXin LI if (cvt_8(p, m) == -1)
11583e41d09dSXin LI goto out;
1159b6cee71dSXin LI return 1;
1160b6cee71dSXin LI case FILE_SHORT:
1161a4d6d3b8SXin LI case FILE_MSDOSDATE:
1162a4d6d3b8SXin LI case FILE_LEMSDOSDATE:
1163a4d6d3b8SXin LI case FILE_BEMSDOSDATE:
1164a4d6d3b8SXin LI case FILE_MSDOSTIME:
1165a4d6d3b8SXin LI case FILE_LEMSDOSTIME:
1166a4d6d3b8SXin LI case FILE_BEMSDOSTIME:
11673e41d09dSXin LI if (cvt_16(p, m) == -1)
11683e41d09dSXin LI goto out;
1169b6cee71dSXin LI return 1;
1170b6cee71dSXin LI case FILE_LONG:
1171b6cee71dSXin LI case FILE_DATE:
1172b6cee71dSXin LI case FILE_LDATE:
11733e41d09dSXin LI if (cvt_32(p, m) == -1)
11743e41d09dSXin LI goto out;
1175b6cee71dSXin LI return 1;
1176b6cee71dSXin LI case FILE_QUAD:
1177b6cee71dSXin LI case FILE_QDATE:
1178b6cee71dSXin LI case FILE_QLDATE:
1179b6cee71dSXin LI case FILE_QWDATE:
11802726a701SXin LI case FILE_OFFSET:
11813e41d09dSXin LI if (cvt_64(p, m) == -1)
11823e41d09dSXin LI goto out;
1183b6cee71dSXin LI return 1;
1184b6cee71dSXin LI case FILE_STRING:
1185b6cee71dSXin LI case FILE_BESTRING16:
1186a2dfb722SXin LI case FILE_LESTRING16:
1187a2dfb722SXin LI case FILE_OCTAL: {
1188b6cee71dSXin LI /* Null terminate and eat *trailing* return */
1189b6cee71dSXin LI p->s[sizeof(p->s) - 1] = '\0';
1190b6cee71dSXin LI return 1;
1191b6cee71dSXin LI }
1192b6cee71dSXin LI case FILE_PSTRING: {
11932726a701SXin LI char *ptr1, *ptr2;
11942726a701SXin LI size_t len, sz = file_pstring_length_size(ms, m);
11952726a701SXin LI if (sz == FILE_BADSIZE)
11962726a701SXin LI return 0;
11972726a701SXin LI ptr1 = p->s;
11982726a701SXin LI ptr2 = ptr1 + sz;
11992726a701SXin LI len = file_pstring_get_length(ms, m, ptr1);
12002726a701SXin LI if (len == FILE_BADSIZE)
12012726a701SXin LI return 0;
1202c2931133SXin LI sz = sizeof(p->s) - sz; /* maximum length of string */
1203c2931133SXin LI if (len >= sz) {
1204b6cee71dSXin LI /*
1205b6cee71dSXin LI * The size of the pascal string length (sz)
1206b6cee71dSXin LI * is 1, 2, or 4. We need at least 1 byte for NUL
1207b6cee71dSXin LI * termination, but we've already truncated the
1208b6cee71dSXin LI * string by p->s, so we need to deduct sz.
1209c2931133SXin LI * Because we can use one of the bytes of the length
1210c2931133SXin LI * after we shifted as NUL termination.
1211b6cee71dSXin LI */
1212c2931133SXin LI len = sz;
1213b6cee71dSXin LI }
1214b6cee71dSXin LI while (len--)
1215b6cee71dSXin LI *ptr1++ = *ptr2++;
1216b6cee71dSXin LI *ptr1 = '\0';
1217b6cee71dSXin LI return 1;
1218b6cee71dSXin LI }
1219b6cee71dSXin LI case FILE_BESHORT:
1220*ae316d1dSXin LI p->h = CAST(short, BE16(p->hs));
12213e41d09dSXin LI if (cvt_16(p, m) == -1)
12223e41d09dSXin LI goto out;
1223b6cee71dSXin LI return 1;
1224b6cee71dSXin LI case FILE_BELONG:
1225b6cee71dSXin LI case FILE_BEDATE:
1226b6cee71dSXin LI case FILE_BELDATE:
1227*ae316d1dSXin LI p->l = CAST(int32_t, BE32(p->hl));
12283e41d09dSXin LI if (cvt_32(p, m) == -1)
12293e41d09dSXin LI goto out;
1230b6cee71dSXin LI return 1;
1231b6cee71dSXin LI case FILE_BEQUAD:
1232b6cee71dSXin LI case FILE_BEQDATE:
1233b6cee71dSXin LI case FILE_BEQLDATE:
1234b6cee71dSXin LI case FILE_BEQWDATE:
1235*ae316d1dSXin LI p->q = CAST(uint64_t, BE64(p->hq));
12363e41d09dSXin LI if (cvt_64(p, m) == -1)
12373e41d09dSXin LI goto out;
1238b6cee71dSXin LI return 1;
1239b6cee71dSXin LI case FILE_LESHORT:
1240*ae316d1dSXin LI p->h = CAST(short, LE16(p->hs));
12413e41d09dSXin LI if (cvt_16(p, m) == -1)
12423e41d09dSXin LI goto out;
1243b6cee71dSXin LI return 1;
1244b6cee71dSXin LI case FILE_LELONG:
1245b6cee71dSXin LI case FILE_LEDATE:
1246b6cee71dSXin LI case FILE_LELDATE:
1247*ae316d1dSXin LI p->l = CAST(int32_t, LE32(p->hl));
12483e41d09dSXin LI if (cvt_32(p, m) == -1)
12493e41d09dSXin LI goto out;
1250b6cee71dSXin LI return 1;
1251b6cee71dSXin LI case FILE_LEQUAD:
1252b6cee71dSXin LI case FILE_LEQDATE:
1253b6cee71dSXin LI case FILE_LEQLDATE:
1254b6cee71dSXin LI case FILE_LEQWDATE:
1255*ae316d1dSXin LI p->q = CAST(uint64_t, LE64(p->hq));
12563e41d09dSXin LI if (cvt_64(p, m) == -1)
12573e41d09dSXin LI goto out;
1258b6cee71dSXin LI return 1;
1259b6cee71dSXin LI case FILE_MELONG:
1260b6cee71dSXin LI case FILE_MEDATE:
1261b6cee71dSXin LI case FILE_MELDATE:
1262*ae316d1dSXin LI p->l = CAST(int32_t, ME32(p->hl));
12633e41d09dSXin LI if (cvt_32(p, m) == -1)
12643e41d09dSXin LI goto out;
1265b6cee71dSXin LI return 1;
1266b6cee71dSXin LI case FILE_FLOAT:
12673e41d09dSXin LI if (cvt_float(p, m) == -1)
12683e41d09dSXin LI goto out;
1269b6cee71dSXin LI return 1;
1270b6cee71dSXin LI case FILE_BEFLOAT:
1271*ae316d1dSXin LI p->l = BE32(p->hl);
12723e41d09dSXin LI if (cvt_float(p, m) == -1)
12733e41d09dSXin LI goto out;
1274b6cee71dSXin LI return 1;
1275b6cee71dSXin LI case FILE_LEFLOAT:
1276*ae316d1dSXin LI p->l = LE32(p->hl);
12773e41d09dSXin LI if (cvt_float(p, m) == -1)
12783e41d09dSXin LI goto out;
1279b6cee71dSXin LI return 1;
1280b6cee71dSXin LI case FILE_DOUBLE:
12813e41d09dSXin LI if (cvt_double(p, m) == -1)
12823e41d09dSXin LI goto out;
1283b6cee71dSXin LI return 1;
1284b6cee71dSXin LI case FILE_BEDOUBLE:
1285*ae316d1dSXin LI p->q = BE64(p->hq);
12863e41d09dSXin LI if (cvt_double(p, m) == -1)
12873e41d09dSXin LI goto out;
1288b6cee71dSXin LI return 1;
1289b6cee71dSXin LI case FILE_LEDOUBLE:
1290*ae316d1dSXin LI p->q = LE64(p->hq);
12913e41d09dSXin LI if (cvt_double(p, m) == -1)
12923e41d09dSXin LI goto out;
1293b6cee71dSXin LI return 1;
1294b6cee71dSXin LI case FILE_REGEX:
1295b6cee71dSXin LI case FILE_SEARCH:
1296b6cee71dSXin LI case FILE_DEFAULT:
1297b6cee71dSXin LI case FILE_CLEAR:
1298b6cee71dSXin LI case FILE_NAME:
1299b6cee71dSXin LI case FILE_USE:
13003e41d09dSXin LI case FILE_DER:
13012726a701SXin LI case FILE_GUID:
1302b6cee71dSXin LI return 1;
1303b6cee71dSXin LI default:
1304b6cee71dSXin LI file_magerror(ms, "invalid type %d in mconvert()", m->type);
1305b6cee71dSXin LI return 0;
1306b6cee71dSXin LI }
13073e41d09dSXin LI out:
13083e41d09dSXin LI file_magerror(ms, "zerodivide in mconvert()");
13093e41d09dSXin LI return 0;
1310b6cee71dSXin LI }
1311b6cee71dSXin LI
1312b6cee71dSXin LI
1313898496eeSXin LI file_private void
mdebug(uint32_t offset,const char * str,size_t len)1314b6cee71dSXin LI mdebug(uint32_t offset, const char *str, size_t len)
1315b6cee71dSXin LI {
1316c2931133SXin LI (void) fprintf(stderr, "mget/%" SIZE_T_FORMAT "u @%d: ", len, offset);
1317b6cee71dSXin LI file_showstr(stderr, str, len);
1318b6cee71dSXin LI (void) fputc('\n', stderr);
1319b6cee71dSXin LI (void) fputc('\n', stderr);
1320b6cee71dSXin LI }
1321b6cee71dSXin LI
1322898496eeSXin LI file_private int
mcopy(struct magic_set * ms,union VALUETYPE * p,int type,int indir,const unsigned char * s,uint32_t offset,size_t nbytes,struct magic * m)1323b6cee71dSXin LI mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
1324b6cee71dSXin LI const unsigned char *s, uint32_t offset, size_t nbytes, struct magic *m)
1325b6cee71dSXin LI {
1326898496eeSXin LI size_t size = sizeof(*p);
1327b6cee71dSXin LI /*
1328b6cee71dSXin LI * Note: FILE_SEARCH and FILE_REGEX do not actually copy
1329b6cee71dSXin LI * anything, but setup pointers into the source
1330b6cee71dSXin LI */
1331b6cee71dSXin LI if (indir == 0) {
1332b6cee71dSXin LI switch (type) {
13333e41d09dSXin LI case FILE_DER:
1334b6cee71dSXin LI case FILE_SEARCH:
1335282e23f0SXin LI if (offset > nbytes)
133640427ccaSGordon Tetlow offset = CAST(uint32_t, nbytes);
1337b6cee71dSXin LI ms->search.s = RCAST(const char *, s) + offset;
1338b6cee71dSXin LI ms->search.s_len = nbytes - offset;
1339b6cee71dSXin LI ms->search.offset = offset;
1340b6cee71dSXin LI return 0;
1341b6cee71dSXin LI
1342b6cee71dSXin LI case FILE_REGEX: {
1343b6cee71dSXin LI const char *b;
1344b6cee71dSXin LI const char *c;
1345b6cee71dSXin LI const char *last; /* end of search region */
1346b6cee71dSXin LI const char *buf; /* start of search region */
1347b6cee71dSXin LI const char *end;
1348b6cee71dSXin LI size_t lines, linecnt, bytecnt;
1349b6cee71dSXin LI
135040427ccaSGordon Tetlow if (s == NULL || nbytes < offset) {
1351b6cee71dSXin LI ms->search.s_len = 0;
1352b6cee71dSXin LI ms->search.s = NULL;
1353b6cee71dSXin LI return 0;
1354b6cee71dSXin LI }
1355b6cee71dSXin LI
1356b6cee71dSXin LI if (m->str_flags & REGEX_LINE_COUNT) {
1357b6cee71dSXin LI linecnt = m->str_range;
1358b6cee71dSXin LI bytecnt = linecnt * 80;
1359b6cee71dSXin LI } else {
1360b6cee71dSXin LI linecnt = 0;
1361b6cee71dSXin LI bytecnt = m->str_range;
1362b6cee71dSXin LI }
1363b6cee71dSXin LI
13645f0216bdSXin LI if (bytecnt == 0 || bytecnt > nbytes - offset)
13655f0216bdSXin LI bytecnt = nbytes - offset;
13669ce06829SXin LI if (bytecnt > ms->regex_max)
13679ce06829SXin LI bytecnt = ms->regex_max;
1368b6cee71dSXin LI
1369b6cee71dSXin LI buf = RCAST(const char *, s) + offset;
13705f0216bdSXin LI end = last = RCAST(const char *, s) + bytecnt + offset;
1371b6cee71dSXin LI /* mget() guarantees buf <= last */
1372b6cee71dSXin LI for (lines = linecnt, b = buf; lines && b < end &&
1373b6cee71dSXin LI ((b = CAST(const char *,
1374b6cee71dSXin LI memchr(c = b, '\n', CAST(size_t, (end - b)))))
1375b6cee71dSXin LI || (b = CAST(const char *,
1376b6cee71dSXin LI memchr(c, '\r', CAST(size_t, (end - c))))));
1377b6cee71dSXin LI lines--, b++) {
1378a5d223e6SXin LI if (b < end - 1 && b[0] == '\r' && b[1] == '\n')
1379b6cee71dSXin LI b++;
138048c779cdSXin LI if (b < end - 1 && b[0] == '\n')
138148c779cdSXin LI b++;
138248c779cdSXin LI last = b;
1383b6cee71dSXin LI }
1384b6cee71dSXin LI if (lines)
138558a0f0d0SEitan Adler last = end;
1386b6cee71dSXin LI
1387b6cee71dSXin LI ms->search.s = buf;
1388b6cee71dSXin LI ms->search.s_len = last - buf;
1389b6cee71dSXin LI ms->search.offset = offset;
1390b6cee71dSXin LI ms->search.rm_len = 0;
1391b6cee71dSXin LI return 0;
1392b6cee71dSXin LI }
1393b6cee71dSXin LI case FILE_BESTRING16:
1394b6cee71dSXin LI case FILE_LESTRING16: {
1395b6cee71dSXin LI const unsigned char *src = s + offset;
1396b6cee71dSXin LI const unsigned char *esrc = s + nbytes;
1397b6cee71dSXin LI char *dst = p->s;
1398b6cee71dSXin LI char *edst = &p->s[sizeof(p->s) - 1];
1399b6cee71dSXin LI
1400b6cee71dSXin LI if (type == FILE_BESTRING16)
1401b6cee71dSXin LI src++;
1402b6cee71dSXin LI
1403b6cee71dSXin LI /* check that offset is within range */
1404b6cee71dSXin LI if (offset >= nbytes)
1405b6cee71dSXin LI break;
1406b6cee71dSXin LI for (/*EMPTY*/; src < esrc; src += 2, dst++) {
1407b6cee71dSXin LI if (dst < edst)
1408b6cee71dSXin LI *dst = *src;
1409b6cee71dSXin LI else
1410b6cee71dSXin LI break;
1411b6cee71dSXin LI if (*dst == '\0') {
1412b6cee71dSXin LI if (type == FILE_BESTRING16 ?
1413b6cee71dSXin LI *(src - 1) != '\0' :
141440427ccaSGordon Tetlow ((src + 1 < esrc) &&
141540427ccaSGordon Tetlow *(src + 1) != '\0'))
1416b6cee71dSXin LI *dst = ' ';
1417b6cee71dSXin LI }
1418b6cee71dSXin LI }
1419b6cee71dSXin LI *edst = '\0';
1420*ae316d1dSXin LI *dst = '\0';
1421b6cee71dSXin LI return 0;
1422b6cee71dSXin LI }
1423b6cee71dSXin LI case FILE_STRING: /* XXX - these two should not need */
1424b6cee71dSXin LI case FILE_PSTRING: /* to copy anything, but do anyway. */
1425898496eeSXin LI if (m->str_range != 0 && m->str_range < sizeof(*p))
1426898496eeSXin LI size = m->str_range;
1427898496eeSXin LI break;
1428b6cee71dSXin LI default:
1429b6cee71dSXin LI break;
1430b6cee71dSXin LI }
1431b6cee71dSXin LI }
1432b6cee71dSXin LI
14332726a701SXin LI if (type == FILE_OFFSET) {
14342726a701SXin LI (void)memset(p, '\0', sizeof(*p));
14352726a701SXin LI p->q = offset;
14362726a701SXin LI return 0;
14372726a701SXin LI }
14382726a701SXin LI
1439b6cee71dSXin LI if (offset >= nbytes) {
1440b6cee71dSXin LI (void)memset(p, '\0', sizeof(*p));
1441b6cee71dSXin LI return 0;
1442b6cee71dSXin LI }
1443898496eeSXin LI if (nbytes - offset < size)
1444b6cee71dSXin LI nbytes = nbytes - offset;
1445b6cee71dSXin LI else
1446898496eeSXin LI nbytes = size;
1447b6cee71dSXin LI
1448b6cee71dSXin LI (void)memcpy(p, s + offset, nbytes);
1449b6cee71dSXin LI
1450b6cee71dSXin LI /*
1451b6cee71dSXin LI * the usefulness of padding with zeroes eludes me, it
1452b6cee71dSXin LI * might even cause problems
1453b6cee71dSXin LI */
1454b6cee71dSXin LI if (nbytes < sizeof(*p))
145548c779cdSXin LI (void)memset(RCAST(char *, RCAST(void *, p)) + nbytes, '\0',
1456b6cee71dSXin LI sizeof(*p) - nbytes);
1457b6cee71dSXin LI return 0;
1458b6cee71dSXin LI }
1459b6cee71dSXin LI
1460898496eeSXin LI file_private int
do_ops(struct magic_set * ms,struct magic * m,uint32_t * rv,intmax_t lhs,intmax_t off)1461898496eeSXin LI do_ops(struct magic_set *ms, struct magic *m, uint32_t *rv, intmax_t lhs,
1462898496eeSXin LI intmax_t off)
1463a5d223e6SXin LI {
1464a5d223e6SXin LI intmax_t offset;
1465898496eeSXin LI // On purpose not INTMAX_MAX
1466898496eeSXin LI if (lhs >= UINT_MAX || lhs <= INT_MIN ||
1467898496eeSXin LI off >= UINT_MAX || off <= INT_MIN) {
1468898496eeSXin LI if ((ms->flags & MAGIC_DEBUG) != 0)
1469898496eeSXin LI fprintf(stderr, "lhs/off overflow %jd %jd\n", lhs, off);
1470898496eeSXin LI return 1;
1471898496eeSXin LI }
1472898496eeSXin LI
1473a5d223e6SXin LI if (off) {
1474a5d223e6SXin LI switch (m->in_op & FILE_OPS_MASK) {
1475a5d223e6SXin LI case FILE_OPAND:
1476a5d223e6SXin LI offset = lhs & off;
1477a5d223e6SXin LI break;
1478a5d223e6SXin LI case FILE_OPOR:
1479a5d223e6SXin LI offset = lhs | off;
1480a5d223e6SXin LI break;
1481a5d223e6SXin LI case FILE_OPXOR:
1482a5d223e6SXin LI offset = lhs ^ off;
1483a5d223e6SXin LI break;
1484a5d223e6SXin LI case FILE_OPADD:
1485a5d223e6SXin LI offset = lhs + off;
1486a5d223e6SXin LI break;
1487a5d223e6SXin LI case FILE_OPMINUS:
1488a5d223e6SXin LI offset = lhs - off;
1489a5d223e6SXin LI break;
1490a5d223e6SXin LI case FILE_OPMULTIPLY:
1491a5d223e6SXin LI offset = lhs * off;
1492a5d223e6SXin LI break;
1493a5d223e6SXin LI case FILE_OPDIVIDE:
1494a5d223e6SXin LI offset = lhs / off;
1495a5d223e6SXin LI break;
1496a5d223e6SXin LI case FILE_OPMODULO:
1497a5d223e6SXin LI offset = lhs % off;
1498a5d223e6SXin LI break;
1499a5d223e6SXin LI }
1500a5d223e6SXin LI } else
1501a5d223e6SXin LI offset = lhs;
1502a5d223e6SXin LI if (m->in_op & FILE_OPINVERSE)
1503a5d223e6SXin LI offset = ~offset;
1504898496eeSXin LI if (offset >= UINT_MAX) {
1505898496eeSXin LI if ((ms->flags & MAGIC_DEBUG) != 0)
1506898496eeSXin LI fprintf(stderr, "offset overflow %jd\n", offset);
1507898496eeSXin LI return 1;
1508898496eeSXin LI }
1509898496eeSXin LI *rv = CAST(uint32_t, offset);
1510898496eeSXin LI return 0;
1511a5d223e6SXin LI }
1512a5d223e6SXin LI
1513898496eeSXin LI file_private int
msetoffset(struct magic_set * ms,struct magic * m,struct buffer * bb,const struct buffer * b,size_t o,unsigned int cont_level)151458a0f0d0SEitan Adler msetoffset(struct magic_set *ms, struct magic *m, struct buffer *bb,
151558a0f0d0SEitan Adler const struct buffer *b, size_t o, unsigned int cont_level)
151658a0f0d0SEitan Adler {
15172726a701SXin LI int32_t offset;
15182726a701SXin LI if (m->flag & OFFNEGATIVE) {
15192726a701SXin LI offset = -m->offset;
152058a0f0d0SEitan Adler if (cont_level > 0) {
152158a0f0d0SEitan Adler if (m->flag & (OFFADD|INDIROFFADD))
152258a0f0d0SEitan Adler goto normal;
152358a0f0d0SEitan Adler #if 0
152458a0f0d0SEitan Adler file_error(ms, 0, "negative offset %d at continuation"
152558a0f0d0SEitan Adler "level %u", m->offset, cont_level);
152658a0f0d0SEitan Adler return -1;
152758a0f0d0SEitan Adler #endif
152858a0f0d0SEitan Adler }
152958a0f0d0SEitan Adler if (buffer_fill(b) == -1)
153058a0f0d0SEitan Adler return -1;
153158a0f0d0SEitan Adler if (o != 0) {
153258a0f0d0SEitan Adler // Not yet!
153348c779cdSXin LI file_magerror(ms, "non zero offset %" SIZE_T_FORMAT
153448c779cdSXin LI "u at level %u", o, cont_level);
153558a0f0d0SEitan Adler return -1;
153658a0f0d0SEitan Adler }
15372726a701SXin LI if (CAST(size_t, m->offset) > b->elen)
153858a0f0d0SEitan Adler return -1;
153948c779cdSXin LI buffer_init(bb, -1, NULL, b->ebuf, b->elen);
15402726a701SXin LI ms->eoffset = ms->offset = CAST(int32_t, b->elen - m->offset);
154158a0f0d0SEitan Adler } else {
15422726a701SXin LI offset = m->offset;
1543*ae316d1dSXin LI if ((m->flag & OFFPOSITIVE) || cont_level == 0) {
154458a0f0d0SEitan Adler normal:
154558a0f0d0SEitan Adler // XXX: Pass real fd, then who frees bb?
154648c779cdSXin LI buffer_init(bb, -1, NULL, b->fbuf, b->flen);
15472726a701SXin LI ms->offset = offset;
154858a0f0d0SEitan Adler ms->eoffset = 0;
154958a0f0d0SEitan Adler } else {
15502726a701SXin LI ms->offset = ms->eoffset + offset;
155158a0f0d0SEitan Adler }
155258a0f0d0SEitan Adler }
155358a0f0d0SEitan Adler if ((ms->flags & MAGIC_DEBUG) != 0) {
15542726a701SXin LI fprintf(stderr, "bb=[%p,%" SIZE_T_FORMAT "u,%"
15552726a701SXin LI SIZE_T_FORMAT "u], %d [b=%p,%"
15562726a701SXin LI SIZE_T_FORMAT "u,%" SIZE_T_FORMAT "u], [o=%#x, c=%d]\n",
15572726a701SXin LI bb->fbuf, bb->flen, bb->elen, ms->offset, b->fbuf,
15582726a701SXin LI b->flen, b->elen, offset, cont_level);
155958a0f0d0SEitan Adler }
156058a0f0d0SEitan Adler return 0;
156158a0f0d0SEitan Adler }
156258a0f0d0SEitan Adler
1563898496eeSXin LI file_private int
save_cont(struct magic_set * ms,struct cont * c)156443a5ec4eSXin LI save_cont(struct magic_set *ms, struct cont *c)
156543a5ec4eSXin LI {
156643a5ec4eSXin LI size_t len;
156743a5ec4eSXin LI *c = ms->c;
156843a5ec4eSXin LI len = c->len * sizeof(*c->li);
156943a5ec4eSXin LI ms->c.li = CAST(struct level_info *, malloc(len));
157043a5ec4eSXin LI if (ms->c.li == NULL) {
157143a5ec4eSXin LI ms->c = *c;
157243a5ec4eSXin LI return -1;
157343a5ec4eSXin LI }
157443a5ec4eSXin LI memcpy(ms->c.li, c->li, len);
157543a5ec4eSXin LI return 0;
157643a5ec4eSXin LI }
157743a5ec4eSXin LI
1578898496eeSXin LI file_private void
restore_cont(struct magic_set * ms,struct cont * c)157943a5ec4eSXin LI restore_cont(struct magic_set *ms, struct cont *c)
158043a5ec4eSXin LI {
158143a5ec4eSXin LI free(ms->c.li);
158243a5ec4eSXin LI ms->c = *c;
158343a5ec4eSXin LI }
158443a5ec4eSXin LI
1585898496eeSXin LI file_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 * firstline,int * returnval,int * found_match)158658a0f0d0SEitan Adler mget(struct magic_set *ms, struct magic *m, const struct buffer *b,
158758a0f0d0SEitan Adler const unsigned char *s, size_t nbytes, size_t o, unsigned int cont_level,
158858a0f0d0SEitan Adler int mode, int text, int flip, uint16_t *indir_count, uint16_t *name_count,
1589898496eeSXin LI int *printed_something, int *need_separator, int *firstline, int *returnval,
159048c779cdSXin LI int *found_match)
1591b6cee71dSXin LI {
159243a5ec4eSXin LI uint32_t eoffset, offset = ms->offset;
159358a0f0d0SEitan Adler struct buffer bb;
1594a5d223e6SXin LI intmax_t lhs;
15952c4f1647SXin LI file_pushbuf_t *pb;
159643a5ec4eSXin LI int rv, oneed_separator, in_type, nfound_match;
15972c4f1647SXin LI char *rbuf;
1598b6cee71dSXin LI union VALUETYPE *p = &ms->ms_value;
159943a5ec4eSXin LI struct mlist ml, *mlp;
160043a5ec4eSXin LI struct cont c;
1601b6cee71dSXin LI
16023e41d09dSXin LI if (*indir_count >= ms->indir_max) {
16033e41d09dSXin LI file_error(ms, 0, "indirect count (%hu) exceeded",
16043e41d09dSXin LI *indir_count);
1605c2931133SXin LI return -1;
1606c2931133SXin LI }
1607c2931133SXin LI
1608c2931133SXin LI if (*name_count >= ms->name_max) {
1609c2931133SXin LI file_error(ms, 0, "name use count (%hu) exceeded",
1610c2931133SXin LI *name_count);
1611b6cee71dSXin LI return -1;
1612b6cee71dSXin LI }
1613b6cee71dSXin LI
161458a0f0d0SEitan Adler
161548c779cdSXin LI if (mcopy(ms, p, m->type, m->flag & INDIR, s,
161648c779cdSXin LI CAST(uint32_t, offset + o), CAST(uint32_t, nbytes), m) == -1)
1617b6cee71dSXin LI return -1;
1618b6cee71dSXin LI
1619b6cee71dSXin LI if ((ms->flags & MAGIC_DEBUG) != 0) {
162040427ccaSGordon Tetlow fprintf(stderr, "mget(type=%d, flag=%#x, offset=%u, o=%"
1621c2931133SXin LI SIZE_T_FORMAT "u, " "nbytes=%" SIZE_T_FORMAT
1622c2931133SXin LI "u, il=%hu, nc=%hu)\n",
1623c2931133SXin LI m->type, m->flag, offset, o, nbytes,
16243e41d09dSXin LI *indir_count, *name_count);
162548c779cdSXin LI mdebug(offset, RCAST(char *, RCAST(void *, p)),
162648c779cdSXin LI sizeof(union VALUETYPE));
1627b6cee71dSXin LI #ifndef COMPILE_ONLY
1628b6cee71dSXin LI file_mdump(m);
1629b6cee71dSXin LI #endif
1630b6cee71dSXin LI }
1631b6cee71dSXin LI
1632b6cee71dSXin LI if (m->flag & INDIR) {
1633a5d223e6SXin LI intmax_t off = m->in_offset;
1634a5d223e6SXin LI const int sgn = m->in_op & FILE_OPSIGNED;
1635b6cee71dSXin LI if (m->in_op & FILE_OPINDIRECT) {
1636*ae316d1dSXin LI
1637*ae316d1dSXin LI uint8_t *hb = CCAST(uint8_t *, s + offset + off);
1638*ae316d1dSXin LI uint16_t hs;
1639*ae316d1dSXin LI uint32_t hl;
16402726a701SXin LI int op;
16412726a701SXin LI switch (op = cvt_flip(m->in_type, flip)) {
1642b6cee71dSXin LI case FILE_BYTE:
164348c779cdSXin LI if (OFFSET_OOB(nbytes, offset + off, 1))
164448c779cdSXin LI return 0;
1645*ae316d1dSXin LI off = SEXT(sgn,8,hb[0]);
1646b6cee71dSXin LI break;
1647b6cee71dSXin LI case FILE_SHORT:
164848c779cdSXin LI if (OFFSET_OOB(nbytes, offset + off, 2))
164948c779cdSXin LI return 0;
1650*ae316d1dSXin LI memcpy(&hs, hb, sizeof(hs));
1651*ae316d1dSXin LI off = SEXT(sgn,16,hs);
1652b6cee71dSXin LI break;
1653b6cee71dSXin LI case FILE_BESHORT:
165448c779cdSXin LI if (OFFSET_OOB(nbytes, offset + off, 2))
165548c779cdSXin LI return 0;
1656*ae316d1dSXin LI off = SEXT(sgn,16,BE16(hb));
1657b6cee71dSXin LI break;
1658b6cee71dSXin LI case FILE_LESHORT:
165948c779cdSXin LI if (OFFSET_OOB(nbytes, offset + off, 2))
166048c779cdSXin LI return 0;
1661*ae316d1dSXin LI off = SEXT(sgn,16,LE16(hb));
1662b6cee71dSXin LI break;
1663b6cee71dSXin LI case FILE_LONG:
166448c779cdSXin LI if (OFFSET_OOB(nbytes, offset + off, 4))
166548c779cdSXin LI return 0;
1666*ae316d1dSXin LI memcpy(&hl, hb, sizeof(hl));
1667*ae316d1dSXin LI off = SEXT(sgn,32,hl);
1668b6cee71dSXin LI break;
1669b6cee71dSXin LI case FILE_BELONG:
1670b6cee71dSXin LI case FILE_BEID3:
167148c779cdSXin LI if (OFFSET_OOB(nbytes, offset + off, 4))
167248c779cdSXin LI return 0;
1673*ae316d1dSXin LI off = SEXT(sgn,32,BE32(hb));
1674b6cee71dSXin LI break;
1675b6cee71dSXin LI case FILE_LEID3:
1676b6cee71dSXin LI case FILE_LELONG:
167748c779cdSXin LI if (OFFSET_OOB(nbytes, offset + off, 4))
167848c779cdSXin LI return 0;
1679*ae316d1dSXin LI off = SEXT(sgn,32,LE32(hb));
1680b6cee71dSXin LI break;
1681b6cee71dSXin LI case FILE_MELONG:
168248c779cdSXin LI if (OFFSET_OOB(nbytes, offset + off, 4))
168348c779cdSXin LI return 0;
1684*ae316d1dSXin LI off = SEXT(sgn,32,ME32(hb));
1685b6cee71dSXin LI break;
16862dc4dbb9SEitan Adler case FILE_BEQUAD:
168748c779cdSXin LI if (OFFSET_OOB(nbytes, offset + off, 8))
168848c779cdSXin LI return 0;
1689*ae316d1dSXin LI off = SEXT(sgn,64,BE64(hb));
16902dc4dbb9SEitan Adler break;
16912dc4dbb9SEitan Adler case FILE_LEQUAD:
169248c779cdSXin LI if (OFFSET_OOB(nbytes, offset + off, 8))
169348c779cdSXin LI return 0;
1694*ae316d1dSXin LI off = SEXT(sgn,64,LE64(hb));
16952dc4dbb9SEitan Adler break;
1696a2dfb722SXin LI case FILE_OCTAL:
1697a2dfb722SXin LI if (OFFSET_OOB(nbytes, offset, m->vallen))
1698a2dfb722SXin LI return 0;
1699a2dfb722SXin LI off = SEXT(sgn,64,strtoull(p->s, NULL, 8));
1700a2dfb722SXin LI break;
17012dc4dbb9SEitan Adler default:
17022726a701SXin LI if ((ms->flags & MAGIC_DEBUG) != 0)
17032726a701SXin LI fprintf(stderr, "bad op=%d\n", op);
17042726a701SXin LI return 0;
1705b6cee71dSXin LI }
1706b6cee71dSXin LI if ((ms->flags & MAGIC_DEBUG) != 0)
1707a5d223e6SXin LI fprintf(stderr, "indirect offs=%jd\n", off);
1708b6cee71dSXin LI }
1709b6cee71dSXin LI switch (in_type = cvt_flip(m->in_type, flip)) {
1710b6cee71dSXin LI case FILE_BYTE:
1711b6cee71dSXin LI if (OFFSET_OOB(nbytes, offset, 1))
1712b6cee71dSXin LI return 0;
1713898496eeSXin LI if (do_ops(ms, m, &offset, SEXT(sgn,8,p->b), off))
1714898496eeSXin LI return 0;
1715b6cee71dSXin LI break;
1716b6cee71dSXin LI case FILE_BESHORT:
1717b6cee71dSXin LI if (OFFSET_OOB(nbytes, offset, 2))
1718b6cee71dSXin LI return 0;
1719*ae316d1dSXin LI if (do_ops(ms, m, &offset, SEXT(sgn,16,BE16(p->hs)), off))
1720898496eeSXin LI return 0;
1721b6cee71dSXin LI break;
1722b6cee71dSXin LI case FILE_LESHORT:
1723b6cee71dSXin LI if (OFFSET_OOB(nbytes, offset, 2))
1724b6cee71dSXin LI return 0;
1725*ae316d1dSXin LI if (do_ops(ms, m, &offset, SEXT(sgn,16,LE16(p->hs)), off))
1726898496eeSXin LI return 0;
1727b6cee71dSXin LI break;
1728b6cee71dSXin LI case FILE_SHORT:
1729b6cee71dSXin LI if (OFFSET_OOB(nbytes, offset, 2))
1730b6cee71dSXin LI return 0;
1731898496eeSXin LI if (do_ops(ms, m, &offset, SEXT(sgn,16,p->h), off))
1732898496eeSXin LI return 0;
1733b6cee71dSXin LI break;
1734b6cee71dSXin LI case FILE_BELONG:
1735b6cee71dSXin LI case FILE_BEID3:
1736b6cee71dSXin LI if (OFFSET_OOB(nbytes, offset, 4))
1737b6cee71dSXin LI return 0;
1738*ae316d1dSXin LI lhs = BE32(p->hl);
17393e41d09dSXin LI if (in_type == FILE_BEID3)
174048c779cdSXin LI lhs = cvt_id3(ms, CAST(uint32_t, lhs));
1741898496eeSXin LI if (do_ops(ms, m, &offset, SEXT(sgn,32,lhs), off))
1742898496eeSXin LI return 0;
1743b6cee71dSXin LI break;
1744b6cee71dSXin LI case FILE_LELONG:
1745b6cee71dSXin LI case FILE_LEID3:
1746b6cee71dSXin LI if (OFFSET_OOB(nbytes, offset, 4))
1747b6cee71dSXin LI return 0;
1748*ae316d1dSXin LI lhs = LE32(p->hl);
17493e41d09dSXin LI if (in_type == FILE_LEID3)
175048c779cdSXin LI lhs = cvt_id3(ms, CAST(uint32_t, lhs));
1751898496eeSXin LI if (do_ops(ms, m, &offset, SEXT(sgn,32,lhs), off))
1752898496eeSXin LI return 0;
1753b6cee71dSXin LI break;
1754b6cee71dSXin LI case FILE_MELONG:
1755b6cee71dSXin LI if (OFFSET_OOB(nbytes, offset, 4))
1756b6cee71dSXin LI return 0;
1757*ae316d1dSXin LI if (do_ops(ms, m, &offset, SEXT(sgn,32,ME32(p->hl)), off))
1758898496eeSXin LI return 0;
1759b6cee71dSXin LI break;
1760b6cee71dSXin LI case FILE_LONG:
1761b6cee71dSXin LI if (OFFSET_OOB(nbytes, offset, 4))
1762b6cee71dSXin LI return 0;
1763898496eeSXin LI if (do_ops(ms, m, &offset, SEXT(sgn,32,p->l), off))
1764898496eeSXin LI return 0;
1765b6cee71dSXin LI break;
17662dc4dbb9SEitan Adler case FILE_LEQUAD:
17672dc4dbb9SEitan Adler if (OFFSET_OOB(nbytes, offset, 8))
17682dc4dbb9SEitan Adler return 0;
1769*ae316d1dSXin LI if (do_ops(ms, m, &offset, SEXT(sgn,64,LE64(p->hq)), off))
1770898496eeSXin LI return 0;
1771b6cee71dSXin LI break;
17722dc4dbb9SEitan Adler case FILE_BEQUAD:
17732dc4dbb9SEitan Adler if (OFFSET_OOB(nbytes, offset, 8))
17742dc4dbb9SEitan Adler return 0;
1775*ae316d1dSXin LI if (do_ops(ms, m, &offset, SEXT(sgn,64,BE64(p->hq)), off))
1776898496eeSXin LI return 0;
17772dc4dbb9SEitan Adler break;
1778a2dfb722SXin LI case FILE_OCTAL:
1779a2dfb722SXin LI if (OFFSET_OOB(nbytes, offset, m->vallen))
1780a2dfb722SXin LI return 0;
1781898496eeSXin LI if(do_ops(ms, m, &offset,
1782898496eeSXin LI SEXT(sgn,64,strtoull(p->s, NULL, 8)), off))
1783898496eeSXin LI return 0;
1784a2dfb722SXin LI break;
17852dc4dbb9SEitan Adler default:
17862726a701SXin LI if ((ms->flags & MAGIC_DEBUG) != 0)
17872726a701SXin LI fprintf(stderr, "bad in_type=%d\n", in_type);
17882726a701SXin LI return 0;
1789b6cee71dSXin LI }
1790b6cee71dSXin LI
1791b6cee71dSXin LI if (m->flag & INDIROFFADD) {
17922726a701SXin LI if (cont_level == 0) {
17932726a701SXin LI if ((ms->flags & MAGIC_DEBUG) != 0)
17942726a701SXin LI fprintf(stderr,
17952726a701SXin LI "indirect *zero* cont_level\n");
17962726a701SXin LI return 0;
17972726a701SXin LI }
1798b6cee71dSXin LI offset += ms->c.li[cont_level - 1].off;
1799b6cee71dSXin LI if (offset == 0) {
1800b6cee71dSXin LI if ((ms->flags & MAGIC_DEBUG) != 0)
1801b6cee71dSXin LI fprintf(stderr,
1802b6cee71dSXin LI "indirect *zero* offset\n");
1803b6cee71dSXin LI return 0;
1804b6cee71dSXin LI }
1805b6cee71dSXin LI if ((ms->flags & MAGIC_DEBUG) != 0)
1806b6cee71dSXin LI fprintf(stderr, "indirect +offs=%u\n", offset);
1807b6cee71dSXin LI }
1808b6cee71dSXin LI if (mcopy(ms, p, m->type, 0, s, offset, nbytes, m) == -1)
1809b6cee71dSXin LI return -1;
1810b6cee71dSXin LI ms->offset = offset;
1811b6cee71dSXin LI
1812b6cee71dSXin LI if ((ms->flags & MAGIC_DEBUG) != 0) {
181348c779cdSXin LI mdebug(offset, RCAST(char *, RCAST(void *, p)),
1814b6cee71dSXin LI sizeof(union VALUETYPE));
1815b6cee71dSXin LI #ifndef COMPILE_ONLY
1816b6cee71dSXin LI file_mdump(m);
1817b6cee71dSXin LI #endif
1818b6cee71dSXin LI }
1819b6cee71dSXin LI }
1820b6cee71dSXin LI
1821b6cee71dSXin LI /* Verify we have enough data to match magic type */
1822b6cee71dSXin LI switch (m->type) {
1823b6cee71dSXin LI case FILE_BYTE:
1824b6cee71dSXin LI if (OFFSET_OOB(nbytes, offset, 1))
1825b6cee71dSXin LI return 0;
1826b6cee71dSXin LI break;
1827b6cee71dSXin LI
1828b6cee71dSXin LI case FILE_SHORT:
1829b6cee71dSXin LI case FILE_BESHORT:
1830b6cee71dSXin LI case FILE_LESHORT:
1831b6cee71dSXin LI if (OFFSET_OOB(nbytes, offset, 2))
1832b6cee71dSXin LI return 0;
1833b6cee71dSXin LI break;
1834b6cee71dSXin LI
1835b6cee71dSXin LI case FILE_LONG:
1836b6cee71dSXin LI case FILE_BELONG:
1837b6cee71dSXin LI case FILE_LELONG:
1838b6cee71dSXin LI case FILE_MELONG:
1839b6cee71dSXin LI case FILE_DATE:
1840b6cee71dSXin LI case FILE_BEDATE:
1841b6cee71dSXin LI case FILE_LEDATE:
1842b6cee71dSXin LI case FILE_MEDATE:
1843b6cee71dSXin LI case FILE_LDATE:
1844b6cee71dSXin LI case FILE_BELDATE:
1845b6cee71dSXin LI case FILE_LELDATE:
1846b6cee71dSXin LI case FILE_MELDATE:
1847b6cee71dSXin LI case FILE_FLOAT:
1848b6cee71dSXin LI case FILE_BEFLOAT:
1849b6cee71dSXin LI case FILE_LEFLOAT:
1850b6cee71dSXin LI if (OFFSET_OOB(nbytes, offset, 4))
1851b6cee71dSXin LI return 0;
1852b6cee71dSXin LI break;
1853b6cee71dSXin LI
1854b6cee71dSXin LI case FILE_DOUBLE:
1855b6cee71dSXin LI case FILE_BEDOUBLE:
1856b6cee71dSXin LI case FILE_LEDOUBLE:
1857b6cee71dSXin LI if (OFFSET_OOB(nbytes, offset, 8))
1858b6cee71dSXin LI return 0;
1859b6cee71dSXin LI break;
1860b6cee71dSXin LI
18612726a701SXin LI case FILE_GUID:
18622726a701SXin LI if (OFFSET_OOB(nbytes, offset, 16))
18632726a701SXin LI return 0;
18642726a701SXin LI break;
18652726a701SXin LI
1866b6cee71dSXin LI case FILE_STRING:
1867b6cee71dSXin LI case FILE_PSTRING:
1868b6cee71dSXin LI case FILE_SEARCH:
1869a2dfb722SXin LI case FILE_OCTAL:
1870b6cee71dSXin LI if (OFFSET_OOB(nbytes, offset, m->vallen))
1871b6cee71dSXin LI return 0;
1872b6cee71dSXin LI break;
1873b6cee71dSXin LI
1874b6cee71dSXin LI case FILE_REGEX:
1875b6cee71dSXin LI if (nbytes < offset)
1876b6cee71dSXin LI return 0;
1877b6cee71dSXin LI break;
1878b6cee71dSXin LI
1879b6cee71dSXin LI case FILE_INDIRECT:
18804460e5b0SXin LI if (m->str_flags & INDIRECT_RELATIVE)
18815f0216bdSXin LI offset += CAST(uint32_t, o);
1882b6cee71dSXin LI if (offset == 0)
1883b6cee71dSXin LI return 0;
18842c4f1647SXin LI
1885b6cee71dSXin LI if (nbytes < offset)
1886b6cee71dSXin LI return 0;
18872c4f1647SXin LI
18882c4f1647SXin LI if ((pb = file_push_buffer(ms)) == NULL)
18892c4f1647SXin LI return -1;
18902c4f1647SXin LI
18913e41d09dSXin LI (*indir_count)++;
189258a0f0d0SEitan Adler bb = *b;
189358a0f0d0SEitan Adler bb.fbuf = s + offset;
189458a0f0d0SEitan Adler bb.flen = nbytes - offset;
1895898496eeSXin LI bb.ebuf = NULL;
1896898496eeSXin LI bb.elen = 0;
1897a4d6d3b8SXin LI rv = -1;
189843a5ec4eSXin LI for (mlp = ms->mlist[0]->next; mlp != ms->mlist[0];
189943a5ec4eSXin LI mlp = mlp->next)
190043a5ec4eSXin LI {
1901a4d6d3b8SXin LI if ((rv = match(ms, mlp->magic, mlp->magic_rxcomp,
1902a4d6d3b8SXin LI mlp->nmagic, &bb, 0, BINTEST, text, 0, indir_count,
1903a2dfb722SXin LI name_count, printed_something, need_separator,
1904898496eeSXin LI firstline, NULL, NULL)) != 0)
190543a5ec4eSXin LI break;
190643a5ec4eSXin LI }
1907898496eeSXin LI buffer_fini(&bb);
19082c4f1647SXin LI
1909b6cee71dSXin LI if ((ms->flags & MAGIC_DEBUG) != 0)
1910b6cee71dSXin LI fprintf(stderr, "indirect @offs=%u[%d]\n", offset, rv);
19112c4f1647SXin LI
19122c4f1647SXin LI rbuf = file_pop_buffer(ms, pb);
19132c4f1647SXin LI if (rbuf == NULL && ms->event_flags & EVENT_HAD_ERR)
19142c4f1647SXin LI return -1;
19152c4f1647SXin LI
1916b6cee71dSXin LI if (rv == 1) {
19175f0216bdSXin LI if ((ms->flags & MAGIC_NODESC) == 0 &&
191848c779cdSXin LI file_printf(ms, F(ms, m->desc, "%u"), offset) == -1)
191948c779cdSXin LI {
1920b6cee71dSXin LI free(rbuf);
1921b6cee71dSXin LI return -1;
1922b6cee71dSXin LI }
1923b6cee71dSXin LI if (file_printf(ms, "%s", rbuf) == -1) {
1924b6cee71dSXin LI free(rbuf);
1925b6cee71dSXin LI return -1;
1926b6cee71dSXin LI }
1927b6cee71dSXin LI }
1928b6cee71dSXin LI free(rbuf);
1929b6cee71dSXin LI return rv;
1930b6cee71dSXin LI
1931b6cee71dSXin LI case FILE_USE:
1932b6cee71dSXin LI if (nbytes < offset)
1933b6cee71dSXin LI return 0;
19342c4f1647SXin LI rbuf = m->value.s;
19352c4f1647SXin LI if (*rbuf == '^') {
19362c4f1647SXin LI rbuf++;
1937b6cee71dSXin LI flip = !flip;
1938b6cee71dSXin LI }
19392c4f1647SXin LI if (file_magicfind(ms, rbuf, &ml) == -1) {
19402c4f1647SXin LI file_error(ms, 0, "cannot find entry `%s'", rbuf);
1941b6cee71dSXin LI return -1;
1942b6cee71dSXin LI }
194343a5ec4eSXin LI if (save_cont(ms, &c) == -1) {
194443a5ec4eSXin LI file_error(ms, errno, "can't allocate continuation");
194543a5ec4eSXin LI return -1;
194643a5ec4eSXin LI }
194743a5ec4eSXin LI
1948b6cee71dSXin LI oneed_separator = *need_separator;
1949b6cee71dSXin LI if (m->flag & NOSPACE)
1950b6cee71dSXin LI *need_separator = 0;
195143a5ec4eSXin LI
195243a5ec4eSXin LI nfound_match = 0;
195343a5ec4eSXin LI (*name_count)++;
195443a5ec4eSXin LI eoffset = ms->eoffset;
1955a4d6d3b8SXin LI rv = match(ms, ml.magic, ml.magic_rxcomp, ml.nmagic, b,
1956a4d6d3b8SXin LI offset + o, mode, text, flip, indir_count, name_count,
1957898496eeSXin LI printed_something, need_separator, firstline, returnval,
195843a5ec4eSXin LI &nfound_match);
195943a5ec4eSXin LI ms->ms_value.q = nfound_match;
196048c779cdSXin LI (*name_count)--;
196143a5ec4eSXin LI *found_match |= nfound_match;
196243a5ec4eSXin LI
196343a5ec4eSXin LI restore_cont(ms, &c);
196443a5ec4eSXin LI
1965b6cee71dSXin LI if (rv != 1)
1966b6cee71dSXin LI *need_separator = oneed_separator;
196743a5ec4eSXin LI ms->offset = offset;
196843a5ec4eSXin LI ms->eoffset = eoffset;
1969898496eeSXin LI return rv || *found_match;
1970b6cee71dSXin LI
1971b6cee71dSXin LI case FILE_NAME:
19725f0216bdSXin LI if (ms->flags & MAGIC_NODESC)
19735f0216bdSXin LI return 1;
1974b6cee71dSXin LI if (file_printf(ms, "%s", m->desc) == -1)
1975b6cee71dSXin LI return -1;
1976b6cee71dSXin LI return 1;
19773e41d09dSXin LI case FILE_DER:
1978b6cee71dSXin LI case FILE_DEFAULT: /* nothing to check */
1979b6cee71dSXin LI case FILE_CLEAR:
1980b6cee71dSXin LI default:
1981b6cee71dSXin LI break;
1982b6cee71dSXin LI }
1983b6cee71dSXin LI if (!mconvert(ms, m, flip))
1984b6cee71dSXin LI return 0;
1985b6cee71dSXin LI return 1;
1986b6cee71dSXin LI }
1987b6cee71dSXin LI
1988898496eeSXin LI file_private uint64_t
file_strncmp(const char * s1,const char * s2,size_t len,size_t maxlen,uint32_t flags)19892726a701SXin LI file_strncmp(const char *s1, const char *s2, size_t len, size_t maxlen,
19902726a701SXin LI uint32_t flags)
1991b6cee71dSXin LI {
1992b6cee71dSXin LI /*
1993b6cee71dSXin LI * Convert the source args to unsigned here so that (1) the
1994b6cee71dSXin LI * compare will be unsigned as it is in strncmp() and (2) so
1995b6cee71dSXin LI * the ctype functions will work correctly without extra
1996b6cee71dSXin LI * casting.
1997b6cee71dSXin LI */
199848c779cdSXin LI const unsigned char *a = RCAST(const unsigned char *, s1);
199948c779cdSXin LI const unsigned char *b = RCAST(const unsigned char *, s2);
20002726a701SXin LI uint32_t ws = flags & (STRING_COMPACT_WHITESPACE |
20012726a701SXin LI STRING_COMPACT_OPTIONAL_WHITESPACE);
20022726a701SXin LI const unsigned char *eb = b + (ws ? maxlen : len);
2003b6cee71dSXin LI uint64_t v;
2004b6cee71dSXin LI
2005b6cee71dSXin LI /*
2006b6cee71dSXin LI * What we want here is v = strncmp(s1, s2, len),
2007b6cee71dSXin LI * but ignoring any nulls.
2008b6cee71dSXin LI */
2009b6cee71dSXin LI v = 0;
201043a5ec4eSXin LI len++;
2011b6cee71dSXin LI if (0L == flags) { /* normal string: do it fast */
201243a5ec4eSXin LI while (--len > 0)
2013b6cee71dSXin LI if ((v = *b++ - *a++) != '\0')
2014b6cee71dSXin LI break;
2015b6cee71dSXin LI }
2016b6cee71dSXin LI else { /* combine the others */
201743a5ec4eSXin LI while (--len > 0) {
201840427ccaSGordon Tetlow if (b >= eb) {
201940427ccaSGordon Tetlow v = 1;
202040427ccaSGordon Tetlow break;
202140427ccaSGordon Tetlow }
2022b6cee71dSXin LI if ((flags & STRING_IGNORE_LOWERCASE) &&
2023b6cee71dSXin LI islower(*a)) {
2024b6cee71dSXin LI if ((v = tolower(*b++) - *a++) != '\0')
2025b6cee71dSXin LI break;
2026b6cee71dSXin LI }
2027b6cee71dSXin LI else if ((flags & STRING_IGNORE_UPPERCASE) &&
2028b6cee71dSXin LI isupper(*a)) {
2029b6cee71dSXin LI if ((v = toupper(*b++) - *a++) != '\0')
2030b6cee71dSXin LI break;
2031b6cee71dSXin LI }
2032b6cee71dSXin LI else if ((flags & STRING_COMPACT_WHITESPACE) &&
2033b6cee71dSXin LI isspace(*a)) {
2034b6cee71dSXin LI a++;
203543a5ec4eSXin LI if (isspace(*b)) {
203643a5ec4eSXin LI b++;
2037b6cee71dSXin LI if (!isspace(*a))
203840427ccaSGordon Tetlow while (b < eb && isspace(*b))
2039b6cee71dSXin LI b++;
2040b6cee71dSXin LI }
2041b6cee71dSXin LI else {
2042b6cee71dSXin LI v = 1;
2043b6cee71dSXin LI break;
2044b6cee71dSXin LI }
2045b6cee71dSXin LI }
2046b6cee71dSXin LI else if ((flags & STRING_COMPACT_OPTIONAL_WHITESPACE) &&
2047b6cee71dSXin LI isspace(*a)) {
2048b6cee71dSXin LI a++;
204940427ccaSGordon Tetlow while (b < eb && isspace(*b))
2050b6cee71dSXin LI b++;
2051b6cee71dSXin LI }
2052b6cee71dSXin LI else {
2053b6cee71dSXin LI if ((v = *b++ - *a++) != '\0')
2054b6cee71dSXin LI break;
2055b6cee71dSXin LI }
2056b6cee71dSXin LI }
205743a5ec4eSXin LI if (len == 0 && v == 0 && (flags & STRING_FULL_WORD)) {
205843a5ec4eSXin LI if (*b && !isspace(*b))
205943a5ec4eSXin LI v = 1;
206043a5ec4eSXin LI }
2061b6cee71dSXin LI }
2062b6cee71dSXin LI return v;
2063b6cee71dSXin LI }
2064b6cee71dSXin LI
2065898496eeSXin LI file_private uint64_t
file_strncmp16(const char * a,const char * b,size_t len,size_t maxlen,uint32_t flags)20662726a701SXin LI file_strncmp16(const char *a, const char *b, size_t len, size_t maxlen,
20672726a701SXin LI uint32_t flags)
2068b6cee71dSXin LI {
2069b6cee71dSXin LI /*
2070b6cee71dSXin LI * XXX - The 16-bit string compare probably needs to be done
2071b6cee71dSXin LI * differently, especially if the flags are to be supported.
2072b6cee71dSXin LI * At the moment, I am unsure.
2073b6cee71dSXin LI */
2074b6cee71dSXin LI flags = 0;
20752726a701SXin LI return file_strncmp(a, b, len, maxlen, flags);
2076b6cee71dSXin LI }
2077b6cee71dSXin LI
2078898496eeSXin LI file_private file_regex_t *
alloc_regex(struct magic_set * ms,struct magic * m)2079a4d6d3b8SXin LI alloc_regex(struct magic_set *ms, struct magic *m)
2080a4d6d3b8SXin LI {
2081a4d6d3b8SXin LI int rc;
2082a4d6d3b8SXin LI file_regex_t *rx = CAST(file_regex_t *, malloc(sizeof(*rx)));
2083a4d6d3b8SXin LI
2084a4d6d3b8SXin LI if (rx == NULL) {
2085a4d6d3b8SXin LI file_error(ms, errno, "can't allocate %" SIZE_T_FORMAT
2086a4d6d3b8SXin LI "u bytes", sizeof(*rx));
2087a4d6d3b8SXin LI return NULL;
2088a4d6d3b8SXin LI }
2089a4d6d3b8SXin LI
2090a4d6d3b8SXin LI rc = file_regcomp(ms, rx, m->value.s, REG_EXTENDED | REG_NEWLINE |
2091a4d6d3b8SXin LI ((m->str_flags & STRING_IGNORE_CASE) ? REG_ICASE : 0));
2092a4d6d3b8SXin LI if (rc == 0)
2093a4d6d3b8SXin LI return rx;
2094a4d6d3b8SXin LI
2095a4d6d3b8SXin LI free(rx);
2096a4d6d3b8SXin LI return NULL;
2097a4d6d3b8SXin LI }
2098a4d6d3b8SXin LI
2099898496eeSXin LI file_private int
magiccheck(struct magic_set * ms,struct magic * m,file_regex_t ** m_cache)2100a4d6d3b8SXin LI magiccheck(struct magic_set *ms, struct magic *m, file_regex_t **m_cache)
2101b6cee71dSXin LI {
2102b6cee71dSXin LI uint64_t l = m->value.q;
2103b6cee71dSXin LI uint64_t v;
2104b6cee71dSXin LI float fl, fv;
2105b6cee71dSXin LI double dl, dv;
2106b6cee71dSXin LI int matched;
2107b6cee71dSXin LI union VALUETYPE *p = &ms->ms_value;
2108b6cee71dSXin LI
2109b6cee71dSXin LI switch (m->type) {
2110b6cee71dSXin LI case FILE_BYTE:
2111b6cee71dSXin LI v = p->b;
2112b6cee71dSXin LI break;
2113b6cee71dSXin LI
2114b6cee71dSXin LI case FILE_SHORT:
2115b6cee71dSXin LI case FILE_BESHORT:
2116b6cee71dSXin LI case FILE_LESHORT:
2117a4d6d3b8SXin LI case FILE_MSDOSDATE:
2118a4d6d3b8SXin LI case FILE_LEMSDOSDATE:
2119a4d6d3b8SXin LI case FILE_BEMSDOSDATE:
2120a4d6d3b8SXin LI case FILE_MSDOSTIME:
2121a4d6d3b8SXin LI case FILE_LEMSDOSTIME:
2122a4d6d3b8SXin LI case FILE_BEMSDOSTIME:
2123b6cee71dSXin LI v = p->h;
2124b6cee71dSXin LI break;
2125b6cee71dSXin LI
2126b6cee71dSXin LI case FILE_LONG:
2127b6cee71dSXin LI case FILE_BELONG:
2128b6cee71dSXin LI case FILE_LELONG:
2129b6cee71dSXin LI case FILE_MELONG:
2130b6cee71dSXin LI case FILE_DATE:
2131b6cee71dSXin LI case FILE_BEDATE:
2132b6cee71dSXin LI case FILE_LEDATE:
2133b6cee71dSXin LI case FILE_MEDATE:
2134b6cee71dSXin LI case FILE_LDATE:
2135b6cee71dSXin LI case FILE_BELDATE:
2136b6cee71dSXin LI case FILE_LELDATE:
2137b6cee71dSXin LI case FILE_MELDATE:
2138b6cee71dSXin LI v = p->l;
2139b6cee71dSXin LI break;
2140b6cee71dSXin LI
2141b6cee71dSXin LI case FILE_QUAD:
2142b6cee71dSXin LI case FILE_LEQUAD:
2143b6cee71dSXin LI case FILE_BEQUAD:
2144b6cee71dSXin LI case FILE_QDATE:
2145b6cee71dSXin LI case FILE_BEQDATE:
2146b6cee71dSXin LI case FILE_LEQDATE:
2147b6cee71dSXin LI case FILE_QLDATE:
2148b6cee71dSXin LI case FILE_BEQLDATE:
2149b6cee71dSXin LI case FILE_LEQLDATE:
2150b6cee71dSXin LI case FILE_QWDATE:
2151b6cee71dSXin LI case FILE_BEQWDATE:
2152b6cee71dSXin LI case FILE_LEQWDATE:
21532726a701SXin LI case FILE_OFFSET:
2154b6cee71dSXin LI v = p->q;
2155b6cee71dSXin LI break;
2156b6cee71dSXin LI
2157b6cee71dSXin LI case FILE_FLOAT:
2158b6cee71dSXin LI case FILE_BEFLOAT:
2159b6cee71dSXin LI case FILE_LEFLOAT:
2160b6cee71dSXin LI fl = m->value.f;
2161b6cee71dSXin LI fv = p->f;
2162b6cee71dSXin LI switch (m->reln) {
2163b6cee71dSXin LI case 'x':
2164b6cee71dSXin LI matched = 1;
2165b6cee71dSXin LI break;
2166b6cee71dSXin LI
2167b6cee71dSXin LI case '!':
2168898496eeSXin LI matched = isunordered(fl, fv) ? 1 : fv != fl;
2169b6cee71dSXin LI break;
2170b6cee71dSXin LI
2171b6cee71dSXin LI case '=':
2172898496eeSXin LI matched = isunordered(fl, fv) ? 0 : fv == fl;
2173b6cee71dSXin LI break;
2174b6cee71dSXin LI
2175b6cee71dSXin LI case '>':
2176898496eeSXin LI matched = isgreater(fv, fl);
2177b6cee71dSXin LI break;
2178b6cee71dSXin LI
2179b6cee71dSXin LI case '<':
2180898496eeSXin LI matched = isless(fv, fl);
2181b6cee71dSXin LI break;
2182b6cee71dSXin LI
2183b6cee71dSXin LI default:
2184a4d6d3b8SXin LI file_magerror(ms, "cannot happen with float: "
2185a4d6d3b8SXin LI "invalid relation `%c'", m->reln);
2186b6cee71dSXin LI return -1;
2187b6cee71dSXin LI }
2188b6cee71dSXin LI return matched;
2189b6cee71dSXin LI
2190b6cee71dSXin LI case FILE_DOUBLE:
2191b6cee71dSXin LI case FILE_BEDOUBLE:
2192b6cee71dSXin LI case FILE_LEDOUBLE:
2193b6cee71dSXin LI dl = m->value.d;
2194b6cee71dSXin LI dv = p->d;
2195b6cee71dSXin LI switch (m->reln) {
2196b6cee71dSXin LI case 'x':
2197b6cee71dSXin LI matched = 1;
2198b6cee71dSXin LI break;
2199b6cee71dSXin LI
2200b6cee71dSXin LI case '!':
2201898496eeSXin LI matched = isunordered(dv, dl) ? 1 : dv != dl;
2202b6cee71dSXin LI break;
2203b6cee71dSXin LI
2204b6cee71dSXin LI case '=':
2205898496eeSXin LI matched = isunordered(dv, dl) ? 0 : dv == dl;
2206b6cee71dSXin LI break;
2207b6cee71dSXin LI
2208b6cee71dSXin LI case '>':
2209898496eeSXin LI matched = isgreater(dv, dl);
2210b6cee71dSXin LI break;
2211b6cee71dSXin LI
2212b6cee71dSXin LI case '<':
2213898496eeSXin LI matched = isless(dv, dl);
2214b6cee71dSXin LI break;
2215b6cee71dSXin LI
2216b6cee71dSXin LI default:
2217a4d6d3b8SXin LI file_magerror(ms, "cannot happen with double: "
2218a4d6d3b8SXin LI "invalid relation `%c'", m->reln);
2219b6cee71dSXin LI return -1;
2220b6cee71dSXin LI }
2221b6cee71dSXin LI return matched;
2222b6cee71dSXin LI
2223b6cee71dSXin LI case FILE_DEFAULT:
2224b6cee71dSXin LI case FILE_CLEAR:
2225b6cee71dSXin LI l = 0;
2226b6cee71dSXin LI v = 0;
2227b6cee71dSXin LI break;
2228b6cee71dSXin LI
2229b6cee71dSXin LI case FILE_STRING:
2230b6cee71dSXin LI case FILE_PSTRING:
2231a2dfb722SXin LI case FILE_OCTAL:
2232b6cee71dSXin LI l = 0;
223348c779cdSXin LI v = file_strncmp(m->value.s, p->s, CAST(size_t, m->vallen),
22342726a701SXin LI sizeof(p->s), m->str_flags);
2235b6cee71dSXin LI break;
2236b6cee71dSXin LI
2237b6cee71dSXin LI case FILE_BESTRING16:
2238b6cee71dSXin LI case FILE_LESTRING16:
2239b6cee71dSXin LI l = 0;
224048c779cdSXin LI v = file_strncmp16(m->value.s, p->s, CAST(size_t, m->vallen),
22412726a701SXin LI sizeof(p->s), m->str_flags);
2242b6cee71dSXin LI break;
2243b6cee71dSXin LI
2244b6cee71dSXin LI case FILE_SEARCH: { /* search ms->search.s for the string m->value.s */
2245b6cee71dSXin LI size_t slen;
2246b6cee71dSXin LI size_t idx;
2247b6cee71dSXin LI
2248b6cee71dSXin LI if (ms->search.s == NULL)
2249b6cee71dSXin LI return 0;
2250b6cee71dSXin LI
2251b6cee71dSXin LI slen = MIN(m->vallen, sizeof(m->value.s));
2252b6cee71dSXin LI l = 0;
2253b6cee71dSXin LI v = 0;
2254898496eeSXin LI if ((ms->flags & MAGIC_DEBUG) != 0) {
2255898496eeSXin LI size_t xlen = ms->search.s_len > 100 ? 100
2256898496eeSXin LI : ms->search.s_len;
2257898496eeSXin LI
2258898496eeSXin LI fprintf(stderr, "search: [");
2259898496eeSXin LI file_showstr(stderr, ms->search.s, xlen);
2260898496eeSXin LI fprintf(stderr, "%s] for [", ms->search.s_len == xlen
2261898496eeSXin LI ? "" : "...");
2262898496eeSXin LI file_showstr(stderr, m->value.s, slen);
2263898496eeSXin LI }
226448c779cdSXin LI #ifdef HAVE_MEMMEM
226548c779cdSXin LI if (slen > 0 && m->str_flags == 0) {
226648c779cdSXin LI const char *found;
226748c779cdSXin LI idx = m->str_range + slen;
226848c779cdSXin LI if (m->str_range == 0 || ms->search.s_len < idx)
226948c779cdSXin LI idx = ms->search.s_len;
227048c779cdSXin LI found = CAST(const char *, memmem(ms->search.s, idx,
227148c779cdSXin LI m->value.s, slen));
2272898496eeSXin LI if ((ms->flags & MAGIC_DEBUG) != 0) {
2273898496eeSXin LI fprintf(stderr, "] %sfound\n",
2274898496eeSXin LI found ? "" : "not ");
2275898496eeSXin LI }
227643a5ec4eSXin LI if (!found) {
227743a5ec4eSXin LI v = 1;
227843a5ec4eSXin LI break;
227943a5ec4eSXin LI }
228048c779cdSXin LI idx = found - ms->search.s;
228148c779cdSXin LI ms->search.offset += idx;
228248c779cdSXin LI ms->search.rm_len = ms->search.s_len - idx;
228348c779cdSXin LI break;
228448c779cdSXin LI }
228548c779cdSXin LI #endif
2286b6cee71dSXin LI
2287b6cee71dSXin LI for (idx = 0; m->str_range == 0 || idx < m->str_range; idx++) {
228843a5ec4eSXin LI if (slen + idx > ms->search.s_len) {
228943a5ec4eSXin LI v = 1;
229043a5ec4eSXin LI break;
229143a5ec4eSXin LI }
2292b6cee71dSXin LI
2293b6cee71dSXin LI v = file_strncmp(m->value.s, ms->search.s + idx, slen,
22942726a701SXin LI ms->search.s_len - idx, m->str_flags);
2295b6cee71dSXin LI if (v == 0) { /* found match */
2296b6cee71dSXin LI ms->search.offset += idx;
229740427ccaSGordon Tetlow ms->search.rm_len = ms->search.s_len - idx;
2298b6cee71dSXin LI break;
2299b6cee71dSXin LI }
2300b6cee71dSXin LI }
2301898496eeSXin LI if ((ms->flags & MAGIC_DEBUG) != 0) {
2302898496eeSXin LI fprintf(stderr, "] %sfound\n", v == 0 ? "" : "not ");
2303898496eeSXin LI }
2304b6cee71dSXin LI break;
2305b6cee71dSXin LI }
2306b6cee71dSXin LI case FILE_REGEX: {
2307b6cee71dSXin LI int rc;
2308a4d6d3b8SXin LI file_regex_t *rx = *m_cache;
2309c2931133SXin LI const char *search;
2310a4d6d3b8SXin LI regmatch_t pmatch;
2311a4d6d3b8SXin LI size_t slen = ms->search.s_len;
2312a4d6d3b8SXin LI char *copy;
2313b6cee71dSXin LI
2314b6cee71dSXin LI if (ms->search.s == NULL)
2315b6cee71dSXin LI return 0;
2316b6cee71dSXin LI
2317a4d6d3b8SXin LI if (rx == NULL) {
2318a4d6d3b8SXin LI rx = *m_cache = alloc_regex(ms, m);
2319a4d6d3b8SXin LI if (rx == NULL)
2320a4d6d3b8SXin LI return -1;
2321a4d6d3b8SXin LI }
2322b6cee71dSXin LI l = 0;
2323c2931133SXin LI if (slen != 0) {
2324a5d223e6SXin LI copy = CAST(char *, malloc(slen));
2325c2931133SXin LI if (copy == NULL) {
2326c2931133SXin LI file_error(ms, errno,
2327c2931133SXin LI "can't allocate %" SIZE_T_FORMAT "u bytes",
2328c2931133SXin LI slen);
2329c2931133SXin LI return -1;
2330c2931133SXin LI }
2331c2931133SXin LI memcpy(copy, ms->search.s, slen);
2332c2931133SXin LI copy[--slen] = '\0';
2333c2931133SXin LI search = copy;
2334c2931133SXin LI } else {
233540427ccaSGordon Tetlow search = CCAST(char *, "");
2336c2931133SXin LI copy = NULL;
2337c2931133SXin LI }
2338a4d6d3b8SXin LI rc = file_regexec(ms, rx, RCAST(const char *, search),
23393e41d09dSXin LI 1, &pmatch, 0);
2340c2931133SXin LI free(copy);
2341b6cee71dSXin LI switch (rc) {
2342b6cee71dSXin LI case 0:
234348c779cdSXin LI ms->search.s += CAST(int, pmatch.rm_so);
234448c779cdSXin LI ms->search.offset += CAST(size_t, pmatch.rm_so);
234548c779cdSXin LI ms->search.rm_len = CAST(size_t,
234648c779cdSXin LI pmatch.rm_eo - pmatch.rm_so);
2347b6cee71dSXin LI v = 0;
2348b6cee71dSXin LI break;
2349b6cee71dSXin LI
2350b6cee71dSXin LI case REG_NOMATCH:
2351b6cee71dSXin LI v = 1;
2352b6cee71dSXin LI break;
2353b6cee71dSXin LI
2354b6cee71dSXin LI default:
2355a4d6d3b8SXin LI return -1;
2356b6cee71dSXin LI }
2357b6cee71dSXin LI break;
2358b6cee71dSXin LI }
2359b6cee71dSXin LI case FILE_USE:
236043a5ec4eSXin LI return ms->ms_value.q != 0;
2361b6cee71dSXin LI case FILE_NAME:
236243a5ec4eSXin LI case FILE_INDIRECT:
2363b6cee71dSXin LI return 1;
23643e41d09dSXin LI case FILE_DER:
23653e41d09dSXin LI matched = der_cmp(ms, m);
236653021c7eSXin LI if (matched == -1) {
236753021c7eSXin LI if ((ms->flags & MAGIC_DEBUG) != 0) {
236853021c7eSXin LI (void) fprintf(stderr,
2369a2dfb722SXin LI "EOF comparing DER entries\n");
237053021c7eSXin LI }
237153021c7eSXin LI return 0;
237253021c7eSXin LI }
23733e41d09dSXin LI return matched;
23742726a701SXin LI case FILE_GUID:
23752726a701SXin LI l = 0;
23762726a701SXin LI v = memcmp(m->value.guid, p->guid, sizeof(p->guid));
23772726a701SXin LI break;
2378b6cee71dSXin LI default:
2379b6cee71dSXin LI file_magerror(ms, "invalid type %d in magiccheck()", m->type);
2380b6cee71dSXin LI return -1;
2381b6cee71dSXin LI }
2382b6cee71dSXin LI
2383b6cee71dSXin LI v = file_signextend(ms, m, v);
2384b6cee71dSXin LI
2385b6cee71dSXin LI switch (m->reln) {
2386b6cee71dSXin LI case 'x':
2387b6cee71dSXin LI if ((ms->flags & MAGIC_DEBUG) != 0)
2388b6cee71dSXin LI (void) fprintf(stderr, "%" INT64_T_FORMAT
2389898496eeSXin LI "u == *any* = 1", CAST(unsigned long long, v));
2390b6cee71dSXin LI matched = 1;
2391b6cee71dSXin LI break;
2392b6cee71dSXin LI
2393b6cee71dSXin LI case '!':
2394b6cee71dSXin LI matched = v != l;
2395b6cee71dSXin LI if ((ms->flags & MAGIC_DEBUG) != 0)
2396b6cee71dSXin LI (void) fprintf(stderr, "%" INT64_T_FORMAT "u != %"
2397898496eeSXin LI INT64_T_FORMAT "u = %d",
239848c779cdSXin LI CAST(unsigned long long, v),
239948c779cdSXin LI CAST(unsigned long long, l), matched);
2400b6cee71dSXin LI break;
2401b6cee71dSXin LI
2402b6cee71dSXin LI case '=':
2403b6cee71dSXin LI matched = v == l;
2404b6cee71dSXin LI if ((ms->flags & MAGIC_DEBUG) != 0)
2405b6cee71dSXin LI (void) fprintf(stderr, "%" INT64_T_FORMAT "u == %"
2406898496eeSXin LI INT64_T_FORMAT "u = %d",
240748c779cdSXin LI CAST(unsigned long long, v),
240848c779cdSXin LI CAST(unsigned long long, l), matched);
2409b6cee71dSXin LI break;
2410b6cee71dSXin LI
2411b6cee71dSXin LI case '>':
2412b6cee71dSXin LI if (m->flag & UNSIGNED) {
2413b6cee71dSXin LI matched = v > l;
2414b6cee71dSXin LI if ((ms->flags & MAGIC_DEBUG) != 0)
2415b6cee71dSXin LI (void) fprintf(stderr, "%" INT64_T_FORMAT
2416898496eeSXin LI "u > %" INT64_T_FORMAT "u = %d",
241748c779cdSXin LI CAST(unsigned long long, v),
241848c779cdSXin LI CAST(unsigned long long, l), matched);
2419b6cee71dSXin LI }
2420b6cee71dSXin LI else {
242148c779cdSXin LI matched = CAST(int64_t, v) > CAST(int64_t, l);
2422b6cee71dSXin LI if ((ms->flags & MAGIC_DEBUG) != 0)
2423b6cee71dSXin LI (void) fprintf(stderr, "%" INT64_T_FORMAT
2424898496eeSXin LI "d > %" INT64_T_FORMAT "d = %d",
242548c779cdSXin LI CAST(long long, v),
242648c779cdSXin LI CAST(long long, l), matched);
2427b6cee71dSXin LI }
2428b6cee71dSXin LI break;
2429b6cee71dSXin LI
2430b6cee71dSXin LI case '<':
2431b6cee71dSXin LI if (m->flag & UNSIGNED) {
2432b6cee71dSXin LI matched = v < l;
2433b6cee71dSXin LI if ((ms->flags & MAGIC_DEBUG) != 0)
2434b6cee71dSXin LI (void) fprintf(stderr, "%" INT64_T_FORMAT
2435898496eeSXin LI "u < %" INT64_T_FORMAT "u = %d",
243648c779cdSXin LI CAST(unsigned long long, v),
243748c779cdSXin LI CAST(unsigned long long, l), matched);
2438b6cee71dSXin LI }
2439b6cee71dSXin LI else {
244048c779cdSXin LI matched = CAST(int64_t, v) < CAST(int64_t, l);
2441b6cee71dSXin LI if ((ms->flags & MAGIC_DEBUG) != 0)
2442b6cee71dSXin LI (void) fprintf(stderr, "%" INT64_T_FORMAT
2443898496eeSXin LI "d < %" INT64_T_FORMAT "d = %d",
244448c779cdSXin LI CAST(long long, v),
244548c779cdSXin LI CAST(long long, l), matched);
2446b6cee71dSXin LI }
2447b6cee71dSXin LI break;
2448b6cee71dSXin LI
2449b6cee71dSXin LI case '&':
2450b6cee71dSXin LI matched = (v & l) == l;
2451b6cee71dSXin LI if ((ms->flags & MAGIC_DEBUG) != 0)
2452b6cee71dSXin LI (void) fprintf(stderr, "((%" INT64_T_FORMAT "x & %"
2453b6cee71dSXin LI INT64_T_FORMAT "x) == %" INT64_T_FORMAT
2454898496eeSXin LI "x) = %d", CAST(unsigned long long, v),
245548c779cdSXin LI CAST(unsigned long long, l),
245648c779cdSXin LI CAST(unsigned long long, l),
2457b6cee71dSXin LI matched);
2458b6cee71dSXin LI break;
2459b6cee71dSXin LI
2460b6cee71dSXin LI case '^':
2461b6cee71dSXin LI matched = (v & l) != l;
2462b6cee71dSXin LI if ((ms->flags & MAGIC_DEBUG) != 0)
2463b6cee71dSXin LI (void) fprintf(stderr, "((%" INT64_T_FORMAT "x & %"
2464b6cee71dSXin LI INT64_T_FORMAT "x) != %" INT64_T_FORMAT
2465898496eeSXin LI "x) = %d", CAST(unsigned long long, v),
246648c779cdSXin LI CAST(unsigned long long, l),
246748c779cdSXin LI CAST(unsigned long long, l), matched);
2468b6cee71dSXin LI break;
2469b6cee71dSXin LI
2470b6cee71dSXin LI default:
2471b6cee71dSXin LI file_magerror(ms, "cannot happen: invalid relation `%c'",
2472b6cee71dSXin LI m->reln);
2473b6cee71dSXin LI return -1;
2474b6cee71dSXin LI }
2475898496eeSXin LI if ((ms->flags & MAGIC_DEBUG) != 0) {
2476898496eeSXin LI (void) fprintf(stderr, " strength=%zu\n",
2477898496eeSXin LI file_magic_strength(m, 1));
2478898496eeSXin LI }
2479b6cee71dSXin LI
2480b6cee71dSXin LI return matched;
2481b6cee71dSXin LI }
2482b6cee71dSXin LI
2483898496eeSXin LI file_private int
handle_annotation(struct magic_set * ms,struct magic * m,int firstline)24842dc4dbb9SEitan Adler handle_annotation(struct magic_set *ms, struct magic *m, int firstline)
2485b6cee71dSXin LI {
24863e41d09dSXin LI if ((ms->flags & MAGIC_APPLE) && m->apple[0]) {
248748c779cdSXin LI if (print_sep(ms, firstline) == -1)
2488a5d223e6SXin LI return -1;
2489b6cee71dSXin LI if (file_printf(ms, "%.8s", m->apple) == -1)
2490b6cee71dSXin LI return -1;
2491b6cee71dSXin LI return 1;
2492b6cee71dSXin LI }
24933e41d09dSXin LI if ((ms->flags & MAGIC_EXTENSION) && m->ext[0]) {
249448c779cdSXin LI if (print_sep(ms, firstline) == -1)
2495a5d223e6SXin LI return -1;
24965f0216bdSXin LI if (file_printf(ms, "%s", m->ext) == -1)
24975f0216bdSXin LI return -1;
24985f0216bdSXin LI return 1;
24995f0216bdSXin LI }
2500b6cee71dSXin LI if ((ms->flags & MAGIC_MIME_TYPE) && m->mimetype[0]) {
250158a0f0d0SEitan Adler char buf[1024];
250258a0f0d0SEitan Adler const char *p;
250348c779cdSXin LI if (print_sep(ms, firstline) == -1)
2504a5d223e6SXin LI return -1;
25052dc4dbb9SEitan Adler if (varexpand(ms, buf, sizeof(buf), m->mimetype) == -1)
250658a0f0d0SEitan Adler p = m->mimetype;
250758a0f0d0SEitan Adler else
250858a0f0d0SEitan Adler p = buf;
250958a0f0d0SEitan Adler if (file_printf(ms, "%s", p) == -1)
2510b6cee71dSXin LI return -1;
2511b6cee71dSXin LI return 1;
2512b6cee71dSXin LI }
2513b6cee71dSXin LI return 0;
2514b6cee71dSXin LI }
2515b6cee71dSXin LI
2516898496eeSXin LI file_private int
print_sep(struct magic_set * ms,int firstline)2517b6cee71dSXin LI print_sep(struct magic_set *ms, int firstline)
2518b6cee71dSXin LI {
2519b6cee71dSXin LI if (firstline)
2520b6cee71dSXin LI return 0;
2521b6cee71dSXin LI /*
2522b6cee71dSXin LI * we found another match
2523b6cee71dSXin LI * put a newline and '-' to do some simple formatting
2524b6cee71dSXin LI */
252548c779cdSXin LI return file_separator(ms);
2526b6cee71dSXin LI }
2527