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