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