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