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