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