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