1/*
2 * Copyright (c) Ian F. Darwin 1986-1995.
3 * Software written by Ian F. Darwin and others;
4 * maintained 1995-present by Christos Zoulas and others.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice immediately at the beginning of the file, without modification,
11 *    this list of conditions, and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28/*
29 * softmagic - interpret variable magic from MAGIC
30 */
31
32#include "file.h"
33
34#ifndef	lint
35FILE_RCSID("@(#)$File: softmagic.c,v 1.249 2017/06/19 18:30:25 christos Exp $")
36#endif	/* lint */
37
38#include "magic.h"
39#include <assert.h>
40#include <string.h>
41#include <ctype.h>
42#include <stdlib.h>
43#include <time.h>
44#include "der.h"
45
46private int match(struct magic_set *, struct magic *, uint32_t,
47    const unsigned char *, size_t, size_t, int, int, int, uint16_t *,
48    uint16_t *, int *, int *, int *);
49private int mget(struct magic_set *, const unsigned char *,
50    struct magic *, size_t, size_t, unsigned int, int, int, int, uint16_t *,
51    uint16_t *, int *, int *, int *);
52private int magiccheck(struct magic_set *, struct magic *);
53private int32_t mprint(struct magic_set *, struct magic *);
54private int moffset(struct magic_set *, struct magic *, size_t, int32_t *);
55private void mdebug(uint32_t, const char *, size_t);
56private int mcopy(struct magic_set *, union VALUETYPE *, int, int,
57    const unsigned char *, uint32_t, size_t, struct magic *);
58private int mconvert(struct magic_set *, struct magic *, int);
59private int print_sep(struct magic_set *, int);
60private int handle_annotation(struct magic_set *, struct magic *, int);
61private int cvt_8(union VALUETYPE *, const struct magic *);
62private int cvt_16(union VALUETYPE *, const struct magic *);
63private int cvt_32(union VALUETYPE *, const struct magic *);
64private int cvt_64(union VALUETYPE *, const struct magic *);
65
66#define OFFSET_OOB(n, o, i)	((n) < (uint32_t)(o) || (i) > ((n) - (o)))
67#define BE64(p) (((uint64_t)(p)->hq[0]<<56)|((uint64_t)(p)->hq[1]<<48)| \
68    ((uint64_t)(p)->hq[2]<<40)|((uint64_t)(p)->hq[3]<<32)| \
69    ((uint64_t)(p)->hq[4]<<24)|((uint64_t)(p)->hq[5]<<16)| \
70    ((uint64_t)(p)->hq[6]<<8)|((uint64_t)(p)->hq[7]))
71#define LE64(p) (((uint64_t)(p)->hq[7]<<56)|((uint64_t)(p)->hq[6]<<48)| \
72    ((uint64_t)(p)->hq[5]<<40)|((uint64_t)(p)->hq[4]<<32)| \
73    ((uint64_t)(p)->hq[3]<<24)|((uint64_t)(p)->hq[2]<<16)| \
74    ((uint64_t)(p)->hq[1]<<8)|((uint64_t)(p)->hq[0]))
75#define LE32(p) (((uint32_t)(p)->hl[3]<<24)|((uint32_t)(p)->hl[2]<<16)| \
76     ((uint32_t)(p)->hl[1]<<8)|((uint32_t)(p)->hl[0]))
77#define BE32(p) (((uint32_t)(p)->hl[0]<<24)|((uint32_t)(p)->hl[1]<<16)| \
78     ((uint32_t)(p)->hl[2]<<8)|((uint32_t)(p)->hl[3]))
79#define ME32(p) (((uint32_t)(p)->hl[1]<<24)|((uint32_t)(p)->hl[0]<<16)| \
80     ((uint32_t)(p)->hl[3]<<8)|((uint32_t)(p)->hl[2]))
81#define BE16(p) (((uint16_t)(p)->hs[0]<<8)|((uint16_t)(p)->hs[1]))
82#define LE16(p) (((uint16_t)(p)->hs[1]<<8)|((uint16_t)(p)->hs[0]))
83#define SEXT(s,v,p) ((s)?(intmax_t)(int##v##_t)(p):(intmax_t)(uint##v##_t)(p))
84
85/*
86 * softmagic - lookup one file in parsed, in-memory copy of database
87 * Passed the name and FILE * of one file to be typed.
88 */
89/*ARGSUSED1*/		/* nbytes passed for regularity, maybe need later */
90protected int
91file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes,
92    uint16_t *indir_count, uint16_t *name_count, int mode, int text)
93{
94	struct mlist *ml;
95	int rv, printed_something = 0, need_separator = 0;
96	uint16_t nc, ic;
97
98	if (name_count == NULL) {
99		nc = 0;
100		name_count = &nc;
101	}
102	if (indir_count == NULL) {
103		ic = 0;
104		indir_count = &ic;
105	}
106
107	for (ml = ms->mlist[0]->next; ml != ms->mlist[0]; ml = ml->next)
108		if ((rv = match(ms, ml->magic, ml->nmagic, buf, nbytes, 0, mode,
109		    text, 0, indir_count, name_count,
110		    &printed_something, &need_separator, NULL)) != 0)
111			return rv;
112
113	return 0;
114}
115
116#define FILE_FMTDEBUG
117#ifdef FILE_FMTDEBUG
118#define F(a, b, c) file_fmtcheck((a), (b), (c), __FILE__, __LINE__)
119
120private const char * __attribute__((__format_arg__(3)))
121file_fmtcheck(struct magic_set *ms, const struct magic *m, const char *def,
122	const char *file, size_t line)
123{
124	const char *ptr = fmtcheck(m->desc, def);
125	if (ptr == def)
126		file_magerror(ms,
127		    "%s, %" SIZE_T_FORMAT "u: format `%s' does not match"
128		    " with `%s'", file, line, m->desc, def);
129	return ptr;
130}
131#else
132#define F(a, b, c) fmtcheck((b)->desc, (c))
133#endif
134
135/*
136 * Go through the whole list, stopping if you find a match.  Process all
137 * the continuations of that match before returning.
138 *
139 * We support multi-level continuations:
140 *
141 *	At any time when processing a successful top-level match, there is a
142 *	current continuation level; it represents the level of the last
143 *	successfully matched continuation.
144 *
145 *	Continuations above that level are skipped as, if we see one, it
146 *	means that the continuation that controls them - i.e, the
147 *	lower-level continuation preceding them - failed to match.
148 *
149 *	Continuations below that level are processed as, if we see one,
150 *	it means we've finished processing or skipping higher-level
151 *	continuations under the control of a successful or unsuccessful
152 *	lower-level continuation, and are now seeing the next lower-level
153 *	continuation and should process it.  The current continuation
154 *	level reverts to the level of the one we're seeing.
155 *
156 *	Continuations at the current level are processed as, if we see
157 *	one, there's no lower-level continuation that may have failed.
158 *
159 *	If a continuation matches, we bump the current continuation level
160 *	so that higher-level continuations are processed.
161 */
162private int
163match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
164    const unsigned char *s, size_t nbytes, size_t offset, int mode, int text,
165    int flip, uint16_t *indir_count, uint16_t *name_count,
166    int *printed_something, int *need_separator, int *returnval)
167{
168	uint32_t magindex = 0;
169	unsigned int cont_level = 0;
170	int returnvalv = 0, e; /* if a match is found it is set to 1*/
171	int firstline = 1; /* a flag to print X\n  X\n- X */
172	int print = (ms->flags & MAGIC_NODESC) == 0;
173
174	if (returnval == NULL)
175		returnval = &returnvalv;
176
177	if (file_check_mem(ms, cont_level) == -1)
178		return -1;
179
180	for (magindex = 0; magindex < nmagic; magindex++) {
181		int flush = 0;
182		struct magic *m = &magic[magindex];
183
184		if (m->type != FILE_NAME)
185		if ((IS_STRING(m->type) &&
186#define FLT (STRING_BINTEST | STRING_TEXTTEST)
187		     ((text && (m->str_flags & FLT) == STRING_BINTEST) ||
188		      (!text && (m->str_flags & FLT) == STRING_TEXTTEST))) ||
189		    (m->flag & mode) != mode) {
190flush:
191			/* Skip sub-tests */
192			while (magindex < nmagic - 1 &&
193			    magic[magindex + 1].cont_level != 0)
194				magindex++;
195			cont_level = 0;
196			continue; /* Skip to next top-level test*/
197		}
198
199		ms->offset = m->offset;
200		ms->line = m->lineno;
201
202		/* if main entry matches, print it... */
203		switch (mget(ms, s, m, nbytes, offset, cont_level, mode, text,
204		    flip, indir_count, name_count,
205		    printed_something, need_separator, returnval)) {
206		case -1:
207			return -1;
208		case 0:
209			flush = m->reln != '!';
210			break;
211		default:
212			if (m->type == FILE_INDIRECT)
213				*returnval = 1;
214
215			switch (magiccheck(ms, m)) {
216			case -1:
217				return -1;
218			case 0:
219				flush++;
220				break;
221			default:
222				flush = 0;
223				break;
224			}
225			break;
226		}
227		if (flush) {
228			/*
229			 * main entry didn't match,
230			 * flush its continuations
231			 */
232			goto flush;
233		}
234
235		if ((e = handle_annotation(ms, m, firstline)) != 0) {
236			*need_separator = 1;
237			*printed_something = 1;
238			*returnval = 1;
239			return e;
240		}
241
242		/*
243		 * If we are going to print something, we'll need to print
244		 * a blank before we print something else.
245		 */
246		if (*m->desc) {
247			*need_separator = 1;
248			*printed_something = 1;
249			if (print_sep(ms, firstline) == -1)
250				return -1;
251		}
252
253
254		if (print && mprint(ms, m) == -1)
255			return -1;
256
257		switch (moffset(ms, m, nbytes, &ms->c.li[cont_level].off)) {
258		case -1:
259		case 0:
260			goto flush;
261		default:
262			break;
263		}
264
265		/* and any continuations that match */
266		if (file_check_mem(ms, ++cont_level) == -1)
267			return -1;
268
269		while (magindex + 1 < nmagic &&
270		    magic[magindex + 1].cont_level != 0) {
271			m = &magic[++magindex];
272			ms->line = m->lineno; /* for messages */
273
274			if (cont_level < m->cont_level)
275				continue;
276			if (cont_level > m->cont_level) {
277				/*
278				 * We're at the end of the level
279				 * "cont_level" continuations.
280				 */
281				cont_level = m->cont_level;
282			}
283			ms->offset = m->offset;
284			if (m->flag & OFFADD) {
285				ms->offset +=
286				    ms->c.li[cont_level - 1].off;
287			}
288
289#ifdef ENABLE_CONDITIONALS
290			if (m->cond == COND_ELSE ||
291			    m->cond == COND_ELIF) {
292				if (ms->c.li[cont_level].last_match == 1)
293					continue;
294			}
295#endif
296			switch (mget(ms, s, m, nbytes, offset, cont_level, mode,
297			    text, flip, indir_count, name_count,
298			    printed_something, need_separator, returnval)) {
299			case -1:
300				return -1;
301			case 0:
302				if (m->reln != '!')
303					continue;
304				flush = 1;
305				break;
306			default:
307				if (m->type == FILE_INDIRECT)
308					*returnval = 1;
309				flush = 0;
310				break;
311			}
312
313			switch (flush ? 1 : magiccheck(ms, m)) {
314			case -1:
315				return -1;
316			case 0:
317#ifdef ENABLE_CONDITIONALS
318				ms->c.li[cont_level].last_match = 0;
319#endif
320				break;
321			default:
322#ifdef ENABLE_CONDITIONALS
323				ms->c.li[cont_level].last_match = 1;
324#endif
325				if (m->type == FILE_CLEAR)
326					ms->c.li[cont_level].got_match = 0;
327				else if (ms->c.li[cont_level].got_match) {
328					if (m->type == FILE_DEFAULT)
329						break;
330				} else
331					ms->c.li[cont_level].got_match = 1;
332
333				if ((e = handle_annotation(ms, m, firstline)) != 0) {
334					*need_separator = 1;
335					*printed_something = 1;
336					*returnval = 1;
337					return e;
338				}
339				/*
340				 * If we are going to print something,
341				 * make sure that we have a separator first.
342				 */
343				if (*m->desc) {
344					if (!*printed_something) {
345						*printed_something = 1;
346						if (print_sep(ms, firstline)
347						    == -1)
348							return -1;
349					}
350				}
351				/*
352				 * This continuation matched.  Print
353				 * its message, with a blank before it
354				 * if the previous item printed and
355				 * this item isn't empty.
356				 */
357				/* space if previous printed */
358				if (*need_separator
359				    && ((m->flag & NOSPACE) == 0)
360				    && *m->desc) {
361					if (print &&
362					    file_printf(ms, " ") == -1)
363						return -1;
364					*need_separator = 0;
365				}
366				if (print && mprint(ms, m) == -1)
367					return -1;
368
369				switch (moffset(ms, m, nbytes,
370				    &ms->c.li[cont_level].off)) {
371				case -1:
372				case 0:
373					flush = 1;
374					cont_level--;
375					break;
376				default:
377					break;
378				}
379
380				if (*m->desc)
381					*need_separator = 1;
382
383				/*
384				 * If we see any continuations
385				 * at a higher level,
386				 * process them.
387				 */
388				if (file_check_mem(ms, ++cont_level) == -1)
389					return -1;
390				break;
391			}
392		}
393		if (*printed_something) {
394			firstline = 0;
395			if (print)
396				*returnval = 1;
397		}
398		if ((ms->flags & MAGIC_CONTINUE) == 0 && *printed_something) {
399			return *returnval; /* don't keep searching */
400		}
401		cont_level = 0;
402	}
403	return *returnval;  /* This is hit if -k is set or there is no match */
404}
405
406private int
407check_fmt(struct magic_set *ms, struct magic *m)
408{
409	file_regex_t rx;
410	int rc, rv = -1;
411
412	if (strchr(m->desc, '%') == NULL)
413		return 0;
414
415	rc = file_regcomp(&rx, "%[-0-9\\.]*s", REG_EXTENDED|REG_NOSUB);
416	if (rc) {
417		file_regerror(&rx, rc, ms);
418	} else {
419		rc = file_regexec(&rx, m->desc, 0, 0, 0);
420		rv = !rc;
421	}
422	file_regfree(&rx);
423	return rv;
424}
425
426#ifndef HAVE_STRNDUP
427char * strndup(const char *, size_t);
428
429char *
430strndup(const char *str, size_t n)
431{
432	size_t len;
433	char *copy;
434
435	for (len = 0; len < n && str[len]; len++)
436		continue;
437	if ((copy = malloc(len + 1)) == NULL)
438		return NULL;
439	(void)memcpy(copy, str, len);
440	copy[len] = '\0';
441	return copy;
442}
443#endif /* HAVE_STRNDUP */
444
445private int32_t
446mprint(struct magic_set *ms, struct magic *m)
447{
448	uint64_t v;
449	float vf;
450	double vd;
451	int64_t t = 0;
452 	char buf[128], tbuf[26], sbuf[512];
453	union VALUETYPE *p = &ms->ms_value;
454
455  	switch (m->type) {
456  	case FILE_BYTE:
457		v = file_signextend(ms, m, (uint64_t)p->b);
458		switch (check_fmt(ms, m)) {
459		case -1:
460			return -1;
461		case 1:
462			(void)snprintf(buf, sizeof(buf), "%d",
463			    (unsigned char)v);
464			if (file_printf(ms, F(ms, m, "%s"), buf) == -1)
465				return -1;
466			break;
467		default:
468			if (file_printf(ms, F(ms, m, "%d"),
469			    (unsigned char) v) == -1)
470				return -1;
471			break;
472		}
473		t = ms->offset + sizeof(char);
474		break;
475
476  	case FILE_SHORT:
477  	case FILE_BESHORT:
478  	case FILE_LESHORT:
479		v = file_signextend(ms, m, (uint64_t)p->h);
480		switch (check_fmt(ms, m)) {
481		case -1:
482			return -1;
483		case 1:
484			(void)snprintf(buf, sizeof(buf), "%u",
485			    (unsigned short)v);
486			if (file_printf(ms, F(ms, m, "%s"), buf) == -1)
487				return -1;
488			break;
489		default:
490			if (file_printf(ms, F(ms, m, "%u"),
491			    (unsigned short) v) == -1)
492				return -1;
493			break;
494		}
495		t = ms->offset + sizeof(short);
496		break;
497
498  	case FILE_LONG:
499  	case FILE_BELONG:
500  	case FILE_LELONG:
501  	case FILE_MELONG:
502		v = file_signextend(ms, m, (uint64_t)p->l);
503		switch (check_fmt(ms, m)) {
504		case -1:
505			return -1;
506		case 1:
507			(void)snprintf(buf, sizeof(buf), "%u", (uint32_t) v);
508			if (file_printf(ms, F(ms, m, "%s"), buf) == -1)
509				return -1;
510			break;
511		default:
512			if (file_printf(ms, F(ms, m, "%u"), (uint32_t) v) == -1)
513				return -1;
514			break;
515		}
516		t = ms->offset + sizeof(int32_t);
517  		break;
518
519  	case FILE_QUAD:
520  	case FILE_BEQUAD:
521  	case FILE_LEQUAD:
522		v = file_signextend(ms, m, p->q);
523		switch (check_fmt(ms, m)) {
524		case -1:
525			return -1;
526		case 1:
527			(void)snprintf(buf, sizeof(buf), "%" INT64_T_FORMAT "u",
528			    (unsigned long long)v);
529			if (file_printf(ms, F(ms, m, "%s"), buf) == -1)
530				return -1;
531			break;
532		default:
533			if (file_printf(ms, F(ms, m, "%" INT64_T_FORMAT "u"),
534			    (unsigned long long) v) == -1)
535				return -1;
536			break;
537		}
538		t = ms->offset + sizeof(int64_t);
539  		break;
540
541  	case FILE_STRING:
542  	case FILE_PSTRING:
543  	case FILE_BESTRING16:
544  	case FILE_LESTRING16:
545		if (m->reln == '=' || m->reln == '!') {
546			if (file_printf(ms, F(ms, m, "%s"),
547			    file_printable(sbuf, sizeof(sbuf), m->value.s))
548			    == -1)
549				return -1;
550			t = ms->offset + m->vallen;
551		}
552		else {
553			char *str = p->s;
554
555			/* compute t before we mangle the string? */
556			t = ms->offset + strlen(str);
557
558			if (*m->value.s == '\0')
559				str[strcspn(str, "\r\n")] = '\0';
560
561			if (m->str_flags & STRING_TRIM) {
562				char *last;
563				while (isspace((unsigned char)*str))
564					str++;
565				last = str;
566				while (*last)
567					last++;
568				--last;
569				while (isspace((unsigned char)*last))
570					last--;
571				*++last = '\0';
572			}
573
574			if (file_printf(ms, F(ms, m, "%s"),
575			    file_printable(sbuf, sizeof(sbuf), str)) == -1)
576				return -1;
577
578			if (m->type == FILE_PSTRING)
579				t += file_pstring_length_size(m);
580		}
581		break;
582
583	case FILE_DATE:
584	case FILE_BEDATE:
585	case FILE_LEDATE:
586	case FILE_MEDATE:
587		if (file_printf(ms, F(ms, m, "%s"),
588		    file_fmttime(p->l, 0, tbuf)) == -1)
589			return -1;
590		t = ms->offset + sizeof(uint32_t);
591		break;
592
593	case FILE_LDATE:
594	case FILE_BELDATE:
595	case FILE_LELDATE:
596	case FILE_MELDATE:
597		if (file_printf(ms, F(ms, m, "%s"),
598		    file_fmttime(p->l, FILE_T_LOCAL, tbuf)) == -1)
599			return -1;
600		t = ms->offset + sizeof(uint32_t);
601		break;
602
603	case FILE_QDATE:
604	case FILE_BEQDATE:
605	case FILE_LEQDATE:
606		if (file_printf(ms, F(ms, m, "%s"),
607		    file_fmttime(p->q, 0, tbuf)) == -1)
608			return -1;
609		t = ms->offset + sizeof(uint64_t);
610		break;
611
612	case FILE_QLDATE:
613	case FILE_BEQLDATE:
614	case FILE_LEQLDATE:
615		if (file_printf(ms, F(ms, m, "%s"),
616		    file_fmttime(p->q, FILE_T_LOCAL, tbuf)) == -1)
617			return -1;
618		t = ms->offset + sizeof(uint64_t);
619		break;
620
621	case FILE_QWDATE:
622	case FILE_BEQWDATE:
623	case FILE_LEQWDATE:
624		if (file_printf(ms, F(ms, m, "%s"),
625		    file_fmttime(p->q, FILE_T_WINDOWS, tbuf)) == -1)
626			return -1;
627		t = ms->offset + sizeof(uint64_t);
628		break;
629
630	case FILE_FLOAT:
631	case FILE_BEFLOAT:
632	case FILE_LEFLOAT:
633		vf = p->f;
634		switch (check_fmt(ms, m)) {
635		case -1:
636			return -1;
637		case 1:
638			(void)snprintf(buf, sizeof(buf), "%g", vf);
639			if (file_printf(ms, F(ms, m, "%s"), buf) == -1)
640				return -1;
641			break;
642		default:
643			if (file_printf(ms, F(ms, m, "%g"), vf) == -1)
644				return -1;
645			break;
646		}
647		t = ms->offset + sizeof(float);
648  		break;
649
650	case FILE_DOUBLE:
651	case FILE_BEDOUBLE:
652	case FILE_LEDOUBLE:
653		vd = p->d;
654		switch (check_fmt(ms, m)) {
655		case -1:
656			return -1;
657		case 1:
658			(void)snprintf(buf, sizeof(buf), "%g", vd);
659			if (file_printf(ms, F(ms, m, "%s"), buf) == -1)
660				return -1;
661			break;
662		default:
663			if (file_printf(ms, F(ms, m, "%g"), vd) == -1)
664				return -1;
665			break;
666		}
667		t = ms->offset + sizeof(double);
668  		break;
669
670	case FILE_SEARCH:
671	case FILE_REGEX: {
672		char *cp;
673		int rval;
674
675		cp = strndup((const char *)ms->search.s, ms->search.rm_len);
676		if (cp == NULL) {
677			file_oomem(ms, ms->search.rm_len);
678			return -1;
679		}
680		rval = file_printf(ms, F(ms, m, "%s"),
681		    file_printable(sbuf, sizeof(sbuf), cp));
682		free(cp);
683
684		if (rval == -1)
685			return -1;
686
687		if ((m->str_flags & REGEX_OFFSET_START))
688			t = ms->search.offset;
689		else
690			t = ms->search.offset + ms->search.rm_len;
691		break;
692	}
693
694	case FILE_DEFAULT:
695	case FILE_CLEAR:
696	  	if (file_printf(ms, "%s", m->desc) == -1)
697			return -1;
698		t = ms->offset;
699		break;
700
701	case FILE_INDIRECT:
702	case FILE_USE:
703	case FILE_NAME:
704		t = ms->offset;
705		break;
706	case FILE_DER:
707		if (file_printf(ms, F(ms, m, "%s"),
708		    file_printable(sbuf, sizeof(sbuf), ms->ms_value.s)) == -1)
709			return -1;
710		t = ms->offset;
711		break;
712	default:
713		file_magerror(ms, "invalid m->type (%d) in mprint()", m->type);
714		return -1;
715	}
716	return (int32_t)t;
717}
718
719private int
720moffset(struct magic_set *ms, struct magic *m, size_t nbytes, int32_t *op)
721{
722	int32_t o;
723
724  	switch (m->type) {
725  	case FILE_BYTE:
726		o = CAST(int32_t, (ms->offset + sizeof(char)));
727		break;
728
729  	case FILE_SHORT:
730  	case FILE_BESHORT:
731  	case FILE_LESHORT:
732		o = CAST(int32_t, (ms->offset + sizeof(short)));
733		break;
734
735  	case FILE_LONG:
736  	case FILE_BELONG:
737  	case FILE_LELONG:
738  	case FILE_MELONG:
739		o = CAST(int32_t, (ms->offset + sizeof(int32_t)));
740		break;
741
742  	case FILE_QUAD:
743  	case FILE_BEQUAD:
744  	case FILE_LEQUAD:
745		o = CAST(int32_t, (ms->offset + sizeof(int64_t)));
746		break;
747
748  	case FILE_STRING:
749  	case FILE_PSTRING:
750  	case FILE_BESTRING16:
751  	case FILE_LESTRING16:
752		if (m->reln == '=' || m->reln == '!') {
753			o = ms->offset + m->vallen;
754		} else {
755			union VALUETYPE *p = &ms->ms_value;
756
757			if (*m->value.s == '\0')
758				p->s[strcspn(p->s, "\r\n")] = '\0';
759			o = CAST(uint32_t, (ms->offset + strlen(p->s)));
760			if (m->type == FILE_PSTRING)
761				o += (uint32_t)file_pstring_length_size(m);
762		}
763		break;
764
765	case FILE_DATE:
766	case FILE_BEDATE:
767	case FILE_LEDATE:
768	case FILE_MEDATE:
769		o = CAST(int32_t, (ms->offset + sizeof(uint32_t)));
770		break;
771
772	case FILE_LDATE:
773	case FILE_BELDATE:
774	case FILE_LELDATE:
775	case FILE_MELDATE:
776		o = CAST(int32_t, (ms->offset + sizeof(uint32_t)));
777		break;
778
779	case FILE_QDATE:
780	case FILE_BEQDATE:
781	case FILE_LEQDATE:
782		o = CAST(int32_t, (ms->offset + sizeof(uint64_t)));
783		break;
784
785	case FILE_QLDATE:
786	case FILE_BEQLDATE:
787	case FILE_LEQLDATE:
788		o = CAST(int32_t, (ms->offset + sizeof(uint64_t)));
789		break;
790
791  	case FILE_FLOAT:
792  	case FILE_BEFLOAT:
793  	case FILE_LEFLOAT:
794		o = CAST(int32_t, (ms->offset + sizeof(float)));
795		break;
796
797  	case FILE_DOUBLE:
798  	case FILE_BEDOUBLE:
799  	case FILE_LEDOUBLE:
800		o = CAST(int32_t, (ms->offset + sizeof(double)));
801		break;
802
803	case FILE_REGEX:
804		if ((m->str_flags & REGEX_OFFSET_START) != 0)
805			o = CAST(int32_t, ms->search.offset);
806		else
807			o = CAST(int32_t,
808			    (ms->search.offset + ms->search.rm_len));
809		break;
810
811	case FILE_SEARCH:
812		if ((m->str_flags & REGEX_OFFSET_START) != 0)
813			o = CAST(int32_t, ms->search.offset);
814		else
815			o = CAST(int32_t, (ms->search.offset + m->vallen));
816		break;
817
818	case FILE_CLEAR:
819	case FILE_DEFAULT:
820	case FILE_INDIRECT:
821		o = ms->offset;
822		break;
823
824	case FILE_DER:
825		{
826			o = der_offs(ms, m, nbytes);
827			if (o == -1 || (size_t)o > nbytes) {
828				if ((ms->flags & MAGIC_DEBUG) != 0) {
829					(void)fprintf(stderr,
830					    "Bad DER offset %d nbytes=%zu",
831					    o, nbytes);
832				}
833				*op = 0;
834				return 0;
835			}
836			break;
837		}
838
839	default:
840		o = 0;
841		break;
842	}
843
844	if ((size_t)o > nbytes) {
845#if 0
846		file_error(ms, 0, "Offset out of range %zu > %zu",
847		    (size_t)o, nbytes);
848#endif
849		return -1;
850	}
851	*op = o;
852	return 1;
853}
854
855private uint32_t
856cvt_id3(struct magic_set *ms, uint32_t v)
857{
858	v = ((((v >>  0) & 0x7f) <<  0) |
859	     (((v >>  8) & 0x7f) <<  7) |
860	     (((v >> 16) & 0x7f) << 14) |
861	     (((v >> 24) & 0x7f) << 21));
862	if ((ms->flags & MAGIC_DEBUG) != 0)
863		fprintf(stderr, "id3 offs=%u\n", v);
864	return v;
865}
866
867private int
868cvt_flip(int type, int flip)
869{
870	if (flip == 0)
871		return type;
872	switch (type) {
873	case FILE_BESHORT:
874		return FILE_LESHORT;
875	case FILE_BELONG:
876		return FILE_LELONG;
877	case FILE_BEDATE:
878		return FILE_LEDATE;
879	case FILE_BELDATE:
880		return FILE_LELDATE;
881	case FILE_BEQUAD:
882		return FILE_LEQUAD;
883	case FILE_BEQDATE:
884		return FILE_LEQDATE;
885	case FILE_BEQLDATE:
886		return FILE_LEQLDATE;
887	case FILE_BEQWDATE:
888		return FILE_LEQWDATE;
889	case FILE_LESHORT:
890		return FILE_BESHORT;
891	case FILE_LELONG:
892		return FILE_BELONG;
893	case FILE_LEDATE:
894		return FILE_BEDATE;
895	case FILE_LELDATE:
896		return FILE_BELDATE;
897	case FILE_LEQUAD:
898		return FILE_BEQUAD;
899	case FILE_LEQDATE:
900		return FILE_BEQDATE;
901	case FILE_LEQLDATE:
902		return FILE_BEQLDATE;
903	case FILE_LEQWDATE:
904		return FILE_BEQWDATE;
905	case FILE_BEFLOAT:
906		return FILE_LEFLOAT;
907	case FILE_LEFLOAT:
908		return FILE_BEFLOAT;
909	case FILE_BEDOUBLE:
910		return FILE_LEDOUBLE;
911	case FILE_LEDOUBLE:
912		return FILE_BEDOUBLE;
913	default:
914		return type;
915	}
916}
917#define DO_CVT(fld, cast) \
918	if (m->num_mask) \
919		switch (m->mask_op & FILE_OPS_MASK) { \
920		case FILE_OPAND: \
921			p->fld &= cast m->num_mask; \
922			break; \
923		case FILE_OPOR: \
924			p->fld |= cast m->num_mask; \
925			break; \
926		case FILE_OPXOR: \
927			p->fld ^= cast m->num_mask; \
928			break; \
929		case FILE_OPADD: \
930			p->fld += cast m->num_mask; \
931			break; \
932		case FILE_OPMINUS: \
933			p->fld -= cast m->num_mask; \
934			break; \
935		case FILE_OPMULTIPLY: \
936			p->fld *= cast m->num_mask; \
937			break; \
938		case FILE_OPDIVIDE: \
939			if (cast m->num_mask == 0) \
940				return -1; \
941			p->fld /= cast m->num_mask; \
942			break; \
943		case FILE_OPMODULO: \
944			if (cast m->num_mask == 0) \
945				return -1; \
946			p->fld %= cast m->num_mask; \
947			break; \
948		} \
949	if (m->mask_op & FILE_OPINVERSE) \
950		p->fld = ~p->fld \
951
952private int
953cvt_8(union VALUETYPE *p, const struct magic *m)
954{
955	DO_CVT(b, (uint8_t));
956	return 0;
957}
958
959private int
960cvt_16(union VALUETYPE *p, const struct magic *m)
961{
962	DO_CVT(h, (uint16_t));
963	return 0;
964}
965
966private int
967cvt_32(union VALUETYPE *p, const struct magic *m)
968{
969	DO_CVT(l, (uint32_t));
970	return 0;
971}
972
973private int
974cvt_64(union VALUETYPE *p, const struct magic *m)
975{
976	DO_CVT(q, (uint64_t));
977	return 0;
978}
979
980#define DO_CVT2(fld, cast) \
981	if (m->num_mask) \
982		switch (m->mask_op & FILE_OPS_MASK) { \
983		case FILE_OPADD: \
984			p->fld += cast m->num_mask; \
985			break; \
986		case FILE_OPMINUS: \
987			p->fld -= cast m->num_mask; \
988			break; \
989		case FILE_OPMULTIPLY: \
990			p->fld *= cast m->num_mask; \
991			break; \
992		case FILE_OPDIVIDE: \
993			if (cast m->num_mask == 0) \
994				return -1; \
995			p->fld /= cast m->num_mask; \
996			break; \
997		} \
998
999private int
1000cvt_float(union VALUETYPE *p, const struct magic *m)
1001{
1002	DO_CVT2(f, (float));
1003	return 0;
1004}
1005
1006private int
1007cvt_double(union VALUETYPE *p, const struct magic *m)
1008{
1009	DO_CVT2(d, (double));
1010	return 0;
1011}
1012
1013/*
1014 * Convert the byte order of the data we are looking at
1015 * While we're here, let's apply the mask operation
1016 * (unless you have a better idea)
1017 */
1018private int
1019mconvert(struct magic_set *ms, struct magic *m, int flip)
1020{
1021	union VALUETYPE *p = &ms->ms_value;
1022
1023	switch (cvt_flip(m->type, flip)) {
1024	case FILE_BYTE:
1025		if (cvt_8(p, m) == -1)
1026			goto out;
1027		return 1;
1028	case FILE_SHORT:
1029		if (cvt_16(p, m) == -1)
1030			goto out;
1031		return 1;
1032	case FILE_LONG:
1033	case FILE_DATE:
1034	case FILE_LDATE:
1035		if (cvt_32(p, m) == -1)
1036			goto out;
1037		return 1;
1038	case FILE_QUAD:
1039	case FILE_QDATE:
1040	case FILE_QLDATE:
1041	case FILE_QWDATE:
1042		if (cvt_64(p, m) == -1)
1043			goto out;
1044		return 1;
1045	case FILE_STRING:
1046	case FILE_BESTRING16:
1047	case FILE_LESTRING16: {
1048		/* Null terminate and eat *trailing* return */
1049		p->s[sizeof(p->s) - 1] = '\0';
1050		return 1;
1051	}
1052	case FILE_PSTRING: {
1053		size_t sz = file_pstring_length_size(m);
1054		char *ptr1 = p->s, *ptr2 = ptr1 + sz;
1055		size_t len = file_pstring_get_length(m, ptr1);
1056		sz = sizeof(p->s) - sz; /* maximum length of string */
1057		if (len >= sz) {
1058			/*
1059			 * The size of the pascal string length (sz)
1060			 * is 1, 2, or 4. We need at least 1 byte for NUL
1061			 * termination, but we've already truncated the
1062			 * string by p->s, so we need to deduct sz.
1063			 * Because we can use one of the bytes of the length
1064			 * after we shifted as NUL termination.
1065			 */
1066			len = sz;
1067		}
1068		while (len--)
1069			*ptr1++ = *ptr2++;
1070		*ptr1 = '\0';
1071		return 1;
1072	}
1073	case FILE_BESHORT:
1074		p->h = (short)BE16(p);
1075		if (cvt_16(p, m) == -1)
1076			goto out;
1077		return 1;
1078	case FILE_BELONG:
1079	case FILE_BEDATE:
1080	case FILE_BELDATE:
1081		p->l = (int32_t)BE32(p);
1082		if (cvt_32(p, m) == -1)
1083			goto out;
1084		return 1;
1085	case FILE_BEQUAD:
1086	case FILE_BEQDATE:
1087	case FILE_BEQLDATE:
1088	case FILE_BEQWDATE:
1089		p->q = (uint64_t)BE64(p);
1090		if (cvt_64(p, m) == -1)
1091			goto out;
1092		return 1;
1093	case FILE_LESHORT:
1094		p->h = (short)LE16(p);
1095		if (cvt_16(p, m) == -1)
1096			goto out;
1097		return 1;
1098	case FILE_LELONG:
1099	case FILE_LEDATE:
1100	case FILE_LELDATE:
1101		p->l = (int32_t)LE32(p);
1102		if (cvt_32(p, m) == -1)
1103			goto out;
1104		return 1;
1105	case FILE_LEQUAD:
1106	case FILE_LEQDATE:
1107	case FILE_LEQLDATE:
1108	case FILE_LEQWDATE:
1109		p->q = (uint64_t)LE64(p);
1110		if (cvt_64(p, m) == -1)
1111			goto out;
1112		return 1;
1113	case FILE_MELONG:
1114	case FILE_MEDATE:
1115	case FILE_MELDATE:
1116		p->l = (int32_t)ME32(p);
1117		if (cvt_32(p, m) == -1)
1118			goto out;
1119		return 1;
1120	case FILE_FLOAT:
1121		if (cvt_float(p, m) == -1)
1122			goto out;
1123		return 1;
1124	case FILE_BEFLOAT:
1125		p->l = BE32(p);
1126		if (cvt_float(p, m) == -1)
1127			goto out;
1128		return 1;
1129	case FILE_LEFLOAT:
1130		p->l = LE32(p);
1131		if (cvt_float(p, m) == -1)
1132			goto out;
1133		return 1;
1134	case FILE_DOUBLE:
1135		if (cvt_double(p, m) == -1)
1136			goto out;
1137		return 1;
1138	case FILE_BEDOUBLE:
1139		p->q = BE64(p);
1140		if (cvt_double(p, m) == -1)
1141			goto out;
1142		return 1;
1143	case FILE_LEDOUBLE:
1144		p->q = LE64(p);
1145		if (cvt_double(p, m) == -1)
1146			goto out;
1147		return 1;
1148	case FILE_REGEX:
1149	case FILE_SEARCH:
1150	case FILE_DEFAULT:
1151	case FILE_CLEAR:
1152	case FILE_NAME:
1153	case FILE_USE:
1154	case FILE_DER:
1155		return 1;
1156	default:
1157		file_magerror(ms, "invalid type %d in mconvert()", m->type);
1158		return 0;
1159	}
1160out:
1161	file_magerror(ms, "zerodivide in mconvert()");
1162	return 0;
1163}
1164
1165
1166private void
1167mdebug(uint32_t offset, const char *str, size_t len)
1168{
1169	(void) fprintf(stderr, "mget/%" SIZE_T_FORMAT "u @%d: ", len, offset);
1170	file_showstr(stderr, str, len);
1171	(void) fputc('\n', stderr);
1172	(void) fputc('\n', stderr);
1173}
1174
1175private int
1176mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
1177    const unsigned char *s, uint32_t offset, size_t nbytes, struct magic *m)
1178{
1179	/*
1180	 * Note: FILE_SEARCH and FILE_REGEX do not actually copy
1181	 * anything, but setup pointers into the source
1182	 */
1183	if (indir == 0) {
1184		switch (type) {
1185		case FILE_DER:
1186		case FILE_SEARCH:
1187			if (offset > nbytes)
1188				offset = CAST(uint32_t, nbytes);
1189			ms->search.s = RCAST(const char *, s) + offset;
1190			ms->search.s_len = nbytes - offset;
1191			ms->search.offset = offset;
1192			return 0;
1193
1194		case FILE_REGEX: {
1195			const char *b;
1196			const char *c;
1197			const char *last;	/* end of search region */
1198			const char *buf;	/* start of search region */
1199			const char *end;
1200			size_t lines, linecnt, bytecnt;
1201
1202			if (s == NULL || nbytes < offset) {
1203				ms->search.s_len = 0;
1204				ms->search.s = NULL;
1205				return 0;
1206			}
1207
1208			if (m->str_flags & REGEX_LINE_COUNT) {
1209				linecnt = m->str_range;
1210				bytecnt = linecnt * 80;
1211			} else {
1212				linecnt = 0;
1213				bytecnt = m->str_range;
1214			}
1215
1216			if (bytecnt == 0 || bytecnt > nbytes - offset)
1217				bytecnt = nbytes - offset;
1218			if (bytecnt > ms->regex_max)
1219				bytecnt = ms->regex_max;
1220
1221			buf = RCAST(const char *, s) + offset;
1222			end = last = RCAST(const char *, s) + bytecnt + offset;
1223			/* mget() guarantees buf <= last */
1224			for (lines = linecnt, b = buf; lines && b < end &&
1225			     ((b = CAST(const char *,
1226				 memchr(c = b, '\n', CAST(size_t, (end - b)))))
1227			     || (b = CAST(const char *,
1228				 memchr(c, '\r', CAST(size_t, (end - c))))));
1229			     lines--, b++) {
1230				last = b;
1231				if (b < end - 1 && b[0] == '\r' && b[1] == '\n')
1232					b++;
1233			}
1234			if (lines)
1235				last = RCAST(const char *, s) + bytecnt;
1236
1237			ms->search.s = buf;
1238			ms->search.s_len = last - buf;
1239			ms->search.offset = offset;
1240			ms->search.rm_len = 0;
1241			return 0;
1242		}
1243		case FILE_BESTRING16:
1244		case FILE_LESTRING16: {
1245			const unsigned char *src = s + offset;
1246			const unsigned char *esrc = s + nbytes;
1247			char *dst = p->s;
1248			char *edst = &p->s[sizeof(p->s) - 1];
1249
1250			if (type == FILE_BESTRING16)
1251				src++;
1252
1253			/* check that offset is within range */
1254			if (offset >= nbytes)
1255				break;
1256			for (/*EMPTY*/; src < esrc; src += 2, dst++) {
1257				if (dst < edst)
1258					*dst = *src;
1259				else
1260					break;
1261				if (*dst == '\0') {
1262					if (type == FILE_BESTRING16 ?
1263					    *(src - 1) != '\0' :
1264					    ((src + 1 < esrc) &&
1265					    *(src + 1) != '\0'))
1266						*dst = ' ';
1267				}
1268			}
1269			*edst = '\0';
1270			return 0;
1271		}
1272		case FILE_STRING:	/* XXX - these two should not need */
1273		case FILE_PSTRING:	/* to copy anything, but do anyway. */
1274		default:
1275			break;
1276		}
1277	}
1278
1279	if (offset >= nbytes) {
1280		(void)memset(p, '\0', sizeof(*p));
1281		return 0;
1282	}
1283	if (nbytes - offset < sizeof(*p))
1284		nbytes = nbytes - offset;
1285	else
1286		nbytes = sizeof(*p);
1287
1288	(void)memcpy(p, s + offset, nbytes);
1289
1290	/*
1291	 * the usefulness of padding with zeroes eludes me, it
1292	 * might even cause problems
1293	 */
1294	if (nbytes < sizeof(*p))
1295		(void)memset(((char *)(void *)p) + nbytes, '\0',
1296		    sizeof(*p) - nbytes);
1297	return 0;
1298}
1299
1300private uint32_t
1301do_ops(struct magic *m, intmax_t lhs, intmax_t off)
1302{
1303	intmax_t offset;
1304	if (off) {
1305		switch (m->in_op & FILE_OPS_MASK) {
1306		case FILE_OPAND:
1307			offset = lhs & off;
1308			break;
1309		case FILE_OPOR:
1310			offset = lhs | off;
1311			break;
1312		case FILE_OPXOR:
1313			offset = lhs ^ off;
1314			break;
1315		case FILE_OPADD:
1316			offset = lhs + off;
1317			break;
1318		case FILE_OPMINUS:
1319			offset = lhs - off;
1320			break;
1321		case FILE_OPMULTIPLY:
1322			offset = lhs * off;
1323			break;
1324		case FILE_OPDIVIDE:
1325			offset = lhs / off;
1326			break;
1327		case FILE_OPMODULO:
1328			offset = lhs % off;
1329			break;
1330		}
1331	} else
1332		offset = lhs;
1333	if (m->in_op & FILE_OPINVERSE)
1334		offset = ~offset;
1335
1336	return (uint32_t)offset;
1337}
1338
1339private int
1340mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
1341    size_t nbytes, size_t o, unsigned int cont_level, int mode, int text,
1342    int flip, uint16_t *indir_count, uint16_t *name_count,
1343    int *printed_something, int *need_separator, int *returnval)
1344{
1345	uint32_t offset = ms->offset;
1346	intmax_t lhs;
1347	file_pushbuf_t *pb;
1348	int rv, oneed_separator, in_type;
1349	char *rbuf;
1350	union VALUETYPE *p = &ms->ms_value;
1351	struct mlist ml;
1352
1353	if (*indir_count >= ms->indir_max) {
1354		file_error(ms, 0, "indirect count (%hu) exceeded",
1355		    *indir_count);
1356		return -1;
1357	}
1358
1359	if (*name_count >= ms->name_max) {
1360		file_error(ms, 0, "name use count (%hu) exceeded",
1361		    *name_count);
1362		return -1;
1363	}
1364
1365	if (mcopy(ms, p, m->type, m->flag & INDIR, s, (uint32_t)(offset + o),
1366	    (uint32_t)nbytes, m) == -1)
1367		return -1;
1368
1369	if ((ms->flags & MAGIC_DEBUG) != 0) {
1370		fprintf(stderr, "mget(type=%d, flag=%#x, offset=%u, o=%"
1371		    SIZE_T_FORMAT "u, " "nbytes=%" SIZE_T_FORMAT
1372		    "u, il=%hu, nc=%hu)\n",
1373		    m->type, m->flag, offset, o, nbytes,
1374		    *indir_count, *name_count);
1375		mdebug(offset, (char *)(void *)p, sizeof(union VALUETYPE));
1376#ifndef COMPILE_ONLY
1377		file_mdump(m);
1378#endif
1379	}
1380
1381	if (m->flag & INDIR) {
1382		intmax_t off = m->in_offset;
1383		const int sgn = m->in_op & FILE_OPSIGNED;
1384		if (m->in_op & FILE_OPINDIRECT) {
1385			const union VALUETYPE *q = CAST(const union VALUETYPE *,
1386			    ((const void *)(s + offset + off)));
1387			if (OFFSET_OOB(nbytes, offset + off, sizeof(*q)))
1388				return 0;
1389			switch (cvt_flip(m->in_type, flip)) {
1390			case FILE_BYTE:
1391				off = SEXT(sgn,8,q->b);
1392				break;
1393			case FILE_SHORT:
1394				off = SEXT(sgn,16,q->h);
1395				break;
1396			case FILE_BESHORT:
1397				off = SEXT(sgn,16,BE16(q));
1398				break;
1399			case FILE_LESHORT:
1400				off = SEXT(sgn,16,LE16(q));
1401				break;
1402			case FILE_LONG:
1403				off = SEXT(sgn,32,q->l);
1404				break;
1405			case FILE_BELONG:
1406			case FILE_BEID3:
1407				off = SEXT(sgn,32,BE32(q));
1408				break;
1409			case FILE_LEID3:
1410			case FILE_LELONG:
1411				off = SEXT(sgn,32,LE32(q));
1412				break;
1413			case FILE_MELONG:
1414				off = SEXT(sgn,32,ME32(q));
1415				break;
1416			}
1417			if ((ms->flags & MAGIC_DEBUG) != 0)
1418				fprintf(stderr, "indirect offs=%jd\n", off);
1419		}
1420		switch (in_type = cvt_flip(m->in_type, flip)) {
1421		case FILE_BYTE:
1422			if (OFFSET_OOB(nbytes, offset, 1))
1423				return 0;
1424			offset = do_ops(m, SEXT(sgn,8,p->b), off);
1425			break;
1426		case FILE_BESHORT:
1427			if (OFFSET_OOB(nbytes, offset, 2))
1428				return 0;
1429			offset = do_ops(m, SEXT(sgn,16,BE16(p)), off);
1430			break;
1431		case FILE_LESHORT:
1432			if (OFFSET_OOB(nbytes, offset, 2))
1433				return 0;
1434			offset = do_ops(m, SEXT(sgn,16,LE16(p)), off);
1435			break;
1436		case FILE_SHORT:
1437			if (OFFSET_OOB(nbytes, offset, 2))
1438				return 0;
1439			offset = do_ops(m, SEXT(sgn,16,p->h), off);
1440			break;
1441		case FILE_BELONG:
1442		case FILE_BEID3:
1443			if (OFFSET_OOB(nbytes, offset, 4))
1444				return 0;
1445			lhs = BE32(p);
1446			if (in_type == FILE_BEID3)
1447				lhs = cvt_id3(ms, (uint32_t)lhs);
1448			offset = do_ops(m, SEXT(sgn,32,lhs), off);
1449			break;
1450		case FILE_LELONG:
1451		case FILE_LEID3:
1452			if (OFFSET_OOB(nbytes, offset, 4))
1453				return 0;
1454			lhs = LE32(p);
1455			if (in_type == FILE_LEID3)
1456				lhs = cvt_id3(ms, (uint32_t)lhs);
1457			offset = do_ops(m, SEXT(sgn,32,lhs), off);
1458			break;
1459		case FILE_MELONG:
1460			if (OFFSET_OOB(nbytes, offset, 4))
1461				return 0;
1462			offset = do_ops(m, SEXT(sgn,32,ME32(p)), off);
1463			break;
1464		case FILE_LONG:
1465			if (OFFSET_OOB(nbytes, offset, 4))
1466				return 0;
1467			offset = do_ops(m, SEXT(sgn,32,p->l), off);
1468			break;
1469		default:
1470			break;
1471		}
1472
1473		if (m->flag & INDIROFFADD) {
1474			offset += ms->c.li[cont_level-1].off;
1475			if (offset == 0) {
1476				if ((ms->flags & MAGIC_DEBUG) != 0)
1477					fprintf(stderr,
1478					    "indirect *zero* offset\n");
1479				return 0;
1480			}
1481			if ((ms->flags & MAGIC_DEBUG) != 0)
1482				fprintf(stderr, "indirect +offs=%u\n", offset);
1483		}
1484		if (mcopy(ms, p, m->type, 0, s, offset, nbytes, m) == -1)
1485			return -1;
1486		ms->offset = offset;
1487
1488		if ((ms->flags & MAGIC_DEBUG) != 0) {
1489			mdebug(offset, (char *)(void *)p,
1490			    sizeof(union VALUETYPE));
1491#ifndef COMPILE_ONLY
1492			file_mdump(m);
1493#endif
1494		}
1495	}
1496
1497	/* Verify we have enough data to match magic type */
1498	switch (m->type) {
1499	case FILE_BYTE:
1500		if (OFFSET_OOB(nbytes, offset, 1))
1501			return 0;
1502		break;
1503
1504	case FILE_SHORT:
1505	case FILE_BESHORT:
1506	case FILE_LESHORT:
1507		if (OFFSET_OOB(nbytes, offset, 2))
1508			return 0;
1509		break;
1510
1511	case FILE_LONG:
1512	case FILE_BELONG:
1513	case FILE_LELONG:
1514	case FILE_MELONG:
1515	case FILE_DATE:
1516	case FILE_BEDATE:
1517	case FILE_LEDATE:
1518	case FILE_MEDATE:
1519	case FILE_LDATE:
1520	case FILE_BELDATE:
1521	case FILE_LELDATE:
1522	case FILE_MELDATE:
1523	case FILE_FLOAT:
1524	case FILE_BEFLOAT:
1525	case FILE_LEFLOAT:
1526		if (OFFSET_OOB(nbytes, offset, 4))
1527			return 0;
1528		break;
1529
1530	case FILE_DOUBLE:
1531	case FILE_BEDOUBLE:
1532	case FILE_LEDOUBLE:
1533		if (OFFSET_OOB(nbytes, offset, 8))
1534			return 0;
1535		break;
1536
1537	case FILE_STRING:
1538	case FILE_PSTRING:
1539	case FILE_SEARCH:
1540		if (OFFSET_OOB(nbytes, offset, m->vallen))
1541			return 0;
1542		break;
1543
1544	case FILE_REGEX:
1545		if (nbytes < offset)
1546			return 0;
1547		break;
1548
1549	case FILE_INDIRECT:
1550		if (m->str_flags & INDIRECT_RELATIVE)
1551			offset += CAST(uint32_t, o);
1552		if (offset == 0)
1553			return 0;
1554
1555		if (nbytes < offset)
1556			return 0;
1557
1558		if ((pb = file_push_buffer(ms)) == NULL)
1559			return -1;
1560
1561		(*indir_count)++;
1562		rv = file_softmagic(ms, s + offset, nbytes - offset,
1563		    indir_count, name_count, BINTEST, text);
1564
1565		if ((ms->flags & MAGIC_DEBUG) != 0)
1566			fprintf(stderr, "indirect @offs=%u[%d]\n", offset, rv);
1567
1568		rbuf = file_pop_buffer(ms, pb);
1569		if (rbuf == NULL && ms->event_flags & EVENT_HAD_ERR)
1570			return -1;
1571
1572		if (rv == 1) {
1573			if ((ms->flags & MAGIC_NODESC) == 0 &&
1574			    file_printf(ms, F(ms, m, "%u"), offset) == -1) {
1575				free(rbuf);
1576				return -1;
1577			}
1578			if (file_printf(ms, "%s", rbuf) == -1) {
1579				free(rbuf);
1580				return -1;
1581			}
1582		}
1583		free(rbuf);
1584		return rv;
1585
1586	case FILE_USE:
1587		if (nbytes < offset)
1588			return 0;
1589		rbuf = m->value.s;
1590		if (*rbuf == '^') {
1591			rbuf++;
1592			flip = !flip;
1593		}
1594		if (file_magicfind(ms, rbuf, &ml) == -1) {
1595			file_error(ms, 0, "cannot find entry `%s'", rbuf);
1596			return -1;
1597		}
1598		(*name_count)++;
1599		oneed_separator = *need_separator;
1600		if (m->flag & NOSPACE)
1601			*need_separator = 0;
1602		rv = match(ms, ml.magic, ml.nmagic, s, nbytes, offset + o,
1603		    mode, text, flip, indir_count, name_count,
1604		    printed_something, need_separator, returnval);
1605		if (rv != 1)
1606		    *need_separator = oneed_separator;
1607		return 1;
1608
1609	case FILE_NAME:
1610		if (ms->flags & MAGIC_NODESC)
1611			return 1;
1612		if (file_printf(ms, "%s", m->desc) == -1)
1613			return -1;
1614		return 1;
1615	case FILE_DER:
1616	case FILE_DEFAULT:	/* nothing to check */
1617	case FILE_CLEAR:
1618	default:
1619		break;
1620	}
1621	if (!mconvert(ms, m, flip))
1622		return 0;
1623	return 1;
1624}
1625
1626private uint64_t
1627file_strncmp(const char *s1, const char *s2, size_t len, uint32_t flags)
1628{
1629	/*
1630	 * Convert the source args to unsigned here so that (1) the
1631	 * compare will be unsigned as it is in strncmp() and (2) so
1632	 * the ctype functions will work correctly without extra
1633	 * casting.
1634	 */
1635	const unsigned char *a = (const unsigned char *)s1;
1636	const unsigned char *b = (const unsigned char *)s2;
1637	const unsigned char *eb = b + len;
1638	uint64_t v;
1639
1640	/*
1641	 * What we want here is v = strncmp(s1, s2, len),
1642	 * but ignoring any nulls.
1643	 */
1644	v = 0;
1645	if (0L == flags) { /* normal string: do it fast */
1646		while (len-- > 0)
1647			if ((v = *b++ - *a++) != '\0')
1648				break;
1649	}
1650	else { /* combine the others */
1651		while (len-- > 0) {
1652			if (b >= eb) {
1653				v = 1;
1654				break;
1655			}
1656			if ((flags & STRING_IGNORE_LOWERCASE) &&
1657			    islower(*a)) {
1658				if ((v = tolower(*b++) - *a++) != '\0')
1659					break;
1660			}
1661			else if ((flags & STRING_IGNORE_UPPERCASE) &&
1662			    isupper(*a)) {
1663				if ((v = toupper(*b++) - *a++) != '\0')
1664					break;
1665			}
1666			else if ((flags & STRING_COMPACT_WHITESPACE) &&
1667			    isspace(*a)) {
1668				a++;
1669				if (isspace(*b++)) {
1670					if (!isspace(*a))
1671						while (b < eb && isspace(*b))
1672							b++;
1673				}
1674				else {
1675					v = 1;
1676					break;
1677				}
1678			}
1679			else if ((flags & STRING_COMPACT_OPTIONAL_WHITESPACE) &&
1680			    isspace(*a)) {
1681				a++;
1682				while (b < eb && isspace(*b))
1683					b++;
1684			}
1685			else {
1686				if ((v = *b++ - *a++) != '\0')
1687					break;
1688			}
1689		}
1690	}
1691	return v;
1692}
1693
1694private uint64_t
1695file_strncmp16(const char *a, const char *b, size_t len, uint32_t flags)
1696{
1697	/*
1698	 * XXX - The 16-bit string compare probably needs to be done
1699	 * differently, especially if the flags are to be supported.
1700	 * At the moment, I am unsure.
1701	 */
1702	flags = 0;
1703	return file_strncmp(a, b, len, flags);
1704}
1705
1706private int
1707magiccheck(struct magic_set *ms, struct magic *m)
1708{
1709	uint64_t l = m->value.q;
1710	uint64_t v;
1711	float fl, fv;
1712	double dl, dv;
1713	int matched;
1714	union VALUETYPE *p = &ms->ms_value;
1715
1716	switch (m->type) {
1717	case FILE_BYTE:
1718		v = p->b;
1719		break;
1720
1721	case FILE_SHORT:
1722	case FILE_BESHORT:
1723	case FILE_LESHORT:
1724		v = p->h;
1725		break;
1726
1727	case FILE_LONG:
1728	case FILE_BELONG:
1729	case FILE_LELONG:
1730	case FILE_MELONG:
1731	case FILE_DATE:
1732	case FILE_BEDATE:
1733	case FILE_LEDATE:
1734	case FILE_MEDATE:
1735	case FILE_LDATE:
1736	case FILE_BELDATE:
1737	case FILE_LELDATE:
1738	case FILE_MELDATE:
1739		v = p->l;
1740		break;
1741
1742	case FILE_QUAD:
1743	case FILE_LEQUAD:
1744	case FILE_BEQUAD:
1745	case FILE_QDATE:
1746	case FILE_BEQDATE:
1747	case FILE_LEQDATE:
1748	case FILE_QLDATE:
1749	case FILE_BEQLDATE:
1750	case FILE_LEQLDATE:
1751	case FILE_QWDATE:
1752	case FILE_BEQWDATE:
1753	case FILE_LEQWDATE:
1754		v = p->q;
1755		break;
1756
1757	case FILE_FLOAT:
1758	case FILE_BEFLOAT:
1759	case FILE_LEFLOAT:
1760		fl = m->value.f;
1761		fv = p->f;
1762		switch (m->reln) {
1763		case 'x':
1764			matched = 1;
1765			break;
1766
1767		case '!':
1768			matched = fv != fl;
1769			break;
1770
1771		case '=':
1772			matched = fv == fl;
1773			break;
1774
1775		case '>':
1776			matched = fv > fl;
1777			break;
1778
1779		case '<':
1780			matched = fv < fl;
1781			break;
1782
1783		default:
1784			file_magerror(ms, "cannot happen with float: invalid relation `%c'",
1785			    m->reln);
1786			return -1;
1787		}
1788		return matched;
1789
1790	case FILE_DOUBLE:
1791	case FILE_BEDOUBLE:
1792	case FILE_LEDOUBLE:
1793		dl = m->value.d;
1794		dv = p->d;
1795		switch (m->reln) {
1796		case 'x':
1797			matched = 1;
1798			break;
1799
1800		case '!':
1801			matched = dv != dl;
1802			break;
1803
1804		case '=':
1805			matched = dv == dl;
1806			break;
1807
1808		case '>':
1809			matched = dv > dl;
1810			break;
1811
1812		case '<':
1813			matched = dv < dl;
1814			break;
1815
1816		default:
1817			file_magerror(ms, "cannot happen with double: invalid relation `%c'", m->reln);
1818			return -1;
1819		}
1820		return matched;
1821
1822	case FILE_DEFAULT:
1823	case FILE_CLEAR:
1824		l = 0;
1825		v = 0;
1826		break;
1827
1828	case FILE_STRING:
1829	case FILE_PSTRING:
1830		l = 0;
1831		v = file_strncmp(m->value.s, p->s, (size_t)m->vallen, m->str_flags);
1832		break;
1833
1834	case FILE_BESTRING16:
1835	case FILE_LESTRING16:
1836		l = 0;
1837		v = file_strncmp16(m->value.s, p->s, (size_t)m->vallen, m->str_flags);
1838		break;
1839
1840	case FILE_SEARCH: { /* search ms->search.s for the string m->value.s */
1841		size_t slen;
1842		size_t idx;
1843
1844		if (ms->search.s == NULL)
1845			return 0;
1846
1847		slen = MIN(m->vallen, sizeof(m->value.s));
1848		l = 0;
1849		v = 0;
1850
1851		for (idx = 0; m->str_range == 0 || idx < m->str_range; idx++) {
1852			if (slen + idx > ms->search.s_len)
1853				return 0;
1854
1855			v = file_strncmp(m->value.s, ms->search.s + idx, slen,
1856			    m->str_flags);
1857			if (v == 0) {	/* found match */
1858				ms->search.offset += idx;
1859				ms->search.rm_len = ms->search.s_len - idx;
1860				break;
1861			}
1862		}
1863		break;
1864	}
1865	case FILE_REGEX: {
1866		int rc;
1867		file_regex_t rx;
1868		const char *search;
1869
1870		if (ms->search.s == NULL)
1871			return 0;
1872
1873		l = 0;
1874		rc = file_regcomp(&rx, m->value.s,
1875		    REG_EXTENDED|REG_NEWLINE|
1876		    ((m->str_flags & STRING_IGNORE_CASE) ? REG_ICASE : 0));
1877		if (rc) {
1878			file_regerror(&rx, rc, ms);
1879			v = (uint64_t)-1;
1880		} else {
1881			regmatch_t pmatch;
1882			size_t slen = ms->search.s_len;
1883			char *copy;
1884			if (slen != 0) {
1885			    copy = CAST(char *, malloc(slen));
1886			    if (copy == NULL)  {
1887				file_regfree(&rx);
1888				file_error(ms, errno,
1889				    "can't allocate %" SIZE_T_FORMAT "u bytes",
1890				    slen);
1891				return -1;
1892			    }
1893			    memcpy(copy, ms->search.s, slen);
1894			    copy[--slen] = '\0';
1895			    search = copy;
1896			} else {
1897			    search = CCAST(char *, "");
1898			    copy = NULL;
1899			}
1900			rc = file_regexec(&rx, (const char *)search,
1901			    1, &pmatch, 0);
1902			free(copy);
1903			switch (rc) {
1904			case 0:
1905				ms->search.s += (int)pmatch.rm_so;
1906				ms->search.offset += (size_t)pmatch.rm_so;
1907				ms->search.rm_len =
1908				    (size_t)(pmatch.rm_eo - pmatch.rm_so);
1909				v = 0;
1910				break;
1911
1912			case REG_NOMATCH:
1913				v = 1;
1914				break;
1915
1916			default:
1917				file_regerror(&rx, rc, ms);
1918				v = (uint64_t)-1;
1919				break;
1920			}
1921		}
1922		file_regfree(&rx);
1923		if (v == (uint64_t)-1)
1924			return -1;
1925		break;
1926	}
1927	case FILE_INDIRECT:
1928	case FILE_USE:
1929	case FILE_NAME:
1930		return 1;
1931	case FILE_DER:
1932		matched = der_cmp(ms, m);
1933		if (matched == -1) {
1934			if ((ms->flags & MAGIC_DEBUG) != 0) {
1935				(void) fprintf(stderr,
1936				    "EOF comparing DER entries");
1937			}
1938			return 0;
1939		}
1940		return matched;
1941	default:
1942		file_magerror(ms, "invalid type %d in magiccheck()", m->type);
1943		return -1;
1944	}
1945
1946	v = file_signextend(ms, m, v);
1947
1948	switch (m->reln) {
1949	case 'x':
1950		if ((ms->flags & MAGIC_DEBUG) != 0)
1951			(void) fprintf(stderr, "%" INT64_T_FORMAT
1952			    "u == *any* = 1\n", (unsigned long long)v);
1953		matched = 1;
1954		break;
1955
1956	case '!':
1957		matched = v != l;
1958		if ((ms->flags & MAGIC_DEBUG) != 0)
1959			(void) fprintf(stderr, "%" INT64_T_FORMAT "u != %"
1960			    INT64_T_FORMAT "u = %d\n", (unsigned long long)v,
1961			    (unsigned long long)l, matched);
1962		break;
1963
1964	case '=':
1965		matched = v == l;
1966		if ((ms->flags & MAGIC_DEBUG) != 0)
1967			(void) fprintf(stderr, "%" INT64_T_FORMAT "u == %"
1968			    INT64_T_FORMAT "u = %d\n", (unsigned long long)v,
1969			    (unsigned long long)l, matched);
1970		break;
1971
1972	case '>':
1973		if (m->flag & UNSIGNED) {
1974			matched = v > l;
1975			if ((ms->flags & MAGIC_DEBUG) != 0)
1976				(void) fprintf(stderr, "%" INT64_T_FORMAT
1977				    "u > %" INT64_T_FORMAT "u = %d\n",
1978				    (unsigned long long)v,
1979				    (unsigned long long)l, matched);
1980		}
1981		else {
1982			matched = (int64_t) v > (int64_t) l;
1983			if ((ms->flags & MAGIC_DEBUG) != 0)
1984				(void) fprintf(stderr, "%" INT64_T_FORMAT
1985				    "d > %" INT64_T_FORMAT "d = %d\n",
1986				    (long long)v, (long long)l, matched);
1987		}
1988		break;
1989
1990	case '<':
1991		if (m->flag & UNSIGNED) {
1992			matched = v < l;
1993			if ((ms->flags & MAGIC_DEBUG) != 0)
1994				(void) fprintf(stderr, "%" INT64_T_FORMAT
1995				    "u < %" INT64_T_FORMAT "u = %d\n",
1996				    (unsigned long long)v,
1997				    (unsigned long long)l, matched);
1998		}
1999		else {
2000			matched = (int64_t) v < (int64_t) l;
2001			if ((ms->flags & MAGIC_DEBUG) != 0)
2002				(void) fprintf(stderr, "%" INT64_T_FORMAT
2003				    "d < %" INT64_T_FORMAT "d = %d\n",
2004				     (long long)v, (long long)l, matched);
2005		}
2006		break;
2007
2008	case '&':
2009		matched = (v & l) == l;
2010		if ((ms->flags & MAGIC_DEBUG) != 0)
2011			(void) fprintf(stderr, "((%" INT64_T_FORMAT "x & %"
2012			    INT64_T_FORMAT "x) == %" INT64_T_FORMAT
2013			    "x) = %d\n", (unsigned long long)v,
2014			    (unsigned long long)l, (unsigned long long)l,
2015			    matched);
2016		break;
2017
2018	case '^':
2019		matched = (v & l) != l;
2020		if ((ms->flags & MAGIC_DEBUG) != 0)
2021			(void) fprintf(stderr, "((%" INT64_T_FORMAT "x & %"
2022			    INT64_T_FORMAT "x) != %" INT64_T_FORMAT
2023			    "x) = %d\n", (unsigned long long)v,
2024			    (unsigned long long)l, (unsigned long long)l,
2025			    matched);
2026		break;
2027
2028	default:
2029		file_magerror(ms, "cannot happen: invalid relation `%c'",
2030		    m->reln);
2031		return -1;
2032	}
2033
2034	return matched;
2035}
2036
2037private int
2038handle_annotation(struct magic_set *ms, struct magic *m, int firstline)
2039{
2040	if ((ms->flags & MAGIC_APPLE) && m->apple[0]) {
2041		if (!firstline && file_printf(ms, "\n- ") == -1)
2042			return -1;
2043		if (file_printf(ms, "%.8s", m->apple) == -1)
2044			return -1;
2045		return 1;
2046	}
2047	if ((ms->flags & MAGIC_EXTENSION) && m->ext[0]) {
2048		if (!firstline && file_printf(ms, "\n- ") == -1)
2049			return -1;
2050		if (file_printf(ms, "%s", m->ext) == -1)
2051			return -1;
2052		return 1;
2053	}
2054	if ((ms->flags & MAGIC_MIME_TYPE) && m->mimetype[0]) {
2055		if (!firstline && file_printf(ms, "\n- ") == -1)
2056			return -1;
2057		if (file_printf(ms, "%s", m->mimetype) == -1)
2058			return -1;
2059		return 1;
2060	}
2061	return 0;
2062}
2063
2064private int
2065print_sep(struct magic_set *ms, int firstline)
2066{
2067//	if (ms->flags & MAGIC_NODESC)
2068//		return 0;
2069	if (firstline)
2070		return 0;
2071	/*
2072	 * we found another match
2073	 * put a newline and '-' to do some simple formatting
2074	 */
2075	return file_printf(ms, "\n- ");
2076}
2077