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