softmagic.c revision 277592
1241675Suqs/* 2241675Suqs * Copyright (c) Ian F. Darwin 1986-1995. 3241675Suqs * Software written by Ian F. Darwin and others; 4241675Suqs * maintained 1995-present by Christos Zoulas and others. 5241675Suqs * 6241675Suqs * Redistribution and use in source and binary forms, with or without 7241675Suqs * modification, are permitted provided that the following conditions 8241675Suqs * are met: 9241675Suqs * 1. Redistributions of source code must retain the above copyright 10241675Suqs * notice immediately at the beginning of the file, without modification, 11241675Suqs * this list of conditions, and the following disclaimer. 12241675Suqs * 2. Redistributions in binary form must reproduce the above copyright 13241675Suqs * notice, this list of conditions and the following disclaimer in the 14241675Suqs * documentation and/or other materials provided with the distribution. 15241675Suqs * 16241675Suqs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17241675Suqs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18241675Suqs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19241675Suqs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 20241675Suqs * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21241675Suqs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22241675Suqs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23241675Suqs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24241675Suqs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25241675Suqs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26241675Suqs * SUCH DAMAGE. 27241675Suqs */ 28241675Suqs/* 29241675Suqs * softmagic - interpret variable magic from MAGIC 30241675Suqs */ 31241675Suqs 32241675Suqs#include "file.h" 33241675Suqs 34241675Suqs#ifndef lint 35241675SuqsFILE_RCSID("@(#)$File: softmagic.c,v 1.206 2015/01/01 17:07:34 christos Exp $") 36241675Suqs#endif /* lint */ 37241675Suqs 38241675Suqs#include "magic.h" 39241675Suqs#include <assert.h> 40241675Suqs#include <string.h> 41241675Suqs#include <ctype.h> 42241675Suqs#include <stdlib.h> 43241675Suqs#include <time.h> 44241675Suqs 45241675Suqsprivate int match(struct magic_set *, struct magic *, uint32_t, 46241675Suqs const unsigned char *, size_t, size_t, int, int, int, uint16_t, 47241675Suqs uint16_t *, int *, int *, int *); 48241675Suqsprivate int mget(struct magic_set *, const unsigned char *, 49241675Suqs struct magic *, size_t, size_t, unsigned int, int, int, int, uint16_t, 50241675Suqs uint16_t *, int *, int *, int *); 51241675Suqsprivate int magiccheck(struct magic_set *, struct magic *); 52241675Suqsprivate int32_t mprint(struct magic_set *, struct magic *); 53241675Suqsprivate int32_t moffset(struct magic_set *, struct magic *); 54241675Suqsprivate void mdebug(uint32_t, const char *, size_t); 55241675Suqsprivate int mcopy(struct magic_set *, union VALUETYPE *, int, int, 56241675Suqs const unsigned char *, uint32_t, size_t, struct magic *); 57241675Suqsprivate int mconvert(struct magic_set *, struct magic *, int); 58241675Suqsprivate int print_sep(struct magic_set *, int); 59241675Suqsprivate int handle_annotation(struct magic_set *, struct magic *); 60241675Suqsprivate void cvt_8(union VALUETYPE *, const struct magic *); 61241675Suqsprivate void cvt_16(union VALUETYPE *, const struct magic *); 62241675Suqsprivate void cvt_32(union VALUETYPE *, const struct magic *); 63241675Suqsprivate void cvt_64(union VALUETYPE *, const struct magic *); 64241675Suqs 65241675Suqs#define OFFSET_OOB(n, o, i) ((n) < (o) || (i) > ((n) - (o))) 66241675Suqs 67241675Suqs/* 68241675Suqs * softmagic - lookup one file in parsed, in-memory copy of database 69241675Suqs * Passed the name and FILE * of one file to be typed. 70241675Suqs */ 71241675Suqs/*ARGSUSED1*/ /* nbytes passed for regularity, maybe need later */ 72241675Suqsprotected int 73241675Suqsfile_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes, 74241675Suqs uint16_t indir_level, uint16_t *name_count, int mode, int text) 75241675Suqs{ 76241675Suqs struct mlist *ml; 77241675Suqs int rv, printed_something = 0, need_separator = 0; 78241675Suqs uint16_t nc; 79241675Suqs 80241675Suqs if (name_count == NULL) { 81241675Suqs nc = 0; 82241675Suqs name_count = &nc; 83241675Suqs } 84241675Suqs 85241675Suqs for (ml = ms->mlist[0]->next; ml != ms->mlist[0]; ml = ml->next) 86241675Suqs if ((rv = match(ms, ml->magic, ml->nmagic, buf, nbytes, 0, mode, 87241675Suqs text, 0, indir_level, name_count, 88241675Suqs &printed_something, &need_separator, NULL)) != 0) 89241675Suqs return rv; 90241675Suqs 91241675Suqs return 0; 92241675Suqs} 93241675Suqs 94241675Suqs#define FILE_FMTDEBUG 95241675Suqs#ifdef FILE_FMTDEBUG 96241675Suqs#define F(a, b, c) file_fmtcheck((a), (b), (c), __FILE__, __LINE__) 97241675Suqs 98241675Suqsprivate const char * __attribute__((__format_arg__(3))) 99241675Suqsfile_fmtcheck(struct magic_set *ms, const struct magic *m, const char *def, 100241675Suqs const char *file, size_t line) 101241675Suqs{ 102241675Suqs const char *ptr = fmtcheck(m->desc, def); 103241675Suqs if (ptr == def) 104241675Suqs file_magerror(ms, 105241675Suqs "%s, %" SIZE_T_FORMAT "u: format `%s' does not match" 106241675Suqs " with `%s'", file, line, m->desc, def); 107241675Suqs return ptr; 108241675Suqs} 109241675Suqs#else 110241675Suqs#define F(a, b, c) fmtcheck((b)->desc, (c)) 111241675Suqs#endif 112241675Suqs 113241675Suqs/* 114241675Suqs * Go through the whole list, stopping if you find a match. Process all 115241675Suqs * the continuations of that match before returning. 116241675Suqs * 117241675Suqs * We support multi-level continuations: 118241675Suqs * 119241675Suqs * At any time when processing a successful top-level match, there is a 120241675Suqs * current continuation level; it represents the level of the last 121241675Suqs * successfully matched continuation. 122241675Suqs * 123241675Suqs * Continuations above that level are skipped as, if we see one, it 124241675Suqs * means that the continuation that controls them - i.e, the 125241675Suqs * lower-level continuation preceding them - failed to match. 126241675Suqs * 127241675Suqs * Continuations below that level are processed as, if we see one, 128241675Suqs * it means we've finished processing or skipping higher-level 129241675Suqs * continuations under the control of a successful or unsuccessful 130241675Suqs * lower-level continuation, and are now seeing the next lower-level 131241675Suqs * continuation and should process it. The current continuation 132241675Suqs * level reverts to the level of the one we're seeing. 133241675Suqs * 134241675Suqs * Continuations at the current level are processed as, if we see 135241675Suqs * one, there's no lower-level continuation that may have failed. 136241675Suqs * 137241675Suqs * If a continuation matches, we bump the current continuation level 138241675Suqs * so that higher-level continuations are processed. 139241675Suqs */ 140241675Suqsprivate int 141241675Suqsmatch(struct magic_set *ms, struct magic *magic, uint32_t nmagic, 142241675Suqs const unsigned char *s, size_t nbytes, size_t offset, int mode, int text, 143241675Suqs int flip, uint16_t indir_level, uint16_t *name_count, 144241675Suqs int *printed_something, int *need_separator, int *returnval) 145241675Suqs{ 146241675Suqs uint32_t magindex = 0; 147241675Suqs unsigned int cont_level = 0; 148241675Suqs int returnvalv = 0, e; /* if a match is found it is set to 1*/ 149241675Suqs int firstline = 1; /* a flag to print X\n X\n- X */ 150241675Suqs int print = (ms->flags & (MAGIC_MIME|MAGIC_APPLE)) == 0; 151241675Suqs 152241675Suqs if (returnval == NULL) 153241675Suqs returnval = &returnvalv; 154241675Suqs 155241675Suqs if (file_check_mem(ms, cont_level) == -1) 156241675Suqs return -1; 157241675Suqs 158241675Suqs for (magindex = 0; magindex < nmagic; magindex++) { 159241675Suqs int flush = 0; 160241675Suqs struct magic *m = &magic[magindex]; 161241675Suqs 162241675Suqs if (m->type != FILE_NAME) 163241675Suqs if ((IS_STRING(m->type) && 164241675Suqs#define FLT (STRING_BINTEST | STRING_TEXTTEST) 165241675Suqs ((text && (m->str_flags & FLT) == STRING_BINTEST) || 166241675Suqs (!text && (m->str_flags & FLT) == STRING_TEXTTEST))) || 167241675Suqs (m->flag & mode) != mode) { 168241675Suqs /* Skip sub-tests */ 169241675Suqs while (magindex + 1 < nmagic && 170241675Suqs magic[magindex + 1].cont_level != 0 && 171241675Suqs ++magindex) 172241675Suqs continue; 173241675Suqs continue; /* Skip to next top-level test*/ 174241675Suqs } 175241675Suqs 176241675Suqs ms->offset = m->offset; 177241675Suqs ms->line = m->lineno; 178241675Suqs 179241675Suqs /* if main entry matches, print it... */ 180241675Suqs switch (mget(ms, s, m, nbytes, offset, cont_level, mode, text, 181241675Suqs flip, indir_level, name_count, 182241675Suqs printed_something, need_separator, returnval)) { 183241675Suqs case -1: 184241675Suqs return -1; 185241675Suqs case 0: 186241675Suqs flush = m->reln != '!'; 187241675Suqs break; 188241675Suqs default: 189241675Suqs if (m->type == FILE_INDIRECT) 190241675Suqs *returnval = 1; 191241675Suqs 192241675Suqs switch (magiccheck(ms, m)) { 193241675Suqs case -1: 194241675Suqs return -1; 195241675Suqs case 0: 196241675Suqs flush++; 197241675Suqs break; 198241675Suqs default: 199241675Suqs flush = 0; 200241675Suqs break; 201241675Suqs } 202241675Suqs break; 203241675Suqs } 204241675Suqs if (flush) { 205241675Suqs /* 206241675Suqs * main entry didn't match, 207241675Suqs * flush its continuations 208241675Suqs */ 209241675Suqs while (magindex < nmagic - 1 && 210241675Suqs magic[magindex + 1].cont_level != 0) 211241675Suqs magindex++; 212241675Suqs continue; 213241675Suqs } 214241675Suqs 215241675Suqs if ((e = handle_annotation(ms, m)) != 0) { 216241675Suqs *need_separator = 1; 217241675Suqs *printed_something = 1; 218241675Suqs *returnval = 1; 219241675Suqs return e; 220241675Suqs } 221241675Suqs /* 222241675Suqs * If we are going to print something, we'll need to print 223241675Suqs * a blank before we print something else. 224241675Suqs */ 225241675Suqs if (*m->desc) { 226241675Suqs *need_separator = 1; 227241675Suqs *printed_something = 1; 228241675Suqs if (print_sep(ms, firstline) == -1) 229241675Suqs return -1; 230241675Suqs } 231241675Suqs 232241675Suqs 233241675Suqs if (print && mprint(ms, m) == -1) 234241675Suqs return -1; 235241675Suqs 236241675Suqs ms->c.li[cont_level].off = moffset(ms, m); 237241675Suqs 238241675Suqs /* and any continuations that match */ 239241675Suqs if (file_check_mem(ms, ++cont_level) == -1) 240241675Suqs return -1; 241241675Suqs 242241675Suqs while (magindex + 1 < nmagic && 243241675Suqs magic[magindex + 1].cont_level != 0) { 244241675Suqs m = &magic[++magindex]; 245241675Suqs ms->line = m->lineno; /* for messages */ 246241675Suqs 247241675Suqs if (cont_level < m->cont_level) 248241675Suqs continue; 249241675Suqs if (cont_level > m->cont_level) { 250241675Suqs /* 251241675Suqs * We're at the end of the level 252241675Suqs * "cont_level" continuations. 253241675Suqs */ 254241675Suqs cont_level = m->cont_level; 255241675Suqs } 256241675Suqs ms->offset = m->offset; 257241675Suqs if (m->flag & OFFADD) { 258241675Suqs ms->offset += 259241675Suqs ms->c.li[cont_level - 1].off; 260241675Suqs } 261241675Suqs 262241675Suqs#ifdef ENABLE_CONDITIONALS 263241675Suqs if (m->cond == COND_ELSE || 264241675Suqs m->cond == COND_ELIF) { 265241675Suqs if (ms->c.li[cont_level].last_match == 1) 266241675Suqs continue; 267241675Suqs } 268241675Suqs#endif 269241675Suqs switch (mget(ms, s, m, nbytes, offset, cont_level, mode, 270241675Suqs text, flip, indir_level, name_count, 271241675Suqs printed_something, need_separator, returnval)) { 272241675Suqs case -1: 273241675Suqs return -1; 274241675Suqs case 0: 275241675Suqs if (m->reln != '!') 276241675Suqs continue; 277241675Suqs flush = 1; 278241675Suqs break; 279241675Suqs default: 280241675Suqs if (m->type == FILE_INDIRECT) 281241675Suqs *returnval = 1; 282241675Suqs flush = 0; 283241675Suqs break; 284241675Suqs } 285241675Suqs 286241675Suqs switch (flush ? 1 : magiccheck(ms, m)) { 287241675Suqs case -1: 288241675Suqs return -1; 289241675Suqs case 0: 290241675Suqs#ifdef ENABLE_CONDITIONALS 291241675Suqs ms->c.li[cont_level].last_match = 0; 292241675Suqs#endif 293241675Suqs break; 294241675Suqs default: 295241675Suqs#ifdef ENABLE_CONDITIONALS 296241675Suqs ms->c.li[cont_level].last_match = 1; 297241675Suqs#endif 298241675Suqs if (m->type == FILE_CLEAR) 299241675Suqs ms->c.li[cont_level].got_match = 0; 300241675Suqs else if (ms->c.li[cont_level].got_match) { 301241675Suqs if (m->type == FILE_DEFAULT) 302241675Suqs break; 303241675Suqs } else 304241675Suqs ms->c.li[cont_level].got_match = 1; 305241675Suqs if ((e = handle_annotation(ms, m)) != 0) { 306241675Suqs *need_separator = 1; 307241675Suqs *printed_something = 1; 308241675Suqs *returnval = 1; 309241675Suqs return e; 310241675Suqs } 311241675Suqs /* 312241675Suqs * If we are going to print something, 313241675Suqs * make sure that we have a separator first. 314241675Suqs */ 315241675Suqs if (*m->desc) { 316241675Suqs if (!*printed_something) { 317241675Suqs *printed_something = 1; 318241675Suqs if (print_sep(ms, firstline) 319241675Suqs == -1) 320241675Suqs return -1; 321241675Suqs } 322241675Suqs } 323241675Suqs /* 324241675Suqs * This continuation matched. Print 325241675Suqs * its message, with a blank before it 326241675Suqs * if the previous item printed and 327241675Suqs * this item isn't empty. 328241675Suqs */ 329241675Suqs /* space if previous printed */ 330241675Suqs if (*need_separator 331241675Suqs && ((m->flag & NOSPACE) == 0) 332241675Suqs && *m->desc) { 333241675Suqs if (print && 334241675Suqs file_printf(ms, " ") == -1) 335241675Suqs return -1; 336241675Suqs *need_separator = 0; 337241675Suqs } 338241675Suqs if (print && mprint(ms, m) == -1) 339241675Suqs return -1; 340241675Suqs 341241675Suqs ms->c.li[cont_level].off = moffset(ms, m); 342241675Suqs 343241675Suqs if (*m->desc) 344241675Suqs *need_separator = 1; 345241675Suqs 346241675Suqs /* 347241675Suqs * If we see any continuations 348241675Suqs * at a higher level, 349241675Suqs * process them. 350241675Suqs */ 351241675Suqs if (file_check_mem(ms, ++cont_level) == -1) 352241675Suqs return -1; 353241675Suqs break; 354241675Suqs } 355241675Suqs } 356241675Suqs if (*printed_something) { 357241675Suqs firstline = 0; 358241675Suqs if (print) 359241675Suqs *returnval = 1; 360241675Suqs } 361241675Suqs if ((ms->flags & MAGIC_CONTINUE) == 0 && *printed_something) { 362241675Suqs return *returnval; /* don't keep searching */ 363241675Suqs } 364241675Suqs } 365241675Suqs return *returnval; /* This is hit if -k is set or there is no match */ 366241675Suqs} 367241675Suqs 368241675Suqsprivate int 369241675Suqscheck_fmt(struct magic_set *ms, struct magic *m) 370241675Suqs{ 371241675Suqs file_regex_t rx; 372241675Suqs int rc, rv = -1; 373241675Suqs 374241675Suqs if (strchr(m->desc, '%') == NULL) 375241675Suqs return 0; 376241675Suqs 377241675Suqs rc = file_regcomp(&rx, "%[-0-9\\.]*s", REG_EXTENDED|REG_NOSUB); 378241675Suqs if (rc) { 379241675Suqs file_regerror(&rx, rc, ms); 380241675Suqs } else { 381241675Suqs rc = file_regexec(&rx, m->desc, 0, 0, 0); 382241675Suqs rv = !rc; 383241675Suqs } 384241675Suqs file_regfree(&rx); 385241675Suqs return rv; 386241675Suqs} 387241675Suqs 388241675Suqs#ifndef HAVE_STRNDUP 389241675Suqschar * strndup(const char *, size_t); 390241675Suqs 391241675Suqschar * 392241675Suqsstrndup(const char *str, size_t n) 393241675Suqs{ 394241675Suqs size_t len; 395241675Suqs char *copy; 396241675Suqs 397241675Suqs for (len = 0; len < n && str[len]; len++) 398241675Suqs continue; 399241675Suqs if ((copy = malloc(len + 1)) == NULL) 400241675Suqs return NULL; 401241675Suqs (void)memcpy(copy, str, len); 402241675Suqs copy[len] = '\0'; 403241675Suqs return copy; 404241675Suqs} 405241675Suqs#endif /* HAVE_STRNDUP */ 406241675Suqs 407241675Suqsprivate int32_t 408241675Suqsmprint(struct magic_set *ms, struct magic *m) 409241675Suqs{ 410241675Suqs uint64_t v; 411241675Suqs float vf; 412241675Suqs double vd; 413241675Suqs int64_t t = 0; 414241675Suqs char buf[128], tbuf[26], sbuf[512]; 415241675Suqs union VALUETYPE *p = &ms->ms_value; 416241675Suqs 417241675Suqs switch (m->type) { 418241675Suqs case FILE_BYTE: 419241675Suqs v = file_signextend(ms, m, (uint64_t)p->b); 420241675Suqs switch (check_fmt(ms, m)) { 421241675Suqs case -1: 422241675Suqs return -1; 423241675Suqs case 1: 424241675Suqs (void)snprintf(buf, sizeof(buf), "%d", 425241675Suqs (unsigned char)v); 426241675Suqs if (file_printf(ms, F(ms, m, "%s"), buf) == -1) 427241675Suqs return -1; 428241675Suqs break; 429241675Suqs default: 430241675Suqs if (file_printf(ms, F(ms, m, "%d"), 431241675Suqs (unsigned char) v) == -1) 432241675Suqs return -1; 433241675Suqs break; 434241675Suqs } 435241675Suqs t = ms->offset + sizeof(char); 436241675Suqs break; 437241675Suqs 438241675Suqs case FILE_SHORT: 439241675Suqs case FILE_BESHORT: 440241675Suqs case FILE_LESHORT: 441241675Suqs v = file_signextend(ms, m, (uint64_t)p->h); 442241675Suqs switch (check_fmt(ms, m)) { 443241675Suqs case -1: 444241675Suqs return -1; 445241675Suqs case 1: 446241675Suqs (void)snprintf(buf, sizeof(buf), "%u", 447241675Suqs (unsigned short)v); 448241675Suqs if (file_printf(ms, F(ms, m, "%s"), buf) == -1) 449241675Suqs return -1; 450241675Suqs break; 451241675Suqs default: 452241675Suqs if (file_printf(ms, F(ms, m, "%u"), 453241675Suqs (unsigned short) v) == -1) 454241675Suqs return -1; 455241675Suqs break; 456241675Suqs } 457241675Suqs t = ms->offset + sizeof(short); 458241675Suqs break; 459241675Suqs 460241675Suqs case FILE_LONG: 461241675Suqs case FILE_BELONG: 462241675Suqs case FILE_LELONG: 463241675Suqs case FILE_MELONG: 464241675Suqs v = file_signextend(ms, m, (uint64_t)p->l); 465241675Suqs switch (check_fmt(ms, m)) { 466241675Suqs case -1: 467241675Suqs return -1; 468241675Suqs case 1: 469241675Suqs (void)snprintf(buf, sizeof(buf), "%u", (uint32_t) v); 470241675Suqs if (file_printf(ms, F(ms, m, "%s"), buf) == -1) 471241675Suqs return -1; 472241675Suqs break; 473 default: 474 if (file_printf(ms, F(ms, m, "%u"), (uint32_t) v) == -1) 475 return -1; 476 break; 477 } 478 t = ms->offset + sizeof(int32_t); 479 break; 480 481 case FILE_QUAD: 482 case FILE_BEQUAD: 483 case FILE_LEQUAD: 484 v = file_signextend(ms, m, p->q); 485 switch (check_fmt(ms, m)) { 486 case -1: 487 return -1; 488 case 1: 489 (void)snprintf(buf, sizeof(buf), "%" INT64_T_FORMAT "u", 490 (unsigned long long)v); 491 if (file_printf(ms, F(ms, m, "%s"), buf) == -1) 492 return -1; 493 break; 494 default: 495 if (file_printf(ms, F(ms, m, "%" INT64_T_FORMAT "u"), 496 (unsigned long long) v) == -1) 497 return -1; 498 break; 499 } 500 t = ms->offset + sizeof(int64_t); 501 break; 502 503 case FILE_STRING: 504 case FILE_PSTRING: 505 case FILE_BESTRING16: 506 case FILE_LESTRING16: 507 if (m->reln == '=' || m->reln == '!') { 508 if (file_printf(ms, F(ms, m, "%s"), 509 file_printable(sbuf, sizeof(sbuf), m->value.s)) 510 == -1) 511 return -1; 512 t = ms->offset + m->vallen; 513 } 514 else { 515 char *str = p->s; 516 517 /* compute t before we mangle the string? */ 518 t = ms->offset + strlen(str); 519 520 if (*m->value.s == '\0') 521 str[strcspn(str, "\n")] = '\0'; 522 523 if (m->str_flags & STRING_TRIM) { 524 char *last; 525 while (isspace((unsigned char)*str)) 526 str++; 527 last = str; 528 while (*last) 529 last++; 530 --last; 531 while (isspace((unsigned char)*last)) 532 last--; 533 *++last = '\0'; 534 } 535 536 if (file_printf(ms, F(ms, m, "%s"), 537 file_printable(sbuf, sizeof(sbuf), str)) == -1) 538 return -1; 539 540 if (m->type == FILE_PSTRING) 541 t += file_pstring_length_size(m); 542 } 543 break; 544 545 case FILE_DATE: 546 case FILE_BEDATE: 547 case FILE_LEDATE: 548 case FILE_MEDATE: 549 if (file_printf(ms, F(ms, m, "%s"), 550 file_fmttime(p->l + m->num_mask, FILE_T_LOCAL, tbuf)) == -1) 551 return -1; 552 t = ms->offset + sizeof(uint32_t); 553 break; 554 555 case FILE_LDATE: 556 case FILE_BELDATE: 557 case FILE_LELDATE: 558 case FILE_MELDATE: 559 if (file_printf(ms, F(ms, m, "%s"), 560 file_fmttime(p->l + m->num_mask, 0, tbuf)) == -1) 561 return -1; 562 t = ms->offset + sizeof(uint32_t); 563 break; 564 565 case FILE_QDATE: 566 case FILE_BEQDATE: 567 case FILE_LEQDATE: 568 if (file_printf(ms, F(ms, m, "%s"), 569 file_fmttime(p->q + m->num_mask, FILE_T_LOCAL, tbuf)) == -1) 570 return -1; 571 t = ms->offset + sizeof(uint64_t); 572 break; 573 574 case FILE_QLDATE: 575 case FILE_BEQLDATE: 576 case FILE_LEQLDATE: 577 if (file_printf(ms, F(ms, m, "%s"), 578 file_fmttime(p->q + m->num_mask, 0, tbuf)) == -1) 579 return -1; 580 t = ms->offset + sizeof(uint64_t); 581 break; 582 583 case FILE_QWDATE: 584 case FILE_BEQWDATE: 585 case FILE_LEQWDATE: 586 if (file_printf(ms, F(ms, m, "%s"), 587 file_fmttime(p->q + m->num_mask, FILE_T_WINDOWS, tbuf)) == -1) 588 return -1; 589 t = ms->offset + sizeof(uint64_t); 590 break; 591 592 case FILE_FLOAT: 593 case FILE_BEFLOAT: 594 case FILE_LEFLOAT: 595 vf = p->f; 596 switch (check_fmt(ms, m)) { 597 case -1: 598 return -1; 599 case 1: 600 (void)snprintf(buf, sizeof(buf), "%g", vf); 601 if (file_printf(ms, F(ms, m, "%s"), buf) == -1) 602 return -1; 603 break; 604 default: 605 if (file_printf(ms, F(ms, m, "%g"), vf) == -1) 606 return -1; 607 break; 608 } 609 t = ms->offset + sizeof(float); 610 break; 611 612 case FILE_DOUBLE: 613 case FILE_BEDOUBLE: 614 case FILE_LEDOUBLE: 615 vd = p->d; 616 switch (check_fmt(ms, m)) { 617 case -1: 618 return -1; 619 case 1: 620 (void)snprintf(buf, sizeof(buf), "%g", vd); 621 if (file_printf(ms, F(ms, m, "%s"), buf) == -1) 622 return -1; 623 break; 624 default: 625 if (file_printf(ms, F(ms, m, "%g"), vd) == -1) 626 return -1; 627 break; 628 } 629 t = ms->offset + sizeof(double); 630 break; 631 632 case FILE_REGEX: { 633 char *cp; 634 int rval; 635 636 cp = strndup((const char *)ms->search.s, ms->search.rm_len); 637 if (cp == NULL) { 638 file_oomem(ms, ms->search.rm_len); 639 return -1; 640 } 641 rval = file_printf(ms, F(ms, m, "%s"), 642 file_printable(sbuf, sizeof(sbuf), cp)); 643 free(cp); 644 645 if (rval == -1) 646 return -1; 647 648 if ((m->str_flags & REGEX_OFFSET_START)) 649 t = ms->search.offset; 650 else 651 t = ms->search.offset + ms->search.rm_len; 652 break; 653 } 654 655 case FILE_SEARCH: 656 if (file_printf(ms, F(ms, m, "%s"), 657 file_printable(sbuf, sizeof(sbuf), m->value.s)) == -1) 658 return -1; 659 if ((m->str_flags & REGEX_OFFSET_START)) 660 t = ms->search.offset; 661 else 662 t = ms->search.offset + m->vallen; 663 break; 664 665 case FILE_DEFAULT: 666 case FILE_CLEAR: 667 if (file_printf(ms, "%s", m->desc) == -1) 668 return -1; 669 t = ms->offset; 670 break; 671 672 case FILE_INDIRECT: 673 case FILE_USE: 674 case FILE_NAME: 675 t = ms->offset; 676 break; 677 678 default: 679 file_magerror(ms, "invalid m->type (%d) in mprint()", m->type); 680 return -1; 681 } 682 return (int32_t)t; 683} 684 685private int32_t 686moffset(struct magic_set *ms, struct magic *m) 687{ 688 switch (m->type) { 689 case FILE_BYTE: 690 return CAST(int32_t, (ms->offset + sizeof(char))); 691 692 case FILE_SHORT: 693 case FILE_BESHORT: 694 case FILE_LESHORT: 695 return CAST(int32_t, (ms->offset + sizeof(short))); 696 697 case FILE_LONG: 698 case FILE_BELONG: 699 case FILE_LELONG: 700 case FILE_MELONG: 701 return CAST(int32_t, (ms->offset + sizeof(int32_t))); 702 703 case FILE_QUAD: 704 case FILE_BEQUAD: 705 case FILE_LEQUAD: 706 return CAST(int32_t, (ms->offset + sizeof(int64_t))); 707 708 case FILE_STRING: 709 case FILE_PSTRING: 710 case FILE_BESTRING16: 711 case FILE_LESTRING16: 712 if (m->reln == '=' || m->reln == '!') 713 return ms->offset + m->vallen; 714 else { 715 union VALUETYPE *p = &ms->ms_value; 716 uint32_t t; 717 718 if (*m->value.s == '\0') 719 p->s[strcspn(p->s, "\n")] = '\0'; 720 t = CAST(uint32_t, (ms->offset + strlen(p->s))); 721 if (m->type == FILE_PSTRING) 722 t += (uint32_t)file_pstring_length_size(m); 723 return t; 724 } 725 726 case FILE_DATE: 727 case FILE_BEDATE: 728 case FILE_LEDATE: 729 case FILE_MEDATE: 730 return CAST(int32_t, (ms->offset + sizeof(uint32_t))); 731 732 case FILE_LDATE: 733 case FILE_BELDATE: 734 case FILE_LELDATE: 735 case FILE_MELDATE: 736 return CAST(int32_t, (ms->offset + sizeof(uint32_t))); 737 738 case FILE_QDATE: 739 case FILE_BEQDATE: 740 case FILE_LEQDATE: 741 return CAST(int32_t, (ms->offset + sizeof(uint64_t))); 742 743 case FILE_QLDATE: 744 case FILE_BEQLDATE: 745 case FILE_LEQLDATE: 746 return CAST(int32_t, (ms->offset + sizeof(uint64_t))); 747 748 case FILE_FLOAT: 749 case FILE_BEFLOAT: 750 case FILE_LEFLOAT: 751 return CAST(int32_t, (ms->offset + sizeof(float))); 752 753 case FILE_DOUBLE: 754 case FILE_BEDOUBLE: 755 case FILE_LEDOUBLE: 756 return CAST(int32_t, (ms->offset + sizeof(double))); 757 758 case FILE_REGEX: 759 if ((m->str_flags & REGEX_OFFSET_START) != 0) 760 return CAST(int32_t, ms->search.offset); 761 else 762 return CAST(int32_t, (ms->search.offset + 763 ms->search.rm_len)); 764 765 case FILE_SEARCH: 766 if ((m->str_flags & REGEX_OFFSET_START) != 0) 767 return CAST(int32_t, ms->search.offset); 768 else 769 return CAST(int32_t, (ms->search.offset + m->vallen)); 770 771 case FILE_CLEAR: 772 case FILE_DEFAULT: 773 case FILE_INDIRECT: 774 return ms->offset; 775 776 default: 777 return 0; 778 } 779} 780 781private int 782cvt_flip(int type, int flip) 783{ 784 if (flip == 0) 785 return type; 786 switch (type) { 787 case FILE_BESHORT: 788 return FILE_LESHORT; 789 case FILE_BELONG: 790 return FILE_LELONG; 791 case FILE_BEDATE: 792 return FILE_LEDATE; 793 case FILE_BELDATE: 794 return FILE_LELDATE; 795 case FILE_BEQUAD: 796 return FILE_LEQUAD; 797 case FILE_BEQDATE: 798 return FILE_LEQDATE; 799 case FILE_BEQLDATE: 800 return FILE_LEQLDATE; 801 case FILE_BEQWDATE: 802 return FILE_LEQWDATE; 803 case FILE_LESHORT: 804 return FILE_BESHORT; 805 case FILE_LELONG: 806 return FILE_BELONG; 807 case FILE_LEDATE: 808 return FILE_BEDATE; 809 case FILE_LELDATE: 810 return FILE_BELDATE; 811 case FILE_LEQUAD: 812 return FILE_BEQUAD; 813 case FILE_LEQDATE: 814 return FILE_BEQDATE; 815 case FILE_LEQLDATE: 816 return FILE_BEQLDATE; 817 case FILE_LEQWDATE: 818 return FILE_BEQWDATE; 819 case FILE_BEFLOAT: 820 return FILE_LEFLOAT; 821 case FILE_LEFLOAT: 822 return FILE_BEFLOAT; 823 case FILE_BEDOUBLE: 824 return FILE_LEDOUBLE; 825 case FILE_LEDOUBLE: 826 return FILE_BEDOUBLE; 827 default: 828 return type; 829 } 830} 831#define DO_CVT(fld, cast) \ 832 if (m->num_mask) \ 833 switch (m->mask_op & FILE_OPS_MASK) { \ 834 case FILE_OPAND: \ 835 p->fld &= cast m->num_mask; \ 836 break; \ 837 case FILE_OPOR: \ 838 p->fld |= cast m->num_mask; \ 839 break; \ 840 case FILE_OPXOR: \ 841 p->fld ^= cast m->num_mask; \ 842 break; \ 843 case FILE_OPADD: \ 844 p->fld += cast m->num_mask; \ 845 break; \ 846 case FILE_OPMINUS: \ 847 p->fld -= cast m->num_mask; \ 848 break; \ 849 case FILE_OPMULTIPLY: \ 850 p->fld *= cast m->num_mask; \ 851 break; \ 852 case FILE_OPDIVIDE: \ 853 p->fld /= cast m->num_mask; \ 854 break; \ 855 case FILE_OPMODULO: \ 856 p->fld %= cast m->num_mask; \ 857 break; \ 858 } \ 859 if (m->mask_op & FILE_OPINVERSE) \ 860 p->fld = ~p->fld \ 861 862private void 863cvt_8(union VALUETYPE *p, const struct magic *m) 864{ 865 DO_CVT(b, (uint8_t)); 866} 867 868private void 869cvt_16(union VALUETYPE *p, const struct magic *m) 870{ 871 DO_CVT(h, (uint16_t)); 872} 873 874private void 875cvt_32(union VALUETYPE *p, const struct magic *m) 876{ 877 DO_CVT(l, (uint32_t)); 878} 879 880private void 881cvt_64(union VALUETYPE *p, const struct magic *m) 882{ 883 DO_CVT(q, (uint64_t)); 884} 885 886#define DO_CVT2(fld, cast) \ 887 if (m->num_mask) \ 888 switch (m->mask_op & FILE_OPS_MASK) { \ 889 case FILE_OPADD: \ 890 p->fld += cast m->num_mask; \ 891 break; \ 892 case FILE_OPMINUS: \ 893 p->fld -= cast m->num_mask; \ 894 break; \ 895 case FILE_OPMULTIPLY: \ 896 p->fld *= cast m->num_mask; \ 897 break; \ 898 case FILE_OPDIVIDE: \ 899 p->fld /= cast m->num_mask; \ 900 break; \ 901 } \ 902 903private void 904cvt_float(union VALUETYPE *p, const struct magic *m) 905{ 906 DO_CVT2(f, (float)); 907} 908 909private void 910cvt_double(union VALUETYPE *p, const struct magic *m) 911{ 912 DO_CVT2(d, (double)); 913} 914 915/* 916 * Convert the byte order of the data we are looking at 917 * While we're here, let's apply the mask operation 918 * (unless you have a better idea) 919 */ 920private int 921mconvert(struct magic_set *ms, struct magic *m, int flip) 922{ 923 union VALUETYPE *p = &ms->ms_value; 924 uint8_t type; 925 926 switch (type = cvt_flip(m->type, flip)) { 927 case FILE_BYTE: 928 cvt_8(p, m); 929 return 1; 930 case FILE_SHORT: 931 cvt_16(p, m); 932 return 1; 933 case FILE_LONG: 934 case FILE_DATE: 935 case FILE_LDATE: 936 cvt_32(p, m); 937 return 1; 938 case FILE_QUAD: 939 case FILE_QDATE: 940 case FILE_QLDATE: 941 case FILE_QWDATE: 942 cvt_64(p, m); 943 return 1; 944 case FILE_STRING: 945 case FILE_BESTRING16: 946 case FILE_LESTRING16: { 947 /* Null terminate and eat *trailing* return */ 948 p->s[sizeof(p->s) - 1] = '\0'; 949 return 1; 950 } 951 case FILE_PSTRING: { 952 size_t sz = file_pstring_length_size(m); 953 char *ptr1 = p->s, *ptr2 = ptr1 + sz; 954 size_t len = file_pstring_get_length(m, ptr1); 955 sz = sizeof(p->s) - sz; /* maximum length of string */ 956 if (len >= sz) { 957 /* 958 * The size of the pascal string length (sz) 959 * is 1, 2, or 4. We need at least 1 byte for NUL 960 * termination, but we've already truncated the 961 * string by p->s, so we need to deduct sz. 962 * Because we can use one of the bytes of the length 963 * after we shifted as NUL termination. 964 */ 965 len = sz; 966 } 967 while (len--) 968 *ptr1++ = *ptr2++; 969 *ptr1 = '\0'; 970 return 1; 971 } 972 case FILE_BESHORT: 973 p->h = (short)((p->hs[0]<<8)|(p->hs[1])); 974 cvt_16(p, m); 975 return 1; 976 case FILE_BELONG: 977 case FILE_BEDATE: 978 case FILE_BELDATE: 979 p->l = (int32_t) 980 ((p->hl[0]<<24)|(p->hl[1]<<16)|(p->hl[2]<<8)|(p->hl[3])); 981 if (type == FILE_BELONG) 982 cvt_32(p, m); 983 return 1; 984 case FILE_BEQUAD: 985 case FILE_BEQDATE: 986 case FILE_BEQLDATE: 987 case FILE_BEQWDATE: 988 p->q = (uint64_t) 989 (((uint64_t)p->hq[0]<<56)|((uint64_t)p->hq[1]<<48)| 990 ((uint64_t)p->hq[2]<<40)|((uint64_t)p->hq[3]<<32)| 991 ((uint64_t)p->hq[4]<<24)|((uint64_t)p->hq[5]<<16)| 992 ((uint64_t)p->hq[6]<<8)|((uint64_t)p->hq[7])); 993 if (type == FILE_BEQUAD) 994 cvt_64(p, m); 995 return 1; 996 case FILE_LESHORT: 997 p->h = (short)((p->hs[1]<<8)|(p->hs[0])); 998 cvt_16(p, m); 999 return 1; 1000 case FILE_LELONG: 1001 case FILE_LEDATE: 1002 case FILE_LELDATE: 1003 p->l = (int32_t) 1004 ((p->hl[3]<<24)|(p->hl[2]<<16)|(p->hl[1]<<8)|(p->hl[0])); 1005 if (type == FILE_LELONG) 1006 cvt_32(p, m); 1007 return 1; 1008 case FILE_LEQUAD: 1009 case FILE_LEQDATE: 1010 case FILE_LEQLDATE: 1011 case FILE_LEQWDATE: 1012 p->q = (uint64_t) 1013 (((uint64_t)p->hq[7]<<56)|((uint64_t)p->hq[6]<<48)| 1014 ((uint64_t)p->hq[5]<<40)|((uint64_t)p->hq[4]<<32)| 1015 ((uint64_t)p->hq[3]<<24)|((uint64_t)p->hq[2]<<16)| 1016 ((uint64_t)p->hq[1]<<8)|((uint64_t)p->hq[0])); 1017 if (type == FILE_LEQUAD) 1018 cvt_64(p, m); 1019 return 1; 1020 case FILE_MELONG: 1021 case FILE_MEDATE: 1022 case FILE_MELDATE: 1023 p->l = (int32_t) 1024 ((p->hl[1]<<24)|(p->hl[0]<<16)|(p->hl[3]<<8)|(p->hl[2])); 1025 if (type == FILE_MELONG) 1026 cvt_32(p, m); 1027 return 1; 1028 case FILE_FLOAT: 1029 cvt_float(p, m); 1030 return 1; 1031 case FILE_BEFLOAT: 1032 p->l = ((uint32_t)p->hl[0]<<24)|((uint32_t)p->hl[1]<<16)| 1033 ((uint32_t)p->hl[2]<<8) |((uint32_t)p->hl[3]); 1034 cvt_float(p, m); 1035 return 1; 1036 case FILE_LEFLOAT: 1037 p->l = ((uint32_t)p->hl[3]<<24)|((uint32_t)p->hl[2]<<16)| 1038 ((uint32_t)p->hl[1]<<8) |((uint32_t)p->hl[0]); 1039 cvt_float(p, m); 1040 return 1; 1041 case FILE_DOUBLE: 1042 cvt_double(p, m); 1043 return 1; 1044 case FILE_BEDOUBLE: 1045 p->q = ((uint64_t)p->hq[0]<<56)|((uint64_t)p->hq[1]<<48)| 1046 ((uint64_t)p->hq[2]<<40)|((uint64_t)p->hq[3]<<32)| 1047 ((uint64_t)p->hq[4]<<24)|((uint64_t)p->hq[5]<<16)| 1048 ((uint64_t)p->hq[6]<<8) |((uint64_t)p->hq[7]); 1049 cvt_double(p, m); 1050 return 1; 1051 case FILE_LEDOUBLE: 1052 p->q = ((uint64_t)p->hq[7]<<56)|((uint64_t)p->hq[6]<<48)| 1053 ((uint64_t)p->hq[5]<<40)|((uint64_t)p->hq[4]<<32)| 1054 ((uint64_t)p->hq[3]<<24)|((uint64_t)p->hq[2]<<16)| 1055 ((uint64_t)p->hq[1]<<8) |((uint64_t)p->hq[0]); 1056 cvt_double(p, m); 1057 return 1; 1058 case FILE_REGEX: 1059 case FILE_SEARCH: 1060 case FILE_DEFAULT: 1061 case FILE_CLEAR: 1062 case FILE_NAME: 1063 case FILE_USE: 1064 return 1; 1065 default: 1066 file_magerror(ms, "invalid type %d in mconvert()", m->type); 1067 return 0; 1068 } 1069} 1070 1071 1072private void 1073mdebug(uint32_t offset, const char *str, size_t len) 1074{ 1075 (void) fprintf(stderr, "mget/%" SIZE_T_FORMAT "u @%d: ", len, offset); 1076 file_showstr(stderr, str, len); 1077 (void) fputc('\n', stderr); 1078 (void) fputc('\n', stderr); 1079} 1080 1081private int 1082mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir, 1083 const unsigned char *s, uint32_t offset, size_t nbytes, struct magic *m) 1084{ 1085 /* 1086 * Note: FILE_SEARCH and FILE_REGEX do not actually copy 1087 * anything, but setup pointers into the source 1088 */ 1089 if (indir == 0) { 1090 switch (type) { 1091 case FILE_SEARCH: 1092 ms->search.s = RCAST(const char *, s) + offset; 1093 ms->search.s_len = nbytes - offset; 1094 ms->search.offset = offset; 1095 return 0; 1096 1097 case FILE_REGEX: { 1098 const char *b; 1099 const char *c; 1100 const char *last; /* end of search region */ 1101 const char *buf; /* start of search region */ 1102 const char *end; 1103 size_t lines, linecnt, bytecnt; 1104 1105 if (s == NULL) { 1106 ms->search.s_len = 0; 1107 ms->search.s = NULL; 1108 return 0; 1109 } 1110 1111 if (m->str_flags & REGEX_LINE_COUNT) { 1112 linecnt = m->str_range; 1113 bytecnt = linecnt * 80; 1114 } else { 1115 linecnt = 0; 1116 bytecnt = m->str_range; 1117 } 1118 1119 if (bytecnt == 0) 1120 bytecnt = 8192; 1121 if (bytecnt > nbytes) 1122 bytecnt = nbytes; 1123 1124 buf = RCAST(const char *, s) + offset; 1125 end = last = RCAST(const char *, s) + bytecnt; 1126 /* mget() guarantees buf <= last */ 1127 for (lines = linecnt, b = buf; lines && b < end && 1128 ((b = CAST(const char *, 1129 memchr(c = b, '\n', CAST(size_t, (end - b))))) 1130 || (b = CAST(const char *, 1131 memchr(c, '\r', CAST(size_t, (end - c)))))); 1132 lines--, b++) { 1133 last = b; 1134 if (b[0] == '\r' && b[1] == '\n') 1135 b++; 1136 } 1137 if (lines) 1138 last = RCAST(const char *, s) + bytecnt; 1139 1140 ms->search.s = buf; 1141 ms->search.s_len = last - buf; 1142 ms->search.offset = offset; 1143 ms->search.rm_len = 0; 1144 return 0; 1145 } 1146 case FILE_BESTRING16: 1147 case FILE_LESTRING16: { 1148 const unsigned char *src = s + offset; 1149 const unsigned char *esrc = s + nbytes; 1150 char *dst = p->s; 1151 char *edst = &p->s[sizeof(p->s) - 1]; 1152 1153 if (type == FILE_BESTRING16) 1154 src++; 1155 1156 /* check that offset is within range */ 1157 if (offset >= nbytes) 1158 break; 1159 for (/*EMPTY*/; src < esrc; src += 2, dst++) { 1160 if (dst < edst) 1161 *dst = *src; 1162 else 1163 break; 1164 if (*dst == '\0') { 1165 if (type == FILE_BESTRING16 ? 1166 *(src - 1) != '\0' : 1167 *(src + 1) != '\0') 1168 *dst = ' '; 1169 } 1170 } 1171 *edst = '\0'; 1172 return 0; 1173 } 1174 case FILE_STRING: /* XXX - these two should not need */ 1175 case FILE_PSTRING: /* to copy anything, but do anyway. */ 1176 default: 1177 break; 1178 } 1179 } 1180 1181 if (offset >= nbytes) { 1182 (void)memset(p, '\0', sizeof(*p)); 1183 return 0; 1184 } 1185 if (nbytes - offset < sizeof(*p)) 1186 nbytes = nbytes - offset; 1187 else 1188 nbytes = sizeof(*p); 1189 1190 (void)memcpy(p, s + offset, nbytes); 1191 1192 /* 1193 * the usefulness of padding with zeroes eludes me, it 1194 * might even cause problems 1195 */ 1196 if (nbytes < sizeof(*p)) 1197 (void)memset(((char *)(void *)p) + nbytes, '\0', 1198 sizeof(*p) - nbytes); 1199 return 0; 1200} 1201 1202private int 1203mget(struct magic_set *ms, const unsigned char *s, struct magic *m, 1204 size_t nbytes, size_t o, unsigned int cont_level, int mode, int text, 1205 int flip, uint16_t indir_level, uint16_t *name_count, 1206 int *printed_something, int *need_separator, int *returnval) 1207{ 1208 uint32_t offset = ms->offset; 1209 uint32_t lhs; 1210 file_pushbuf_t *pb; 1211 int rv, oneed_separator, in_type; 1212 char *rbuf; 1213 union VALUETYPE *p = &ms->ms_value; 1214 struct mlist ml; 1215 1216 if (indir_level >= ms->indir_max) { 1217 file_error(ms, 0, "indirect recursion nesting (%hu) exceeded", 1218 indir_level); 1219 return -1; 1220 } 1221 1222 if (*name_count >= ms->name_max) { 1223 file_error(ms, 0, "name use count (%hu) exceeded", 1224 *name_count); 1225 return -1; 1226 } 1227 1228 if (mcopy(ms, p, m->type, m->flag & INDIR, s, (uint32_t)(offset + o), 1229 (uint32_t)nbytes, m) == -1) 1230 return -1; 1231 1232 if ((ms->flags & MAGIC_DEBUG) != 0) { 1233 fprintf(stderr, "mget(type=%d, flag=%x, offset=%u, o=%" 1234 SIZE_T_FORMAT "u, " "nbytes=%" SIZE_T_FORMAT 1235 "u, il=%hu, nc=%hu)\n", 1236 m->type, m->flag, offset, o, nbytes, 1237 indir_level, *name_count); 1238 mdebug(offset, (char *)(void *)p, sizeof(union VALUETYPE)); 1239#ifndef COMPILE_ONLY 1240 file_mdump(m); 1241#endif 1242 } 1243 1244 if (m->flag & INDIR) { 1245 int off = m->in_offset; 1246 if (m->in_op & FILE_OPINDIRECT) { 1247 const union VALUETYPE *q = CAST(const union VALUETYPE *, 1248 ((const void *)(s + offset + off))); 1249 switch (cvt_flip(m->in_type, flip)) { 1250 case FILE_BYTE: 1251 off = q->b; 1252 break; 1253 case FILE_SHORT: 1254 off = q->h; 1255 break; 1256 case FILE_BESHORT: 1257 off = (short)((q->hs[0]<<8)|(q->hs[1])); 1258 break; 1259 case FILE_LESHORT: 1260 off = (short)((q->hs[1]<<8)|(q->hs[0])); 1261 break; 1262 case FILE_LONG: 1263 off = q->l; 1264 break; 1265 case FILE_BELONG: 1266 case FILE_BEID3: 1267 off = (int32_t)((q->hl[0]<<24)|(q->hl[1]<<16)| 1268 (q->hl[2]<<8)|(q->hl[3])); 1269 break; 1270 case FILE_LEID3: 1271 case FILE_LELONG: 1272 off = (int32_t)((q->hl[3]<<24)|(q->hl[2]<<16)| 1273 (q->hl[1]<<8)|(q->hl[0])); 1274 break; 1275 case FILE_MELONG: 1276 off = (int32_t)((q->hl[1]<<24)|(q->hl[0]<<16)| 1277 (q->hl[3]<<8)|(q->hl[2])); 1278 break; 1279 } 1280 if ((ms->flags & MAGIC_DEBUG) != 0) 1281 fprintf(stderr, "indirect offs=%u\n", off); 1282 } 1283 switch (in_type = cvt_flip(m->in_type, flip)) { 1284 case FILE_BYTE: 1285 if (OFFSET_OOB(nbytes, offset, 1)) 1286 return 0; 1287 if (off) { 1288 switch (m->in_op & FILE_OPS_MASK) { 1289 case FILE_OPAND: 1290 offset = p->b & off; 1291 break; 1292 case FILE_OPOR: 1293 offset = p->b | off; 1294 break; 1295 case FILE_OPXOR: 1296 offset = p->b ^ off; 1297 break; 1298 case FILE_OPADD: 1299 offset = p->b + off; 1300 break; 1301 case FILE_OPMINUS: 1302 offset = p->b - off; 1303 break; 1304 case FILE_OPMULTIPLY: 1305 offset = p->b * off; 1306 break; 1307 case FILE_OPDIVIDE: 1308 offset = p->b / off; 1309 break; 1310 case FILE_OPMODULO: 1311 offset = p->b % off; 1312 break; 1313 } 1314 } else 1315 offset = p->b; 1316 if (m->in_op & FILE_OPINVERSE) 1317 offset = ~offset; 1318 break; 1319 case FILE_BESHORT: 1320 if (OFFSET_OOB(nbytes, offset, 2)) 1321 return 0; 1322 lhs = (p->hs[0] << 8) | p->hs[1]; 1323 if (off) { 1324 switch (m->in_op & FILE_OPS_MASK) { 1325 case FILE_OPAND: 1326 offset = lhs & off; 1327 break; 1328 case FILE_OPOR: 1329 offset = lhs | off; 1330 break; 1331 case FILE_OPXOR: 1332 offset = lhs ^ off; 1333 break; 1334 case FILE_OPADD: 1335 offset = lhs + off; 1336 break; 1337 case FILE_OPMINUS: 1338 offset = lhs - off; 1339 break; 1340 case FILE_OPMULTIPLY: 1341 offset = lhs * off; 1342 break; 1343 case FILE_OPDIVIDE: 1344 offset = lhs / off; 1345 break; 1346 case FILE_OPMODULO: 1347 offset = lhs % off; 1348 break; 1349 } 1350 } else 1351 offset = lhs; 1352 if (m->in_op & FILE_OPINVERSE) 1353 offset = ~offset; 1354 break; 1355 case FILE_LESHORT: 1356 if (OFFSET_OOB(nbytes, offset, 2)) 1357 return 0; 1358 lhs = (p->hs[1] << 8) | p->hs[0]; 1359 if (off) { 1360 switch (m->in_op & FILE_OPS_MASK) { 1361 case FILE_OPAND: 1362 offset = lhs & off; 1363 break; 1364 case FILE_OPOR: 1365 offset = lhs | off; 1366 break; 1367 case FILE_OPXOR: 1368 offset = lhs ^ off; 1369 break; 1370 case FILE_OPADD: 1371 offset = lhs + off; 1372 break; 1373 case FILE_OPMINUS: 1374 offset = lhs - off; 1375 break; 1376 case FILE_OPMULTIPLY: 1377 offset = lhs * off; 1378 break; 1379 case FILE_OPDIVIDE: 1380 offset = lhs / off; 1381 break; 1382 case FILE_OPMODULO: 1383 offset = lhs % off; 1384 break; 1385 } 1386 } else 1387 offset = lhs; 1388 if (m->in_op & FILE_OPINVERSE) 1389 offset = ~offset; 1390 break; 1391 case FILE_SHORT: 1392 if (OFFSET_OOB(nbytes, offset, 2)) 1393 return 0; 1394 if (off) { 1395 switch (m->in_op & FILE_OPS_MASK) { 1396 case FILE_OPAND: 1397 offset = p->h & off; 1398 break; 1399 case FILE_OPOR: 1400 offset = p->h | off; 1401 break; 1402 case FILE_OPXOR: 1403 offset = p->h ^ off; 1404 break; 1405 case FILE_OPADD: 1406 offset = p->h + off; 1407 break; 1408 case FILE_OPMINUS: 1409 offset = p->h - off; 1410 break; 1411 case FILE_OPMULTIPLY: 1412 offset = p->h * off; 1413 break; 1414 case FILE_OPDIVIDE: 1415 offset = p->h / off; 1416 break; 1417 case FILE_OPMODULO: 1418 offset = p->h % off; 1419 break; 1420 } 1421 } 1422 else 1423 offset = p->h; 1424 if (m->in_op & FILE_OPINVERSE) 1425 offset = ~offset; 1426 break; 1427 case FILE_BELONG: 1428 case FILE_BEID3: 1429 if (OFFSET_OOB(nbytes, offset, 4)) 1430 return 0; 1431 lhs = (p->hl[0] << 24) | (p->hl[1] << 16) | 1432 (p->hl[2] << 8) | p->hl[3]; 1433 if (off) { 1434 switch (m->in_op & FILE_OPS_MASK) { 1435 case FILE_OPAND: 1436 offset = lhs & off; 1437 break; 1438 case FILE_OPOR: 1439 offset = lhs | off; 1440 break; 1441 case FILE_OPXOR: 1442 offset = lhs ^ off; 1443 break; 1444 case FILE_OPADD: 1445 offset = lhs + off; 1446 break; 1447 case FILE_OPMINUS: 1448 offset = lhs - off; 1449 break; 1450 case FILE_OPMULTIPLY: 1451 offset = lhs * off; 1452 break; 1453 case FILE_OPDIVIDE: 1454 offset = lhs / off; 1455 break; 1456 case FILE_OPMODULO: 1457 offset = lhs % off; 1458 break; 1459 } 1460 } else 1461 offset = lhs; 1462 if (m->in_op & FILE_OPINVERSE) 1463 offset = ~offset; 1464 break; 1465 case FILE_LELONG: 1466 case FILE_LEID3: 1467 if (OFFSET_OOB(nbytes, offset, 4)) 1468 return 0; 1469 lhs = (p->hl[3] << 24) | (p->hl[2] << 16) | 1470 (p->hl[1] << 8) | p->hl[0]; 1471 if (off) { 1472 switch (m->in_op & FILE_OPS_MASK) { 1473 case FILE_OPAND: 1474 offset = lhs & off; 1475 break; 1476 case FILE_OPOR: 1477 offset = lhs | off; 1478 break; 1479 case FILE_OPXOR: 1480 offset = lhs ^ off; 1481 break; 1482 case FILE_OPADD: 1483 offset = lhs + off; 1484 break; 1485 case FILE_OPMINUS: 1486 offset = lhs - off; 1487 break; 1488 case FILE_OPMULTIPLY: 1489 offset = lhs * off; 1490 break; 1491 case FILE_OPDIVIDE: 1492 offset = lhs / off; 1493 break; 1494 case FILE_OPMODULO: 1495 offset = lhs % off; 1496 break; 1497 } 1498 } else 1499 offset = lhs; 1500 if (m->in_op & FILE_OPINVERSE) 1501 offset = ~offset; 1502 break; 1503 case FILE_MELONG: 1504 if (OFFSET_OOB(nbytes, offset, 4)) 1505 return 0; 1506 lhs = (p->hl[1] << 24) | (p->hl[0] << 16) | 1507 (p->hl[3] << 8) | p->hl[2]; 1508 if (off) { 1509 switch (m->in_op & FILE_OPS_MASK) { 1510 case FILE_OPAND: 1511 offset = lhs & off; 1512 break; 1513 case FILE_OPOR: 1514 offset = lhs | off; 1515 break; 1516 case FILE_OPXOR: 1517 offset = lhs ^ off; 1518 break; 1519 case FILE_OPADD: 1520 offset = lhs + off; 1521 break; 1522 case FILE_OPMINUS: 1523 offset = lhs - off; 1524 break; 1525 case FILE_OPMULTIPLY: 1526 offset = lhs * off; 1527 break; 1528 case FILE_OPDIVIDE: 1529 offset = lhs / off; 1530 break; 1531 case FILE_OPMODULO: 1532 offset = lhs % off; 1533 break; 1534 } 1535 } else 1536 offset = lhs; 1537 if (m->in_op & FILE_OPINVERSE) 1538 offset = ~offset; 1539 break; 1540 case FILE_LONG: 1541 if (OFFSET_OOB(nbytes, offset, 4)) 1542 return 0; 1543 if (off) { 1544 switch (m->in_op & FILE_OPS_MASK) { 1545 case FILE_OPAND: 1546 offset = p->l & off; 1547 break; 1548 case FILE_OPOR: 1549 offset = p->l | off; 1550 break; 1551 case FILE_OPXOR: 1552 offset = p->l ^ off; 1553 break; 1554 case FILE_OPADD: 1555 offset = p->l + off; 1556 break; 1557 case FILE_OPMINUS: 1558 offset = p->l - off; 1559 break; 1560 case FILE_OPMULTIPLY: 1561 offset = p->l * off; 1562 break; 1563 case FILE_OPDIVIDE: 1564 offset = p->l / off; 1565 break; 1566 case FILE_OPMODULO: 1567 offset = p->l % off; 1568 break; 1569 } 1570 } else 1571 offset = p->l; 1572 if (m->in_op & FILE_OPINVERSE) 1573 offset = ~offset; 1574 break; 1575 default: 1576 break; 1577 } 1578 1579 switch (in_type) { 1580 case FILE_LEID3: 1581 case FILE_BEID3: 1582 offset = ((((offset >> 0) & 0x7f) << 0) | 1583 (((offset >> 8) & 0x7f) << 7) | 1584 (((offset >> 16) & 0x7f) << 14) | 1585 (((offset >> 24) & 0x7f) << 21)) + 10; 1586 break; 1587 default: 1588 break; 1589 } 1590 1591 if (m->flag & INDIROFFADD) { 1592 offset += ms->c.li[cont_level-1].off; 1593 if (offset == 0) { 1594 if ((ms->flags & MAGIC_DEBUG) != 0) 1595 fprintf(stderr, 1596 "indirect *zero* offset\n"); 1597 return 0; 1598 } 1599 if ((ms->flags & MAGIC_DEBUG) != 0) 1600 fprintf(stderr, "indirect +offs=%u\n", offset); 1601 } 1602 if (mcopy(ms, p, m->type, 0, s, offset, nbytes, m) == -1) 1603 return -1; 1604 ms->offset = offset; 1605 1606 if ((ms->flags & MAGIC_DEBUG) != 0) { 1607 mdebug(offset, (char *)(void *)p, 1608 sizeof(union VALUETYPE)); 1609#ifndef COMPILE_ONLY 1610 file_mdump(m); 1611#endif 1612 } 1613 } 1614 1615 /* Verify we have enough data to match magic type */ 1616 switch (m->type) { 1617 case FILE_BYTE: 1618 if (OFFSET_OOB(nbytes, offset, 1)) 1619 return 0; 1620 break; 1621 1622 case FILE_SHORT: 1623 case FILE_BESHORT: 1624 case FILE_LESHORT: 1625 if (OFFSET_OOB(nbytes, offset, 2)) 1626 return 0; 1627 break; 1628 1629 case FILE_LONG: 1630 case FILE_BELONG: 1631 case FILE_LELONG: 1632 case FILE_MELONG: 1633 case FILE_DATE: 1634 case FILE_BEDATE: 1635 case FILE_LEDATE: 1636 case FILE_MEDATE: 1637 case FILE_LDATE: 1638 case FILE_BELDATE: 1639 case FILE_LELDATE: 1640 case FILE_MELDATE: 1641 case FILE_FLOAT: 1642 case FILE_BEFLOAT: 1643 case FILE_LEFLOAT: 1644 if (OFFSET_OOB(nbytes, offset, 4)) 1645 return 0; 1646 break; 1647 1648 case FILE_DOUBLE: 1649 case FILE_BEDOUBLE: 1650 case FILE_LEDOUBLE: 1651 if (OFFSET_OOB(nbytes, offset, 8)) 1652 return 0; 1653 break; 1654 1655 case FILE_STRING: 1656 case FILE_PSTRING: 1657 case FILE_SEARCH: 1658 if (OFFSET_OOB(nbytes, offset, m->vallen)) 1659 return 0; 1660 break; 1661 1662 case FILE_REGEX: 1663 if (nbytes < offset) 1664 return 0; 1665 break; 1666 1667 case FILE_INDIRECT: 1668 if (m->str_flags & INDIRECT_RELATIVE) 1669 offset += o; 1670 if (offset == 0) 1671 return 0; 1672 1673 if (nbytes < offset) 1674 return 0; 1675 1676 if ((pb = file_push_buffer(ms)) == NULL) 1677 return -1; 1678 1679 rv = file_softmagic(ms, s + offset, nbytes - offset, 1680 indir_level + 1, name_count, BINTEST, text); 1681 1682 if ((ms->flags & MAGIC_DEBUG) != 0) 1683 fprintf(stderr, "indirect @offs=%u[%d]\n", offset, rv); 1684 1685 rbuf = file_pop_buffer(ms, pb); 1686 if (rbuf == NULL && ms->event_flags & EVENT_HAD_ERR) 1687 return -1; 1688 1689 if (rv == 1) { 1690 if ((ms->flags & (MAGIC_MIME|MAGIC_APPLE)) == 0 && 1691 file_printf(ms, F(ms, m, "%u"), offset) == -1) { 1692 free(rbuf); 1693 return -1; 1694 } 1695 if (file_printf(ms, "%s", rbuf) == -1) { 1696 free(rbuf); 1697 return -1; 1698 } 1699 } 1700 free(rbuf); 1701 return rv; 1702 1703 case FILE_USE: 1704 if (nbytes < offset) 1705 return 0; 1706 rbuf = m->value.s; 1707 if (*rbuf == '^') { 1708 rbuf++; 1709 flip = !flip; 1710 } 1711 if (file_magicfind(ms, rbuf, &ml) == -1) { 1712 file_error(ms, 0, "cannot find entry `%s'", rbuf); 1713 return -1; 1714 } 1715 (*name_count)++; 1716 oneed_separator = *need_separator; 1717 if (m->flag & NOSPACE) 1718 *need_separator = 0; 1719 rv = match(ms, ml.magic, ml.nmagic, s, nbytes, offset + o, 1720 mode, text, flip, indir_level, name_count, 1721 printed_something, need_separator, returnval); 1722 if (rv != 1) 1723 *need_separator = oneed_separator; 1724 return rv; 1725 1726 case FILE_NAME: 1727 if (file_printf(ms, "%s", m->desc) == -1) 1728 return -1; 1729 return 1; 1730 case FILE_DEFAULT: /* nothing to check */ 1731 case FILE_CLEAR: 1732 default: 1733 break; 1734 } 1735 if (!mconvert(ms, m, flip)) 1736 return 0; 1737 return 1; 1738} 1739 1740private uint64_t 1741file_strncmp(const char *s1, const char *s2, size_t len, uint32_t flags) 1742{ 1743 /* 1744 * Convert the source args to unsigned here so that (1) the 1745 * compare will be unsigned as it is in strncmp() and (2) so 1746 * the ctype functions will work correctly without extra 1747 * casting. 1748 */ 1749 const unsigned char *a = (const unsigned char *)s1; 1750 const unsigned char *b = (const unsigned char *)s2; 1751 uint64_t v; 1752 1753 /* 1754 * What we want here is v = strncmp(s1, s2, len), 1755 * but ignoring any nulls. 1756 */ 1757 v = 0; 1758 if (0L == flags) { /* normal string: do it fast */ 1759 while (len-- > 0) 1760 if ((v = *b++ - *a++) != '\0') 1761 break; 1762 } 1763 else { /* combine the others */ 1764 while (len-- > 0) { 1765 if ((flags & STRING_IGNORE_LOWERCASE) && 1766 islower(*a)) { 1767 if ((v = tolower(*b++) - *a++) != '\0') 1768 break; 1769 } 1770 else if ((flags & STRING_IGNORE_UPPERCASE) && 1771 isupper(*a)) { 1772 if ((v = toupper(*b++) - *a++) != '\0') 1773 break; 1774 } 1775 else if ((flags & STRING_COMPACT_WHITESPACE) && 1776 isspace(*a)) { 1777 a++; 1778 if (isspace(*b++)) { 1779 if (!isspace(*a)) 1780 while (isspace(*b)) 1781 b++; 1782 } 1783 else { 1784 v = 1; 1785 break; 1786 } 1787 } 1788 else if ((flags & STRING_COMPACT_OPTIONAL_WHITESPACE) && 1789 isspace(*a)) { 1790 a++; 1791 while (isspace(*b)) 1792 b++; 1793 } 1794 else { 1795 if ((v = *b++ - *a++) != '\0') 1796 break; 1797 } 1798 } 1799 } 1800 return v; 1801} 1802 1803private uint64_t 1804file_strncmp16(const char *a, const char *b, size_t len, uint32_t flags) 1805{ 1806 /* 1807 * XXX - The 16-bit string compare probably needs to be done 1808 * differently, especially if the flags are to be supported. 1809 * At the moment, I am unsure. 1810 */ 1811 flags = 0; 1812 return file_strncmp(a, b, len, flags); 1813} 1814 1815private int 1816magiccheck(struct magic_set *ms, struct magic *m) 1817{ 1818 uint64_t l = m->value.q; 1819 uint64_t v; 1820 float fl, fv; 1821 double dl, dv; 1822 int matched; 1823 union VALUETYPE *p = &ms->ms_value; 1824 1825 switch (m->type) { 1826 case FILE_BYTE: 1827 v = p->b; 1828 break; 1829 1830 case FILE_SHORT: 1831 case FILE_BESHORT: 1832 case FILE_LESHORT: 1833 v = p->h; 1834 break; 1835 1836 case FILE_LONG: 1837 case FILE_BELONG: 1838 case FILE_LELONG: 1839 case FILE_MELONG: 1840 case FILE_DATE: 1841 case FILE_BEDATE: 1842 case FILE_LEDATE: 1843 case FILE_MEDATE: 1844 case FILE_LDATE: 1845 case FILE_BELDATE: 1846 case FILE_LELDATE: 1847 case FILE_MELDATE: 1848 v = p->l; 1849 break; 1850 1851 case FILE_QUAD: 1852 case FILE_LEQUAD: 1853 case FILE_BEQUAD: 1854 case FILE_QDATE: 1855 case FILE_BEQDATE: 1856 case FILE_LEQDATE: 1857 case FILE_QLDATE: 1858 case FILE_BEQLDATE: 1859 case FILE_LEQLDATE: 1860 case FILE_QWDATE: 1861 case FILE_BEQWDATE: 1862 case FILE_LEQWDATE: 1863 v = p->q; 1864 break; 1865 1866 case FILE_FLOAT: 1867 case FILE_BEFLOAT: 1868 case FILE_LEFLOAT: 1869 fl = m->value.f; 1870 fv = p->f; 1871 switch (m->reln) { 1872 case 'x': 1873 matched = 1; 1874 break; 1875 1876 case '!': 1877 matched = fv != fl; 1878 break; 1879 1880 case '=': 1881 matched = fv == fl; 1882 break; 1883 1884 case '>': 1885 matched = fv > fl; 1886 break; 1887 1888 case '<': 1889 matched = fv < fl; 1890 break; 1891 1892 default: 1893 file_magerror(ms, "cannot happen with float: invalid relation `%c'", 1894 m->reln); 1895 return -1; 1896 } 1897 return matched; 1898 1899 case FILE_DOUBLE: 1900 case FILE_BEDOUBLE: 1901 case FILE_LEDOUBLE: 1902 dl = m->value.d; 1903 dv = p->d; 1904 switch (m->reln) { 1905 case 'x': 1906 matched = 1; 1907 break; 1908 1909 case '!': 1910 matched = dv != dl; 1911 break; 1912 1913 case '=': 1914 matched = dv == dl; 1915 break; 1916 1917 case '>': 1918 matched = dv > dl; 1919 break; 1920 1921 case '<': 1922 matched = dv < dl; 1923 break; 1924 1925 default: 1926 file_magerror(ms, "cannot happen with double: invalid relation `%c'", m->reln); 1927 return -1; 1928 } 1929 return matched; 1930 1931 case FILE_DEFAULT: 1932 case FILE_CLEAR: 1933 l = 0; 1934 v = 0; 1935 break; 1936 1937 case FILE_STRING: 1938 case FILE_PSTRING: 1939 l = 0; 1940 v = file_strncmp(m->value.s, p->s, (size_t)m->vallen, m->str_flags); 1941 break; 1942 1943 case FILE_BESTRING16: 1944 case FILE_LESTRING16: 1945 l = 0; 1946 v = file_strncmp16(m->value.s, p->s, (size_t)m->vallen, m->str_flags); 1947 break; 1948 1949 case FILE_SEARCH: { /* search ms->search.s for the string m->value.s */ 1950 size_t slen; 1951 size_t idx; 1952 1953 if (ms->search.s == NULL) 1954 return 0; 1955 1956 slen = MIN(m->vallen, sizeof(m->value.s)); 1957 l = 0; 1958 v = 0; 1959 1960 for (idx = 0; m->str_range == 0 || idx < m->str_range; idx++) { 1961 if (slen + idx > ms->search.s_len) 1962 break; 1963 1964 v = file_strncmp(m->value.s, ms->search.s + idx, slen, 1965 m->str_flags); 1966 if (v == 0) { /* found match */ 1967 ms->search.offset += idx; 1968 break; 1969 } 1970 } 1971 break; 1972 } 1973 case FILE_REGEX: { 1974 int rc; 1975 file_regex_t rx; 1976 const char *search; 1977 1978 if (ms->search.s == NULL) 1979 return 0; 1980 1981 l = 0; 1982 rc = file_regcomp(&rx, m->value.s, 1983 REG_EXTENDED|REG_NEWLINE| 1984 ((m->str_flags & STRING_IGNORE_CASE) ? REG_ICASE : 0)); 1985 if (rc) { 1986 file_regerror(&rx, rc, ms); 1987 v = (uint64_t)-1; 1988 } else { 1989 regmatch_t pmatch[1]; 1990 size_t slen = ms->search.s_len; 1991#ifndef REG_STARTEND 1992#define REG_STARTEND 0 1993 char *copy; 1994 if (slen != 0) { 1995 copy = malloc(slen); 1996 if (copy == NULL) { 1997 file_error(ms, errno, 1998 "can't allocate %" SIZE_T_FORMAT "u bytes", 1999 slen); 2000 return -1; 2001 } 2002 memcpy(copy, ms->search.s, slen); 2003 copy[--slen] = '\0'; 2004 search = copy; 2005 } else { 2006 search = ms->search.s; 2007 copy = NULL; 2008 } 2009#else 2010 search = ms->search.s; 2011 pmatch[0].rm_so = 0; 2012 pmatch[0].rm_eo = slen; 2013#endif 2014 rc = file_regexec(&rx, (const char *)search, 2015 1, pmatch, REG_STARTEND); 2016#if REG_STARTEND == 0 2017 free(copy); 2018#endif 2019 switch (rc) { 2020 case 0: 2021 ms->search.s += (int)pmatch[0].rm_so; 2022 ms->search.offset += (size_t)pmatch[0].rm_so; 2023 ms->search.rm_len = 2024 (size_t)(pmatch[0].rm_eo - pmatch[0].rm_so); 2025 v = 0; 2026 break; 2027 2028 case REG_NOMATCH: 2029 v = 1; 2030 break; 2031 2032 default: 2033 file_regerror(&rx, rc, ms); 2034 v = (uint64_t)-1; 2035 break; 2036 } 2037 } 2038 file_regfree(&rx); 2039 if (v == (uint64_t)-1) 2040 return -1; 2041 break; 2042 } 2043 case FILE_INDIRECT: 2044 case FILE_USE: 2045 case FILE_NAME: 2046 return 1; 2047 default: 2048 file_magerror(ms, "invalid type %d in magiccheck()", m->type); 2049 return -1; 2050 } 2051 2052 v = file_signextend(ms, m, v); 2053 2054 switch (m->reln) { 2055 case 'x': 2056 if ((ms->flags & MAGIC_DEBUG) != 0) 2057 (void) fprintf(stderr, "%" INT64_T_FORMAT 2058 "u == *any* = 1\n", (unsigned long long)v); 2059 matched = 1; 2060 break; 2061 2062 case '!': 2063 matched = v != l; 2064 if ((ms->flags & MAGIC_DEBUG) != 0) 2065 (void) fprintf(stderr, "%" INT64_T_FORMAT "u != %" 2066 INT64_T_FORMAT "u = %d\n", (unsigned long long)v, 2067 (unsigned long long)l, matched); 2068 break; 2069 2070 case '=': 2071 matched = v == l; 2072 if ((ms->flags & MAGIC_DEBUG) != 0) 2073 (void) fprintf(stderr, "%" INT64_T_FORMAT "u == %" 2074 INT64_T_FORMAT "u = %d\n", (unsigned long long)v, 2075 (unsigned long long)l, matched); 2076 break; 2077 2078 case '>': 2079 if (m->flag & UNSIGNED) { 2080 matched = v > l; 2081 if ((ms->flags & MAGIC_DEBUG) != 0) 2082 (void) fprintf(stderr, "%" INT64_T_FORMAT 2083 "u > %" INT64_T_FORMAT "u = %d\n", 2084 (unsigned long long)v, 2085 (unsigned long long)l, matched); 2086 } 2087 else { 2088 matched = (int64_t) v > (int64_t) l; 2089 if ((ms->flags & MAGIC_DEBUG) != 0) 2090 (void) fprintf(stderr, "%" INT64_T_FORMAT 2091 "d > %" INT64_T_FORMAT "d = %d\n", 2092 (long long)v, (long long)l, matched); 2093 } 2094 break; 2095 2096 case '<': 2097 if (m->flag & UNSIGNED) { 2098 matched = v < l; 2099 if ((ms->flags & MAGIC_DEBUG) != 0) 2100 (void) fprintf(stderr, "%" INT64_T_FORMAT 2101 "u < %" INT64_T_FORMAT "u = %d\n", 2102 (unsigned long long)v, 2103 (unsigned long long)l, matched); 2104 } 2105 else { 2106 matched = (int64_t) v < (int64_t) l; 2107 if ((ms->flags & MAGIC_DEBUG) != 0) 2108 (void) fprintf(stderr, "%" INT64_T_FORMAT 2109 "d < %" INT64_T_FORMAT "d = %d\n", 2110 (long long)v, (long long)l, matched); 2111 } 2112 break; 2113 2114 case '&': 2115 matched = (v & l) == l; 2116 if ((ms->flags & MAGIC_DEBUG) != 0) 2117 (void) fprintf(stderr, "((%" INT64_T_FORMAT "x & %" 2118 INT64_T_FORMAT "x) == %" INT64_T_FORMAT 2119 "x) = %d\n", (unsigned long long)v, 2120 (unsigned long long)l, (unsigned long long)l, 2121 matched); 2122 break; 2123 2124 case '^': 2125 matched = (v & l) != l; 2126 if ((ms->flags & MAGIC_DEBUG) != 0) 2127 (void) fprintf(stderr, "((%" INT64_T_FORMAT "x & %" 2128 INT64_T_FORMAT "x) != %" INT64_T_FORMAT 2129 "x) = %d\n", (unsigned long long)v, 2130 (unsigned long long)l, (unsigned long long)l, 2131 matched); 2132 break; 2133 2134 default: 2135 file_magerror(ms, "cannot happen: invalid relation `%c'", 2136 m->reln); 2137 return -1; 2138 } 2139 2140 return matched; 2141} 2142 2143private int 2144handle_annotation(struct magic_set *ms, struct magic *m) 2145{ 2146 if (ms->flags & MAGIC_APPLE) { 2147 if (file_printf(ms, "%.8s", m->apple) == -1) 2148 return -1; 2149 return 1; 2150 } 2151 if ((ms->flags & MAGIC_MIME_TYPE) && m->mimetype[0]) { 2152 if (file_printf(ms, "%s", m->mimetype) == -1) 2153 return -1; 2154 return 1; 2155 } 2156 return 0; 2157} 2158 2159private int 2160print_sep(struct magic_set *ms, int firstline) 2161{ 2162 if (ms->flags & MAGIC_MIME) 2163 return 0; 2164 if (firstline) 2165 return 0; 2166 /* 2167 * we found another match 2168 * put a newline and '-' to do some simple formatting 2169 */ 2170 return file_printf(ms, "\n- "); 2171} 2172