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