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