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