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.345 2023/07/02 12:48:39 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 *, const struct buffer *, 60 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)->hq[0])<<56)| \ 75 (CAST(uint64_t, (p)->hq[1])<<48)| \ 76 (CAST(uint64_t, (p)->hq[2])<<40)| \ 77 (CAST(uint64_t, (p)->hq[3])<<32)| \ 78 (CAST(uint64_t, (p)->hq[4])<<24)| \ 79 (CAST(uint64_t, (p)->hq[5])<<16)| \ 80 (CAST(uint64_t, (p)->hq[6])<<8)| \ 81 (CAST(uint64_t, (p)->hq[7]))) 82 #define LE64(p) ( \ 83 (CAST(uint64_t, (p)->hq[7])<<56)| \ 84 (CAST(uint64_t, (p)->hq[6])<<48)| \ 85 (CAST(uint64_t, (p)->hq[5])<<40)| \ 86 (CAST(uint64_t, (p)->hq[4])<<32)| \ 87 (CAST(uint64_t, (p)->hq[3])<<24)| \ 88 (CAST(uint64_t, (p)->hq[2])<<16)| \ 89 (CAST(uint64_t, (p)->hq[1])<<8)| \ 90 (CAST(uint64_t, (p)->hq[0]))) 91 #define LE32(p) ( \ 92 (CAST(uint32_t, (p)->hl[3])<<24)| \ 93 (CAST(uint32_t, (p)->hl[2])<<16)| \ 94 (CAST(uint32_t, (p)->hl[1])<<8)| \ 95 (CAST(uint32_t, (p)->hl[0]))) 96 #define BE32(p) ( \ 97 (CAST(uint32_t, (p)->hl[0])<<24)| \ 98 (CAST(uint32_t, (p)->hl[1])<<16)| \ 99 (CAST(uint32_t, (p)->hl[2])<<8)| \ 100 (CAST(uint32_t, (p)->hl[3]))) 101 #define ME32(p) ( \ 102 (CAST(uint32_t, (p)->hl[1])<<24)| \ 103 (CAST(uint32_t, (p)->hl[0])<<16)| \ 104 (CAST(uint32_t, (p)->hl[3])<<8)| \ 105 (CAST(uint32_t, (p)->hl[2]))) 106 107 #define BE16(p) ((CAST(uint16_t, (p)->hs[0])<<8)|(CAST(uint16_t, (p)->hs[1]))) 108 #define LE16(p) ((CAST(uint16_t, (p)->hs[1])<<8)|(CAST(uint16_t, (p)->hs[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, &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, 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 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); 934 else 935 o = CAST(int32_t, 936 (ms->search.offset + ms->search.rm_len)); 937 break; 938 939 case FILE_SEARCH: 940 if ((m->str_flags & REGEX_OFFSET_START) != 0) 941 o = CAST(int32_t, ms->search.offset); 942 else 943 o = CAST(int32_t, (ms->search.offset + m->vallen)); 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)); 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)); 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)); 1236 if (cvt_64(p, m) == -1) 1237 goto out; 1238 return 1; 1239 case FILE_LESHORT: 1240 p->h = CAST(short, LE16(p)); 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)); 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)); 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)); 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); 1272 if (cvt_float(p, m) == -1) 1273 goto out; 1274 return 1; 1275 case FILE_LEFLOAT: 1276 p->l = LE32(p); 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); 1286 if (cvt_double(p, m) == -1) 1287 goto out; 1288 return 1; 1289 case FILE_LEDOUBLE: 1290 p->q = LE64(p); 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 return 0; 1421 } 1422 case FILE_STRING: /* XXX - these two should not need */ 1423 case FILE_PSTRING: /* to copy anything, but do anyway. */ 1424 if (m->str_range != 0 && m->str_range < sizeof(*p)) 1425 size = m->str_range; 1426 break; 1427 default: 1428 break; 1429 } 1430 } 1431 1432 if (type == FILE_OFFSET) { 1433 (void)memset(p, '\0', sizeof(*p)); 1434 p->q = offset; 1435 return 0; 1436 } 1437 1438 if (offset >= nbytes) { 1439 (void)memset(p, '\0', sizeof(*p)); 1440 return 0; 1441 } 1442 if (nbytes - offset < size) 1443 nbytes = nbytes - offset; 1444 else 1445 nbytes = size; 1446 1447 (void)memcpy(p, s + offset, nbytes); 1448 1449 /* 1450 * the usefulness of padding with zeroes eludes me, it 1451 * might even cause problems 1452 */ 1453 if (nbytes < sizeof(*p)) 1454 (void)memset(RCAST(char *, RCAST(void *, p)) + nbytes, '\0', 1455 sizeof(*p) - nbytes); 1456 return 0; 1457 } 1458 1459 file_private int 1460 do_ops(struct magic_set *ms, struct magic *m, uint32_t *rv, intmax_t lhs, 1461 intmax_t off) 1462 { 1463 intmax_t offset; 1464 // On purpose not INTMAX_MAX 1465 if (lhs >= UINT_MAX || lhs <= INT_MIN || 1466 off >= UINT_MAX || off <= INT_MIN) { 1467 if ((ms->flags & MAGIC_DEBUG) != 0) 1468 fprintf(stderr, "lhs/off overflow %jd %jd\n", lhs, off); 1469 return 1; 1470 } 1471 1472 if (off) { 1473 switch (m->in_op & FILE_OPS_MASK) { 1474 case FILE_OPAND: 1475 offset = lhs & off; 1476 break; 1477 case FILE_OPOR: 1478 offset = lhs | off; 1479 break; 1480 case FILE_OPXOR: 1481 offset = lhs ^ off; 1482 break; 1483 case FILE_OPADD: 1484 offset = lhs + off; 1485 break; 1486 case FILE_OPMINUS: 1487 offset = lhs - off; 1488 break; 1489 case FILE_OPMULTIPLY: 1490 offset = lhs * off; 1491 break; 1492 case FILE_OPDIVIDE: 1493 offset = lhs / off; 1494 break; 1495 case FILE_OPMODULO: 1496 offset = lhs % off; 1497 break; 1498 } 1499 } else 1500 offset = lhs; 1501 if (m->in_op & FILE_OPINVERSE) 1502 offset = ~offset; 1503 if (offset >= UINT_MAX) { 1504 if ((ms->flags & MAGIC_DEBUG) != 0) 1505 fprintf(stderr, "offset overflow %jd\n", offset); 1506 return 1; 1507 } 1508 *rv = CAST(uint32_t, offset); 1509 return 0; 1510 } 1511 1512 file_private int 1513 msetoffset(struct magic_set *ms, struct magic *m, struct buffer *bb, 1514 const struct buffer *b, size_t o, unsigned int cont_level) 1515 { 1516 int32_t offset; 1517 if (m->flag & OFFNEGATIVE) { 1518 offset = -m->offset; 1519 if (cont_level > 0) { 1520 if (m->flag & (OFFADD|INDIROFFADD)) 1521 goto normal; 1522 #if 0 1523 file_error(ms, 0, "negative offset %d at continuation" 1524 "level %u", m->offset, cont_level); 1525 return -1; 1526 #endif 1527 } 1528 if (buffer_fill(b) == -1) 1529 return -1; 1530 if (o != 0) { 1531 // Not yet! 1532 file_magerror(ms, "non zero offset %" SIZE_T_FORMAT 1533 "u at level %u", o, cont_level); 1534 return -1; 1535 } 1536 if (CAST(size_t, m->offset) > b->elen) 1537 return -1; 1538 buffer_init(bb, -1, NULL, b->ebuf, b->elen); 1539 ms->eoffset = ms->offset = CAST(int32_t, b->elen - m->offset); 1540 } else { 1541 offset = m->offset; 1542 if (cont_level == 0) { 1543 normal: 1544 // XXX: Pass real fd, then who frees bb? 1545 buffer_init(bb, -1, NULL, b->fbuf, b->flen); 1546 ms->offset = offset; 1547 ms->eoffset = 0; 1548 } else { 1549 ms->offset = ms->eoffset + offset; 1550 } 1551 } 1552 if ((ms->flags & MAGIC_DEBUG) != 0) { 1553 fprintf(stderr, "bb=[%p,%" SIZE_T_FORMAT "u,%" 1554 SIZE_T_FORMAT "u], %d [b=%p,%" 1555 SIZE_T_FORMAT "u,%" SIZE_T_FORMAT "u], [o=%#x, c=%d]\n", 1556 bb->fbuf, bb->flen, bb->elen, ms->offset, b->fbuf, 1557 b->flen, b->elen, offset, cont_level); 1558 } 1559 return 0; 1560 } 1561 1562 file_private int 1563 save_cont(struct magic_set *ms, struct cont *c) 1564 { 1565 size_t len; 1566 *c = ms->c; 1567 len = c->len * sizeof(*c->li); 1568 ms->c.li = CAST(struct level_info *, malloc(len)); 1569 if (ms->c.li == NULL) { 1570 ms->c = *c; 1571 return -1; 1572 } 1573 memcpy(ms->c.li, c->li, len); 1574 return 0; 1575 } 1576 1577 file_private void 1578 restore_cont(struct magic_set *ms, struct cont *c) 1579 { 1580 free(ms->c.li); 1581 ms->c = *c; 1582 } 1583 1584 file_private int 1585 mget(struct magic_set *ms, struct magic *m, const struct buffer *b, 1586 const unsigned char *s, size_t nbytes, size_t o, unsigned int cont_level, 1587 int mode, int text, int flip, uint16_t *indir_count, uint16_t *name_count, 1588 int *printed_something, int *need_separator, int *firstline, int *returnval, 1589 int *found_match) 1590 { 1591 uint32_t eoffset, offset = ms->offset; 1592 struct buffer bb; 1593 intmax_t lhs; 1594 file_pushbuf_t *pb; 1595 int rv, oneed_separator, in_type, nfound_match; 1596 char *rbuf; 1597 union VALUETYPE *p = &ms->ms_value; 1598 struct mlist ml, *mlp; 1599 struct cont c; 1600 1601 if (*indir_count >= ms->indir_max) { 1602 file_error(ms, 0, "indirect count (%hu) exceeded", 1603 *indir_count); 1604 return -1; 1605 } 1606 1607 if (*name_count >= ms->name_max) { 1608 file_error(ms, 0, "name use count (%hu) exceeded", 1609 *name_count); 1610 return -1; 1611 } 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 const union VALUETYPE *q = CAST(const union VALUETYPE *, 1637 RCAST(const void *, s + offset + off)); 1638 int op; 1639 switch (op = cvt_flip(m->in_type, flip)) { 1640 case FILE_BYTE: 1641 if (OFFSET_OOB(nbytes, offset + off, 1)) 1642 return 0; 1643 off = SEXT(sgn,8,q->b); 1644 break; 1645 case FILE_SHORT: 1646 if (OFFSET_OOB(nbytes, offset + off, 2)) 1647 return 0; 1648 off = SEXT(sgn,16,q->h); 1649 break; 1650 case FILE_BESHORT: 1651 if (OFFSET_OOB(nbytes, offset + off, 2)) 1652 return 0; 1653 off = SEXT(sgn,16,BE16(q)); 1654 break; 1655 case FILE_LESHORT: 1656 if (OFFSET_OOB(nbytes, offset + off, 2)) 1657 return 0; 1658 off = SEXT(sgn,16,LE16(q)); 1659 break; 1660 case FILE_LONG: 1661 if (OFFSET_OOB(nbytes, offset + off, 4)) 1662 return 0; 1663 off = SEXT(sgn,32,q->l); 1664 break; 1665 case FILE_BELONG: 1666 case FILE_BEID3: 1667 if (OFFSET_OOB(nbytes, offset + off, 4)) 1668 return 0; 1669 off = SEXT(sgn,32,BE32(q)); 1670 break; 1671 case FILE_LEID3: 1672 case FILE_LELONG: 1673 if (OFFSET_OOB(nbytes, offset + off, 4)) 1674 return 0; 1675 off = SEXT(sgn,32,LE32(q)); 1676 break; 1677 case FILE_MELONG: 1678 if (OFFSET_OOB(nbytes, offset + off, 4)) 1679 return 0; 1680 off = SEXT(sgn,32,ME32(q)); 1681 break; 1682 case FILE_BEQUAD: 1683 if (OFFSET_OOB(nbytes, offset + off, 8)) 1684 return 0; 1685 off = SEXT(sgn,64,BE64(q)); 1686 break; 1687 case FILE_LEQUAD: 1688 if (OFFSET_OOB(nbytes, offset + off, 8)) 1689 return 0; 1690 off = SEXT(sgn,64,LE64(q)); 1691 break; 1692 case FILE_OCTAL: 1693 if (OFFSET_OOB(nbytes, offset, m->vallen)) 1694 return 0; 1695 off = SEXT(sgn,64,strtoull(p->s, NULL, 8)); 1696 break; 1697 default: 1698 if ((ms->flags & MAGIC_DEBUG) != 0) 1699 fprintf(stderr, "bad op=%d\n", op); 1700 return 0; 1701 } 1702 if ((ms->flags & MAGIC_DEBUG) != 0) 1703 fprintf(stderr, "indirect offs=%jd\n", off); 1704 } 1705 switch (in_type = cvt_flip(m->in_type, flip)) { 1706 case FILE_BYTE: 1707 if (OFFSET_OOB(nbytes, offset, 1)) 1708 return 0; 1709 if (do_ops(ms, m, &offset, SEXT(sgn,8,p->b), off)) 1710 return 0; 1711 break; 1712 case FILE_BESHORT: 1713 if (OFFSET_OOB(nbytes, offset, 2)) 1714 return 0; 1715 if (do_ops(ms, m, &offset, SEXT(sgn,16,BE16(p)), off)) 1716 return 0; 1717 break; 1718 case FILE_LESHORT: 1719 if (OFFSET_OOB(nbytes, offset, 2)) 1720 return 0; 1721 if (do_ops(ms, m, &offset, SEXT(sgn,16,LE16(p)), off)) 1722 return 0; 1723 break; 1724 case FILE_SHORT: 1725 if (OFFSET_OOB(nbytes, offset, 2)) 1726 return 0; 1727 if (do_ops(ms, m, &offset, SEXT(sgn,16,p->h), off)) 1728 return 0; 1729 break; 1730 case FILE_BELONG: 1731 case FILE_BEID3: 1732 if (OFFSET_OOB(nbytes, offset, 4)) 1733 return 0; 1734 lhs = BE32(p); 1735 if (in_type == FILE_BEID3) 1736 lhs = cvt_id3(ms, CAST(uint32_t, lhs)); 1737 if (do_ops(ms, m, &offset, SEXT(sgn,32,lhs), off)) 1738 return 0; 1739 break; 1740 case FILE_LELONG: 1741 case FILE_LEID3: 1742 if (OFFSET_OOB(nbytes, offset, 4)) 1743 return 0; 1744 lhs = LE32(p); 1745 if (in_type == FILE_LEID3) 1746 lhs = cvt_id3(ms, CAST(uint32_t, lhs)); 1747 if (do_ops(ms, m, &offset, SEXT(sgn,32,lhs), off)) 1748 return 0; 1749 break; 1750 case FILE_MELONG: 1751 if (OFFSET_OOB(nbytes, offset, 4)) 1752 return 0; 1753 if (do_ops(ms, m, &offset, SEXT(sgn,32,ME32(p)), off)) 1754 return 0; 1755 break; 1756 case FILE_LONG: 1757 if (OFFSET_OOB(nbytes, offset, 4)) 1758 return 0; 1759 if (do_ops(ms, m, &offset, SEXT(sgn,32,p->l), off)) 1760 return 0; 1761 break; 1762 case FILE_LEQUAD: 1763 if (OFFSET_OOB(nbytes, offset, 8)) 1764 return 0; 1765 if (do_ops(ms, m, &offset, SEXT(sgn,64,LE64(p)), off)) 1766 return 0; 1767 break; 1768 case FILE_BEQUAD: 1769 if (OFFSET_OOB(nbytes, offset, 8)) 1770 return 0; 1771 if (do_ops(ms, m, &offset, SEXT(sgn,64,BE64(p)), off)) 1772 return 0; 1773 break; 1774 case FILE_OCTAL: 1775 if (OFFSET_OOB(nbytes, offset, m->vallen)) 1776 return 0; 1777 if(do_ops(ms, m, &offset, 1778 SEXT(sgn,64,strtoull(p->s, NULL, 8)), off)) 1779 return 0; 1780 break; 1781 default: 1782 if ((ms->flags & MAGIC_DEBUG) != 0) 1783 fprintf(stderr, "bad in_type=%d\n", in_type); 1784 return 0; 1785 } 1786 1787 if (m->flag & INDIROFFADD) { 1788 if (cont_level == 0) { 1789 if ((ms->flags & MAGIC_DEBUG) != 0) 1790 fprintf(stderr, 1791 "indirect *zero* cont_level\n"); 1792 return 0; 1793 } 1794 offset += ms->c.li[cont_level - 1].off; 1795 if (offset == 0) { 1796 if ((ms->flags & MAGIC_DEBUG) != 0) 1797 fprintf(stderr, 1798 "indirect *zero* offset\n"); 1799 return 0; 1800 } 1801 if ((ms->flags & MAGIC_DEBUG) != 0) 1802 fprintf(stderr, "indirect +offs=%u\n", offset); 1803 } 1804 if (mcopy(ms, p, m->type, 0, s, offset, nbytes, m) == -1) 1805 return -1; 1806 ms->offset = offset; 1807 1808 if ((ms->flags & MAGIC_DEBUG) != 0) { 1809 mdebug(offset, RCAST(char *, RCAST(void *, p)), 1810 sizeof(union VALUETYPE)); 1811 #ifndef COMPILE_ONLY 1812 file_mdump(m); 1813 #endif 1814 } 1815 } 1816 1817 /* Verify we have enough data to match magic type */ 1818 switch (m->type) { 1819 case FILE_BYTE: 1820 if (OFFSET_OOB(nbytes, offset, 1)) 1821 return 0; 1822 break; 1823 1824 case FILE_SHORT: 1825 case FILE_BESHORT: 1826 case FILE_LESHORT: 1827 if (OFFSET_OOB(nbytes, offset, 2)) 1828 return 0; 1829 break; 1830 1831 case FILE_LONG: 1832 case FILE_BELONG: 1833 case FILE_LELONG: 1834 case FILE_MELONG: 1835 case FILE_DATE: 1836 case FILE_BEDATE: 1837 case FILE_LEDATE: 1838 case FILE_MEDATE: 1839 case FILE_LDATE: 1840 case FILE_BELDATE: 1841 case FILE_LELDATE: 1842 case FILE_MELDATE: 1843 case FILE_FLOAT: 1844 case FILE_BEFLOAT: 1845 case FILE_LEFLOAT: 1846 if (OFFSET_OOB(nbytes, offset, 4)) 1847 return 0; 1848 break; 1849 1850 case FILE_DOUBLE: 1851 case FILE_BEDOUBLE: 1852 case FILE_LEDOUBLE: 1853 if (OFFSET_OOB(nbytes, offset, 8)) 1854 return 0; 1855 break; 1856 1857 case FILE_GUID: 1858 if (OFFSET_OOB(nbytes, offset, 16)) 1859 return 0; 1860 break; 1861 1862 case FILE_STRING: 1863 case FILE_PSTRING: 1864 case FILE_SEARCH: 1865 case FILE_OCTAL: 1866 if (OFFSET_OOB(nbytes, offset, m->vallen)) 1867 return 0; 1868 break; 1869 1870 case FILE_REGEX: 1871 if (nbytes < offset) 1872 return 0; 1873 break; 1874 1875 case FILE_INDIRECT: 1876 if (m->str_flags & INDIRECT_RELATIVE) 1877 offset += CAST(uint32_t, o); 1878 if (offset == 0) 1879 return 0; 1880 1881 if (nbytes < offset) 1882 return 0; 1883 1884 if ((pb = file_push_buffer(ms)) == NULL) 1885 return -1; 1886 1887 (*indir_count)++; 1888 bb = *b; 1889 bb.fbuf = s + offset; 1890 bb.flen = nbytes - offset; 1891 bb.ebuf = NULL; 1892 bb.elen = 0; 1893 rv = -1; 1894 for (mlp = ms->mlist[0]->next; mlp != ms->mlist[0]; 1895 mlp = mlp->next) 1896 { 1897 if ((rv = match(ms, mlp->magic, mlp->magic_rxcomp, 1898 mlp->nmagic, &bb, 0, BINTEST, text, 0, indir_count, 1899 name_count, printed_something, need_separator, 1900 firstline, NULL, NULL)) != 0) 1901 break; 1902 } 1903 buffer_fini(&bb); 1904 1905 if ((ms->flags & MAGIC_DEBUG) != 0) 1906 fprintf(stderr, "indirect @offs=%u[%d]\n", offset, rv); 1907 1908 rbuf = file_pop_buffer(ms, pb); 1909 if (rbuf == NULL && ms->event_flags & EVENT_HAD_ERR) 1910 return -1; 1911 1912 if (rv == 1) { 1913 if ((ms->flags & MAGIC_NODESC) == 0 && 1914 file_printf(ms, F(ms, m->desc, "%u"), offset) == -1) 1915 { 1916 free(rbuf); 1917 return -1; 1918 } 1919 if (file_printf(ms, "%s", rbuf) == -1) { 1920 free(rbuf); 1921 return -1; 1922 } 1923 } 1924 free(rbuf); 1925 return rv; 1926 1927 case FILE_USE: 1928 if (nbytes < offset) 1929 return 0; 1930 rbuf = m->value.s; 1931 if (*rbuf == '^') { 1932 rbuf++; 1933 flip = !flip; 1934 } 1935 if (file_magicfind(ms, rbuf, &ml) == -1) { 1936 file_error(ms, 0, "cannot find entry `%s'", rbuf); 1937 return -1; 1938 } 1939 if (save_cont(ms, &c) == -1) { 1940 file_error(ms, errno, "can't allocate continuation"); 1941 return -1; 1942 } 1943 1944 oneed_separator = *need_separator; 1945 if (m->flag & NOSPACE) 1946 *need_separator = 0; 1947 1948 nfound_match = 0; 1949 (*name_count)++; 1950 eoffset = ms->eoffset; 1951 rv = match(ms, ml.magic, ml.magic_rxcomp, ml.nmagic, b, 1952 offset + o, mode, text, flip, indir_count, name_count, 1953 printed_something, need_separator, firstline, returnval, 1954 &nfound_match); 1955 ms->ms_value.q = nfound_match; 1956 (*name_count)--; 1957 *found_match |= nfound_match; 1958 1959 restore_cont(ms, &c); 1960 1961 if (rv != 1) 1962 *need_separator = oneed_separator; 1963 ms->offset = offset; 1964 ms->eoffset = eoffset; 1965 return rv || *found_match; 1966 1967 case FILE_NAME: 1968 if (ms->flags & MAGIC_NODESC) 1969 return 1; 1970 if (file_printf(ms, "%s", m->desc) == -1) 1971 return -1; 1972 return 1; 1973 case FILE_DER: 1974 case FILE_DEFAULT: /* nothing to check */ 1975 case FILE_CLEAR: 1976 default: 1977 break; 1978 } 1979 if (!mconvert(ms, m, flip)) 1980 return 0; 1981 return 1; 1982 } 1983 1984 file_private uint64_t 1985 file_strncmp(const char *s1, const char *s2, size_t len, size_t maxlen, 1986 uint32_t flags) 1987 { 1988 /* 1989 * Convert the source args to unsigned here so that (1) the 1990 * compare will be unsigned as it is in strncmp() and (2) so 1991 * the ctype functions will work correctly without extra 1992 * casting. 1993 */ 1994 const unsigned char *a = RCAST(const unsigned char *, s1); 1995 const unsigned char *b = RCAST(const unsigned char *, s2); 1996 uint32_t ws = flags & (STRING_COMPACT_WHITESPACE | 1997 STRING_COMPACT_OPTIONAL_WHITESPACE); 1998 const unsigned char *eb = b + (ws ? maxlen : len); 1999 uint64_t v; 2000 2001 /* 2002 * What we want here is v = strncmp(s1, s2, len), 2003 * but ignoring any nulls. 2004 */ 2005 v = 0; 2006 len++; 2007 if (0L == flags) { /* normal string: do it fast */ 2008 while (--len > 0) 2009 if ((v = *b++ - *a++) != '\0') 2010 break; 2011 } 2012 else { /* combine the others */ 2013 while (--len > 0) { 2014 if (b >= eb) { 2015 v = 1; 2016 break; 2017 } 2018 if ((flags & STRING_IGNORE_LOWERCASE) && 2019 islower(*a)) { 2020 if ((v = tolower(*b++) - *a++) != '\0') 2021 break; 2022 } 2023 else if ((flags & STRING_IGNORE_UPPERCASE) && 2024 isupper(*a)) { 2025 if ((v = toupper(*b++) - *a++) != '\0') 2026 break; 2027 } 2028 else if ((flags & STRING_COMPACT_WHITESPACE) && 2029 isspace(*a)) { 2030 a++; 2031 if (isspace(*b)) { 2032 b++; 2033 if (!isspace(*a)) 2034 while (b < eb && isspace(*b)) 2035 b++; 2036 } 2037 else { 2038 v = 1; 2039 break; 2040 } 2041 } 2042 else if ((flags & STRING_COMPACT_OPTIONAL_WHITESPACE) && 2043 isspace(*a)) { 2044 a++; 2045 while (b < eb && isspace(*b)) 2046 b++; 2047 } 2048 else { 2049 if ((v = *b++ - *a++) != '\0') 2050 break; 2051 } 2052 } 2053 if (len == 0 && v == 0 && (flags & STRING_FULL_WORD)) { 2054 if (*b && !isspace(*b)) 2055 v = 1; 2056 } 2057 } 2058 return v; 2059 } 2060 2061 file_private uint64_t 2062 file_strncmp16(const char *a, const char *b, size_t len, size_t maxlen, 2063 uint32_t flags) 2064 { 2065 /* 2066 * XXX - The 16-bit string compare probably needs to be done 2067 * differently, especially if the flags are to be supported. 2068 * At the moment, I am unsure. 2069 */ 2070 flags = 0; 2071 return file_strncmp(a, b, len, maxlen, flags); 2072 } 2073 2074 file_private file_regex_t * 2075 alloc_regex(struct magic_set *ms, struct magic *m) 2076 { 2077 int rc; 2078 file_regex_t *rx = CAST(file_regex_t *, malloc(sizeof(*rx))); 2079 2080 if (rx == NULL) { 2081 file_error(ms, errno, "can't allocate %" SIZE_T_FORMAT 2082 "u bytes", sizeof(*rx)); 2083 return NULL; 2084 } 2085 2086 rc = file_regcomp(ms, rx, m->value.s, REG_EXTENDED | REG_NEWLINE | 2087 ((m->str_flags & STRING_IGNORE_CASE) ? REG_ICASE : 0)); 2088 if (rc == 0) 2089 return rx; 2090 2091 free(rx); 2092 return NULL; 2093 } 2094 2095 file_private int 2096 magiccheck(struct magic_set *ms, struct magic *m, file_regex_t **m_cache) 2097 { 2098 uint64_t l = m->value.q; 2099 uint64_t v; 2100 float fl, fv; 2101 double dl, dv; 2102 int matched; 2103 union VALUETYPE *p = &ms->ms_value; 2104 2105 switch (m->type) { 2106 case FILE_BYTE: 2107 v = p->b; 2108 break; 2109 2110 case FILE_SHORT: 2111 case FILE_BESHORT: 2112 case FILE_LESHORT: 2113 case FILE_MSDOSDATE: 2114 case FILE_LEMSDOSDATE: 2115 case FILE_BEMSDOSDATE: 2116 case FILE_MSDOSTIME: 2117 case FILE_LEMSDOSTIME: 2118 case FILE_BEMSDOSTIME: 2119 v = p->h; 2120 break; 2121 2122 case FILE_LONG: 2123 case FILE_BELONG: 2124 case FILE_LELONG: 2125 case FILE_MELONG: 2126 case FILE_DATE: 2127 case FILE_BEDATE: 2128 case FILE_LEDATE: 2129 case FILE_MEDATE: 2130 case FILE_LDATE: 2131 case FILE_BELDATE: 2132 case FILE_LELDATE: 2133 case FILE_MELDATE: 2134 v = p->l; 2135 break; 2136 2137 case FILE_QUAD: 2138 case FILE_LEQUAD: 2139 case FILE_BEQUAD: 2140 case FILE_QDATE: 2141 case FILE_BEQDATE: 2142 case FILE_LEQDATE: 2143 case FILE_QLDATE: 2144 case FILE_BEQLDATE: 2145 case FILE_LEQLDATE: 2146 case FILE_QWDATE: 2147 case FILE_BEQWDATE: 2148 case FILE_LEQWDATE: 2149 case FILE_OFFSET: 2150 v = p->q; 2151 break; 2152 2153 case FILE_FLOAT: 2154 case FILE_BEFLOAT: 2155 case FILE_LEFLOAT: 2156 fl = m->value.f; 2157 fv = p->f; 2158 switch (m->reln) { 2159 case 'x': 2160 matched = 1; 2161 break; 2162 2163 case '!': 2164 matched = isunordered(fl, fv) ? 1 : fv != fl; 2165 break; 2166 2167 case '=': 2168 matched = isunordered(fl, fv) ? 0 : fv == fl; 2169 break; 2170 2171 case '>': 2172 matched = isgreater(fv, fl); 2173 break; 2174 2175 case '<': 2176 matched = isless(fv, fl); 2177 break; 2178 2179 default: 2180 file_magerror(ms, "cannot happen with float: " 2181 "invalid relation `%c'", m->reln); 2182 return -1; 2183 } 2184 return matched; 2185 2186 case FILE_DOUBLE: 2187 case FILE_BEDOUBLE: 2188 case FILE_LEDOUBLE: 2189 dl = m->value.d; 2190 dv = p->d; 2191 switch (m->reln) { 2192 case 'x': 2193 matched = 1; 2194 break; 2195 2196 case '!': 2197 matched = isunordered(dv, dl) ? 1 : dv != dl; 2198 break; 2199 2200 case '=': 2201 matched = isunordered(dv, dl) ? 0 : dv == dl; 2202 break; 2203 2204 case '>': 2205 matched = isgreater(dv, dl); 2206 break; 2207 2208 case '<': 2209 matched = isless(dv, dl); 2210 break; 2211 2212 default: 2213 file_magerror(ms, "cannot happen with double: " 2214 "invalid relation `%c'", m->reln); 2215 return -1; 2216 } 2217 return matched; 2218 2219 case FILE_DEFAULT: 2220 case FILE_CLEAR: 2221 l = 0; 2222 v = 0; 2223 break; 2224 2225 case FILE_STRING: 2226 case FILE_PSTRING: 2227 case FILE_OCTAL: 2228 l = 0; 2229 v = file_strncmp(m->value.s, p->s, CAST(size_t, m->vallen), 2230 sizeof(p->s), m->str_flags); 2231 break; 2232 2233 case FILE_BESTRING16: 2234 case FILE_LESTRING16: 2235 l = 0; 2236 v = file_strncmp16(m->value.s, p->s, CAST(size_t, m->vallen), 2237 sizeof(p->s), m->str_flags); 2238 break; 2239 2240 case FILE_SEARCH: { /* search ms->search.s for the string m->value.s */ 2241 size_t slen; 2242 size_t idx; 2243 2244 if (ms->search.s == NULL) 2245 return 0; 2246 2247 slen = MIN(m->vallen, sizeof(m->value.s)); 2248 l = 0; 2249 v = 0; 2250 if ((ms->flags & MAGIC_DEBUG) != 0) { 2251 size_t xlen = ms->search.s_len > 100 ? 100 2252 : ms->search.s_len; 2253 2254 fprintf(stderr, "search: ["); 2255 file_showstr(stderr, ms->search.s, xlen); 2256 fprintf(stderr, "%s] for [", ms->search.s_len == xlen 2257 ? "" : "..."); 2258 file_showstr(stderr, m->value.s, slen); 2259 } 2260 #ifdef HAVE_MEMMEM 2261 if (slen > 0 && m->str_flags == 0) { 2262 const char *found; 2263 idx = m->str_range + slen; 2264 if (m->str_range == 0 || ms->search.s_len < idx) 2265 idx = ms->search.s_len; 2266 found = CAST(const char *, memmem(ms->search.s, idx, 2267 m->value.s, slen)); 2268 if ((ms->flags & MAGIC_DEBUG) != 0) { 2269 fprintf(stderr, "] %sfound\n", 2270 found ? "" : "not "); 2271 } 2272 if (!found) { 2273 v = 1; 2274 break; 2275 } 2276 idx = found - ms->search.s; 2277 ms->search.offset += idx; 2278 ms->search.rm_len = ms->search.s_len - idx; 2279 break; 2280 } 2281 #endif 2282 2283 for (idx = 0; m->str_range == 0 || idx < m->str_range; idx++) { 2284 if (slen + idx > ms->search.s_len) { 2285 v = 1; 2286 break; 2287 } 2288 2289 v = file_strncmp(m->value.s, ms->search.s + idx, slen, 2290 ms->search.s_len - idx, m->str_flags); 2291 if (v == 0) { /* found match */ 2292 ms->search.offset += idx; 2293 ms->search.rm_len = ms->search.s_len - idx; 2294 break; 2295 } 2296 } 2297 if ((ms->flags & MAGIC_DEBUG) != 0) { 2298 fprintf(stderr, "] %sfound\n", v == 0 ? "" : "not "); 2299 } 2300 break; 2301 } 2302 case FILE_REGEX: { 2303 int rc; 2304 file_regex_t *rx = *m_cache; 2305 const char *search; 2306 regmatch_t pmatch; 2307 size_t slen = ms->search.s_len; 2308 char *copy; 2309 2310 if (ms->search.s == NULL) 2311 return 0; 2312 2313 if (rx == NULL) { 2314 rx = *m_cache = alloc_regex(ms, m); 2315 if (rx == NULL) 2316 return -1; 2317 } 2318 l = 0; 2319 if (slen != 0) { 2320 copy = CAST(char *, malloc(slen)); 2321 if (copy == NULL) { 2322 file_error(ms, errno, 2323 "can't allocate %" SIZE_T_FORMAT "u bytes", 2324 slen); 2325 return -1; 2326 } 2327 memcpy(copy, ms->search.s, slen); 2328 copy[--slen] = '\0'; 2329 search = copy; 2330 } else { 2331 search = CCAST(char *, ""); 2332 copy = NULL; 2333 } 2334 rc = file_regexec(ms, rx, RCAST(const char *, search), 2335 1, &pmatch, 0); 2336 free(copy); 2337 switch (rc) { 2338 case 0: 2339 ms->search.s += CAST(int, pmatch.rm_so); 2340 ms->search.offset += CAST(size_t, pmatch.rm_so); 2341 ms->search.rm_len = CAST(size_t, 2342 pmatch.rm_eo - pmatch.rm_so); 2343 v = 0; 2344 break; 2345 2346 case REG_NOMATCH: 2347 v = 1; 2348 break; 2349 2350 default: 2351 return -1; 2352 } 2353 break; 2354 } 2355 case FILE_USE: 2356 return ms->ms_value.q != 0; 2357 case FILE_NAME: 2358 case FILE_INDIRECT: 2359 return 1; 2360 case FILE_DER: 2361 matched = der_cmp(ms, m); 2362 if (matched == -1) { 2363 if ((ms->flags & MAGIC_DEBUG) != 0) { 2364 (void) fprintf(stderr, 2365 "EOF comparing DER entries\n"); 2366 } 2367 return 0; 2368 } 2369 return matched; 2370 case FILE_GUID: 2371 l = 0; 2372 v = memcmp(m->value.guid, p->guid, sizeof(p->guid)); 2373 break; 2374 default: 2375 file_magerror(ms, "invalid type %d in magiccheck()", m->type); 2376 return -1; 2377 } 2378 2379 v = file_signextend(ms, m, v); 2380 2381 switch (m->reln) { 2382 case 'x': 2383 if ((ms->flags & MAGIC_DEBUG) != 0) 2384 (void) fprintf(stderr, "%" INT64_T_FORMAT 2385 "u == *any* = 1", CAST(unsigned long long, v)); 2386 matched = 1; 2387 break; 2388 2389 case '!': 2390 matched = v != l; 2391 if ((ms->flags & MAGIC_DEBUG) != 0) 2392 (void) fprintf(stderr, "%" INT64_T_FORMAT "u != %" 2393 INT64_T_FORMAT "u = %d", 2394 CAST(unsigned long long, v), 2395 CAST(unsigned long long, l), matched); 2396 break; 2397 2398 case '=': 2399 matched = v == l; 2400 if ((ms->flags & MAGIC_DEBUG) != 0) 2401 (void) fprintf(stderr, "%" INT64_T_FORMAT "u == %" 2402 INT64_T_FORMAT "u = %d", 2403 CAST(unsigned long long, v), 2404 CAST(unsigned long long, l), matched); 2405 break; 2406 2407 case '>': 2408 if (m->flag & UNSIGNED) { 2409 matched = v > l; 2410 if ((ms->flags & MAGIC_DEBUG) != 0) 2411 (void) fprintf(stderr, "%" INT64_T_FORMAT 2412 "u > %" INT64_T_FORMAT "u = %d", 2413 CAST(unsigned long long, v), 2414 CAST(unsigned long long, l), matched); 2415 } 2416 else { 2417 matched = CAST(int64_t, v) > CAST(int64_t, l); 2418 if ((ms->flags & MAGIC_DEBUG) != 0) 2419 (void) fprintf(stderr, "%" INT64_T_FORMAT 2420 "d > %" INT64_T_FORMAT "d = %d", 2421 CAST(long long, v), 2422 CAST(long long, l), matched); 2423 } 2424 break; 2425 2426 case '<': 2427 if (m->flag & UNSIGNED) { 2428 matched = v < l; 2429 if ((ms->flags & MAGIC_DEBUG) != 0) 2430 (void) fprintf(stderr, "%" INT64_T_FORMAT 2431 "u < %" INT64_T_FORMAT "u = %d", 2432 CAST(unsigned long long, v), 2433 CAST(unsigned long long, l), matched); 2434 } 2435 else { 2436 matched = CAST(int64_t, v) < CAST(int64_t, l); 2437 if ((ms->flags & MAGIC_DEBUG) != 0) 2438 (void) fprintf(stderr, "%" INT64_T_FORMAT 2439 "d < %" INT64_T_FORMAT "d = %d", 2440 CAST(long long, v), 2441 CAST(long long, l), matched); 2442 } 2443 break; 2444 2445 case '&': 2446 matched = (v & l) == l; 2447 if ((ms->flags & MAGIC_DEBUG) != 0) 2448 (void) fprintf(stderr, "((%" INT64_T_FORMAT "x & %" 2449 INT64_T_FORMAT "x) == %" INT64_T_FORMAT 2450 "x) = %d", CAST(unsigned long long, v), 2451 CAST(unsigned long long, l), 2452 CAST(unsigned long long, l), 2453 matched); 2454 break; 2455 2456 case '^': 2457 matched = (v & l) != l; 2458 if ((ms->flags & MAGIC_DEBUG) != 0) 2459 (void) fprintf(stderr, "((%" INT64_T_FORMAT "x & %" 2460 INT64_T_FORMAT "x) != %" INT64_T_FORMAT 2461 "x) = %d", CAST(unsigned long long, v), 2462 CAST(unsigned long long, l), 2463 CAST(unsigned long long, l), matched); 2464 break; 2465 2466 default: 2467 file_magerror(ms, "cannot happen: invalid relation `%c'", 2468 m->reln); 2469 return -1; 2470 } 2471 if ((ms->flags & MAGIC_DEBUG) != 0) { 2472 (void) fprintf(stderr, " strength=%zu\n", 2473 file_magic_strength(m, 1)); 2474 } 2475 2476 return matched; 2477 } 2478 2479 file_private int 2480 handle_annotation(struct magic_set *ms, struct magic *m, int firstline) 2481 { 2482 if ((ms->flags & MAGIC_APPLE) && m->apple[0]) { 2483 if (print_sep(ms, firstline) == -1) 2484 return -1; 2485 if (file_printf(ms, "%.8s", m->apple) == -1) 2486 return -1; 2487 return 1; 2488 } 2489 if ((ms->flags & MAGIC_EXTENSION) && m->ext[0]) { 2490 if (print_sep(ms, firstline) == -1) 2491 return -1; 2492 if (file_printf(ms, "%s", m->ext) == -1) 2493 return -1; 2494 return 1; 2495 } 2496 if ((ms->flags & MAGIC_MIME_TYPE) && m->mimetype[0]) { 2497 char buf[1024]; 2498 const char *p; 2499 if (print_sep(ms, firstline) == -1) 2500 return -1; 2501 if (varexpand(ms, buf, sizeof(buf), m->mimetype) == -1) 2502 p = m->mimetype; 2503 else 2504 p = buf; 2505 if (file_printf(ms, "%s", p) == -1) 2506 return -1; 2507 return 1; 2508 } 2509 return 0; 2510 } 2511 2512 file_private int 2513 print_sep(struct magic_set *ms, int firstline) 2514 { 2515 if (firstline) 2516 return 0; 2517 /* 2518 * we found another match 2519 * put a newline and '-' to do some simple formatting 2520 */ 2521 return file_separator(ms); 2522 } 2523