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