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