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