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