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