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