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