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