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