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