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