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