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