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