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