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