xref: /openbsd/usr.bin/file/magic-test.c (revision bb180e11)
1 /* $OpenBSD: magic-test.c,v 1.27 2019/01/15 09:24:59 nicm Exp $ */
2 
3 /*
4  * Copyright (c) 2015 Nicholas Marriott <nicm@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/types.h>
20 
21 #include <ctype.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <limits.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include <stdint.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <time.h>
31 #include <unistd.h>
32 #include <vis.h>
33 
34 #include "magic.h"
35 #include "xmalloc.h"
36 
37 static int magic_test_line(struct magic_line *, struct magic_state *);
38 
39 static struct magic_line *
magic_get_named(struct magic * m,const char * name)40 magic_get_named(struct magic *m, const char *name)
41 {
42 	struct magic_line	ml;
43 
44 	ml.name = name;
45 	return (RB_FIND(magic_named_tree, &m->named, &ml));
46 }
47 
48 static enum magic_type
magic_reverse_type(struct magic_state * ms,enum magic_type type)49 magic_reverse_type(struct magic_state *ms, enum magic_type type)
50 {
51 	if (!ms->reverse)
52 		return (type);
53 	switch (type) {
54 	case MAGIC_TYPE_BESHORT:
55 		return (MAGIC_TYPE_LESHORT);
56 	case MAGIC_TYPE_BELONG:
57 		return (MAGIC_TYPE_LELONG);
58 	case MAGIC_TYPE_BEQUAD:
59 		return (MAGIC_TYPE_LEQUAD);
60 	case MAGIC_TYPE_UBESHORT:
61 		return (MAGIC_TYPE_ULESHORT);
62 	case MAGIC_TYPE_UBELONG:
63 		return (MAGIC_TYPE_ULELONG);
64 	case MAGIC_TYPE_UBEQUAD:
65 		return (MAGIC_TYPE_ULEQUAD);
66 	case MAGIC_TYPE_BEFLOAT:
67 		return (MAGIC_TYPE_LEFLOAT);
68 	case MAGIC_TYPE_BEDOUBLE:
69 		return (MAGIC_TYPE_LEDOUBLE);
70 	case MAGIC_TYPE_BEDATE:
71 		return (MAGIC_TYPE_LEDATE);
72 	case MAGIC_TYPE_BEQDATE:
73 		return (MAGIC_TYPE_LEQDATE);
74 	case MAGIC_TYPE_BELDATE:
75 		return (MAGIC_TYPE_LELDATE);
76 	case MAGIC_TYPE_BEQLDATE:
77 		return (MAGIC_TYPE_LEQLDATE);
78 	case MAGIC_TYPE_UBEDATE:
79 		return (MAGIC_TYPE_ULEDATE);
80 	case MAGIC_TYPE_UBEQDATE:
81 		return (MAGIC_TYPE_ULEQDATE);
82 	case MAGIC_TYPE_UBELDATE:
83 		return (MAGIC_TYPE_ULELDATE);
84 	case MAGIC_TYPE_UBEQLDATE:
85 		return (MAGIC_TYPE_ULEQLDATE);
86 	case MAGIC_TYPE_LESHORT:
87 		return (MAGIC_TYPE_BESHORT);
88 	case MAGIC_TYPE_LELONG:
89 		return (MAGIC_TYPE_LELONG);
90 	case MAGIC_TYPE_LEQUAD:
91 		return (MAGIC_TYPE_LEQUAD);
92 	case MAGIC_TYPE_ULESHORT:
93 		return (MAGIC_TYPE_UBESHORT);
94 	case MAGIC_TYPE_ULELONG:
95 		return (MAGIC_TYPE_UBELONG);
96 	case MAGIC_TYPE_ULEQUAD:
97 		return (MAGIC_TYPE_UBEQUAD);
98 	case MAGIC_TYPE_LEFLOAT:
99 		return (MAGIC_TYPE_BEFLOAT);
100 	case MAGIC_TYPE_LEDOUBLE:
101 		return (MAGIC_TYPE_BEDOUBLE);
102 	case MAGIC_TYPE_LEDATE:
103 		return (MAGIC_TYPE_BEDATE);
104 	case MAGIC_TYPE_LEQDATE:
105 		return (MAGIC_TYPE_BEQDATE);
106 	case MAGIC_TYPE_LELDATE:
107 		return (MAGIC_TYPE_BELDATE);
108 	case MAGIC_TYPE_LEQLDATE:
109 		return (MAGIC_TYPE_BEQLDATE);
110 	case MAGIC_TYPE_ULEDATE:
111 		return (MAGIC_TYPE_UBEDATE);
112 	case MAGIC_TYPE_ULEQDATE:
113 		return (MAGIC_TYPE_UBEQDATE);
114 	case MAGIC_TYPE_ULELDATE:
115 		return (MAGIC_TYPE_UBELDATE);
116 	case MAGIC_TYPE_ULEQLDATE:
117 		return (MAGIC_TYPE_UBEQLDATE);
118 	default:
119 		return (type);
120 	}
121 }
122 
123 static int
magic_one_eq(char a,char b,int cflag)124 magic_one_eq(char a, char b, int cflag)
125 {
126 	if (a == b)
127 		return (1);
128 	if (cflag && islower((u_char)b) && tolower((u_char)a) == (u_char)b)
129 		return (1);
130 	return (0);
131 }
132 
133 static int
magic_test_eq(const char * ap,size_t asize,const char * bp,size_t bsize,int cflag,int bflag,int Bflag)134 magic_test_eq(const char *ap, size_t asize, const char *bp, size_t bsize,
135     int cflag, int bflag, int Bflag)
136 {
137 	size_t	aoff, boff, aspaces, bspaces;
138 
139 	aoff = boff = 0;
140 	while (aoff != asize && boff != bsize) {
141 		if (Bflag && isspace((u_char)ap[aoff])) {
142 			aspaces = 0;
143 			while (aoff != asize && isspace((u_char)ap[aoff])) {
144 				aspaces++;
145 				aoff++;
146 			}
147 			bspaces = 0;
148 			while (boff != bsize && isspace((u_char)bp[boff])) {
149 				bspaces++;
150 				boff++;
151 			}
152 			if (bspaces >= aspaces)
153 				continue;
154 			return (1);
155 		}
156 		if (magic_one_eq(ap[aoff], bp[boff], cflag)) {
157 			aoff++;
158 			boff++;
159 			continue;
160 		}
161 		if (bflag && isspace((u_char)bp[boff])) {
162 			boff++;
163 			continue;
164 		}
165 		if (ap[aoff] < bp[boff])
166 			return (-1);
167 		return (1);
168 	}
169 	return (0);
170 }
171 
172 static int
magic_copy_from(struct magic_state * ms,ssize_t offset,void * dst,size_t size)173 magic_copy_from(struct magic_state *ms, ssize_t offset, void *dst, size_t size)
174 {
175 	if (offset < 0)
176 		offset = ms->offset;
177 	if (offset + size > ms->size)
178 		return (-1);
179 	memcpy(dst, ms->base + offset, size);
180 	return (0);
181 }
182 
183 static void
magic_add_result(struct magic_state * ms,struct magic_line * ml,const char * fmt,...)184 magic_add_result(struct magic_state *ms, struct magic_line *ml,
185     const char *fmt, ...)
186 {
187 	va_list	 ap;
188 	int	 separate;
189 	char	*s, *tmp, *add;
190 
191 	va_start(ap, fmt);
192 	if (ml->stringify) {
193 		if (vasprintf(&s, fmt, ap) == -1) {
194 			va_end(ap);
195 			return;
196 		}
197 		va_end(ap);
198 		if (asprintf(&tmp, ml->result, s) == -1) {
199 			free(s);
200 			return;
201 		}
202 		free(s);
203 	} else {
204 		if (vasprintf(&tmp, ml->result, ap) == -1) {
205 			va_end(ap);
206 			return;
207 		}
208 		va_end(ap);
209 	}
210 
211 	separate = 1;
212 	if (tmp[0] == '\\' && tmp[1] == 'b') {
213 		separate = 0;
214 		add = tmp + 2;
215 	} else
216 		add = tmp;
217 
218 	if (separate && *ms->out != '\0')
219 		strlcat(ms->out, " ", sizeof ms->out);
220 	strlcat(ms->out, add, sizeof ms->out);
221 
222 	free(tmp);
223 }
224 
225 static void
magic_add_string(struct magic_state * ms,struct magic_line * ml,const char * s,size_t slen)226 magic_add_string(struct magic_state *ms, struct magic_line *ml,
227     const char *s, size_t slen)
228 {
229 	char	*out;
230 	size_t	 outlen, offset;
231 
232 	outlen = MAGIC_STRING_SIZE;
233 	if (outlen > slen)
234 		outlen = slen;
235 	for (offset = 0; offset < outlen; offset++) {
236 		if (s[offset] == '\0' || !isprint((u_char)s[offset])) {
237 			outlen = offset;
238 			break;
239 		}
240 	}
241 	out = xreallocarray(NULL, 4, outlen + 1);
242 	strvisx(out, s, outlen, VIS_TAB|VIS_NL|VIS_CSTYLE|VIS_OCTAL);
243 	magic_add_result(ms, ml, "%s", out);
244 	free(out);
245 }
246 
247 static int
magic_test_signed(struct magic_line * ml,int64_t value,int64_t wanted)248 magic_test_signed(struct magic_line *ml, int64_t value, int64_t wanted)
249 {
250 	switch (ml->test_operator) {
251 	case 'x':
252 		return (1);
253 	case '<':
254 		return (value < wanted);
255 	case '[':
256 		return (value <= wanted);
257 	case '>':
258 		return (value > wanted);
259 	case ']':
260 		return (value >= wanted);
261 	case '=':
262 		return (value == wanted);
263 	case '&':
264 		return ((value & wanted) == wanted);
265 	case '^':
266 		return ((~value & wanted) == wanted);
267 	}
268 	return (-1);
269 }
270 
271 static int
magic_test_unsigned(struct magic_line * ml,uint64_t value,uint64_t wanted)272 magic_test_unsigned(struct magic_line *ml, uint64_t value, uint64_t wanted)
273 {
274 	switch (ml->test_operator) {
275 	case 'x':
276 		return (1);
277 	case '<':
278 		return (value < wanted);
279 	case '[':
280 		return (value <= wanted);
281 	case '>':
282 		return (value > wanted);
283 	case ']':
284 		return (value >= wanted);
285 	case '=':
286 		return (value == wanted);
287 	case '&':
288 		return ((value & wanted) == wanted);
289 	case '^':
290 		return ((~value & wanted) == wanted);
291 	}
292 	return (-1);
293 }
294 
295 static int
magic_test_double(struct magic_line * ml,double value,double wanted)296 magic_test_double(struct magic_line *ml, double value, double wanted)
297 {
298 	switch (ml->test_operator) {
299 	case 'x':
300 		return (1);
301 	case '=':
302 		return (value == wanted);
303 	}
304 	return (-1);
305 }
306 
307 static int
magic_test_type_none(__unused struct magic_line * ml,__unused struct magic_state * ms)308 magic_test_type_none(__unused struct magic_line *ml,
309     __unused struct magic_state *ms)
310 {
311 	return (0);
312 }
313 
314 static int
magic_test_type_byte(struct magic_line * ml,struct magic_state * ms)315 magic_test_type_byte(struct magic_line *ml, struct magic_state *ms)
316 {
317 	int8_t	value;
318 	int	result;
319 
320 	if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
321 		return (0);
322 
323 	if (ml->type_operator == '&')
324 		value &= (int8_t)ml->type_operand;
325 	else if (ml->type_operator == '-')
326 		value -= (int8_t)ml->type_operand;
327 	else if (ml->type_operator == '+')
328 		value += (int8_t)ml->type_operand;
329 	else if (ml->type_operator == '/')
330 		value /= (int8_t)ml->type_operand;
331 	else if (ml->type_operator == '%')
332 		value %= (int8_t)ml->type_operand;
333 	else if (ml->type_operator == '*')
334 		value *= (int8_t)ml->type_operand;
335 	else if (ml->type_operator != ' ')
336 		return (-1);
337 
338 	result = magic_test_signed(ml, value, (int8_t)ml->test_signed);
339 	if (result == !ml->test_not && ml->result != NULL) {
340 		magic_add_result(ms, ml, "%c", (int)value);
341 		ms->offset += sizeof value;
342 	}
343 	return (result);
344 }
345 
346 static int
magic_test_type_short(struct magic_line * ml,struct magic_state * ms)347 magic_test_type_short(struct magic_line *ml, struct magic_state *ms)
348 {
349 	int16_t value;
350 	int	result;
351 
352 	if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
353 		return (0);
354 	if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_BESHORT))
355 		value = be16toh(value);
356 	if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LESHORT))
357 		value = le16toh(value);
358 
359 	if (ml->type_operator == '&')
360 		value &= (int16_t)ml->type_operand;
361 	else if (ml->type_operator == '-')
362 		value -= (int16_t)ml->type_operand;
363 	else if (ml->type_operator == '+')
364 		value += (int16_t)ml->type_operand;
365 	else if (ml->type_operator == '/')
366 		value /= (int16_t)ml->type_operand;
367 	else if (ml->type_operator == '%')
368 		value %= (int16_t)ml->type_operand;
369 	else if (ml->type_operator == '*')
370 		value *= (int16_t)ml->type_operand;
371 	else if (ml->type_operator != ' ')
372 		return (-1);
373 
374 	result = magic_test_signed(ml, value, (int16_t)ml->test_signed);
375 	if (result == !ml->test_not && ml->result != NULL) {
376 		magic_add_result(ms, ml, "%hd", (int)value);
377 		ms->offset += sizeof value;
378 	}
379 	return (result);
380 }
381 
382 static int
magic_test_type_long(struct magic_line * ml,struct magic_state * ms)383 magic_test_type_long(struct magic_line *ml, struct magic_state *ms)
384 {
385 	int32_t value;
386 	int	result;
387 
388 	if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
389 		return (0);
390 	if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_BELONG))
391 		value = be32toh(value);
392 	if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LELONG))
393 		value = le32toh(value);
394 
395 	if (ml->type_operator == '&')
396 		value &= (int32_t)ml->type_operand;
397 	else if (ml->type_operator == '-')
398 		value -= (int32_t)ml->type_operand;
399 	else if (ml->type_operator == '+')
400 		value += (int32_t)ml->type_operand;
401 	else if (ml->type_operator == '/')
402 		value /= (int32_t)ml->type_operand;
403 	else if (ml->type_operator == '%')
404 		value %= (int32_t)ml->type_operand;
405 	else if (ml->type_operator == '*')
406 		value *= (int32_t)ml->type_operand;
407 	else if (ml->type_operator != ' ')
408 		return (-1);
409 
410 	result = magic_test_signed(ml, value, (int32_t)ml->test_signed);
411 	if (result == !ml->test_not && ml->result != NULL) {
412 		magic_add_result(ms, ml, "%d", (int)value);
413 		ms->offset += sizeof value;
414 	}
415 	return (result);
416 }
417 
418 static int
magic_test_type_quad(struct magic_line * ml,struct magic_state * ms)419 magic_test_type_quad(struct magic_line *ml, struct magic_state *ms)
420 {
421 	int64_t value;
422 	int	result;
423 
424 	if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
425 		return (0);
426 	if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_BEQUAD))
427 		value = be64toh(value);
428 	if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LEQUAD))
429 		value = le64toh(value);
430 
431 	if (ml->type_operator == '&')
432 		value &= (int64_t)ml->type_operand;
433 	else if (ml->type_operator == '-')
434 		value -= (int64_t)ml->type_operand;
435 	else if (ml->type_operator == '+')
436 		value += (int64_t)ml->type_operand;
437 	else if (ml->type_operator == '/')
438 		value /= (int64_t)ml->type_operand;
439 	else if (ml->type_operator == '%')
440 		value %= (int64_t)ml->type_operand;
441 	else if (ml->type_operator == '*')
442 		value *= (int64_t)ml->type_operand;
443 	else if (ml->type_operator != ' ')
444 		return (-1);
445 
446 	result = magic_test_signed(ml, value, (int64_t)ml->test_signed);
447 	if (result == !ml->test_not && ml->result != NULL) {
448 		magic_add_result(ms, ml, "%lld", (long long)value);
449 		ms->offset += sizeof value;
450 	}
451 	return (result);
452 }
453 
454 static int
magic_test_type_ubyte(struct magic_line * ml,struct magic_state * ms)455 magic_test_type_ubyte(struct magic_line *ml, struct magic_state *ms)
456 {
457 	uint8_t value;
458 	int	result;
459 
460 	if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
461 		return (0);
462 
463 	if (ml->type_operator == '&')
464 		value &= (uint8_t)ml->type_operand;
465 	else if (ml->type_operator == '-')
466 		value -= (uint8_t)ml->type_operand;
467 	else if (ml->type_operator == '+')
468 		value += (uint8_t)ml->type_operand;
469 	else if (ml->type_operator == '/')
470 		value /= (uint8_t)ml->type_operand;
471 	else if (ml->type_operator == '%')
472 		value %= (uint8_t)ml->type_operand;
473 	else if (ml->type_operator == '*')
474 		value *= (uint8_t)ml->type_operand;
475 	else if (ml->type_operator != ' ')
476 		return (-1);
477 
478 	result = magic_test_unsigned(ml, value, (uint8_t)ml->test_unsigned);
479 	if (result == !ml->test_not && ml->result != NULL) {
480 		magic_add_result(ms, ml, "%c", (unsigned int)value);
481 		ms->offset += sizeof value;
482 	}
483 	return (result);
484 }
485 
486 static int
magic_test_type_ushort(struct magic_line * ml,struct magic_state * ms)487 magic_test_type_ushort(struct magic_line *ml, struct magic_state *ms)
488 {
489 	uint16_t	value;
490 	int		result;
491 
492 	if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
493 		return (0);
494 	if (ml->type == MAGIC_TYPE_UBESHORT)
495 		value = be16toh(value);
496 	if (ml->type == MAGIC_TYPE_ULESHORT)
497 		value = le16toh(value);
498 
499 	if (ml->type_operator == '&')
500 		value &= (uint16_t)ml->type_operand;
501 	else if (ml->type_operator == '-')
502 		value -= (uint16_t)ml->type_operand;
503 	else if (ml->type_operator == '+')
504 		value += (uint16_t)ml->type_operand;
505 	else if (ml->type_operator == '/')
506 		value /= (uint16_t)ml->type_operand;
507 	else if (ml->type_operator == '%')
508 		value %= (uint16_t)ml->type_operand;
509 	else if (ml->type_operator == '*')
510 		value *= (uint16_t)ml->type_operand;
511 	else if (ml->type_operator != ' ')
512 		return (-1);
513 
514 	result = magic_test_unsigned(ml, value, (uint16_t)ml->test_unsigned);
515 	if (result == !ml->test_not && ml->result != NULL) {
516 		magic_add_result(ms, ml, "%hu", (unsigned int)value);
517 		ms->offset += sizeof value;
518 	}
519 	return (result);
520 }
521 
522 static int
magic_test_type_ulong(struct magic_line * ml,struct magic_state * ms)523 magic_test_type_ulong(struct magic_line *ml, struct magic_state *ms)
524 {
525 	uint32_t	value;
526 	int		result;
527 
528 	if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
529 		return (0);
530 	if (ml->type == MAGIC_TYPE_UBELONG)
531 		value = be32toh(value);
532 	if (ml->type == MAGIC_TYPE_ULELONG)
533 		value = le32toh(value);
534 
535 	if (ml->type_operator == '&')
536 		value &= (uint32_t)ml->type_operand;
537 	else if (ml->type_operator == '-')
538 		value -= (uint32_t)ml->type_operand;
539 	else if (ml->type_operator == '+')
540 		value += (uint32_t)ml->type_operand;
541 	else if (ml->type_operator == '/')
542 		value /= (uint32_t)ml->type_operand;
543 	else if (ml->type_operator == '%')
544 		value %= (uint32_t)ml->type_operand;
545 	else if (ml->type_operator == '*')
546 		value *= (uint32_t)ml->type_operand;
547 	else if (ml->type_operator != ' ')
548 		return (-1);
549 
550 	result = magic_test_unsigned(ml, value, (uint32_t)ml->test_unsigned);
551 	if (result == !ml->test_not && ml->result != NULL) {
552 		magic_add_result(ms, ml, "%u", (unsigned int)value);
553 		ms->offset += sizeof value;
554 	}
555 	return (result);
556 }
557 
558 static int
magic_test_type_uquad(struct magic_line * ml,struct magic_state * ms)559 magic_test_type_uquad(struct magic_line *ml, struct magic_state *ms)
560 {
561 	uint64_t	value;
562 	int		result;
563 
564 	if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
565 		return (0);
566 	if (ml->type == MAGIC_TYPE_UBEQUAD)
567 		value = be64toh(value);
568 	if (ml->type == MAGIC_TYPE_ULEQUAD)
569 		value = le64toh(value);
570 
571 	if (ml->type_operator == '&')
572 		value &= (uint64_t)ml->type_operand;
573 	else if (ml->type_operator == '-')
574 		value -= (uint64_t)ml->type_operand;
575 	else if (ml->type_operator == '+')
576 		value += (uint64_t)ml->type_operand;
577 	else if (ml->type_operator == '/')
578 		value /= (uint64_t)ml->type_operand;
579 	else if (ml->type_operator == '%')
580 		value %= (uint64_t)ml->type_operand;
581 	else if (ml->type_operator == '*')
582 		value *= (uint64_t)ml->type_operand;
583 	else if (ml->type_operator != ' ')
584 		return (-1);
585 
586 	result = magic_test_unsigned(ml, value, (uint64_t)ml->test_unsigned);
587 	if (result == !ml->test_not && ml->result != NULL) {
588 		magic_add_result(ms, ml, "%llu", (unsigned long long)value);
589 		ms->offset += sizeof value;
590 	}
591 	return (result);
592 }
593 
594 static int
magic_test_type_float(struct magic_line * ml,struct magic_state * ms)595 magic_test_type_float(struct magic_line *ml, struct magic_state *ms)
596 {
597 	uint32_t	value0;
598 	float		value;
599 	int		result;
600 
601 	if (magic_copy_from(ms, -1, &value0, sizeof value0) != 0)
602 		return (0);
603 	if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_BEFLOAT))
604 		value0 = be32toh(value0);
605 	if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LEFLOAT))
606 		value0 = le32toh(value0);
607 	memcpy(&value, &value0, sizeof value);
608 
609 	if (ml->type_operator != ' ')
610 		return (-1);
611 
612 	result = magic_test_double(ml, value, (float)ml->test_double);
613 	if (result == !ml->test_not && ml->result != NULL) {
614 		magic_add_result(ms, ml, "%g", value);
615 		ms->offset += sizeof value0;
616 	}
617 	return (1);
618 }
619 
620 static int
magic_test_type_double(struct magic_line * ml,struct magic_state * ms)621 magic_test_type_double(struct magic_line *ml, struct magic_state *ms)
622 {
623 	uint64_t	value0;
624 	double		value;
625 	int		result;
626 
627 	if (magic_copy_from(ms, -1, &value0, sizeof value0) != 0)
628 		return (0);
629 	if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_BEDOUBLE))
630 		value0 = be64toh(value0);
631 	if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LEDOUBLE))
632 		value0 = le64toh(value0);
633 	memcpy(&value, &value0, sizeof value);
634 
635 	if (ml->type_operator != ' ')
636 		return (-1);
637 
638 	result = magic_test_double(ml, value, (double)ml->test_double);
639 	if (result == !ml->test_not && ml->result != NULL) {
640 		magic_add_result(ms, ml, "%g", value);
641 		ms->offset += sizeof value0;
642 	}
643 	return (1);
644 }
645 
646 static int
magic_test_type_string(struct magic_line * ml,struct magic_state * ms)647 magic_test_type_string(struct magic_line *ml, struct magic_state *ms)
648 {
649 	const char	*s, *cp;
650 	size_t		 slen;
651 	int		 result, cflag = 0, bflag = 0, Bflag = 0;
652 
653 	cp = &ml->type_string[(sizeof "string") - 1];
654 	if (*cp != '\0') {
655 		if (*cp != '/')
656 			return (-1);
657 		cp++;
658 		for (; *cp != '\0'; cp++) {
659 			switch (*cp) {
660 			case 'B':
661 			case 'W':
662 				Bflag = 1;
663 				break;
664 			case 'b':
665 			case 'w':
666 				bflag = 1;
667 				break;
668 			case 'c':
669 				cflag = 1;
670 				break;
671 			case 't':
672 				break;
673 			default:
674 				return (-1);
675 			}
676 		}
677 	}
678 
679 	s = ms->base + ms->offset;
680 	slen = ms->size - ms->offset;
681 	if (slen < ml->test_string_size)
682 		return (0);
683 
684 	result = magic_test_eq(s, slen, ml->test_string, ml->test_string_size,
685 	    cflag, bflag, Bflag);
686 	switch (ml->test_operator) {
687 	case 'x':
688 		result = 1;
689 		break;
690 	case '<':
691 		result = result < 0;
692 		break;
693 	case '>':
694 		result = result > 0;
695 		break;
696 	case '=':
697 		slen = ml->test_string_size; /* only print what was found */
698 		result = result == 0;
699 		break;
700 	default:
701 		result = -1;
702 		break;
703 	}
704 	if (result == !ml->test_not) {
705 		if (ml->result != NULL)
706 			magic_add_string(ms, ml, s, slen);
707 		if (result && ml->test_operator == '=')
708 			ms->offset = s - ms->base + ml->test_string_size;
709 	}
710 	return (result);
711 }
712 
713 static int
magic_test_type_pstring(struct magic_line * ml,struct magic_state * ms)714 magic_test_type_pstring(struct magic_line *ml, struct magic_state *ms)
715 {
716 	const char	*s, *cp;
717 	size_t		 slen;
718 	int		 result;
719 
720 	cp = &ml->type_string[(sizeof "pstring") - 1];
721 	if (*cp != '\0') {
722 		if (*cp != '/')
723 			return (-1);
724 		cp++;
725 		for (; *cp != '\0'; cp++) {
726 			switch (*cp) {
727 			default:
728 				return (-1);
729 			}
730 		}
731 	}
732 
733 	s = ms->base + ms->offset;
734 	if (ms->size - ms->offset < 1)
735 		return (-1);
736 	slen = *(u_char *)s;
737 	if (slen + 1 > ms->size - ms->offset)
738 		return (-1);
739 	s++;
740 
741 	if (slen < ml->test_string_size)
742 		result = -1;
743 	else if (slen > ml->test_string_size)
744 		result = 1;
745 	else
746 		result = memcmp(s, ml->test_string, ml->test_string_size);
747 	switch (ml->test_operator) {
748 	case 'x':
749 		result = 1;
750 		break;
751 	case '<':
752 		result = result < 0;
753 		break;
754 	case '>':
755 		result = result > 0;
756 		break;
757 	case '=':
758 		result = result == 0;
759 		break;
760 	default:
761 		result = -1;
762 		break;
763 	}
764 	if (result == !ml->test_not) {
765 		if (ml->result != NULL)
766 			magic_add_string(ms, ml, s, slen);
767 		if (result && ml->test_operator == '=')
768 			ms->offset += slen + 1;
769 	}
770 	return (result);
771 }
772 
773 static int
magic_test_type_date(struct magic_line * ml,struct magic_state * ms)774 magic_test_type_date(struct magic_line *ml, struct magic_state *ms)
775 {
776 	int32_t	value;
777 	int	result;
778 	time_t	t;
779 	char	s[64];
780 
781 	if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
782 		return (0);
783 	if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_BEDATE) ||
784 	    ml->type == magic_reverse_type(ms, MAGIC_TYPE_BELDATE))
785 		value = be32toh(value);
786 	if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LEDATE) ||
787 	    ml->type == magic_reverse_type(ms, MAGIC_TYPE_LELDATE))
788 		value = le32toh(value);
789 
790 	if (ml->type_operator == '&')
791 		value &= (int32_t)ml->type_operand;
792 	else if (ml->type_operator == '-')
793 		value -= (int32_t)ml->type_operand;
794 	else if (ml->type_operator == '+')
795 		value += (int32_t)ml->type_operand;
796 	else if (ml->type_operator != ' ')
797 		return (-1);
798 
799 	result = magic_test_signed(ml, value, (int32_t)ml->test_signed);
800 	if (result == !ml->test_not && ml->result != NULL) {
801 		t = value;
802 		switch (ml->type) {
803 		case MAGIC_TYPE_LDATE:
804 		case MAGIC_TYPE_LELDATE:
805 		case MAGIC_TYPE_BELDATE:
806 			ctime_r(&t, s);
807 			break;
808 		default:
809 			asctime_r(gmtime(&t), s);
810 			break;
811 		}
812 		s[strcspn(s, "\n")] = '\0';
813 		magic_add_result(ms, ml, "%s", s);
814 		ms->offset += sizeof value;
815 	}
816 	return (result);
817 }
818 
819 static int
magic_test_type_qdate(struct magic_line * ml,struct magic_state * ms)820 magic_test_type_qdate(struct magic_line *ml, struct magic_state *ms)
821 {
822 	int64_t value;
823 	int	result;
824 	time_t	t;
825 	char	s[64];
826 
827 	if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
828 		return (0);
829 	if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_BEQDATE) ||
830 	    ml->type == magic_reverse_type(ms, MAGIC_TYPE_BEQLDATE))
831 		value = be64toh(value);
832 	if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LEQDATE) ||
833 	    ml->type == magic_reverse_type(ms, MAGIC_TYPE_LEQLDATE))
834 		value = le64toh(value);
835 
836 	if (ml->type_operator == '&')
837 		value &= (int64_t)ml->type_operand;
838 	else if (ml->type_operator == '-')
839 		value -= (int64_t)ml->type_operand;
840 	else if (ml->type_operator == '+')
841 		value += (int64_t)ml->type_operand;
842 	else if (ml->type_operator != ' ')
843 		return (-1);
844 
845 	result = magic_test_signed(ml, value, (int64_t)ml->test_signed);
846 	if (result == !ml->test_not && ml->result != NULL) {
847 		t = value;
848 		switch (ml->type) {
849 		case MAGIC_TYPE_QLDATE:
850 		case MAGIC_TYPE_LEQLDATE:
851 		case MAGIC_TYPE_BEQLDATE:
852 			ctime_r(&t, s);
853 			break;
854 		default:
855 			asctime_r(gmtime(&t), s);
856 			break;
857 		}
858 		s[strcspn(s, "\n")] = '\0';
859 		magic_add_result(ms, ml, "%s", s);
860 		ms->offset += sizeof value;
861 	}
862 	return (result);
863 }
864 
865 static int
magic_test_type_udate(struct magic_line * ml,struct magic_state * ms)866 magic_test_type_udate(struct magic_line *ml, struct magic_state *ms)
867 {
868 	uint32_t	value;
869 	int		result;
870 	time_t		t;
871 	char		s[64];
872 
873 	if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
874 		return (0);
875 	if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_BEDATE) ||
876 	    ml->type == magic_reverse_type(ms, MAGIC_TYPE_BELDATE))
877 		value = be32toh(value);
878 	if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LEDATE) ||
879 	    ml->type == magic_reverse_type(ms, MAGIC_TYPE_LELDATE))
880 		value = le32toh(value);
881 
882 	if (ml->type_operator == '&')
883 		value &= (uint32_t)ml->type_operand;
884 	else if (ml->type_operator == '-')
885 		value -= (uint32_t)ml->type_operand;
886 	else if (ml->type_operator == '+')
887 		value += (uint32_t)ml->type_operand;
888 	else if (ml->type_operator != ' ')
889 		return (-1);
890 
891 	result = magic_test_unsigned(ml, value, (uint32_t)ml->test_unsigned);
892 	if (result == !ml->test_not && ml->result != NULL) {
893 		t = value;
894 		switch (ml->type) {
895 		case MAGIC_TYPE_LDATE:
896 		case MAGIC_TYPE_LELDATE:
897 		case MAGIC_TYPE_BELDATE:
898 			ctime_r(&t, s);
899 			break;
900 		default:
901 			asctime_r(gmtime(&t), s);
902 			break;
903 		}
904 		s[strcspn(s, "\n")] = '\0';
905 		magic_add_result(ms, ml, "%s", s);
906 		ms->offset += sizeof value;
907 	}
908 	return (result);
909 }
910 
911 static int
magic_test_type_uqdate(struct magic_line * ml,struct magic_state * ms)912 magic_test_type_uqdate(struct magic_line *ml, struct magic_state *ms)
913 {
914 	uint64_t	value;
915 	int		result;
916 	time_t		t;
917 	char		s[64];
918 
919 	if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
920 		return (0);
921 	if (ml->type == MAGIC_TYPE_UBEQDATE ||
922 	    ml->type == MAGIC_TYPE_UBEQLDATE)
923 		value = be64toh(value);
924 	if (ml->type == MAGIC_TYPE_ULEQDATE ||
925 	    ml->type == MAGIC_TYPE_ULEQLDATE)
926 		value = le64toh(value);
927 
928 	if (ml->type_operator == '&')
929 		value &= (uint64_t)ml->type_operand;
930 	else if (ml->type_operator == '-')
931 		value -= (uint64_t)ml->type_operand;
932 	else if (ml->type_operator == '+')
933 		value += (uint64_t)ml->type_operand;
934 	else if (ml->type_operator != ' ')
935 		return (-1);
936 
937 	result = magic_test_unsigned(ml, value, (uint64_t)ml->test_unsigned);
938 	if (result == !ml->test_not && ml->result != NULL) {
939 		t = value;
940 		switch (ml->type) {
941 		case MAGIC_TYPE_UQLDATE:
942 		case MAGIC_TYPE_ULEQLDATE:
943 		case MAGIC_TYPE_UBEQLDATE:
944 			ctime_r(&t, s);
945 			break;
946 		default:
947 			asctime_r(gmtime(&t), s);
948 			break;
949 		}
950 		s[strcspn(s, "\n")] = '\0';
951 		magic_add_result(ms, ml, "%s", s);
952 		ms->offset += sizeof value;
953 	}
954 	return (result);
955 }
956 
957 static int
magic_test_type_bestring16(__unused struct magic_line * ml,__unused struct magic_state * ms)958 magic_test_type_bestring16(__unused struct magic_line *ml,
959     __unused struct magic_state *ms)
960 {
961 	return (-2);
962 }
963 
964 static int
magic_test_type_lestring16(__unused struct magic_line * ml,__unused struct magic_state * ms)965 magic_test_type_lestring16(__unused struct magic_line *ml,
966     __unused struct magic_state *ms)
967 {
968 	return (-2);
969 }
970 
971 static int
magic_test_type_melong(__unused struct magic_line * ml,__unused struct magic_state * ms)972 magic_test_type_melong(__unused struct magic_line *ml,
973     __unused struct magic_state *ms)
974 {
975 	return (-2);
976 }
977 
978 static int
magic_test_type_medate(__unused struct magic_line * ml,__unused struct magic_state * ms)979 magic_test_type_medate(__unused struct magic_line *ml,
980     __unused struct magic_state *ms)
981 {
982 	return (-2);
983 }
984 
985 static int
magic_test_type_meldate(__unused struct magic_line * ml,__unused struct magic_state * ms)986 magic_test_type_meldate(__unused struct magic_line *ml,
987     __unused struct magic_state *ms)
988 {
989 	return (-2);
990 }
991 
992 static int
magic_test_type_regex(struct magic_line * ml,struct magic_state * ms)993 magic_test_type_regex(struct magic_line *ml, struct magic_state *ms)
994 {
995 	const char	*cp;
996 	regex_t		 re;
997 	regmatch_t	 m;
998 	int		 result, flags = 0, sflag = 0;
999 
1000 	cp = &ml->type_string[(sizeof "regex") - 1];
1001 	if (*cp != '\0') {
1002 		if (*cp != '/')
1003 			return (-1);
1004 		cp++;
1005 		for (; *cp != '\0'; cp++) {
1006 			switch (*cp) {
1007 			case 's':
1008 				sflag = 1;
1009 				break;
1010 			case 'c':
1011 				flags |= REG_ICASE;
1012 				break;
1013 			default:
1014 				return (-1);
1015 			}
1016 		}
1017 	}
1018 
1019 	if (regcomp(&re, ml->test_string, REG_EXTENDED|REG_NEWLINE|flags) != 0)
1020 		return (-1);
1021 	m.rm_so = ms->offset;
1022 	m.rm_eo = ms->size;
1023 
1024 	result = (regexec(&re, ms->base, 1, &m, REG_STARTEND) == 0);
1025 	if (result == !ml->test_not) {
1026 		if (ml->result != NULL) {
1027 			magic_add_string(ms, ml, ms->base + m.rm_so,
1028 			    m.rm_eo - m.rm_so);
1029 		}
1030 		if (result) {
1031 			if (sflag)
1032 				ms->offset = m.rm_so;
1033 			else
1034 				ms->offset = m.rm_eo;
1035 		}
1036 	}
1037 	regfree(&re);
1038 	return (result);
1039 }
1040 
1041 static int
magic_test_type_search(struct magic_line * ml,struct magic_state * ms)1042 magic_test_type_search(struct magic_line *ml, struct magic_state *ms)
1043 {
1044 	const char	*cp, *endptr, *start, *found;
1045 	size_t		 size, end, i;
1046 	uint64_t	 range;
1047 	int		 result, n, cflag = 0, bflag = 0, Bflag = 0;
1048 
1049 	cp = &ml->type_string[(sizeof "search") - 1];
1050 	if (*cp != '\0') {
1051 		if (*cp != '/')
1052 			return (-1);
1053 		cp++;
1054 
1055 		endptr = magic_strtoull(cp, &range);
1056 		if (endptr == NULL || (*endptr != '/' && *endptr != '\0'))
1057 			return (-1);
1058 
1059 		if (*endptr == '/') {
1060 			for (cp = endptr + 1; *cp != '\0'; cp++) {
1061 				switch (*cp) {
1062 				case 'B':
1063 				case 'W':
1064 					Bflag = 1;
1065 					break;
1066 				case 'b':
1067 				case 'w':
1068 					bflag = 1;
1069 					break;
1070 				case 'c':
1071 					cflag = 1;
1072 					break;
1073 				case 't':
1074 					break;
1075 				default:
1076 					return (-1);
1077 				}
1078 			}
1079 		}
1080 	} else
1081 		range = UINT64_MAX;
1082 	if (range > (uint64_t)ms->size - ms->offset)
1083 		range = ms->size - ms->offset;
1084 	size = ml->test_string_size;
1085 
1086 	/* Want to search every starting position from up to range + size. */
1087 	end = range + size;
1088 	if (end > ms->size - ms->offset) {
1089 		if (size > ms->size - ms->offset)
1090 			end = 0;
1091 		else
1092 			end = ms->size - ms->offset - size;
1093 	}
1094 
1095 	/*
1096 	 * < and > and the flags are only in /etc/magic with search/1 so don't
1097 	 * support them with anything else.
1098 	 */
1099 	start = ms->base + ms->offset;
1100 	if (end == 0)
1101 		found = NULL;
1102 	else if (ml->test_operator == 'x')
1103 		found = start;
1104 	else if (range == 1) {
1105 		n = magic_test_eq(start, ms->size - ms->offset, ml->test_string,
1106 		    size, cflag, bflag, Bflag);
1107 		if (n == -1 && ml->test_operator == '<')
1108 			found = start;
1109 		else if (n == 1 && ml->test_operator == '>')
1110 			found = start;
1111 		else if (n == 0 && ml->test_operator == '=')
1112 			found = start;
1113 		else
1114 			found = NULL;
1115 	} else {
1116 		if (ml->test_operator != '=')
1117 			return (-2);
1118 		for (i = 0; i < end; i++) {
1119 			n = magic_test_eq(start + i, ms->size - ms->offset - i,
1120 			    ml->test_string, size, cflag, bflag, Bflag);
1121 			if (n == 0) {
1122 				found = start + i;
1123 				break;
1124 			}
1125 		}
1126 		if (i == end)
1127 			found = NULL;
1128 	}
1129 	result = (found != NULL);
1130 
1131 	if (result == !ml->test_not) {
1132 		if (ml->result != NULL)
1133 			magic_add_string(ms, ml, found, ms->size - ms->offset);
1134 		if (result && found != NULL && ml->test_operator == '=')
1135 			ms->offset = (found + size) - ms->base;
1136 	}
1137 	return (result);
1138 }
1139 
1140 static int
magic_test_type_default(struct magic_line * ml,struct magic_state * ms)1141 magic_test_type_default(struct magic_line *ml, struct magic_state *ms)
1142 {
1143 	if (!ms->matched && ml->result != NULL)
1144 		magic_add_result(ms, ml, "%s", "");
1145 	return (!ms->matched);
1146 }
1147 
1148 static int
magic_test_type_clear(struct magic_line * ml,struct magic_state * ms)1149 magic_test_type_clear(struct magic_line *ml, struct magic_state *ms)
1150 {
1151 	if (ml->result != NULL)
1152 		magic_add_result(ms, ml, "%s", "");
1153 	return (1);
1154 }
1155 
1156 static int
magic_test_type_name(__unused struct magic_line * ml,__unused struct magic_state * ms)1157 magic_test_type_name(__unused struct magic_line *ml,
1158     __unused struct magic_state *ms)
1159 {
1160 	return (-1);
1161 }
1162 
1163 static int
magic_test_type_use(__unused struct magic_line * ml,__unused struct magic_state * ms)1164 magic_test_type_use(__unused struct magic_line *ml,
1165     __unused struct magic_state *ms)
1166 {
1167 	return (1);
1168 }
1169 
1170 static int (*magic_test_functions[])(struct magic_line *,
1171     struct magic_state *) = {
1172 	magic_test_type_none,
1173 	magic_test_type_byte,
1174 	magic_test_type_short,
1175 	magic_test_type_long,
1176 	magic_test_type_quad,
1177 	magic_test_type_ubyte,
1178 	magic_test_type_ushort,
1179 	magic_test_type_ulong,
1180 	magic_test_type_uquad,
1181 	magic_test_type_float,
1182 	magic_test_type_double,
1183 	magic_test_type_string,
1184 	magic_test_type_pstring,
1185 	magic_test_type_date,
1186 	magic_test_type_qdate,
1187 	magic_test_type_date,
1188 	magic_test_type_qdate,
1189 	magic_test_type_udate,
1190 	magic_test_type_uqdate,
1191 	magic_test_type_udate,
1192 	magic_test_type_qdate,
1193 	magic_test_type_short,
1194 	magic_test_type_long,
1195 	magic_test_type_quad,
1196 	magic_test_type_ushort,
1197 	magic_test_type_ulong,
1198 	magic_test_type_uquad,
1199 	magic_test_type_float,
1200 	magic_test_type_double,
1201 	magic_test_type_date,
1202 	magic_test_type_qdate,
1203 	magic_test_type_date,
1204 	magic_test_type_qdate,
1205 	magic_test_type_udate,
1206 	magic_test_type_uqdate,
1207 	magic_test_type_udate,
1208 	magic_test_type_uqdate,
1209 	magic_test_type_bestring16,
1210 	magic_test_type_short,
1211 	magic_test_type_long,
1212 	magic_test_type_quad,
1213 	magic_test_type_ushort,
1214 	magic_test_type_ulong,
1215 	magic_test_type_uquad,
1216 	magic_test_type_float,
1217 	magic_test_type_double,
1218 	magic_test_type_date,
1219 	magic_test_type_qdate,
1220 	magic_test_type_date,
1221 	magic_test_type_qdate,
1222 	magic_test_type_udate,
1223 	magic_test_type_uqdate,
1224 	magic_test_type_udate,
1225 	magic_test_type_uqdate,
1226 	magic_test_type_lestring16,
1227 	magic_test_type_melong,
1228 	magic_test_type_medate,
1229 	magic_test_type_meldate,
1230 	magic_test_type_regex,
1231 	magic_test_type_search,
1232 	magic_test_type_default,
1233 	magic_test_type_clear,
1234 	magic_test_type_name,
1235 	magic_test_type_use,
1236 };
1237 
1238 static void
magic_test_children(struct magic_line * ml,struct magic_state * ms,size_t start,int reverse)1239 magic_test_children(struct magic_line *ml, struct magic_state *ms, size_t start,
1240     int reverse)
1241 {
1242 	struct magic_line	*child;
1243 	size_t			 saved_start, saved_offset;
1244 	int			 saved_reverse;
1245 
1246 	saved_start = ms->start;
1247 	saved_reverse = ms->reverse;
1248 	saved_offset = ms->offset;
1249 
1250 	ms->matched = 0; /* no need to save, caller will set too */
1251 
1252 	TAILQ_FOREACH(child, &ml->children, entry) {
1253 		ms->start = start;
1254 		ms->reverse = reverse;
1255 		ms->offset = saved_offset;
1256 
1257 		magic_test_line(child, ms);
1258 	}
1259 
1260 	ms->start = saved_start;
1261 	ms->reverse = saved_reverse;
1262 	ms->offset = saved_offset;
1263 }
1264 
1265 static int
magic_test_line(struct magic_line * ml,struct magic_state * ms)1266 magic_test_line(struct magic_line *ml, struct magic_state *ms)
1267 {
1268 	struct magic		*m = ml->root;
1269 	struct magic_line	*named;
1270 	int64_t			 offset, wanted, next;
1271 	int			 result;
1272 	uint8_t			 b;
1273 	uint16_t		 s;
1274 	uint32_t		 l;
1275 
1276 	if (ml->indirect_type == ' ')
1277 		wanted = ms->start + ml->offset;
1278 	else {
1279 		wanted = ml->indirect_offset;
1280 		if (ml->indirect_relative) {
1281 			if (wanted < 0 && (size_t)-wanted > ms->offset)
1282 				return (0);
1283 			if (wanted > 0 && ms->offset + wanted > ms->size)
1284 				return (0);
1285 			next = ms->offset + ml->indirect_offset;
1286 		} else
1287 			next = wanted;
1288 
1289 		switch (ml->indirect_type) {
1290 		case 'b':
1291 		case 'B':
1292 			if (magic_copy_from(ms, next, &b, sizeof b) != 0)
1293 				return (0);
1294 			wanted = b;
1295 			break;
1296 		case 's':
1297 			if (magic_copy_from(ms, next, &s, sizeof s) != 0)
1298 				return (0);
1299 			wanted = le16toh(s);
1300 			break;
1301 		case 'S':
1302 			if (magic_copy_from(ms, next, &s, sizeof s) != 0)
1303 				return (0);
1304 			wanted = be16toh(s);
1305 			break;
1306 		case 'l':
1307 			if (magic_copy_from(ms, next, &l, sizeof l) != 0)
1308 				return (0);
1309 			wanted = le16toh(l);
1310 			break;
1311 		case 'L':
1312 			if (magic_copy_from(ms, next, &l, sizeof l) != 0)
1313 				return (0);
1314 			wanted = be16toh(l);
1315 			break;
1316 		}
1317 
1318 		switch (ml->indirect_operator) {
1319 		case '+':
1320 			wanted += ml->indirect_operand;
1321 			break;
1322 		case '-':
1323 			wanted -= ml->indirect_operand;
1324 			break;
1325 		case '*':
1326 			wanted *= ml->indirect_operand;
1327 			break;
1328 		}
1329 	}
1330 
1331 	if (ml->offset_relative) {
1332 		if (wanted < 0 && (size_t)-wanted > ms->offset)
1333 			return (0);
1334 		if (wanted > 0 && ms->offset + wanted > ms->size)
1335 			return (0);
1336 		offset = ms->offset + wanted;
1337 	} else
1338 		offset = wanted;
1339 	if (offset < 0 || (size_t)offset > ms->size)
1340 		return (0);
1341 	ms->offset = offset; /* test function may update */
1342 
1343 	result = magic_test_functions[ml->type](ml, ms);
1344 	if (result == -1) {
1345 		magic_warn(ml, "test %s/%c failed", ml->type_string,
1346 		    ml->test_operator);
1347 		return (0);
1348 	}
1349 	if (result == -2) {
1350 		magic_warn(ml, "test %s/%c not implemented", ml->type_string,
1351 		    ml->test_operator);
1352 		return (0);
1353 	}
1354 	if (result == ml->test_not)
1355 		return (0);
1356 	if (ml->mimetype != NULL)
1357 		ms->mimetype = ml->mimetype;
1358 
1359 	magic_warn(ml, "test %s/%c matched at offset %lld (now %zu): "
1360 	    "'%s'", ml->type_string, ml->test_operator, offset,
1361 	    ms->offset, ml->result == NULL ? "" : ml->result);
1362 
1363 	if (ml->type == MAGIC_TYPE_USE) {
1364 		if (*ml->name == '^')
1365 			named = magic_get_named(m, ml->name + 1);
1366 		else
1367 			named = magic_get_named(m, ml->name);
1368 		if (named == NULL) {
1369 			magic_warn(ml, "no name found for use %s", ml->name);
1370 			return (0);
1371 		}
1372 		magic_warn(ml, "use %s at offset %lld", ml->name, offset);
1373 		magic_test_children(named, ms, offset, *ml->name == '^');
1374 	}
1375 
1376 	magic_test_children(ml, ms, ms->start, ms->reverse);
1377 
1378 	if (ml->type == MAGIC_TYPE_CLEAR)
1379 		ms->matched = 0;
1380 	else
1381 		ms->matched = 1;
1382 	return (ml->result != NULL);
1383 }
1384 
1385 const char *
magic_test(struct magic * m,const void * base,size_t size,int flags)1386 magic_test(struct magic *m, const void *base, size_t size, int flags)
1387 {
1388 	struct magic_line		*ml;
1389 	static struct magic_state	 ms;
1390 
1391 	memset(&ms, 0, sizeof ms);
1392 
1393 	ms.base = base;
1394 	ms.size = size;
1395 
1396 	ms.text = !!(flags & MAGIC_TEST_TEXT);
1397 
1398 	RB_FOREACH(ml, magic_tree, &m->tree) {
1399 		ms.offset = 0;
1400 		if (ml->text == ms.text && magic_test_line(ml, &ms))
1401 			break;
1402 	}
1403 
1404 	if (*ms.out != '\0') {
1405 		if (flags & MAGIC_TEST_MIME) {
1406 			if (ms.mimetype != NULL)
1407 				return (ms.mimetype);
1408 			return (NULL);
1409 		}
1410 		return (ms.out);
1411 	}
1412 	return (NULL);
1413 }
1414