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