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