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