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