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