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