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