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