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