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