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