1 /* $NetBSD: softmagic.c,v 1.4 2011/09/16 21:06:27 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.145 2011/05/13 22:15:40 christos Exp $") 39 #else 40 __RCSID("$NetBSD: softmagic.c,v 1.4 2011/09/16 21:06:27 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 & mode) != 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 if ((e = handle_annotation(ms, m)) != 0) 178 return e; 179 /* 180 * If we are going to print something, we'll need to print 181 * a blank before we print something else. 182 */ 183 if (*m->desc) { 184 need_separator = 1; 185 printed_something = 1; 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 if ((e = handle_annotation(ms, m)) != 0) 261 return e; 262 /* 263 * If we are going to print something, 264 * make sure that we have a separator first. 265 */ 266 if (*m->desc) { 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 += file_pstring_length_size(m); 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 += file_pstring_length_size(m); 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 return 1; 800 } 801 case FILE_PSTRING: { 802 char *ptr1 = p->s, *ptr2 = ptr1 + file_pstring_length_size(m); 803 size_t len = file_pstring_get_length(m, ptr1); 804 if (len >= sizeof(p->s)) 805 len = sizeof(p->s) - 1; 806 while (len--) 807 *ptr1++ = *ptr2++; 808 *ptr1 = '\0'; 809 return 1; 810 } 811 case FILE_BESHORT: 812 p->h = (short)((p->hs[0]<<8)|(p->hs[1])); 813 cvt_16(p, m); 814 return 1; 815 case FILE_BELONG: 816 case FILE_BEDATE: 817 case FILE_BELDATE: 818 p->l = (int32_t) 819 ((p->hl[0]<<24)|(p->hl[1]<<16)|(p->hl[2]<<8)|(p->hl[3])); 820 cvt_32(p, m); 821 return 1; 822 case FILE_BEQUAD: 823 case FILE_BEQDATE: 824 case FILE_BEQLDATE: 825 p->q = (uint64_t) 826 (((uint64_t)p->hq[0]<<56)|((uint64_t)p->hq[1]<<48)| 827 ((uint64_t)p->hq[2]<<40)|((uint64_t)p->hq[3]<<32)| 828 ((uint64_t)p->hq[4]<<24)|((uint64_t)p->hq[5]<<16)| 829 ((uint64_t)p->hq[6]<<8)|((uint64_t)p->hq[7])); 830 cvt_64(p, m); 831 return 1; 832 case FILE_LESHORT: 833 p->h = (short)((p->hs[1]<<8)|(p->hs[0])); 834 cvt_16(p, m); 835 return 1; 836 case FILE_LELONG: 837 case FILE_LEDATE: 838 case FILE_LELDATE: 839 p->l = (int32_t) 840 ((p->hl[3]<<24)|(p->hl[2]<<16)|(p->hl[1]<<8)|(p->hl[0])); 841 cvt_32(p, m); 842 return 1; 843 case FILE_LEQUAD: 844 case FILE_LEQDATE: 845 case FILE_LEQLDATE: 846 p->q = (uint64_t) 847 (((uint64_t)p->hq[7]<<56)|((uint64_t)p->hq[6]<<48)| 848 ((uint64_t)p->hq[5]<<40)|((uint64_t)p->hq[4]<<32)| 849 ((uint64_t)p->hq[3]<<24)|((uint64_t)p->hq[2]<<16)| 850 ((uint64_t)p->hq[1]<<8)|((uint64_t)p->hq[0])); 851 cvt_64(p, m); 852 return 1; 853 case FILE_MELONG: 854 case FILE_MEDATE: 855 case FILE_MELDATE: 856 p->l = (int32_t) 857 ((p->hl[1]<<24)|(p->hl[0]<<16)|(p->hl[3]<<8)|(p->hl[2])); 858 cvt_32(p, m); 859 return 1; 860 case FILE_FLOAT: 861 cvt_float(p, m); 862 return 1; 863 case FILE_BEFLOAT: 864 p->l = ((uint32_t)p->hl[0]<<24)|((uint32_t)p->hl[1]<<16)| 865 ((uint32_t)p->hl[2]<<8) |((uint32_t)p->hl[3]); 866 cvt_float(p, m); 867 return 1; 868 case FILE_LEFLOAT: 869 p->l = ((uint32_t)p->hl[3]<<24)|((uint32_t)p->hl[2]<<16)| 870 ((uint32_t)p->hl[1]<<8) |((uint32_t)p->hl[0]); 871 cvt_float(p, m); 872 return 1; 873 case FILE_DOUBLE: 874 cvt_double(p, m); 875 return 1; 876 case FILE_BEDOUBLE: 877 p->q = ((uint64_t)p->hq[0]<<56)|((uint64_t)p->hq[1]<<48)| 878 ((uint64_t)p->hq[2]<<40)|((uint64_t)p->hq[3]<<32)| 879 ((uint64_t)p->hq[4]<<24)|((uint64_t)p->hq[5]<<16)| 880 ((uint64_t)p->hq[6]<<8) |((uint64_t)p->hq[7]); 881 cvt_double(p, m); 882 return 1; 883 case FILE_LEDOUBLE: 884 p->q = ((uint64_t)p->hq[7]<<56)|((uint64_t)p->hq[6]<<48)| 885 ((uint64_t)p->hq[5]<<40)|((uint64_t)p->hq[4]<<32)| 886 ((uint64_t)p->hq[3]<<24)|((uint64_t)p->hq[2]<<16)| 887 ((uint64_t)p->hq[1]<<8) |((uint64_t)p->hq[0]); 888 cvt_double(p, m); 889 return 1; 890 case FILE_REGEX: 891 case FILE_SEARCH: 892 case FILE_DEFAULT: 893 return 1; 894 default: 895 file_magerror(ms, "invalid type %d in mconvert()", m->type); 896 return 0; 897 } 898 } 899 900 901 private void 902 mdebug(uint32_t offset, const char *str, size_t len) 903 { 904 (void) fprintf(stderr, "mget @%d: ", offset); 905 file_showstr(stderr, str, len); 906 (void) fputc('\n', stderr); 907 (void) fputc('\n', stderr); 908 } 909 910 private int 911 mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir, 912 const unsigned char *s, uint32_t offset, size_t nbytes, size_t linecnt) 913 { 914 /* 915 * Note: FILE_SEARCH and FILE_REGEX do not actually copy 916 * anything, but setup pointers into the source 917 */ 918 if (indir == 0) { 919 switch (type) { 920 case FILE_SEARCH: 921 ms->search.s = RCAST(const char *, s) + offset; 922 ms->search.s_len = nbytes - offset; 923 ms->search.offset = offset; 924 return 0; 925 926 case FILE_REGEX: { 927 const char *b; 928 const char *c; 929 const char *last; /* end of search region */ 930 const char *buf; /* start of search region */ 931 const char *end; 932 size_t lines; 933 934 if (s == NULL) { 935 ms->search.s_len = 0; 936 ms->search.s = NULL; 937 return 0; 938 } 939 buf = RCAST(const char *, s) + offset; 940 end = last = RCAST(const char *, s) + nbytes; 941 /* mget() guarantees buf <= last */ 942 for (lines = linecnt, b = buf; lines && b < end && 943 ((b = CAST(const char *, 944 memchr(c = b, '\n', CAST(size_t, (end - b))))) 945 || (b = CAST(const char *, 946 memchr(c, '\r', CAST(size_t, (end - c)))))); 947 lines--, b++) { 948 last = b; 949 if (b[0] == '\r' && b[1] == '\n') 950 b++; 951 } 952 if (lines) 953 last = RCAST(const char *, s) + nbytes; 954 955 ms->search.s = buf; 956 ms->search.s_len = last - buf; 957 ms->search.offset = offset; 958 ms->search.rm_len = 0; 959 return 0; 960 } 961 case FILE_BESTRING16: 962 case FILE_LESTRING16: { 963 const unsigned char *src = s + offset; 964 const unsigned char *esrc = s + nbytes; 965 char *dst = p->s; 966 char *edst = &p->s[sizeof(p->s) - 1]; 967 968 if (type == FILE_BESTRING16) 969 src++; 970 971 /* check for pointer overflow */ 972 if (src < s) { 973 file_magerror(ms, "invalid offset %u in mcopy()", 974 offset); 975 return -1; 976 } 977 for (/*EMPTY*/; src < esrc; src += 2, dst++) { 978 if (dst < edst) 979 *dst = *src; 980 else 981 break; 982 if (*dst == '\0') { 983 if (type == FILE_BESTRING16 ? 984 *(src - 1) != '\0' : 985 *(src + 1) != '\0') 986 *dst = ' '; 987 } 988 } 989 *edst = '\0'; 990 return 0; 991 } 992 case FILE_STRING: /* XXX - these two should not need */ 993 case FILE_PSTRING: /* to copy anything, but do anyway. */ 994 default: 995 break; 996 } 997 } 998 999 if (offset >= nbytes) { 1000 (void)memset(p, '\0', sizeof(*p)); 1001 return 0; 1002 } 1003 if (nbytes - offset < sizeof(*p)) 1004 nbytes = nbytes - offset; 1005 else 1006 nbytes = sizeof(*p); 1007 1008 (void)memcpy(p, s + offset, nbytes); 1009 1010 /* 1011 * the usefulness of padding with zeroes eludes me, it 1012 * might even cause problems 1013 */ 1014 if (nbytes < sizeof(*p)) 1015 (void)memset(((char *)(void *)p) + nbytes, '\0', 1016 sizeof(*p) - nbytes); 1017 return 0; 1018 } 1019 1020 private int 1021 mget(struct magic_set *ms, const unsigned char *s, 1022 struct magic *m, size_t nbytes, unsigned int cont_level) 1023 { 1024 uint32_t offset = ms->offset; 1025 uint32_t count = m->str_range; 1026 union VALUETYPE *p = &ms->ms_value; 1027 1028 if (mcopy(ms, p, m->type, m->flag & INDIR, s, offset, nbytes, count) == -1) 1029 return -1; 1030 1031 if ((ms->flags & MAGIC_DEBUG) != 0) { 1032 mdebug(offset, (char *)(void *)p, sizeof(union VALUETYPE)); 1033 #ifndef COMPILE_ONLY 1034 file_mdump(m); 1035 #endif 1036 } 1037 1038 if (m->flag & INDIR) { 1039 int off = m->in_offset; 1040 if (m->in_op & FILE_OPINDIRECT) { 1041 const union VALUETYPE *q = CAST(const union VALUETYPE *, 1042 ((const void *)(s + offset + off))); 1043 switch (m->in_type) { 1044 case FILE_BYTE: 1045 off = q->b; 1046 break; 1047 case FILE_SHORT: 1048 off = q->h; 1049 break; 1050 case FILE_BESHORT: 1051 off = (short)((q->hs[0]<<8)|(q->hs[1])); 1052 break; 1053 case FILE_LESHORT: 1054 off = (short)((q->hs[1]<<8)|(q->hs[0])); 1055 break; 1056 case FILE_LONG: 1057 off = q->l; 1058 break; 1059 case FILE_BELONG: 1060 case FILE_BEID3: 1061 off = (int32_t)((q->hl[0]<<24)|(q->hl[1]<<16)| 1062 (q->hl[2]<<8)|(q->hl[3])); 1063 break; 1064 case FILE_LEID3: 1065 case FILE_LELONG: 1066 off = (int32_t)((q->hl[3]<<24)|(q->hl[2]<<16)| 1067 (q->hl[1]<<8)|(q->hl[0])); 1068 break; 1069 case FILE_MELONG: 1070 off = (int32_t)((q->hl[1]<<24)|(q->hl[0]<<16)| 1071 (q->hl[3]<<8)|(q->hl[2])); 1072 break; 1073 } 1074 } 1075 switch (m->in_type) { 1076 case FILE_BYTE: 1077 if (nbytes < (offset + 1)) 1078 return 0; 1079 if (off) { 1080 switch (m->in_op & FILE_OPS_MASK) { 1081 case FILE_OPAND: 1082 offset = p->b & off; 1083 break; 1084 case FILE_OPOR: 1085 offset = p->b | off; 1086 break; 1087 case FILE_OPXOR: 1088 offset = p->b ^ off; 1089 break; 1090 case FILE_OPADD: 1091 offset = p->b + off; 1092 break; 1093 case FILE_OPMINUS: 1094 offset = p->b - off; 1095 break; 1096 case FILE_OPMULTIPLY: 1097 offset = p->b * off; 1098 break; 1099 case FILE_OPDIVIDE: 1100 offset = p->b / off; 1101 break; 1102 case FILE_OPMODULO: 1103 offset = p->b % off; 1104 break; 1105 } 1106 } else 1107 offset = p->b; 1108 if (m->in_op & FILE_OPINVERSE) 1109 offset = ~offset; 1110 break; 1111 case FILE_BESHORT: 1112 if (nbytes < (offset + 2)) 1113 return 0; 1114 if (off) { 1115 switch (m->in_op & FILE_OPS_MASK) { 1116 case FILE_OPAND: 1117 offset = (short)((p->hs[0]<<8)| 1118 (p->hs[1])) & 1119 off; 1120 break; 1121 case FILE_OPOR: 1122 offset = (short)((p->hs[0]<<8)| 1123 (p->hs[1])) | 1124 off; 1125 break; 1126 case FILE_OPXOR: 1127 offset = (short)((p->hs[0]<<8)| 1128 (p->hs[1])) ^ 1129 off; 1130 break; 1131 case FILE_OPADD: 1132 offset = (short)((p->hs[0]<<8)| 1133 (p->hs[1])) + 1134 off; 1135 break; 1136 case FILE_OPMINUS: 1137 offset = (short)((p->hs[0]<<8)| 1138 (p->hs[1])) - 1139 off; 1140 break; 1141 case FILE_OPMULTIPLY: 1142 offset = (short)((p->hs[0]<<8)| 1143 (p->hs[1])) * 1144 off; 1145 break; 1146 case FILE_OPDIVIDE: 1147 offset = (short)((p->hs[0]<<8)| 1148 (p->hs[1])) / 1149 off; 1150 break; 1151 case FILE_OPMODULO: 1152 offset = (short)((p->hs[0]<<8)| 1153 (p->hs[1])) % 1154 off; 1155 break; 1156 } 1157 } else 1158 offset = (short)((p->hs[0]<<8)| 1159 (p->hs[1])); 1160 if (m->in_op & FILE_OPINVERSE) 1161 offset = ~offset; 1162 break; 1163 case FILE_LESHORT: 1164 if (nbytes < (offset + 2)) 1165 return 0; 1166 if (off) { 1167 switch (m->in_op & FILE_OPS_MASK) { 1168 case FILE_OPAND: 1169 offset = (short)((p->hs[1]<<8)| 1170 (p->hs[0])) & 1171 off; 1172 break; 1173 case FILE_OPOR: 1174 offset = (short)((p->hs[1]<<8)| 1175 (p->hs[0])) | 1176 off; 1177 break; 1178 case FILE_OPXOR: 1179 offset = (short)((p->hs[1]<<8)| 1180 (p->hs[0])) ^ 1181 off; 1182 break; 1183 case FILE_OPADD: 1184 offset = (short)((p->hs[1]<<8)| 1185 (p->hs[0])) + 1186 off; 1187 break; 1188 case FILE_OPMINUS: 1189 offset = (short)((p->hs[1]<<8)| 1190 (p->hs[0])) - 1191 off; 1192 break; 1193 case FILE_OPMULTIPLY: 1194 offset = (short)((p->hs[1]<<8)| 1195 (p->hs[0])) * 1196 off; 1197 break; 1198 case FILE_OPDIVIDE: 1199 offset = (short)((p->hs[1]<<8)| 1200 (p->hs[0])) / 1201 off; 1202 break; 1203 case FILE_OPMODULO: 1204 offset = (short)((p->hs[1]<<8)| 1205 (p->hs[0])) % 1206 off; 1207 break; 1208 } 1209 } else 1210 offset = (short)((p->hs[1]<<8)| 1211 (p->hs[0])); 1212 if (m->in_op & FILE_OPINVERSE) 1213 offset = ~offset; 1214 break; 1215 case FILE_SHORT: 1216 if (nbytes < (offset + 2)) 1217 return 0; 1218 if (off) { 1219 switch (m->in_op & FILE_OPS_MASK) { 1220 case FILE_OPAND: 1221 offset = p->h & off; 1222 break; 1223 case FILE_OPOR: 1224 offset = p->h | off; 1225 break; 1226 case FILE_OPXOR: 1227 offset = p->h ^ off; 1228 break; 1229 case FILE_OPADD: 1230 offset = p->h + off; 1231 break; 1232 case FILE_OPMINUS: 1233 offset = p->h - off; 1234 break; 1235 case FILE_OPMULTIPLY: 1236 offset = p->h * off; 1237 break; 1238 case FILE_OPDIVIDE: 1239 offset = p->h / off; 1240 break; 1241 case FILE_OPMODULO: 1242 offset = p->h % off; 1243 break; 1244 } 1245 } 1246 else 1247 offset = p->h; 1248 if (m->in_op & FILE_OPINVERSE) 1249 offset = ~offset; 1250 break; 1251 case FILE_BELONG: 1252 case FILE_BEID3: 1253 if (nbytes < (offset + 4)) 1254 return 0; 1255 if (off) { 1256 switch (m->in_op & FILE_OPS_MASK) { 1257 case FILE_OPAND: 1258 offset = (int32_t)((p->hl[0]<<24)| 1259 (p->hl[1]<<16)| 1260 (p->hl[2]<<8)| 1261 (p->hl[3])) & 1262 off; 1263 break; 1264 case FILE_OPOR: 1265 offset = (int32_t)((p->hl[0]<<24)| 1266 (p->hl[1]<<16)| 1267 (p->hl[2]<<8)| 1268 (p->hl[3])) | 1269 off; 1270 break; 1271 case FILE_OPXOR: 1272 offset = (int32_t)((p->hl[0]<<24)| 1273 (p->hl[1]<<16)| 1274 (p->hl[2]<<8)| 1275 (p->hl[3])) ^ 1276 off; 1277 break; 1278 case FILE_OPADD: 1279 offset = (int32_t)((p->hl[0]<<24)| 1280 (p->hl[1]<<16)| 1281 (p->hl[2]<<8)| 1282 (p->hl[3])) + 1283 off; 1284 break; 1285 case FILE_OPMINUS: 1286 offset = (int32_t)((p->hl[0]<<24)| 1287 (p->hl[1]<<16)| 1288 (p->hl[2]<<8)| 1289 (p->hl[3])) - 1290 off; 1291 break; 1292 case FILE_OPMULTIPLY: 1293 offset = (int32_t)((p->hl[0]<<24)| 1294 (p->hl[1]<<16)| 1295 (p->hl[2]<<8)| 1296 (p->hl[3])) * 1297 off; 1298 break; 1299 case FILE_OPDIVIDE: 1300 offset = (int32_t)((p->hl[0]<<24)| 1301 (p->hl[1]<<16)| 1302 (p->hl[2]<<8)| 1303 (p->hl[3])) / 1304 off; 1305 break; 1306 case FILE_OPMODULO: 1307 offset = (int32_t)((p->hl[0]<<24)| 1308 (p->hl[1]<<16)| 1309 (p->hl[2]<<8)| 1310 (p->hl[3])) % 1311 off; 1312 break; 1313 } 1314 } else 1315 offset = (int32_t)((p->hl[0]<<24)| 1316 (p->hl[1]<<16)| 1317 (p->hl[2]<<8)| 1318 (p->hl[3])); 1319 if (m->in_op & FILE_OPINVERSE) 1320 offset = ~offset; 1321 break; 1322 case FILE_LELONG: 1323 case FILE_LEID3: 1324 if (nbytes < (offset + 4)) 1325 return 0; 1326 if (off) { 1327 switch (m->in_op & FILE_OPS_MASK) { 1328 case FILE_OPAND: 1329 offset = (int32_t)((p->hl[3]<<24)| 1330 (p->hl[2]<<16)| 1331 (p->hl[1]<<8)| 1332 (p->hl[0])) & 1333 off; 1334 break; 1335 case FILE_OPOR: 1336 offset = (int32_t)((p->hl[3]<<24)| 1337 (p->hl[2]<<16)| 1338 (p->hl[1]<<8)| 1339 (p->hl[0])) | 1340 off; 1341 break; 1342 case FILE_OPXOR: 1343 offset = (int32_t)((p->hl[3]<<24)| 1344 (p->hl[2]<<16)| 1345 (p->hl[1]<<8)| 1346 (p->hl[0])) ^ 1347 off; 1348 break; 1349 case FILE_OPADD: 1350 offset = (int32_t)((p->hl[3]<<24)| 1351 (p->hl[2]<<16)| 1352 (p->hl[1]<<8)| 1353 (p->hl[0])) + 1354 off; 1355 break; 1356 case FILE_OPMINUS: 1357 offset = (int32_t)((p->hl[3]<<24)| 1358 (p->hl[2]<<16)| 1359 (p->hl[1]<<8)| 1360 (p->hl[0])) - 1361 off; 1362 break; 1363 case FILE_OPMULTIPLY: 1364 offset = (int32_t)((p->hl[3]<<24)| 1365 (p->hl[2]<<16)| 1366 (p->hl[1]<<8)| 1367 (p->hl[0])) * 1368 off; 1369 break; 1370 case FILE_OPDIVIDE: 1371 offset = (int32_t)((p->hl[3]<<24)| 1372 (p->hl[2]<<16)| 1373 (p->hl[1]<<8)| 1374 (p->hl[0])) / 1375 off; 1376 break; 1377 case FILE_OPMODULO: 1378 offset = (int32_t)((p->hl[3]<<24)| 1379 (p->hl[2]<<16)| 1380 (p->hl[1]<<8)| 1381 (p->hl[0])) % 1382 off; 1383 break; 1384 } 1385 } else 1386 offset = (int32_t)((p->hl[3]<<24)| 1387 (p->hl[2]<<16)| 1388 (p->hl[1]<<8)| 1389 (p->hl[0])); 1390 if (m->in_op & FILE_OPINVERSE) 1391 offset = ~offset; 1392 break; 1393 case FILE_MELONG: 1394 if (nbytes < (offset + 4)) 1395 return 0; 1396 if (off) { 1397 switch (m->in_op & FILE_OPS_MASK) { 1398 case FILE_OPAND: 1399 offset = (int32_t)((p->hl[1]<<24)| 1400 (p->hl[0]<<16)| 1401 (p->hl[3]<<8)| 1402 (p->hl[2])) & 1403 off; 1404 break; 1405 case FILE_OPOR: 1406 offset = (int32_t)((p->hl[1]<<24)| 1407 (p->hl[0]<<16)| 1408 (p->hl[3]<<8)| 1409 (p->hl[2])) | 1410 off; 1411 break; 1412 case FILE_OPXOR: 1413 offset = (int32_t)((p->hl[1]<<24)| 1414 (p->hl[0]<<16)| 1415 (p->hl[3]<<8)| 1416 (p->hl[2])) ^ 1417 off; 1418 break; 1419 case FILE_OPADD: 1420 offset = (int32_t)((p->hl[1]<<24)| 1421 (p->hl[0]<<16)| 1422 (p->hl[3]<<8)| 1423 (p->hl[2])) + 1424 off; 1425 break; 1426 case FILE_OPMINUS: 1427 offset = (int32_t)((p->hl[1]<<24)| 1428 (p->hl[0]<<16)| 1429 (p->hl[3]<<8)| 1430 (p->hl[2])) - 1431 off; 1432 break; 1433 case FILE_OPMULTIPLY: 1434 offset = (int32_t)((p->hl[1]<<24)| 1435 (p->hl[0]<<16)| 1436 (p->hl[3]<<8)| 1437 (p->hl[2])) * 1438 off; 1439 break; 1440 case FILE_OPDIVIDE: 1441 offset = (int32_t)((p->hl[1]<<24)| 1442 (p->hl[0]<<16)| 1443 (p->hl[3]<<8)| 1444 (p->hl[2])) / 1445 off; 1446 break; 1447 case FILE_OPMODULO: 1448 offset = (int32_t)((p->hl[1]<<24)| 1449 (p->hl[0]<<16)| 1450 (p->hl[3]<<8)| 1451 (p->hl[2])) % 1452 off; 1453 break; 1454 } 1455 } else 1456 offset = (int32_t)((p->hl[1]<<24)| 1457 (p->hl[0]<<16)| 1458 (p->hl[3]<<8)| 1459 (p->hl[2])); 1460 if (m->in_op & FILE_OPINVERSE) 1461 offset = ~offset; 1462 break; 1463 case FILE_LONG: 1464 if (nbytes < (offset + 4)) 1465 return 0; 1466 if (off) { 1467 switch (m->in_op & FILE_OPS_MASK) { 1468 case FILE_OPAND: 1469 offset = p->l & off; 1470 break; 1471 case FILE_OPOR: 1472 offset = p->l | off; 1473 break; 1474 case FILE_OPXOR: 1475 offset = p->l ^ off; 1476 break; 1477 case FILE_OPADD: 1478 offset = p->l + off; 1479 break; 1480 case FILE_OPMINUS: 1481 offset = p->l - off; 1482 break; 1483 case FILE_OPMULTIPLY: 1484 offset = p->l * off; 1485 break; 1486 case FILE_OPDIVIDE: 1487 offset = p->l / off; 1488 break; 1489 case FILE_OPMODULO: 1490 offset = p->l % off; 1491 break; 1492 } 1493 } else 1494 offset = p->l; 1495 if (m->in_op & FILE_OPINVERSE) 1496 offset = ~offset; 1497 break; 1498 } 1499 1500 switch (m->in_type) { 1501 case FILE_LEID3: 1502 case FILE_BEID3: 1503 offset = ((((offset >> 0) & 0x7f) << 0) | 1504 (((offset >> 8) & 0x7f) << 7) | 1505 (((offset >> 16) & 0x7f) << 14) | 1506 (((offset >> 24) & 0x7f) << 21)) + 10; 1507 break; 1508 default: 1509 break; 1510 } 1511 1512 if (m->flag & INDIROFFADD) { 1513 offset += ms->c.li[cont_level-1].off; 1514 } 1515 if (mcopy(ms, p, m->type, 0, s, offset, nbytes, count) == -1) 1516 return -1; 1517 ms->offset = offset; 1518 1519 if ((ms->flags & MAGIC_DEBUG) != 0) { 1520 mdebug(offset, (char *)(void *)p, 1521 sizeof(union VALUETYPE)); 1522 #ifndef COMPILE_ONLY 1523 file_mdump(m); 1524 #endif 1525 } 1526 } 1527 1528 /* Verify we have enough data to match magic type */ 1529 switch (m->type) { 1530 case FILE_BYTE: 1531 if (nbytes < (offset + 1)) /* should alway be true */ 1532 return 0; 1533 break; 1534 1535 case FILE_SHORT: 1536 case FILE_BESHORT: 1537 case FILE_LESHORT: 1538 if (nbytes < (offset + 2)) 1539 return 0; 1540 break; 1541 1542 case FILE_LONG: 1543 case FILE_BELONG: 1544 case FILE_LELONG: 1545 case FILE_MELONG: 1546 case FILE_DATE: 1547 case FILE_BEDATE: 1548 case FILE_LEDATE: 1549 case FILE_MEDATE: 1550 case FILE_LDATE: 1551 case FILE_BELDATE: 1552 case FILE_LELDATE: 1553 case FILE_MELDATE: 1554 case FILE_FLOAT: 1555 case FILE_BEFLOAT: 1556 case FILE_LEFLOAT: 1557 if (nbytes < (offset + 4)) 1558 return 0; 1559 break; 1560 1561 case FILE_DOUBLE: 1562 case FILE_BEDOUBLE: 1563 case FILE_LEDOUBLE: 1564 if (nbytes < (offset + 8)) 1565 return 0; 1566 break; 1567 1568 case FILE_STRING: 1569 case FILE_PSTRING: 1570 case FILE_SEARCH: 1571 if (nbytes < (offset + m->vallen)) 1572 return 0; 1573 break; 1574 1575 case FILE_REGEX: 1576 if (nbytes < offset) 1577 return 0; 1578 break; 1579 1580 case FILE_INDIRECT: 1581 if ((ms->flags & (MAGIC_MIME|MAGIC_APPLE)) == 0 && 1582 file_printf(ms, "%s", m->desc) == -1) 1583 return -1; 1584 if (nbytes < offset) 1585 return 0; 1586 return file_softmagic(ms, s + offset, nbytes - offset, 1587 BINTEST); 1588 1589 case FILE_DEFAULT: /* nothing to check */ 1590 default: 1591 break; 1592 } 1593 if (!mconvert(ms, m)) 1594 return 0; 1595 return 1; 1596 } 1597 1598 private uint64_t 1599 file_strncmp(const char *s1, const char *s2, size_t len, uint32_t flags) 1600 { 1601 /* 1602 * Convert the source args to unsigned here so that (1) the 1603 * compare will be unsigned as it is in strncmp() and (2) so 1604 * the ctype functions will work correctly without extra 1605 * casting. 1606 */ 1607 const unsigned char *a = (const unsigned char *)s1; 1608 const unsigned char *b = (const unsigned char *)s2; 1609 uint64_t v; 1610 1611 /* 1612 * What we want here is v = strncmp(s1, s2, len), 1613 * but ignoring any nulls. 1614 */ 1615 v = 0; 1616 if (0L == flags) { /* normal string: do it fast */ 1617 while (len-- > 0) 1618 if ((v = *b++ - *a++) != '\0') 1619 break; 1620 } 1621 else { /* combine the others */ 1622 while (len-- > 0) { 1623 if ((flags & STRING_IGNORE_LOWERCASE) && 1624 islower(*a)) { 1625 if ((v = tolower(*b++) - *a++) != '\0') 1626 break; 1627 } 1628 else if ((flags & STRING_IGNORE_UPPERCASE) && 1629 isupper(*a)) { 1630 if ((v = toupper(*b++) - *a++) != '\0') 1631 break; 1632 } 1633 else if ((flags & STRING_COMPACT_WHITESPACE) && 1634 isspace(*a)) { 1635 a++; 1636 if (isspace(*b++)) { 1637 if (!isspace(*a)) 1638 while (isspace(*b)) 1639 b++; 1640 } 1641 else { 1642 v = 1; 1643 break; 1644 } 1645 } 1646 else if ((flags & STRING_COMPACT_OPTIONAL_WHITESPACE) && 1647 isspace(*a)) { 1648 a++; 1649 while (isspace(*b)) 1650 b++; 1651 } 1652 else { 1653 if ((v = *b++ - *a++) != '\0') 1654 break; 1655 } 1656 } 1657 } 1658 return v; 1659 } 1660 1661 private uint64_t 1662 file_strncmp16(const char *a, const char *b, size_t len, uint32_t flags) 1663 { 1664 /* 1665 * XXX - The 16-bit string compare probably needs to be done 1666 * differently, especially if the flags are to be supported. 1667 * At the moment, I am unsure. 1668 */ 1669 flags = 0; 1670 return file_strncmp(a, b, len, flags); 1671 } 1672 1673 private int 1674 magiccheck(struct magic_set *ms, struct magic *m) 1675 { 1676 uint64_t l = m->value.q; 1677 uint64_t v; 1678 float fl, fv; 1679 double dl, dv; 1680 int matched; 1681 union VALUETYPE *p = &ms->ms_value; 1682 1683 switch (m->type) { 1684 case FILE_BYTE: 1685 v = p->b; 1686 break; 1687 1688 case FILE_SHORT: 1689 case FILE_BESHORT: 1690 case FILE_LESHORT: 1691 v = p->h; 1692 break; 1693 1694 case FILE_LONG: 1695 case FILE_BELONG: 1696 case FILE_LELONG: 1697 case FILE_MELONG: 1698 case FILE_DATE: 1699 case FILE_BEDATE: 1700 case FILE_LEDATE: 1701 case FILE_MEDATE: 1702 case FILE_LDATE: 1703 case FILE_BELDATE: 1704 case FILE_LELDATE: 1705 case FILE_MELDATE: 1706 v = p->l; 1707 break; 1708 1709 case FILE_QUAD: 1710 case FILE_LEQUAD: 1711 case FILE_BEQUAD: 1712 case FILE_QDATE: 1713 case FILE_BEQDATE: 1714 case FILE_LEQDATE: 1715 case FILE_QLDATE: 1716 case FILE_BEQLDATE: 1717 case FILE_LEQLDATE: 1718 v = p->q; 1719 break; 1720 1721 case FILE_FLOAT: 1722 case FILE_BEFLOAT: 1723 case FILE_LEFLOAT: 1724 fl = m->value.f; 1725 fv = p->f; 1726 switch (m->reln) { 1727 case 'x': 1728 matched = 1; 1729 break; 1730 1731 case '!': 1732 matched = fv != fl; 1733 break; 1734 1735 case '=': 1736 matched = fv == fl; 1737 break; 1738 1739 case '>': 1740 matched = fv > fl; 1741 break; 1742 1743 case '<': 1744 matched = fv < fl; 1745 break; 1746 1747 default: 1748 matched = 0; 1749 file_magerror(ms, "cannot happen with float: invalid relation `%c'", 1750 m->reln); 1751 return -1; 1752 } 1753 return matched; 1754 1755 case FILE_DOUBLE: 1756 case FILE_BEDOUBLE: 1757 case FILE_LEDOUBLE: 1758 dl = m->value.d; 1759 dv = p->d; 1760 switch (m->reln) { 1761 case 'x': 1762 matched = 1; 1763 break; 1764 1765 case '!': 1766 matched = dv != dl; 1767 break; 1768 1769 case '=': 1770 matched = dv == dl; 1771 break; 1772 1773 case '>': 1774 matched = dv > dl; 1775 break; 1776 1777 case '<': 1778 matched = dv < dl; 1779 break; 1780 1781 default: 1782 matched = 0; 1783 file_magerror(ms, "cannot happen with double: invalid relation `%c'", m->reln); 1784 return -1; 1785 } 1786 return matched; 1787 1788 case FILE_DEFAULT: 1789 l = 0; 1790 v = 0; 1791 break; 1792 1793 case FILE_STRING: 1794 case FILE_PSTRING: 1795 l = 0; 1796 v = file_strncmp(m->value.s, p->s, (size_t)m->vallen, m->str_flags); 1797 break; 1798 1799 case FILE_BESTRING16: 1800 case FILE_LESTRING16: 1801 l = 0; 1802 v = file_strncmp16(m->value.s, p->s, (size_t)m->vallen, m->str_flags); 1803 break; 1804 1805 case FILE_SEARCH: { /* search ms->search.s for the string m->value.s */ 1806 size_t slen; 1807 size_t idx; 1808 1809 if (ms->search.s == NULL) 1810 return 0; 1811 1812 slen = MIN(m->vallen, sizeof(m->value.s)); 1813 l = 0; 1814 v = 0; 1815 1816 for (idx = 0; m->str_range == 0 || idx < m->str_range; idx++) { 1817 if (slen + idx > ms->search.s_len) 1818 break; 1819 1820 v = file_strncmp(m->value.s, ms->search.s + idx, slen, m->str_flags); 1821 if (v == 0) { /* found match */ 1822 ms->search.offset += idx; 1823 break; 1824 } 1825 } 1826 break; 1827 } 1828 case FILE_REGEX: { 1829 int rc; 1830 regex_t rx; 1831 char errmsg[512]; 1832 1833 if (ms->search.s == NULL) 1834 return 0; 1835 1836 l = 0; 1837 rc = regcomp(&rx, m->value.s, 1838 REG_EXTENDED|REG_NEWLINE| 1839 ((m->str_flags & STRING_IGNORE_CASE) ? REG_ICASE : 0)); 1840 if (rc) { 1841 (void)regerror(rc, &rx, errmsg, sizeof(errmsg)); 1842 file_magerror(ms, "regex error %d, (%s)", 1843 rc, errmsg); 1844 v = (uint64_t)-1; 1845 } 1846 else { 1847 regmatch_t pmatch[1]; 1848 #ifndef REG_STARTEND 1849 #define REG_STARTEND 0 1850 size_t l = ms->search.s_len - 1; 1851 char c = ms->search.s[l]; 1852 ((char *)(intptr_t)ms->search.s)[l] = '\0'; 1853 #else 1854 pmatch[0].rm_so = 0; 1855 pmatch[0].rm_eo = ms->search.s_len; 1856 #endif 1857 rc = regexec(&rx, (const char *)ms->search.s, 1858 1, pmatch, REG_STARTEND); 1859 #if REG_STARTEND == 0 1860 ((char *)(intptr_t)ms->search.s)[l] = c; 1861 #endif 1862 switch (rc) { 1863 case 0: 1864 ms->search.s += (int)pmatch[0].rm_so; 1865 ms->search.offset += (size_t)pmatch[0].rm_so; 1866 ms->search.rm_len = 1867 (size_t)(pmatch[0].rm_eo - pmatch[0].rm_so); 1868 v = 0; 1869 break; 1870 1871 case REG_NOMATCH: 1872 v = 1; 1873 break; 1874 1875 default: 1876 (void)regerror(rc, &rx, errmsg, sizeof(errmsg)); 1877 file_magerror(ms, "regexec error %d, (%s)", 1878 rc, errmsg); 1879 v = (uint64_t)-1; 1880 break; 1881 } 1882 regfree(&rx); 1883 } 1884 if (v == (uint64_t)-1) 1885 return -1; 1886 break; 1887 } 1888 case FILE_INDIRECT: 1889 return 1; 1890 default: 1891 file_magerror(ms, "invalid type %d in magiccheck()", m->type); 1892 return -1; 1893 } 1894 1895 v = file_signextend(ms, m, v); 1896 1897 switch (m->reln) { 1898 case 'x': 1899 if ((ms->flags & MAGIC_DEBUG) != 0) 1900 (void) fprintf(stderr, "%" INT64_T_FORMAT 1901 "u == *any* = 1\n", (unsigned long long)v); 1902 matched = 1; 1903 break; 1904 1905 case '!': 1906 matched = v != l; 1907 if ((ms->flags & MAGIC_DEBUG) != 0) 1908 (void) fprintf(stderr, "%" INT64_T_FORMAT "u != %" 1909 INT64_T_FORMAT "u = %d\n", (unsigned long long)v, 1910 (unsigned long long)l, matched); 1911 break; 1912 1913 case '=': 1914 matched = v == l; 1915 if ((ms->flags & MAGIC_DEBUG) != 0) 1916 (void) fprintf(stderr, "%" INT64_T_FORMAT "u == %" 1917 INT64_T_FORMAT "u = %d\n", (unsigned long long)v, 1918 (unsigned long long)l, matched); 1919 break; 1920 1921 case '>': 1922 if (m->flag & UNSIGNED) { 1923 matched = v > l; 1924 if ((ms->flags & MAGIC_DEBUG) != 0) 1925 (void) fprintf(stderr, "%" INT64_T_FORMAT 1926 "u > %" INT64_T_FORMAT "u = %d\n", 1927 (unsigned long long)v, 1928 (unsigned long long)l, matched); 1929 } 1930 else { 1931 matched = (int64_t) v > (int64_t) l; 1932 if ((ms->flags & MAGIC_DEBUG) != 0) 1933 (void) fprintf(stderr, "%" INT64_T_FORMAT 1934 "d > %" INT64_T_FORMAT "d = %d\n", 1935 (long long)v, (long long)l, matched); 1936 } 1937 break; 1938 1939 case '<': 1940 if (m->flag & UNSIGNED) { 1941 matched = v < l; 1942 if ((ms->flags & MAGIC_DEBUG) != 0) 1943 (void) fprintf(stderr, "%" INT64_T_FORMAT 1944 "u < %" INT64_T_FORMAT "u = %d\n", 1945 (unsigned long long)v, 1946 (unsigned long long)l, matched); 1947 } 1948 else { 1949 matched = (int64_t) v < (int64_t) l; 1950 if ((ms->flags & MAGIC_DEBUG) != 0) 1951 (void) fprintf(stderr, "%" INT64_T_FORMAT 1952 "d < %" INT64_T_FORMAT "d = %d\n", 1953 (long long)v, (long long)l, matched); 1954 } 1955 break; 1956 1957 case '&': 1958 matched = (v & l) == l; 1959 if ((ms->flags & MAGIC_DEBUG) != 0) 1960 (void) fprintf(stderr, "((%" INT64_T_FORMAT "x & %" 1961 INT64_T_FORMAT "x) == %" INT64_T_FORMAT 1962 "x) = %d\n", (unsigned long long)v, 1963 (unsigned long long)l, (unsigned long long)l, 1964 matched); 1965 break; 1966 1967 case '^': 1968 matched = (v & l) != l; 1969 if ((ms->flags & MAGIC_DEBUG) != 0) 1970 (void) fprintf(stderr, "((%" INT64_T_FORMAT "x & %" 1971 INT64_T_FORMAT "x) != %" INT64_T_FORMAT 1972 "x) = %d\n", (unsigned long long)v, 1973 (unsigned long long)l, (unsigned long long)l, 1974 matched); 1975 break; 1976 1977 default: 1978 matched = 0; 1979 file_magerror(ms, "cannot happen: invalid relation `%c'", 1980 m->reln); 1981 return -1; 1982 } 1983 1984 return matched; 1985 } 1986 1987 private int 1988 handle_annotation(struct magic_set *ms, struct magic *m) 1989 { 1990 if (ms->flags & MAGIC_APPLE) { 1991 if (file_printf(ms, "%.8s", m->apple) == -1) 1992 return -1; 1993 return 1; 1994 } 1995 if ((ms->flags & MAGIC_MIME_TYPE) && m->mimetype[0]) { 1996 if (file_printf(ms, "%s", m->mimetype) == -1) 1997 return -1; 1998 return 1; 1999 } 2000 return 0; 2001 } 2002 2003 private int 2004 print_sep(struct magic_set *ms, int firstline) 2005 { 2006 if (ms->flags & MAGIC_MIME) 2007 return 0; 2008 if (firstline) 2009 return 0; 2010 /* 2011 * we found another match 2012 * put a newline and '-' to do some simple formatting 2013 */ 2014 return file_printf(ms, "\n- "); 2015 } 2016