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