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.323 2022/05/28 00:44:22 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 *, file_regex_t **, 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 *, file_regex_t **); 56 private int 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->magic_rxcomp, ml->nmagic, b, 135 0, mode, 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, file_regex_t **magic_rxcomp, 195 uint32_t nmagic, 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 file_regex_t **m_rxcomp = &magic_rxcomp[magindex]; 224 225 if (m->type != FILE_NAME) 226 if ((IS_STRING(m->type) && 227 #define FLT (STRING_BINTEST | STRING_TEXTTEST) 228 ((text && (m->str_flags & FLT) == STRING_BINTEST) || 229 (!text && (m->str_flags & FLT) == STRING_TEXTTEST))) || 230 (m->flag & mode) != mode) { 231 flush: 232 /* Skip sub-tests */ 233 while (magindex < nmagic - 1 && 234 magic[magindex + 1].cont_level != 0) 235 magindex++; 236 cont_level = 0; 237 continue; /* Skip to next top-level test*/ 238 } 239 240 if (msetoffset(ms, m, &bb, b, offset, cont_level) == -1) 241 goto flush; 242 ms->line = m->lineno; 243 244 /* if main entry matches, print it... */ 245 switch (mget(ms, m, b, CAST(const unsigned char *, bb.fbuf), 246 bb.flen, offset, cont_level, 247 mode, text, flip, indir_count, name_count, 248 printed_something, need_separator, returnval, found_match)) 249 { 250 case -1: 251 return -1; 252 case 0: 253 flush = m->reln != '!'; 254 break; 255 default: 256 if (m->type == FILE_INDIRECT) { 257 *found_match = 1; 258 *returnval = 1; 259 } 260 261 switch (magiccheck(ms, m, m_rxcomp)) { 262 case -1: 263 return -1; 264 case 0: 265 flush++; 266 break; 267 default: 268 flush = 0; 269 break; 270 } 271 break; 272 } 273 if (flush) { 274 /* 275 * main entry didn't match, 276 * flush its continuations 277 */ 278 goto flush; 279 } 280 281 if ((e = handle_annotation(ms, m, firstline)) != 0) 282 { 283 *found_match = 1; 284 *need_separator = 1; 285 *printed_something = 1; 286 *returnval = 1; 287 return e; 288 } 289 290 /* 291 * If we are going to print something, we'll need to print 292 * a blank before we print something else. 293 */ 294 if (*m->desc) { 295 *found_match = 1; 296 if (print) { 297 *returnval = 1; 298 *need_separator = 1; 299 *printed_something = 1; 300 if (print_sep(ms, firstline) == -1) 301 return -1; 302 if (mprint(ms, m) == -1) 303 return -1; 304 } 305 } 306 307 switch (moffset(ms, m, &bb, &ms->c.li[cont_level].off)) { 308 case -1: 309 case 0: 310 goto flush; 311 default: 312 break; 313 } 314 315 /* and any continuations that match */ 316 if (file_check_mem(ms, ++cont_level) == -1) 317 return -1; 318 319 while (magindex + 1 < nmagic && 320 magic[magindex + 1].cont_level != 0) { 321 m = &magic[++magindex]; 322 m_rxcomp = &magic_rxcomp[magindex]; 323 ms->line = m->lineno; /* for messages */ 324 325 if (cont_level < m->cont_level) 326 continue; 327 if (cont_level > m->cont_level) { 328 /* 329 * We're at the end of the level 330 * "cont_level" continuations. 331 */ 332 cont_level = m->cont_level; 333 } 334 if (msetoffset(ms, m, &bb, b, offset, cont_level) == -1) 335 goto flush; 336 if (m->flag & OFFADD) { 337 if (cont_level == 0) { 338 if ((ms->flags & MAGIC_DEBUG) != 0) 339 fprintf(stderr, 340 "direct *zero*" 341 " cont_level\n"); 342 return 0; 343 } 344 ms->offset += 345 ms->c.li[cont_level - 1].off; 346 } 347 348 #ifdef ENABLE_CONDITIONALS 349 if (m->cond == COND_ELSE || 350 m->cond == COND_ELIF) { 351 if (ms->c.li[cont_level].last_match == 1) 352 continue; 353 } 354 #endif 355 switch (mget(ms, m, b, CAST(const unsigned char *, 356 bb.fbuf), bb.flen, offset, 357 cont_level, mode, text, flip, indir_count, 358 name_count, printed_something, need_separator, 359 returnval, found_match)) { 360 case -1: 361 return -1; 362 case 0: 363 if (m->reln != '!') 364 continue; 365 flush = 1; 366 break; 367 default: 368 if (m->type == FILE_INDIRECT) { 369 *found_match = 1; 370 *returnval = 1; 371 } 372 flush = 0; 373 break; 374 } 375 376 switch (flush ? 1 : magiccheck(ms, m, m_rxcomp)) { 377 case -1: 378 return -1; 379 case 0: 380 #ifdef ENABLE_CONDITIONALS 381 ms->c.li[cont_level].last_match = 0; 382 #endif 383 break; 384 default: 385 #ifdef ENABLE_CONDITIONALS 386 ms->c.li[cont_level].last_match = 1; 387 #endif 388 if (m->type == FILE_CLEAR) 389 ms->c.li[cont_level].got_match = 0; 390 else if (ms->c.li[cont_level].got_match) { 391 if (m->type == FILE_DEFAULT) 392 break; 393 } else 394 ms->c.li[cont_level].got_match = 1; 395 396 if ((e = handle_annotation(ms, m, firstline)) 397 != 0) { 398 *found_match = 1; 399 *need_separator = 1; 400 *printed_something = 1; 401 *returnval = 1; 402 return e; 403 } 404 if (*m->desc) { 405 *found_match = 1; 406 } 407 if (print && *m->desc) { 408 *returnval = 1; 409 /* 410 * This continuation matched. Print 411 * its message, with a blank before it 412 * if the previous item printed and 413 * this item isn't empty. 414 */ 415 /* 416 * If we are going to print something, 417 * make sure that we have a separator 418 * first. 419 */ 420 if (!*printed_something) { 421 *printed_something = 1; 422 if (print_sep(ms, firstline) 423 == -1) 424 return -1; 425 } 426 /* space if previous printed */ 427 if (*need_separator 428 && (m->flag & NOSPACE) == 0) { 429 if (file_printf(ms, " ") == -1) 430 return -1; 431 } 432 if (mprint(ms, m) == -1) 433 return -1; 434 *need_separator = 1; 435 } 436 437 switch (moffset(ms, m, &bb, 438 &ms->c.li[cont_level].off)) { 439 case -1: 440 case 0: 441 cont_level--; 442 break; 443 default: 444 break; 445 } 446 447 /* 448 * If we see any continuations 449 * at a higher level, 450 * process them. 451 */ 452 if (file_check_mem(ms, ++cont_level) == -1) 453 return -1; 454 break; 455 } 456 } 457 if (*printed_something) { 458 firstline = 0; 459 } 460 if (*found_match) { 461 if ((ms->flags & MAGIC_CONTINUE) == 0) 462 return *returnval; 463 // So that we print a separator 464 *printed_something = 0; 465 firstline = 0; 466 } 467 cont_level = 0; 468 } 469 return *returnval; 470 } 471 472 private int 473 check_fmt(struct magic_set *ms, const char *fmt) 474 { 475 file_regex_t rx; 476 int rc, rv = -1; 477 const char* pat = "%[-0-9\\.]*s"; 478 479 if (strchr(fmt, '%') == NULL) 480 return 0; 481 482 rc = file_regcomp(ms, &rx, pat, REG_EXTENDED|REG_NOSUB); 483 if (rc == 0) { 484 rc = file_regexec(ms, &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 = CAST(char *, 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 int 569 mprint(struct magic_set *ms, struct magic *m) 570 { 571 uint64_t v; 572 float vf; 573 double vd; 574 char buf[128], tbuf[26], sbuf[512], ebuf[512]; 575 const char *desc; 576 union VALUETYPE *p = &ms->ms_value; 577 578 if (varexpand(ms, ebuf, sizeof(ebuf), m->desc) == -1) 579 desc = m->desc; 580 else 581 desc = ebuf; 582 583 #define PRINTER(value, format, stype, utype) \ 584 v = file_signextend(ms, m, CAST(uint64_t, value)); \ 585 switch (check_fmt(ms, desc)) { \ 586 case -1: \ 587 return -1; \ 588 case 1: \ 589 if (m->flag & UNSIGNED) { \ 590 (void)snprintf(buf, sizeof(buf), "%" format "u", \ 591 CAST(utype, v)); \ 592 } else { \ 593 (void)snprintf(buf, sizeof(buf), "%" format "d", \ 594 CAST(stype, v)); \ 595 } \ 596 if (file_printf(ms, F(ms, desc, "%s"), buf) == -1) \ 597 return -1; \ 598 break; \ 599 default: \ 600 if (m->flag & UNSIGNED) { \ 601 if (file_printf(ms, F(ms, desc, "%" format "u"), \ 602 CAST(utype, v)) == -1) \ 603 return -1; \ 604 } else { \ 605 if (file_printf(ms, F(ms, desc, "%" format "d"), \ 606 CAST(stype, v)) == -1) \ 607 return -1; \ 608 } \ 609 break; \ 610 } \ 611 break 612 613 switch (m->type) { 614 case FILE_BYTE: 615 PRINTER(p->b, "", int8_t, uint8_t); 616 617 case FILE_SHORT: 618 case FILE_BESHORT: 619 case FILE_LESHORT: 620 PRINTER(p->h, "", int16_t, uint16_t); 621 622 case FILE_LONG: 623 case FILE_BELONG: 624 case FILE_LELONG: 625 case FILE_MELONG: 626 PRINTER(p->l, "", int32_t, uint32_t); 627 628 case FILE_QUAD: 629 case FILE_BEQUAD: 630 case FILE_LEQUAD: 631 case FILE_OFFSET: 632 PRINTER(p->q, INT64_T_FORMAT, long long, unsigned long long); 633 634 case FILE_STRING: 635 case FILE_PSTRING: 636 case FILE_BESTRING16: 637 case FILE_LESTRING16: 638 if (m->reln == '=' || m->reln == '!') { 639 if (file_printf(ms, F(ms, desc, "%s"), 640 file_printable(ms, sbuf, sizeof(sbuf), m->value.s, 641 sizeof(m->value.s))) == -1) 642 return -1; 643 } 644 else { 645 char *str = p->s; 646 647 /* compute t before we mangle the string? */ 648 649 if (*m->value.s == '\0') 650 str[strcspn(str, "\r\n")] = '\0'; 651 652 if (m->str_flags & STRING_TRIM) 653 str = file_strtrim(str); 654 655 if (file_printf(ms, F(ms, desc, "%s"), 656 file_printable(ms, sbuf, sizeof(sbuf), str, 657 sizeof(p->s) - (str - p->s))) == -1) 658 return -1; 659 660 if (m->type == FILE_PSTRING) { 661 size_t l = file_pstring_length_size(ms, m); 662 if (l == FILE_BADSIZE) 663 return -1; 664 } 665 } 666 break; 667 668 case FILE_DATE: 669 case FILE_BEDATE: 670 case FILE_LEDATE: 671 case FILE_MEDATE: 672 if (file_printf(ms, F(ms, desc, "%s"), 673 file_fmtdatetime(tbuf, sizeof(tbuf), p->l, 0)) == -1) 674 return -1; 675 break; 676 677 case FILE_LDATE: 678 case FILE_BELDATE: 679 case FILE_LELDATE: 680 case FILE_MELDATE: 681 if (file_printf(ms, F(ms, desc, "%s"), 682 file_fmtdatetime(tbuf, sizeof(tbuf), p->l, FILE_T_LOCAL)) 683 == -1) 684 return -1; 685 break; 686 687 case FILE_QDATE: 688 case FILE_BEQDATE: 689 case FILE_LEQDATE: 690 if (file_printf(ms, F(ms, desc, "%s"), 691 file_fmtdatetime(tbuf, sizeof(tbuf), p->q, 0)) == -1) 692 return -1; 693 break; 694 695 case FILE_QLDATE: 696 case FILE_BEQLDATE: 697 case FILE_LEQLDATE: 698 if (file_printf(ms, F(ms, desc, "%s"), 699 file_fmtdatetime(tbuf, sizeof(tbuf), p->q, FILE_T_LOCAL)) == -1) 700 return -1; 701 break; 702 703 case FILE_QWDATE: 704 case FILE_BEQWDATE: 705 case FILE_LEQWDATE: 706 if (file_printf(ms, F(ms, desc, "%s"), 707 file_fmtdatetime(tbuf, sizeof(tbuf), p->q, FILE_T_WINDOWS)) 708 == -1) 709 return -1; 710 break; 711 712 case FILE_FLOAT: 713 case FILE_BEFLOAT: 714 case FILE_LEFLOAT: 715 vf = p->f; 716 switch (check_fmt(ms, desc)) { 717 case -1: 718 return -1; 719 case 1: 720 (void)snprintf(buf, sizeof(buf), "%g", vf); 721 if (file_printf(ms, F(ms, desc, "%s"), buf) == -1) 722 return -1; 723 break; 724 default: 725 if (file_printf(ms, F(ms, desc, "%g"), vf) == -1) 726 return -1; 727 break; 728 } 729 break; 730 731 case FILE_DOUBLE: 732 case FILE_BEDOUBLE: 733 case FILE_LEDOUBLE: 734 vd = p->d; 735 switch (check_fmt(ms, desc)) { 736 case -1: 737 return -1; 738 case 1: 739 (void)snprintf(buf, sizeof(buf), "%g", vd); 740 if (file_printf(ms, F(ms, desc, "%s"), buf) == -1) 741 return -1; 742 break; 743 default: 744 if (file_printf(ms, F(ms, desc, "%g"), vd) == -1) 745 return -1; 746 break; 747 } 748 break; 749 750 case FILE_SEARCH: 751 case FILE_REGEX: { 752 char *cp, *scp; 753 int rval; 754 755 cp = strndup(RCAST(const char *, ms->search.s), 756 ms->search.rm_len); 757 if (cp == NULL) { 758 file_oomem(ms, ms->search.rm_len); 759 return -1; 760 } 761 scp = (m->str_flags & STRING_TRIM) ? file_strtrim(cp) : cp; 762 763 rval = file_printf(ms, F(ms, desc, "%s"), file_printable(ms, 764 sbuf, sizeof(sbuf), scp, ms->search.rm_len)); 765 free(cp); 766 767 if (rval == -1) 768 return -1; 769 break; 770 } 771 772 case FILE_DEFAULT: 773 case FILE_CLEAR: 774 if (file_printf(ms, "%s", m->desc) == -1) 775 return -1; 776 break; 777 778 case FILE_INDIRECT: 779 case FILE_USE: 780 case FILE_NAME: 781 break; 782 case FILE_DER: 783 if (file_printf(ms, F(ms, desc, "%s"), 784 file_printable(ms, sbuf, sizeof(sbuf), ms->ms_value.s, 785 sizeof(ms->ms_value.s))) == -1) 786 return -1; 787 break; 788 case FILE_GUID: 789 (void) file_print_guid(buf, sizeof(buf), ms->ms_value.guid); 790 if (file_printf(ms, F(ms, desc, "%s"), buf) == -1) 791 return -1; 792 break; 793 case FILE_MSDOSDATE: 794 case FILE_BEMSDOSDATE: 795 case FILE_LEMSDOSDATE: 796 if (file_printf(ms, F(ms, desc, "%s"), 797 file_fmtdate(tbuf, sizeof(tbuf), p->h)) == -1) 798 return -1; 799 break; 800 case FILE_MSDOSTIME: 801 case FILE_BEMSDOSTIME: 802 case FILE_LEMSDOSTIME: 803 if (file_printf(ms, F(ms, desc, "%s"), 804 file_fmttime(tbuf, sizeof(tbuf), p->h)) == -1) 805 return -1; 806 break; 807 default: 808 file_magerror(ms, "invalid m->type (%d) in mprint()", m->type); 809 return -1; 810 } 811 return 0; 812 } 813 814 private int 815 moffset(struct magic_set *ms, struct magic *m, const struct buffer *b, 816 int32_t *op) 817 { 818 size_t nbytes = b->flen; 819 int32_t o; 820 821 switch (m->type) { 822 case FILE_BYTE: 823 o = CAST(int32_t, (ms->offset + sizeof(char))); 824 break; 825 826 case FILE_SHORT: 827 case FILE_BESHORT: 828 case FILE_LESHORT: 829 case FILE_MSDOSDATE: 830 case FILE_LEMSDOSDATE: 831 case FILE_BEMSDOSDATE: 832 case FILE_MSDOSTIME: 833 case FILE_LEMSDOSTIME: 834 case FILE_BEMSDOSTIME: 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 case FILE_MSDOSDATE: 1141 case FILE_LEMSDOSDATE: 1142 case FILE_BEMSDOSDATE: 1143 case FILE_MSDOSTIME: 1144 case FILE_LEMSDOSTIME: 1145 case FILE_BEMSDOSTIME: 1146 if (cvt_16(p, m) == -1) 1147 goto out; 1148 return 1; 1149 case FILE_LONG: 1150 case FILE_DATE: 1151 case FILE_LDATE: 1152 if (cvt_32(p, m) == -1) 1153 goto out; 1154 return 1; 1155 case FILE_QUAD: 1156 case FILE_QDATE: 1157 case FILE_QLDATE: 1158 case FILE_QWDATE: 1159 case FILE_OFFSET: 1160 if (cvt_64(p, m) == -1) 1161 goto out; 1162 return 1; 1163 case FILE_STRING: 1164 case FILE_BESTRING16: 1165 case FILE_LESTRING16: { 1166 /* Null terminate and eat *trailing* return */ 1167 p->s[sizeof(p->s) - 1] = '\0'; 1168 return 1; 1169 } 1170 case FILE_PSTRING: { 1171 char *ptr1, *ptr2; 1172 size_t len, sz = file_pstring_length_size(ms, m); 1173 if (sz == FILE_BADSIZE) 1174 return 0; 1175 ptr1 = p->s; 1176 ptr2 = ptr1 + sz; 1177 len = file_pstring_get_length(ms, m, ptr1); 1178 if (len == FILE_BADSIZE) 1179 return 0; 1180 sz = sizeof(p->s) - sz; /* maximum length of string */ 1181 if (len >= sz) { 1182 /* 1183 * The size of the pascal string length (sz) 1184 * is 1, 2, or 4. We need at least 1 byte for NUL 1185 * termination, but we've already truncated the 1186 * string by p->s, so we need to deduct sz. 1187 * Because we can use one of the bytes of the length 1188 * after we shifted as NUL termination. 1189 */ 1190 len = sz; 1191 } 1192 while (len--) 1193 *ptr1++ = *ptr2++; 1194 *ptr1 = '\0'; 1195 return 1; 1196 } 1197 case FILE_BESHORT: 1198 p->h = CAST(short, BE16(p)); 1199 if (cvt_16(p, m) == -1) 1200 goto out; 1201 return 1; 1202 case FILE_BELONG: 1203 case FILE_BEDATE: 1204 case FILE_BELDATE: 1205 p->l = CAST(int32_t, BE32(p)); 1206 if (cvt_32(p, m) == -1) 1207 goto out; 1208 return 1; 1209 case FILE_BEQUAD: 1210 case FILE_BEQDATE: 1211 case FILE_BEQLDATE: 1212 case FILE_BEQWDATE: 1213 p->q = CAST(uint64_t, BE64(p)); 1214 if (cvt_64(p, m) == -1) 1215 goto out; 1216 return 1; 1217 case FILE_LESHORT: 1218 p->h = CAST(short, LE16(p)); 1219 if (cvt_16(p, m) == -1) 1220 goto out; 1221 return 1; 1222 case FILE_LELONG: 1223 case FILE_LEDATE: 1224 case FILE_LELDATE: 1225 p->l = CAST(int32_t, LE32(p)); 1226 if (cvt_32(p, m) == -1) 1227 goto out; 1228 return 1; 1229 case FILE_LEQUAD: 1230 case FILE_LEQDATE: 1231 case FILE_LEQLDATE: 1232 case FILE_LEQWDATE: 1233 p->q = CAST(uint64_t, LE64(p)); 1234 if (cvt_64(p, m) == -1) 1235 goto out; 1236 return 1; 1237 case FILE_MELONG: 1238 case FILE_MEDATE: 1239 case FILE_MELDATE: 1240 p->l = CAST(int32_t, ME32(p)); 1241 if (cvt_32(p, m) == -1) 1242 goto out; 1243 return 1; 1244 case FILE_FLOAT: 1245 if (cvt_float(p, m) == -1) 1246 goto out; 1247 return 1; 1248 case FILE_BEFLOAT: 1249 p->l = BE32(p); 1250 if (cvt_float(p, m) == -1) 1251 goto out; 1252 return 1; 1253 case FILE_LEFLOAT: 1254 p->l = LE32(p); 1255 if (cvt_float(p, m) == -1) 1256 goto out; 1257 return 1; 1258 case FILE_DOUBLE: 1259 if (cvt_double(p, m) == -1) 1260 goto out; 1261 return 1; 1262 case FILE_BEDOUBLE: 1263 p->q = BE64(p); 1264 if (cvt_double(p, m) == -1) 1265 goto out; 1266 return 1; 1267 case FILE_LEDOUBLE: 1268 p->q = LE64(p); 1269 if (cvt_double(p, m) == -1) 1270 goto out; 1271 return 1; 1272 case FILE_REGEX: 1273 case FILE_SEARCH: 1274 case FILE_DEFAULT: 1275 case FILE_CLEAR: 1276 case FILE_NAME: 1277 case FILE_USE: 1278 case FILE_DER: 1279 case FILE_GUID: 1280 return 1; 1281 default: 1282 file_magerror(ms, "invalid type %d in mconvert()", m->type); 1283 return 0; 1284 } 1285 out: 1286 file_magerror(ms, "zerodivide in mconvert()"); 1287 return 0; 1288 } 1289 1290 1291 private void 1292 mdebug(uint32_t offset, const char *str, size_t len) 1293 { 1294 (void) fprintf(stderr, "mget/%" SIZE_T_FORMAT "u @%d: ", len, offset); 1295 file_showstr(stderr, str, len); 1296 (void) fputc('\n', stderr); 1297 (void) fputc('\n', stderr); 1298 } 1299 1300 private int 1301 mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir, 1302 const unsigned char *s, uint32_t offset, size_t nbytes, struct magic *m) 1303 { 1304 /* 1305 * Note: FILE_SEARCH and FILE_REGEX do not actually copy 1306 * anything, but setup pointers into the source 1307 */ 1308 if (indir == 0) { 1309 switch (type) { 1310 case FILE_DER: 1311 case FILE_SEARCH: 1312 if (offset > nbytes) 1313 offset = CAST(uint32_t, nbytes); 1314 ms->search.s = RCAST(const char *, s) + offset; 1315 ms->search.s_len = nbytes - offset; 1316 ms->search.offset = offset; 1317 return 0; 1318 1319 case FILE_REGEX: { 1320 const char *b; 1321 const char *c; 1322 const char *last; /* end of search region */ 1323 const char *buf; /* start of search region */ 1324 const char *end; 1325 size_t lines, linecnt, bytecnt; 1326 1327 if (s == NULL || nbytes < offset) { 1328 ms->search.s_len = 0; 1329 ms->search.s = NULL; 1330 return 0; 1331 } 1332 1333 if (m->str_flags & REGEX_LINE_COUNT) { 1334 linecnt = m->str_range; 1335 bytecnt = linecnt * 80; 1336 } else { 1337 linecnt = 0; 1338 bytecnt = m->str_range; 1339 } 1340 1341 if (bytecnt == 0 || bytecnt > nbytes - offset) 1342 bytecnt = nbytes - offset; 1343 if (bytecnt > ms->regex_max) 1344 bytecnt = ms->regex_max; 1345 1346 buf = RCAST(const char *, s) + offset; 1347 end = last = RCAST(const char *, s) + bytecnt + offset; 1348 /* mget() guarantees buf <= last */ 1349 for (lines = linecnt, b = buf; lines && b < end && 1350 ((b = CAST(const char *, 1351 memchr(c = b, '\n', CAST(size_t, (end - b))))) 1352 || (b = CAST(const char *, 1353 memchr(c, '\r', CAST(size_t, (end - c)))))); 1354 lines--, b++) { 1355 if (b < end - 1 && b[0] == '\r' && b[1] == '\n') 1356 b++; 1357 if (b < end - 1 && b[0] == '\n') 1358 b++; 1359 last = b; 1360 } 1361 if (lines) 1362 last = end; 1363 1364 ms->search.s = buf; 1365 ms->search.s_len = last - buf; 1366 ms->search.offset = offset; 1367 ms->search.rm_len = 0; 1368 return 0; 1369 } 1370 case FILE_BESTRING16: 1371 case FILE_LESTRING16: { 1372 const unsigned char *src = s + offset; 1373 const unsigned char *esrc = s + nbytes; 1374 char *dst = p->s; 1375 char *edst = &p->s[sizeof(p->s) - 1]; 1376 1377 if (type == FILE_BESTRING16) 1378 src++; 1379 1380 /* check that offset is within range */ 1381 if (offset >= nbytes) 1382 break; 1383 for (/*EMPTY*/; src < esrc; src += 2, dst++) { 1384 if (dst < edst) 1385 *dst = *src; 1386 else 1387 break; 1388 if (*dst == '\0') { 1389 if (type == FILE_BESTRING16 ? 1390 *(src - 1) != '\0' : 1391 ((src + 1 < esrc) && 1392 *(src + 1) != '\0')) 1393 *dst = ' '; 1394 } 1395 } 1396 *edst = '\0'; 1397 return 0; 1398 } 1399 case FILE_STRING: /* XXX - these two should not need */ 1400 case FILE_PSTRING: /* to copy anything, but do anyway. */ 1401 default: 1402 break; 1403 } 1404 } 1405 1406 if (type == FILE_OFFSET) { 1407 (void)memset(p, '\0', sizeof(*p)); 1408 p->q = offset; 1409 return 0; 1410 } 1411 1412 if (offset >= nbytes) { 1413 (void)memset(p, '\0', sizeof(*p)); 1414 return 0; 1415 } 1416 if (nbytes - offset < sizeof(*p)) 1417 nbytes = nbytes - offset; 1418 else 1419 nbytes = sizeof(*p); 1420 1421 (void)memcpy(p, s + offset, nbytes); 1422 1423 /* 1424 * the usefulness of padding with zeroes eludes me, it 1425 * might even cause problems 1426 */ 1427 if (nbytes < sizeof(*p)) 1428 (void)memset(RCAST(char *, RCAST(void *, p)) + nbytes, '\0', 1429 sizeof(*p) - nbytes); 1430 return 0; 1431 } 1432 1433 private uint32_t 1434 do_ops(struct magic *m, intmax_t lhs, intmax_t off) 1435 { 1436 intmax_t offset; 1437 if (off) { 1438 switch (m->in_op & FILE_OPS_MASK) { 1439 case FILE_OPAND: 1440 offset = lhs & off; 1441 break; 1442 case FILE_OPOR: 1443 offset = lhs | off; 1444 break; 1445 case FILE_OPXOR: 1446 offset = lhs ^ off; 1447 break; 1448 case FILE_OPADD: 1449 offset = lhs + off; 1450 break; 1451 case FILE_OPMINUS: 1452 offset = lhs - off; 1453 break; 1454 case FILE_OPMULTIPLY: 1455 offset = lhs * off; 1456 break; 1457 case FILE_OPDIVIDE: 1458 offset = lhs / off; 1459 break; 1460 case FILE_OPMODULO: 1461 offset = lhs % off; 1462 break; 1463 } 1464 } else 1465 offset = lhs; 1466 if (m->in_op & FILE_OPINVERSE) 1467 offset = ~offset; 1468 1469 return CAST(uint32_t, offset); 1470 } 1471 1472 private int 1473 msetoffset(struct magic_set *ms, struct magic *m, struct buffer *bb, 1474 const struct buffer *b, size_t o, unsigned int cont_level) 1475 { 1476 int32_t offset; 1477 if (m->flag & OFFNEGATIVE) { 1478 offset = -m->offset; 1479 if (cont_level > 0) { 1480 if (m->flag & (OFFADD|INDIROFFADD)) 1481 goto normal; 1482 #if 0 1483 file_error(ms, 0, "negative offset %d at continuation" 1484 "level %u", m->offset, cont_level); 1485 return -1; 1486 #endif 1487 } 1488 if (buffer_fill(b) == -1) 1489 return -1; 1490 if (o != 0) { 1491 // Not yet! 1492 file_magerror(ms, "non zero offset %" SIZE_T_FORMAT 1493 "u at level %u", o, cont_level); 1494 return -1; 1495 } 1496 if (CAST(size_t, m->offset) > b->elen) 1497 return -1; 1498 buffer_init(bb, -1, NULL, b->ebuf, b->elen); 1499 ms->eoffset = ms->offset = CAST(int32_t, b->elen - m->offset); 1500 } else { 1501 offset = m->offset; 1502 if (cont_level == 0) { 1503 normal: 1504 // XXX: Pass real fd, then who frees bb? 1505 buffer_init(bb, -1, NULL, b->fbuf, b->flen); 1506 ms->offset = offset; 1507 ms->eoffset = 0; 1508 } else { 1509 ms->offset = ms->eoffset + offset; 1510 } 1511 } 1512 if ((ms->flags & MAGIC_DEBUG) != 0) { 1513 fprintf(stderr, "bb=[%p,%" SIZE_T_FORMAT "u,%" 1514 SIZE_T_FORMAT "u], %d [b=%p,%" 1515 SIZE_T_FORMAT "u,%" SIZE_T_FORMAT "u], [o=%#x, c=%d]\n", 1516 bb->fbuf, bb->flen, bb->elen, ms->offset, b->fbuf, 1517 b->flen, b->elen, offset, cont_level); 1518 } 1519 return 0; 1520 } 1521 1522 private int 1523 save_cont(struct magic_set *ms, struct cont *c) 1524 { 1525 size_t len; 1526 *c = ms->c; 1527 len = c->len * sizeof(*c->li); 1528 ms->c.li = CAST(struct level_info *, malloc(len)); 1529 if (ms->c.li == NULL) { 1530 ms->c = *c; 1531 return -1; 1532 } 1533 memcpy(ms->c.li, c->li, len); 1534 return 0; 1535 } 1536 1537 private void 1538 restore_cont(struct magic_set *ms, struct cont *c) 1539 { 1540 free(ms->c.li); 1541 ms->c = *c; 1542 } 1543 1544 private int 1545 mget(struct magic_set *ms, struct magic *m, const struct buffer *b, 1546 const unsigned char *s, size_t nbytes, size_t o, unsigned int cont_level, 1547 int mode, int text, int flip, uint16_t *indir_count, uint16_t *name_count, 1548 int *printed_something, int *need_separator, int *returnval, 1549 int *found_match) 1550 { 1551 uint32_t eoffset, offset = ms->offset; 1552 struct buffer bb; 1553 intmax_t lhs; 1554 file_pushbuf_t *pb; 1555 int rv, oneed_separator, in_type, nfound_match; 1556 char *rbuf; 1557 union VALUETYPE *p = &ms->ms_value; 1558 struct mlist ml, *mlp; 1559 struct cont c; 1560 1561 if (*indir_count >= ms->indir_max) { 1562 file_error(ms, 0, "indirect count (%hu) exceeded", 1563 *indir_count); 1564 return -1; 1565 } 1566 1567 if (*name_count >= ms->name_max) { 1568 file_error(ms, 0, "name use count (%hu) exceeded", 1569 *name_count); 1570 return -1; 1571 } 1572 1573 1574 1575 if (mcopy(ms, p, m->type, m->flag & INDIR, s, 1576 CAST(uint32_t, offset + o), CAST(uint32_t, nbytes), m) == -1) 1577 return -1; 1578 1579 if ((ms->flags & MAGIC_DEBUG) != 0) { 1580 fprintf(stderr, "mget(type=%d, flag=%#x, offset=%u, o=%" 1581 SIZE_T_FORMAT "u, " "nbytes=%" SIZE_T_FORMAT 1582 "u, il=%hu, nc=%hu)\n", 1583 m->type, m->flag, offset, o, nbytes, 1584 *indir_count, *name_count); 1585 mdebug(offset, RCAST(char *, RCAST(void *, p)), 1586 sizeof(union VALUETYPE)); 1587 #ifndef COMPILE_ONLY 1588 file_mdump(m); 1589 #endif 1590 } 1591 1592 if (m->flag & INDIR) { 1593 intmax_t off = m->in_offset; 1594 const int sgn = m->in_op & FILE_OPSIGNED; 1595 if (m->in_op & FILE_OPINDIRECT) { 1596 const union VALUETYPE *q = CAST(const union VALUETYPE *, 1597 RCAST(const void *, s + offset + off)); 1598 int op; 1599 switch (op = cvt_flip(m->in_type, flip)) { 1600 case FILE_BYTE: 1601 if (OFFSET_OOB(nbytes, offset + off, 1)) 1602 return 0; 1603 off = SEXT(sgn,8,q->b); 1604 break; 1605 case FILE_SHORT: 1606 if (OFFSET_OOB(nbytes, offset + off, 2)) 1607 return 0; 1608 off = SEXT(sgn,16,q->h); 1609 break; 1610 case FILE_BESHORT: 1611 if (OFFSET_OOB(nbytes, offset + off, 2)) 1612 return 0; 1613 off = SEXT(sgn,16,BE16(q)); 1614 break; 1615 case FILE_LESHORT: 1616 if (OFFSET_OOB(nbytes, offset + off, 2)) 1617 return 0; 1618 off = SEXT(sgn,16,LE16(q)); 1619 break; 1620 case FILE_LONG: 1621 if (OFFSET_OOB(nbytes, offset + off, 4)) 1622 return 0; 1623 off = SEXT(sgn,32,q->l); 1624 break; 1625 case FILE_BELONG: 1626 case FILE_BEID3: 1627 if (OFFSET_OOB(nbytes, offset + off, 4)) 1628 return 0; 1629 off = SEXT(sgn,32,BE32(q)); 1630 break; 1631 case FILE_LEID3: 1632 case FILE_LELONG: 1633 if (OFFSET_OOB(nbytes, offset + off, 4)) 1634 return 0; 1635 off = SEXT(sgn,32,LE32(q)); 1636 break; 1637 case FILE_MELONG: 1638 if (OFFSET_OOB(nbytes, offset + off, 4)) 1639 return 0; 1640 off = SEXT(sgn,32,ME32(q)); 1641 break; 1642 case FILE_BEQUAD: 1643 if (OFFSET_OOB(nbytes, offset + off, 8)) 1644 return 0; 1645 off = SEXT(sgn,64,BE64(q)); 1646 break; 1647 case FILE_LEQUAD: 1648 if (OFFSET_OOB(nbytes, offset + off, 8)) 1649 return 0; 1650 off = SEXT(sgn,64,LE64(q)); 1651 break; 1652 default: 1653 if ((ms->flags & MAGIC_DEBUG) != 0) 1654 fprintf(stderr, "bad op=%d\n", op); 1655 return 0; 1656 } 1657 if ((ms->flags & MAGIC_DEBUG) != 0) 1658 fprintf(stderr, "indirect offs=%jd\n", off); 1659 } 1660 switch (in_type = cvt_flip(m->in_type, flip)) { 1661 case FILE_BYTE: 1662 if (OFFSET_OOB(nbytes, offset, 1)) 1663 return 0; 1664 offset = do_ops(m, SEXT(sgn,8,p->b), off); 1665 break; 1666 case FILE_BESHORT: 1667 if (OFFSET_OOB(nbytes, offset, 2)) 1668 return 0; 1669 offset = do_ops(m, SEXT(sgn,16,BE16(p)), off); 1670 break; 1671 case FILE_LESHORT: 1672 if (OFFSET_OOB(nbytes, offset, 2)) 1673 return 0; 1674 offset = do_ops(m, SEXT(sgn,16,LE16(p)), off); 1675 break; 1676 case FILE_SHORT: 1677 if (OFFSET_OOB(nbytes, offset, 2)) 1678 return 0; 1679 offset = do_ops(m, SEXT(sgn,16,p->h), off); 1680 break; 1681 case FILE_BELONG: 1682 case FILE_BEID3: 1683 if (OFFSET_OOB(nbytes, offset, 4)) 1684 return 0; 1685 lhs = BE32(p); 1686 if (in_type == FILE_BEID3) 1687 lhs = cvt_id3(ms, CAST(uint32_t, lhs)); 1688 offset = do_ops(m, SEXT(sgn,32,lhs), off); 1689 break; 1690 case FILE_LELONG: 1691 case FILE_LEID3: 1692 if (OFFSET_OOB(nbytes, offset, 4)) 1693 return 0; 1694 lhs = LE32(p); 1695 if (in_type == FILE_LEID3) 1696 lhs = cvt_id3(ms, CAST(uint32_t, lhs)); 1697 offset = do_ops(m, SEXT(sgn,32,lhs), off); 1698 break; 1699 case FILE_MELONG: 1700 if (OFFSET_OOB(nbytes, offset, 4)) 1701 return 0; 1702 offset = do_ops(m, SEXT(sgn,32,ME32(p)), off); 1703 break; 1704 case FILE_LONG: 1705 if (OFFSET_OOB(nbytes, offset, 4)) 1706 return 0; 1707 offset = do_ops(m, SEXT(sgn,32,p->l), off); 1708 break; 1709 case FILE_LEQUAD: 1710 if (OFFSET_OOB(nbytes, offset, 8)) 1711 return 0; 1712 offset = do_ops(m, SEXT(sgn,64,LE64(p)), off); 1713 break; 1714 case FILE_BEQUAD: 1715 if (OFFSET_OOB(nbytes, offset, 8)) 1716 return 0; 1717 offset = do_ops(m, SEXT(sgn,64,BE64(p)), off); 1718 break; 1719 default: 1720 if ((ms->flags & MAGIC_DEBUG) != 0) 1721 fprintf(stderr, "bad in_type=%d\n", in_type); 1722 return 0; 1723 } 1724 1725 if (m->flag & INDIROFFADD) { 1726 if (cont_level == 0) { 1727 if ((ms->flags & MAGIC_DEBUG) != 0) 1728 fprintf(stderr, 1729 "indirect *zero* cont_level\n"); 1730 return 0; 1731 } 1732 offset += ms->c.li[cont_level - 1].off; 1733 if (offset == 0) { 1734 if ((ms->flags & MAGIC_DEBUG) != 0) 1735 fprintf(stderr, 1736 "indirect *zero* offset\n"); 1737 return 0; 1738 } 1739 if ((ms->flags & MAGIC_DEBUG) != 0) 1740 fprintf(stderr, "indirect +offs=%u\n", offset); 1741 } 1742 if (mcopy(ms, p, m->type, 0, s, offset, nbytes, m) == -1) 1743 return -1; 1744 ms->offset = offset; 1745 1746 if ((ms->flags & MAGIC_DEBUG) != 0) { 1747 mdebug(offset, RCAST(char *, RCAST(void *, p)), 1748 sizeof(union VALUETYPE)); 1749 #ifndef COMPILE_ONLY 1750 file_mdump(m); 1751 #endif 1752 } 1753 } 1754 1755 /* Verify we have enough data to match magic type */ 1756 switch (m->type) { 1757 case FILE_BYTE: 1758 if (OFFSET_OOB(nbytes, offset, 1)) 1759 return 0; 1760 break; 1761 1762 case FILE_SHORT: 1763 case FILE_BESHORT: 1764 case FILE_LESHORT: 1765 if (OFFSET_OOB(nbytes, offset, 2)) 1766 return 0; 1767 break; 1768 1769 case FILE_LONG: 1770 case FILE_BELONG: 1771 case FILE_LELONG: 1772 case FILE_MELONG: 1773 case FILE_DATE: 1774 case FILE_BEDATE: 1775 case FILE_LEDATE: 1776 case FILE_MEDATE: 1777 case FILE_LDATE: 1778 case FILE_BELDATE: 1779 case FILE_LELDATE: 1780 case FILE_MELDATE: 1781 case FILE_FLOAT: 1782 case FILE_BEFLOAT: 1783 case FILE_LEFLOAT: 1784 if (OFFSET_OOB(nbytes, offset, 4)) 1785 return 0; 1786 break; 1787 1788 case FILE_DOUBLE: 1789 case FILE_BEDOUBLE: 1790 case FILE_LEDOUBLE: 1791 if (OFFSET_OOB(nbytes, offset, 8)) 1792 return 0; 1793 break; 1794 1795 case FILE_GUID: 1796 if (OFFSET_OOB(nbytes, offset, 16)) 1797 return 0; 1798 break; 1799 1800 case FILE_STRING: 1801 case FILE_PSTRING: 1802 case FILE_SEARCH: 1803 if (OFFSET_OOB(nbytes, offset, m->vallen)) 1804 return 0; 1805 break; 1806 1807 case FILE_REGEX: 1808 if (nbytes < offset) 1809 return 0; 1810 break; 1811 1812 case FILE_INDIRECT: 1813 if (m->str_flags & INDIRECT_RELATIVE) 1814 offset += CAST(uint32_t, o); 1815 if (offset == 0) 1816 return 0; 1817 1818 if (nbytes < offset) 1819 return 0; 1820 1821 if ((pb = file_push_buffer(ms)) == NULL) 1822 return -1; 1823 1824 (*indir_count)++; 1825 bb = *b; 1826 bb.fbuf = s + offset; 1827 bb.flen = nbytes - offset; 1828 rv = -1; 1829 for (mlp = ms->mlist[0]->next; mlp != ms->mlist[0]; 1830 mlp = mlp->next) 1831 { 1832 if ((rv = match(ms, mlp->magic, mlp->magic_rxcomp, 1833 mlp->nmagic, &bb, 0, BINTEST, text, 0, indir_count, 1834 name_count, printed_something, need_separator, NULL, 1835 NULL)) != 0) 1836 break; 1837 } 1838 1839 if ((ms->flags & MAGIC_DEBUG) != 0) 1840 fprintf(stderr, "indirect @offs=%u[%d]\n", offset, rv); 1841 1842 rbuf = file_pop_buffer(ms, pb); 1843 if (rbuf == NULL && ms->event_flags & EVENT_HAD_ERR) 1844 return -1; 1845 1846 if (rv == 1) { 1847 if ((ms->flags & MAGIC_NODESC) == 0 && 1848 file_printf(ms, F(ms, m->desc, "%u"), offset) == -1) 1849 { 1850 free(rbuf); 1851 return -1; 1852 } 1853 if (file_printf(ms, "%s", rbuf) == -1) { 1854 free(rbuf); 1855 return -1; 1856 } 1857 } 1858 free(rbuf); 1859 return rv; 1860 1861 case FILE_USE: 1862 if (nbytes < offset) 1863 return 0; 1864 rbuf = m->value.s; 1865 if (*rbuf == '^') { 1866 rbuf++; 1867 flip = !flip; 1868 } 1869 if (file_magicfind(ms, rbuf, &ml) == -1) { 1870 file_error(ms, 0, "cannot find entry `%s'", rbuf); 1871 return -1; 1872 } 1873 if (save_cont(ms, &c) == -1) { 1874 file_error(ms, errno, "can't allocate continuation"); 1875 return -1; 1876 } 1877 1878 oneed_separator = *need_separator; 1879 if (m->flag & NOSPACE) 1880 *need_separator = 0; 1881 1882 nfound_match = 0; 1883 (*name_count)++; 1884 eoffset = ms->eoffset; 1885 rv = match(ms, ml.magic, ml.magic_rxcomp, ml.nmagic, b, 1886 offset + o, mode, text, flip, indir_count, name_count, 1887 printed_something, need_separator, returnval, 1888 &nfound_match); 1889 ms->ms_value.q = nfound_match; 1890 (*name_count)--; 1891 *found_match |= nfound_match; 1892 1893 restore_cont(ms, &c); 1894 1895 if (rv != 1) 1896 *need_separator = oneed_separator; 1897 ms->offset = offset; 1898 ms->eoffset = eoffset; 1899 return rv; 1900 1901 case FILE_NAME: 1902 if (ms->flags & MAGIC_NODESC) 1903 return 1; 1904 if (file_printf(ms, "%s", m->desc) == -1) 1905 return -1; 1906 return 1; 1907 case FILE_DER: 1908 case FILE_DEFAULT: /* nothing to check */ 1909 case FILE_CLEAR: 1910 default: 1911 break; 1912 } 1913 if (!mconvert(ms, m, flip)) 1914 return 0; 1915 return 1; 1916 } 1917 1918 private uint64_t 1919 file_strncmp(const char *s1, const char *s2, size_t len, size_t maxlen, 1920 uint32_t flags) 1921 { 1922 /* 1923 * Convert the source args to unsigned here so that (1) the 1924 * compare will be unsigned as it is in strncmp() and (2) so 1925 * the ctype functions will work correctly without extra 1926 * casting. 1927 */ 1928 const unsigned char *a = RCAST(const unsigned char *, s1); 1929 const unsigned char *b = RCAST(const unsigned char *, s2); 1930 uint32_t ws = flags & (STRING_COMPACT_WHITESPACE | 1931 STRING_COMPACT_OPTIONAL_WHITESPACE); 1932 const unsigned char *eb = b + (ws ? maxlen : len); 1933 uint64_t v; 1934 1935 /* 1936 * What we want here is v = strncmp(s1, s2, len), 1937 * but ignoring any nulls. 1938 */ 1939 v = 0; 1940 len++; 1941 if (0L == flags) { /* normal string: do it fast */ 1942 while (--len > 0) 1943 if ((v = *b++ - *a++) != '\0') 1944 break; 1945 } 1946 else { /* combine the others */ 1947 while (--len > 0) { 1948 if (b >= eb) { 1949 v = 1; 1950 break; 1951 } 1952 if ((flags & STRING_IGNORE_LOWERCASE) && 1953 islower(*a)) { 1954 if ((v = tolower(*b++) - *a++) != '\0') 1955 break; 1956 } 1957 else if ((flags & STRING_IGNORE_UPPERCASE) && 1958 isupper(*a)) { 1959 if ((v = toupper(*b++) - *a++) != '\0') 1960 break; 1961 } 1962 else if ((flags & STRING_COMPACT_WHITESPACE) && 1963 isspace(*a)) { 1964 a++; 1965 if (isspace(*b)) { 1966 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 if (len == 0 && v == 0 && (flags & STRING_FULL_WORD)) { 1988 if (*b && !isspace(*b)) 1989 v = 1; 1990 } 1991 } 1992 return v; 1993 } 1994 1995 private uint64_t 1996 file_strncmp16(const char *a, const char *b, size_t len, size_t maxlen, 1997 uint32_t flags) 1998 { 1999 /* 2000 * XXX - The 16-bit string compare probably needs to be done 2001 * differently, especially if the flags are to be supported. 2002 * At the moment, I am unsure. 2003 */ 2004 flags = 0; 2005 return file_strncmp(a, b, len, maxlen, flags); 2006 } 2007 2008 private file_regex_t * 2009 alloc_regex(struct magic_set *ms, struct magic *m) 2010 { 2011 int rc; 2012 file_regex_t *rx = CAST(file_regex_t *, malloc(sizeof(*rx))); 2013 2014 if (rx == NULL) { 2015 file_error(ms, errno, "can't allocate %" SIZE_T_FORMAT 2016 "u bytes", sizeof(*rx)); 2017 return NULL; 2018 } 2019 2020 rc = file_regcomp(ms, rx, m->value.s, REG_EXTENDED | REG_NEWLINE | 2021 ((m->str_flags & STRING_IGNORE_CASE) ? REG_ICASE : 0)); 2022 if (rc == 0) 2023 return rx; 2024 2025 free(rx); 2026 return NULL; 2027 } 2028 2029 private int 2030 magiccheck(struct magic_set *ms, struct magic *m, file_regex_t **m_cache) 2031 { 2032 uint64_t l = m->value.q; 2033 uint64_t v; 2034 float fl, fv; 2035 double dl, dv; 2036 int matched; 2037 union VALUETYPE *p = &ms->ms_value; 2038 2039 switch (m->type) { 2040 case FILE_BYTE: 2041 v = p->b; 2042 break; 2043 2044 case FILE_SHORT: 2045 case FILE_BESHORT: 2046 case FILE_LESHORT: 2047 case FILE_MSDOSDATE: 2048 case FILE_LEMSDOSDATE: 2049 case FILE_BEMSDOSDATE: 2050 case FILE_MSDOSTIME: 2051 case FILE_LEMSDOSTIME: 2052 case FILE_BEMSDOSTIME: 2053 v = p->h; 2054 break; 2055 2056 case FILE_LONG: 2057 case FILE_BELONG: 2058 case FILE_LELONG: 2059 case FILE_MELONG: 2060 case FILE_DATE: 2061 case FILE_BEDATE: 2062 case FILE_LEDATE: 2063 case FILE_MEDATE: 2064 case FILE_LDATE: 2065 case FILE_BELDATE: 2066 case FILE_LELDATE: 2067 case FILE_MELDATE: 2068 v = p->l; 2069 break; 2070 2071 case FILE_QUAD: 2072 case FILE_LEQUAD: 2073 case FILE_BEQUAD: 2074 case FILE_QDATE: 2075 case FILE_BEQDATE: 2076 case FILE_LEQDATE: 2077 case FILE_QLDATE: 2078 case FILE_BEQLDATE: 2079 case FILE_LEQLDATE: 2080 case FILE_QWDATE: 2081 case FILE_BEQWDATE: 2082 case FILE_LEQWDATE: 2083 case FILE_OFFSET: 2084 v = p->q; 2085 break; 2086 2087 case FILE_FLOAT: 2088 case FILE_BEFLOAT: 2089 case FILE_LEFLOAT: 2090 fl = m->value.f; 2091 fv = p->f; 2092 switch (m->reln) { 2093 case 'x': 2094 matched = 1; 2095 break; 2096 2097 case '!': 2098 matched = fv != fl; 2099 break; 2100 2101 case '=': 2102 matched = fv == fl; 2103 break; 2104 2105 case '>': 2106 matched = fv > fl; 2107 break; 2108 2109 case '<': 2110 matched = fv < fl; 2111 break; 2112 2113 default: 2114 file_magerror(ms, "cannot happen with float: " 2115 "invalid relation `%c'", m->reln); 2116 return -1; 2117 } 2118 return matched; 2119 2120 case FILE_DOUBLE: 2121 case FILE_BEDOUBLE: 2122 case FILE_LEDOUBLE: 2123 dl = m->value.d; 2124 dv = p->d; 2125 switch (m->reln) { 2126 case 'x': 2127 matched = 1; 2128 break; 2129 2130 case '!': 2131 matched = dv != dl; 2132 break; 2133 2134 case '=': 2135 matched = dv == dl; 2136 break; 2137 2138 case '>': 2139 matched = dv > dl; 2140 break; 2141 2142 case '<': 2143 matched = dv < dl; 2144 break; 2145 2146 default: 2147 file_magerror(ms, "cannot happen with double: " 2148 "invalid relation `%c'", m->reln); 2149 return -1; 2150 } 2151 return matched; 2152 2153 case FILE_DEFAULT: 2154 case FILE_CLEAR: 2155 l = 0; 2156 v = 0; 2157 break; 2158 2159 case FILE_STRING: 2160 case FILE_PSTRING: 2161 l = 0; 2162 v = file_strncmp(m->value.s, p->s, CAST(size_t, m->vallen), 2163 sizeof(p->s), m->str_flags); 2164 break; 2165 2166 case FILE_BESTRING16: 2167 case FILE_LESTRING16: 2168 l = 0; 2169 v = file_strncmp16(m->value.s, p->s, CAST(size_t, m->vallen), 2170 sizeof(p->s), m->str_flags); 2171 break; 2172 2173 case FILE_SEARCH: { /* search ms->search.s for the string m->value.s */ 2174 size_t slen; 2175 size_t idx; 2176 2177 if (ms->search.s == NULL) 2178 return 0; 2179 2180 slen = MIN(m->vallen, sizeof(m->value.s)); 2181 l = 0; 2182 v = 0; 2183 #ifdef HAVE_MEMMEM 2184 if (slen > 0 && m->str_flags == 0) { 2185 const char *found; 2186 idx = m->str_range + slen; 2187 if (m->str_range == 0 || ms->search.s_len < idx) 2188 idx = ms->search.s_len; 2189 found = CAST(const char *, memmem(ms->search.s, idx, 2190 m->value.s, slen)); 2191 if (!found) { 2192 v = 1; 2193 break; 2194 } 2195 idx = found - ms->search.s; 2196 ms->search.offset += idx; 2197 ms->search.rm_len = ms->search.s_len - idx; 2198 break; 2199 } 2200 #endif 2201 2202 for (idx = 0; m->str_range == 0 || idx < m->str_range; idx++) { 2203 if (slen + idx > ms->search.s_len) { 2204 v = 1; 2205 break; 2206 } 2207 2208 v = file_strncmp(m->value.s, ms->search.s + idx, slen, 2209 ms->search.s_len - idx, m->str_flags); 2210 if (v == 0) { /* found match */ 2211 ms->search.offset += idx; 2212 ms->search.rm_len = ms->search.s_len - idx; 2213 break; 2214 } 2215 } 2216 break; 2217 } 2218 case FILE_REGEX: { 2219 int rc; 2220 file_regex_t *rx = *m_cache; 2221 const char *search; 2222 regmatch_t pmatch; 2223 size_t slen = ms->search.s_len; 2224 char *copy; 2225 2226 if (ms->search.s == NULL) 2227 return 0; 2228 2229 if (rx == NULL) { 2230 rx = *m_cache = alloc_regex(ms, m); 2231 if (rx == NULL) 2232 return -1; 2233 } 2234 l = 0; 2235 if (slen != 0) { 2236 copy = CAST(char *, malloc(slen)); 2237 if (copy == NULL) { 2238 file_error(ms, errno, 2239 "can't allocate %" SIZE_T_FORMAT "u bytes", 2240 slen); 2241 return -1; 2242 } 2243 memcpy(copy, ms->search.s, slen); 2244 copy[--slen] = '\0'; 2245 search = copy; 2246 } else { 2247 search = CCAST(char *, ""); 2248 copy = NULL; 2249 } 2250 rc = file_regexec(ms, rx, RCAST(const char *, search), 2251 1, &pmatch, 0); 2252 free(copy); 2253 switch (rc) { 2254 case 0: 2255 ms->search.s += CAST(int, pmatch.rm_so); 2256 ms->search.offset += CAST(size_t, pmatch.rm_so); 2257 ms->search.rm_len = CAST(size_t, 2258 pmatch.rm_eo - pmatch.rm_so); 2259 v = 0; 2260 break; 2261 2262 case REG_NOMATCH: 2263 v = 1; 2264 break; 2265 2266 default: 2267 return -1; 2268 break; 2269 } 2270 break; 2271 } 2272 case FILE_USE: 2273 return ms->ms_value.q != 0; 2274 case FILE_NAME: 2275 case FILE_INDIRECT: 2276 return 1; 2277 case FILE_DER: 2278 matched = der_cmp(ms, m); 2279 if (matched == -1) { 2280 if ((ms->flags & MAGIC_DEBUG) != 0) { 2281 (void) fprintf(stderr, 2282 "EOF comparing DER entries"); 2283 } 2284 return 0; 2285 } 2286 return matched; 2287 case FILE_GUID: 2288 l = 0; 2289 v = memcmp(m->value.guid, p->guid, sizeof(p->guid)); 2290 break; 2291 default: 2292 file_magerror(ms, "invalid type %d in magiccheck()", m->type); 2293 return -1; 2294 } 2295 2296 v = file_signextend(ms, m, v); 2297 2298 switch (m->reln) { 2299 case 'x': 2300 if ((ms->flags & MAGIC_DEBUG) != 0) 2301 (void) fprintf(stderr, "%" INT64_T_FORMAT 2302 "u == *any* = 1\n", CAST(unsigned long long, v)); 2303 matched = 1; 2304 break; 2305 2306 case '!': 2307 matched = v != l; 2308 if ((ms->flags & MAGIC_DEBUG) != 0) 2309 (void) fprintf(stderr, "%" INT64_T_FORMAT "u != %" 2310 INT64_T_FORMAT "u = %d\n", 2311 CAST(unsigned long long, v), 2312 CAST(unsigned long long, l), matched); 2313 break; 2314 2315 case '=': 2316 matched = v == l; 2317 if ((ms->flags & MAGIC_DEBUG) != 0) 2318 (void) fprintf(stderr, "%" INT64_T_FORMAT "u == %" 2319 INT64_T_FORMAT "u = %d\n", 2320 CAST(unsigned long long, v), 2321 CAST(unsigned long long, l), matched); 2322 break; 2323 2324 case '>': 2325 if (m->flag & UNSIGNED) { 2326 matched = v > l; 2327 if ((ms->flags & MAGIC_DEBUG) != 0) 2328 (void) fprintf(stderr, "%" INT64_T_FORMAT 2329 "u > %" INT64_T_FORMAT "u = %d\n", 2330 CAST(unsigned long long, v), 2331 CAST(unsigned long long, l), matched); 2332 } 2333 else { 2334 matched = CAST(int64_t, v) > CAST(int64_t, l); 2335 if ((ms->flags & MAGIC_DEBUG) != 0) 2336 (void) fprintf(stderr, "%" INT64_T_FORMAT 2337 "d > %" INT64_T_FORMAT "d = %d\n", 2338 CAST(long long, v), 2339 CAST(long long, l), matched); 2340 } 2341 break; 2342 2343 case '<': 2344 if (m->flag & UNSIGNED) { 2345 matched = v < l; 2346 if ((ms->flags & MAGIC_DEBUG) != 0) 2347 (void) fprintf(stderr, "%" INT64_T_FORMAT 2348 "u < %" INT64_T_FORMAT "u = %d\n", 2349 CAST(unsigned long long, v), 2350 CAST(unsigned long long, l), matched); 2351 } 2352 else { 2353 matched = CAST(int64_t, v) < CAST(int64_t, l); 2354 if ((ms->flags & MAGIC_DEBUG) != 0) 2355 (void) fprintf(stderr, "%" INT64_T_FORMAT 2356 "d < %" INT64_T_FORMAT "d = %d\n", 2357 CAST(long long, v), 2358 CAST(long long, l), matched); 2359 } 2360 break; 2361 2362 case '&': 2363 matched = (v & l) == l; 2364 if ((ms->flags & MAGIC_DEBUG) != 0) 2365 (void) fprintf(stderr, "((%" INT64_T_FORMAT "x & %" 2366 INT64_T_FORMAT "x) == %" INT64_T_FORMAT 2367 "x) = %d\n", CAST(unsigned long long, v), 2368 CAST(unsigned long long, l), 2369 CAST(unsigned long long, l), 2370 matched); 2371 break; 2372 2373 case '^': 2374 matched = (v & l) != l; 2375 if ((ms->flags & MAGIC_DEBUG) != 0) 2376 (void) fprintf(stderr, "((%" INT64_T_FORMAT "x & %" 2377 INT64_T_FORMAT "x) != %" INT64_T_FORMAT 2378 "x) = %d\n", CAST(unsigned long long, v), 2379 CAST(unsigned long long, l), 2380 CAST(unsigned long long, l), matched); 2381 break; 2382 2383 default: 2384 file_magerror(ms, "cannot happen: invalid relation `%c'", 2385 m->reln); 2386 return -1; 2387 } 2388 2389 return matched; 2390 } 2391 2392 private int 2393 handle_annotation(struct magic_set *ms, struct magic *m, int firstline) 2394 { 2395 if ((ms->flags & MAGIC_APPLE) && m->apple[0]) { 2396 if (print_sep(ms, firstline) == -1) 2397 return -1; 2398 if (file_printf(ms, "%.8s", m->apple) == -1) 2399 return -1; 2400 return 1; 2401 } 2402 if ((ms->flags & MAGIC_EXTENSION) && m->ext[0]) { 2403 if (print_sep(ms, firstline) == -1) 2404 return -1; 2405 if (file_printf(ms, "%s", m->ext) == -1) 2406 return -1; 2407 return 1; 2408 } 2409 if ((ms->flags & MAGIC_MIME_TYPE) && m->mimetype[0]) { 2410 char buf[1024]; 2411 const char *p; 2412 if (print_sep(ms, firstline) == -1) 2413 return -1; 2414 if (varexpand(ms, buf, sizeof(buf), m->mimetype) == -1) 2415 p = m->mimetype; 2416 else 2417 p = buf; 2418 if (file_printf(ms, "%s", p) == -1) 2419 return -1; 2420 return 1; 2421 } 2422 return 0; 2423 } 2424 2425 private int 2426 print_sep(struct magic_set *ms, int firstline) 2427 { 2428 if (firstline) 2429 return 0; 2430 /* 2431 * we found another match 2432 * put a newline and '-' to do some simple formatting 2433 */ 2434 return file_separator(ms); 2435 } 2436