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