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