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