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