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