Annotation of embedaddon/php/ext/fileinfo/libmagic/softmagic.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (c) Ian F. Darwin 1986-1995.
! 3: * Software written by Ian F. Darwin and others;
! 4: * maintained 1995-present by Christos Zoulas and others.
! 5: *
! 6: * Redistribution and use in source and binary forms, with or without
! 7: * modification, are permitted provided that the following conditions
! 8: * are met:
! 9: * 1. Redistributions of source code must retain the above copyright
! 10: * notice immediately at the beginning of the file, without modification,
! 11: * this list of conditions, and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: *
! 16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
! 17: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 18: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 19: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
! 20: * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 21: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 22: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 24: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 25: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 26: * SUCH DAMAGE.
! 27: */
! 28: /*
! 29: * softmagic - interpret variable magic from MAGIC
! 30: */
! 31:
! 32: #include "file.h"
! 33:
! 34: #ifndef lint
! 35: FILE_RCSID("@(#)$File: softmagic.c,v 1.135 2009/03/27 22:42:49 christos Exp $")
! 36: #endif /* lint */
! 37:
! 38: #include "magic.h"
! 39: #include <string.h>
! 40: #include <ctype.h>
! 41: #include <stdlib.h>
! 42: #include <time.h>
! 43:
! 44: #ifndef PREG_OFFSET_CAPTURE
! 45: # define PREG_OFFSET_CAPTURE (1<<8)
! 46: #endif
! 47:
! 48:
! 49:
! 50: private int match(struct magic_set *, struct magic *, uint32_t,
! 51: const unsigned char *, size_t, int);
! 52: private int mget(struct magic_set *, const unsigned char *,
! 53: struct magic *, size_t, unsigned int);
! 54: private int magiccheck(struct magic_set *, struct magic *);
! 55: private int32_t mprint(struct magic_set *, struct magic *);
! 56: private int32_t moffset(struct magic_set *, struct magic *);
! 57: private void mdebug(uint32_t, const char *, size_t);
! 58: private int mcopy(struct magic_set *, union VALUETYPE *, int, int,
! 59: const unsigned char *, uint32_t, size_t, size_t);
! 60: private int mconvert(struct magic_set *, struct magic *);
! 61: private int print_sep(struct magic_set *, int);
! 62: private int handle_annotation(struct magic_set *, struct magic *);
! 63: private void cvt_8(union VALUETYPE *, const struct magic *);
! 64: private void cvt_16(union VALUETYPE *, const struct magic *);
! 65: private void cvt_32(union VALUETYPE *, const struct magic *);
! 66: private void cvt_64(union VALUETYPE *, const struct magic *);
! 67:
! 68: /*
! 69: * softmagic - lookup one file in parsed, in-memory copy of database
! 70: * Passed the name and FILE * of one file to be typed.
! 71: */
! 72: /*ARGSUSED1*/ /* nbytes passed for regularity, maybe need later */
! 73: protected int
! 74: file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes, int mode)
! 75: {
! 76: struct mlist *ml;
! 77: int rv;
! 78: for (ml = ms->mlist->next; ml != ms->mlist; ml = ml->next)
! 79: if ((rv = match(ms, ml->magic, ml->nmagic, buf, nbytes, mode)) != 0)
! 80: return rv;
! 81:
! 82: return 0;
! 83: }
! 84:
! 85: /*
! 86: * Go through the whole list, stopping if you find a match. Process all
! 87: * the continuations of that match before returning.
! 88: *
! 89: * We support multi-level continuations:
! 90: *
! 91: * At any time when processing a successful top-level match, there is a
! 92: * current continuation level; it represents the level of the last
! 93: * successfully matched continuation.
! 94: *
! 95: * Continuations above that level are skipped as, if we see one, it
! 96: * means that the continuation that controls them - i.e, the
! 97: * lower-level continuation preceding them - failed to match.
! 98: *
! 99: * Continuations below that level are processed as, if we see one,
! 100: * it means we've finished processing or skipping higher-level
! 101: * continuations under the control of a successful or unsuccessful
! 102: * lower-level continuation, and are now seeing the next lower-level
! 103: * continuation and should process it. The current continuation
! 104: * level reverts to the level of the one we're seeing.
! 105: *
! 106: * Continuations at the current level are processed as, if we see
! 107: * one, there's no lower-level continuation that may have failed.
! 108: *
! 109: * If a continuation matches, we bump the current continuation level
! 110: * so that higher-level continuations are processed.
! 111: */
! 112: private int
! 113: match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
! 114: const unsigned char *s, size_t nbytes, int mode)
! 115: {
! 116: uint32_t magindex = 0;
! 117: unsigned int cont_level = 0;
! 118: int need_separator = 0;
! 119: int returnval = 0, e; /* if a match is found it is set to 1*/
! 120: int firstline = 1; /* a flag to print X\n X\n- X */
! 121: int printed_something = 0;
! 122: int print = (ms->flags & (MAGIC_MIME|MAGIC_APPLE)) == 0;
! 123:
! 124: if (file_check_mem(ms, cont_level) == -1)
! 125: return -1;
! 126:
! 127: for (magindex = 0; magindex < nmagic; magindex++) {
! 128: int flush = 0;
! 129: struct magic *m = &magic[magindex];
! 130:
! 131: if ((m->flag & BINTEST) != mode) {
! 132: /* Skip sub-tests */
! 133: while (magindex < nmagic - 1 && magic[magindex + 1].cont_level != 0) {
! 134: magindex++;
! 135: }
! 136: continue; /* Skip to next top-level test*/
! 137: }
! 138:
! 139: ms->offset = m->offset;
! 140: ms->line = m->lineno;
! 141:
! 142: /* if main entry matches, print it... */
! 143: switch (mget(ms, s, m, nbytes, cont_level)) {
! 144: case -1:
! 145: return -1;
! 146: case 0:
! 147: flush = m->reln != '!';
! 148: break;
! 149: default:
! 150: if (m->type == FILE_INDIRECT)
! 151: returnval = 1;
! 152:
! 153: switch (magiccheck(ms, m)) {
! 154: case -1:
! 155: return -1;
! 156: case 0:
! 157: flush++;
! 158: break;
! 159: default:
! 160: flush = 0;
! 161: break;
! 162: }
! 163: break;
! 164: }
! 165: if (flush) {
! 166: /*
! 167: * main entry didn't match,
! 168: * flush its continuations
! 169: */
! 170: while (magindex < nmagic - 1 && magic[magindex + 1].cont_level != 0) {
! 171: magindex++;
! 172: }
! 173: continue;
! 174: }
! 175:
! 176: /*
! 177: * If we are going to print something, we'll need to print
! 178: * a blank before we print something else.
! 179: */
! 180: if (*m->desc) {
! 181: need_separator = 1;
! 182: printed_something = 1;
! 183: if ((e = handle_annotation(ms, m)) != 0)
! 184: return e;
! 185: if (print_sep(ms, firstline) == -1)
! 186: return -1;
! 187: }
! 188:
! 189:
! 190: if (print && mprint(ms, m) == -1)
! 191: return -1;
! 192:
! 193: ms->c.li[cont_level].off = moffset(ms, m);
! 194:
! 195: /* and any continuations that match */
! 196: if (file_check_mem(ms, ++cont_level) == -1)
! 197: return -1;
! 198:
! 199: while (magindex < nmagic - 1 && magic[magindex + 1].cont_level != 0) {
! 200: magindex++;
! 201: m = &magic[magindex];
! 202: ms->line = m->lineno; /* for messages */
! 203:
! 204: if (cont_level < m->cont_level)
! 205: continue;
! 206: if (cont_level > m->cont_level) {
! 207: /*
! 208: * We're at the end of the level
! 209: * "cont_level" continuations.
! 210: */
! 211: cont_level = m->cont_level;
! 212: }
! 213: ms->offset = m->offset;
! 214: if (m->flag & OFFADD) {
! 215: ms->offset += ms->c.li[cont_level - 1].off;
! 216: }
! 217:
! 218: #ifdef ENABLE_CONDITIONALS
! 219: if (m->cond == COND_ELSE ||
! 220: m->cond == COND_ELIF) {
! 221: if (ms->c.li[cont_level].last_match == 1)
! 222: continue;
! 223: }
! 224: #endif
! 225: switch (mget(ms, s, m, nbytes, cont_level)) {
! 226: case -1:
! 227: return -1;
! 228: case 0:
! 229: if (m->reln != '!')
! 230: continue;
! 231: flush = 1;
! 232: break;
! 233: default:
! 234: if (m->type == FILE_INDIRECT)
! 235: returnval = 1;
! 236: flush = 0;
! 237: break;
! 238: }
! 239:
! 240: switch (flush ? 1 : magiccheck(ms, m)) {
! 241: case -1:
! 242: return -1;
! 243: case 0:
! 244: #ifdef ENABLE_CONDITIONALS
! 245: ms->c.li[cont_level].last_match = 0;
! 246: #endif
! 247: break;
! 248: default:
! 249: #ifdef ENABLE_CONDITIONALS
! 250: ms->c.li[cont_level].last_match = 1;
! 251: #endif
! 252: if (m->type != FILE_DEFAULT)
! 253: ms->c.li[cont_level].got_match = 1;
! 254: else if (ms->c.li[cont_level].got_match) {
! 255: ms->c.li[cont_level].got_match = 0;
! 256: break;
! 257: }
! 258: /*
! 259: * If we are going to print something,
! 260: * make sure that we have a separator first.
! 261: */
! 262: if (*m->desc) {
! 263: if ((e = handle_annotation(ms, m)) != 0)
! 264: return e;
! 265: if (!printed_something) {
! 266: printed_something = 1;
! 267: if (print_sep(ms, firstline)
! 268: == -1)
! 269: return -1;
! 270: }
! 271: }
! 272: /*
! 273: * This continuation matched. Print
! 274: * its message, with a blank before it
! 275: * if the previous item printed and
! 276: * this item isn't empty.
! 277: */
! 278: /* space if previous printed */
! 279: if (need_separator
! 280: && ((m->flag & NOSPACE) == 0)
! 281: && *m->desc) {
! 282: if (print &&
! 283: file_printf(ms, " ") == -1)
! 284: return -1;
! 285: need_separator = 0;
! 286: }
! 287: if (print && mprint(ms, m) == -1)
! 288: return -1;
! 289:
! 290: ms->c.li[cont_level].off = moffset(ms, m);
! 291:
! 292: if (*m->desc)
! 293: need_separator = 1;
! 294:
! 295: /*
! 296: * If we see any continuations
! 297: * at a higher level,
! 298: * process them.
! 299: */
! 300: if (file_check_mem(ms, ++cont_level) == -1)
! 301: return -1;
! 302: break;
! 303: }
! 304: }
! 305: if (printed_something) {
! 306: firstline = 0;
! 307: if (print)
! 308: returnval = 1;
! 309: }
! 310: if ((ms->flags & MAGIC_CONTINUE) == 0 && printed_something) {
! 311: return returnval; /* don't keep searching */
! 312: }
! 313: }
! 314: return returnval; /* This is hit if -k is set or there is no match */
! 315: }
! 316:
! 317: private int
! 318: check_fmt(struct magic_set *ms, struct magic *m)
! 319: {
! 320: pcre *pce;
! 321: int re_options;
! 322: pcre_extra *re_extra;
! 323: TSRMLS_FETCH();
! 324:
! 325: if (strchr(m->desc, '%') == NULL) {
! 326: return 0;
! 327: }
! 328:
! 329: if ((pce = pcre_get_compiled_regex("~%[-0-9.]*s~", &re_extra, &re_options TSRMLS_CC)) == NULL) {
! 330: return -1;
! 331: } else {
! 332: return !pcre_exec(pce, re_extra, m->desc, strlen(m->desc), 0, re_options, NULL, 0);
! 333: }
! 334: }
! 335:
! 336: private int32_t
! 337: mprint(struct magic_set *ms, struct magic *m)
! 338: {
! 339: uint64_t v;
! 340: float vf;
! 341: double vd;
! 342: int64_t t = 0;
! 343: char buf[128];
! 344: union VALUETYPE *p = &ms->ms_value;
! 345:
! 346: switch (m->type) {
! 347: case FILE_BYTE:
! 348: v = file_signextend(ms, m, (uint64_t)p->b);
! 349: switch (check_fmt(ms, m)) {
! 350: case -1:
! 351: return -1;
! 352: case 1:
! 353: (void)snprintf(buf, sizeof(buf), "%c",
! 354: (unsigned char)v);
! 355: if (file_printf(ms, m->desc, buf) == -1)
! 356: return -1;
! 357: break;
! 358: default:
! 359: if (file_printf(ms, m->desc, (unsigned char) v) == -1)
! 360: return -1;
! 361: break;
! 362: }
! 363: t = ms->offset + sizeof(char);
! 364: break;
! 365:
! 366: case FILE_SHORT:
! 367: case FILE_BESHORT:
! 368: case FILE_LESHORT:
! 369: v = file_signextend(ms, m, (uint64_t)p->h);
! 370: switch (check_fmt(ms, m)) {
! 371: case -1:
! 372: return -1;
! 373: case 1:
! 374: (void)snprintf(buf, sizeof(buf), "%hu",
! 375: (unsigned short)v);
! 376: if (file_printf(ms, m->desc, buf) == -1)
! 377: return -1;
! 378: break;
! 379: default:
! 380: if (
! 381: file_printf(ms, m->desc, (unsigned short) v) == -1)
! 382: return -1;
! 383: break;
! 384: }
! 385: t = ms->offset + sizeof(short);
! 386: break;
! 387:
! 388: case FILE_LONG:
! 389: case FILE_BELONG:
! 390: case FILE_LELONG:
! 391: case FILE_MELONG:
! 392: v = file_signextend(ms, m, (uint64_t)p->l);
! 393: switch (check_fmt(ms, m)) {
! 394: case -1:
! 395: return -1;
! 396: case 1:
! 397: (void)snprintf(buf, sizeof(buf), "%u", (uint32_t)v);
! 398: if (file_printf(ms, m->desc, buf) == -1)
! 399: return -1;
! 400: break;
! 401: default:
! 402: if (file_printf(ms, m->desc, (uint32_t) v) == -1)
! 403: return -1;
! 404: break;
! 405: }
! 406: t = ms->offset + sizeof(int32_t);
! 407: break;
! 408:
! 409: case FILE_QUAD:
! 410: case FILE_BEQUAD:
! 411: case FILE_LEQUAD:
! 412: v = file_signextend(ms, m, p->q);
! 413: if (file_printf(ms, m->desc, (uint64_t) v) == -1)
! 414: return -1;
! 415: t = ms->offset + sizeof(int64_t);
! 416: break;
! 417:
! 418: case FILE_STRING:
! 419: case FILE_PSTRING:
! 420: case FILE_BESTRING16:
! 421: case FILE_LESTRING16:
! 422: if (m->reln == '=' || m->reln == '!') {
! 423: if (file_printf(ms, m->desc, m->value.s) == -1)
! 424: return -1;
! 425: t = ms->offset + m->vallen;
! 426: }
! 427: else {
! 428: if (*m->value.s == '\0')
! 429: p->s[strcspn(p->s, "\n")] = '\0';
! 430: if (file_printf(ms, m->desc, p->s) == -1)
! 431: return -1;
! 432: t = ms->offset + strlen(p->s);
! 433: if (m->type == FILE_PSTRING)
! 434: t++;
! 435: }
! 436: break;
! 437:
! 438: case FILE_DATE:
! 439: case FILE_BEDATE:
! 440: case FILE_LEDATE:
! 441: case FILE_MEDATE:
! 442: if (file_printf(ms, m->desc, file_fmttime(p->l, 1)) == -1)
! 443: return -1;
! 444: t = ms->offset + sizeof(time_t);
! 445: break;
! 446:
! 447: case FILE_LDATE:
! 448: case FILE_BELDATE:
! 449: case FILE_LELDATE:
! 450: case FILE_MELDATE:
! 451: if (file_printf(ms, m->desc, file_fmttime(p->l, 0)) == -1)
! 452: return -1;
! 453: t = ms->offset + sizeof(time_t);
! 454: break;
! 455:
! 456: case FILE_QDATE:
! 457: case FILE_BEQDATE:
! 458: case FILE_LEQDATE:
! 459: if (file_printf(ms, m->desc, file_fmttime((uint32_t)p->q,
! 460: 1)) == -1)
! 461: return -1;
! 462: t = ms->offset + sizeof(uint64_t);
! 463: break;
! 464:
! 465: case FILE_QLDATE:
! 466: case FILE_BEQLDATE:
! 467: case FILE_LEQLDATE:
! 468: if (file_printf(ms, m->desc, file_fmttime((uint32_t)p->q,
! 469: 0)) == -1)
! 470: return -1;
! 471: t = ms->offset + sizeof(uint64_t);
! 472: break;
! 473:
! 474: case FILE_FLOAT:
! 475: case FILE_BEFLOAT:
! 476: case FILE_LEFLOAT:
! 477: vf = p->f;
! 478: switch (check_fmt(ms, m)) {
! 479: case -1:
! 480: return -1;
! 481: case 1:
! 482: (void)snprintf(buf, sizeof(buf), "%g", vf);
! 483: if (file_printf(ms, m->desc, buf) == -1)
! 484: return -1;
! 485: break;
! 486: default:
! 487: if (file_printf(ms, m->desc, vf) == -1)
! 488: return -1;
! 489: break;
! 490: }
! 491: t = ms->offset + sizeof(float);
! 492: break;
! 493:
! 494: case FILE_DOUBLE:
! 495: case FILE_BEDOUBLE:
! 496: case FILE_LEDOUBLE:
! 497: vd = p->d;
! 498: switch (check_fmt(ms, m)) {
! 499: case -1:
! 500: return -1;
! 501: case 1:
! 502: (void)snprintf(buf, sizeof(buf), "%g", vd);
! 503: if (file_printf(ms, m->desc, buf) == -1)
! 504: return -1;
! 505: break;
! 506: default:
! 507: if (file_printf(ms, m->desc, vd) == -1)
! 508: return -1;
! 509: break;
! 510: }
! 511: t = ms->offset + sizeof(double);
! 512: break;
! 513:
! 514: case FILE_REGEX: {
! 515: char *cp;
! 516: int rval;
! 517:
! 518: cp = estrndup((const char *)ms->search.s, ms->search.rm_len);
! 519:
! 520: rval = file_printf(ms, m->desc, cp);
! 521: efree(cp);
! 522:
! 523: if (rval == -1)
! 524: return -1;
! 525:
! 526: if ((m->str_flags & REGEX_OFFSET_START))
! 527: t = ms->search.offset;
! 528: else
! 529: t = ms->search.offset + ms->search.rm_len;
! 530: break;
! 531: }
! 532:
! 533: case FILE_SEARCH:
! 534: if (file_printf(ms, m->desc, m->value.s) == -1)
! 535: return -1;
! 536: if ((m->str_flags & REGEX_OFFSET_START))
! 537: t = ms->search.offset;
! 538: else
! 539: t = ms->search.offset + m->vallen;
! 540: break;
! 541:
! 542: case FILE_DEFAULT:
! 543: if (file_printf(ms, m->desc, m->value.s) == -1)
! 544: return -1;
! 545: t = ms->offset;
! 546: break;
! 547:
! 548: case FILE_INDIRECT:
! 549: t = ms->offset;
! 550: break;
! 551:
! 552: default:
! 553: file_magerror(ms, "invalid m->type (%d) in mprint()", m->type);
! 554: return -1;
! 555: }
! 556: return (int32_t)t;
! 557: }
! 558:
! 559: private int32_t
! 560: moffset(struct magic_set *ms, struct magic *m)
! 561: {
! 562: switch (m->type) {
! 563: case FILE_BYTE:
! 564: return ms->offset + sizeof(char);
! 565:
! 566: case FILE_SHORT:
! 567: case FILE_BESHORT:
! 568: case FILE_LESHORT:
! 569: return ms->offset + sizeof(short);
! 570:
! 571: case FILE_LONG:
! 572: case FILE_BELONG:
! 573: case FILE_LELONG:
! 574: case FILE_MELONG:
! 575: return ms->offset + sizeof(int32_t);
! 576:
! 577: case FILE_QUAD:
! 578: case FILE_BEQUAD:
! 579: case FILE_LEQUAD:
! 580: return ms->offset + sizeof(int64_t);
! 581:
! 582: case FILE_STRING:
! 583: case FILE_PSTRING:
! 584: case FILE_BESTRING16:
! 585: case FILE_LESTRING16:
! 586: if (m->reln == '=' || m->reln == '!')
! 587: return ms->offset + m->vallen;
! 588: else {
! 589: union VALUETYPE *p = &ms->ms_value;
! 590: uint32_t t;
! 591:
! 592: if (*m->value.s == '\0')
! 593: p->s[strcspn(p->s, "\n")] = '\0';
! 594: t = ms->offset + strlen(p->s);
! 595: if (m->type == FILE_PSTRING)
! 596: t++;
! 597: return t;
! 598: }
! 599:
! 600: case FILE_DATE:
! 601: case FILE_BEDATE:
! 602: case FILE_LEDATE:
! 603: case FILE_MEDATE:
! 604: return ms->offset + sizeof(time_t);
! 605:
! 606: case FILE_LDATE:
! 607: case FILE_BELDATE:
! 608: case FILE_LELDATE:
! 609: case FILE_MELDATE:
! 610: return ms->offset + sizeof(time_t);
! 611:
! 612: case FILE_QDATE:
! 613: case FILE_BEQDATE:
! 614: case FILE_LEQDATE:
! 615: return ms->offset + sizeof(uint64_t);
! 616:
! 617: case FILE_QLDATE:
! 618: case FILE_BEQLDATE:
! 619: case FILE_LEQLDATE:
! 620: return ms->offset + sizeof(uint64_t);
! 621:
! 622: case FILE_FLOAT:
! 623: case FILE_BEFLOAT:
! 624: case FILE_LEFLOAT:
! 625: return ms->offset + sizeof(float);
! 626:
! 627: case FILE_DOUBLE:
! 628: case FILE_BEDOUBLE:
! 629: case FILE_LEDOUBLE:
! 630: return ms->offset + sizeof(double);
! 631: break;
! 632:
! 633: case FILE_REGEX:
! 634: if ((m->str_flags & REGEX_OFFSET_START) != 0)
! 635: return ms->search.offset;
! 636: else
! 637: return ms->search.offset + ms->search.rm_len;
! 638:
! 639: case FILE_SEARCH:
! 640: if ((m->str_flags & REGEX_OFFSET_START) != 0)
! 641: return ms->search.offset;
! 642: else
! 643: return ms->search.offset + m->vallen;
! 644:
! 645: case FILE_DEFAULT:
! 646: return ms->offset;
! 647:
! 648: case FILE_INDIRECT:
! 649: return ms->offset;
! 650:
! 651: default:
! 652: return 0;
! 653: }
! 654: }
! 655:
! 656: #define DO_CVT(fld, cast) \
! 657: if (m->num_mask) \
! 658: switch (m->mask_op & FILE_OPS_MASK) { \
! 659: case FILE_OPAND: \
! 660: p->fld &= cast m->num_mask; \
! 661: break; \
! 662: case FILE_OPOR: \
! 663: p->fld |= cast m->num_mask; \
! 664: break; \
! 665: case FILE_OPXOR: \
! 666: p->fld ^= cast m->num_mask; \
! 667: break; \
! 668: case FILE_OPADD: \
! 669: p->fld += cast m->num_mask; \
! 670: break; \
! 671: case FILE_OPMINUS: \
! 672: p->fld -= cast m->num_mask; \
! 673: break; \
! 674: case FILE_OPMULTIPLY: \
! 675: p->fld *= cast m->num_mask; \
! 676: break; \
! 677: case FILE_OPDIVIDE: \
! 678: p->fld /= cast m->num_mask; \
! 679: break; \
! 680: case FILE_OPMODULO: \
! 681: p->fld %= cast m->num_mask; \
! 682: break; \
! 683: } \
! 684: if (m->mask_op & FILE_OPINVERSE) \
! 685: p->fld = ~p->fld \
! 686:
! 687: private void
! 688: cvt_8(union VALUETYPE *p, const struct magic *m)
! 689: {
! 690: DO_CVT(b, (uint8_t));
! 691: }
! 692:
! 693: private void
! 694: cvt_16(union VALUETYPE *p, const struct magic *m)
! 695: {
! 696: DO_CVT(h, (uint16_t));
! 697: }
! 698:
! 699: private void
! 700: cvt_32(union VALUETYPE *p, const struct magic *m)
! 701: {
! 702: DO_CVT(l, (uint32_t));
! 703: }
! 704:
! 705: private void
! 706: cvt_64(union VALUETYPE *p, const struct magic *m)
! 707: {
! 708: DO_CVT(q, (uint64_t));
! 709: }
! 710:
! 711: #define DO_CVT2(fld, cast) \
! 712: if (m->num_mask) \
! 713: switch (m->mask_op & FILE_OPS_MASK) { \
! 714: case FILE_OPADD: \
! 715: p->fld += cast (int64_t)m->num_mask; \
! 716: break; \
! 717: case FILE_OPMINUS: \
! 718: p->fld -= cast (int64_t)m->num_mask; \
! 719: break; \
! 720: case FILE_OPMULTIPLY: \
! 721: p->fld *= cast (int64_t)m->num_mask; \
! 722: break; \
! 723: case FILE_OPDIVIDE: \
! 724: p->fld /= cast (int64_t)m->num_mask; \
! 725: break; \
! 726: } \
! 727:
! 728: private void
! 729: cvt_float(union VALUETYPE *p, const struct magic *m)
! 730: {
! 731: DO_CVT2(f, (float));
! 732: }
! 733:
! 734: private void
! 735: cvt_double(union VALUETYPE *p, const struct magic *m)
! 736: {
! 737: DO_CVT2(d, (double));
! 738: }
! 739:
! 740: /*
! 741: * Convert the byte order of the data we are looking at
! 742: * While we're here, let's apply the mask operation
! 743: * (unless you have a better idea)
! 744: */
! 745: private int
! 746: mconvert(struct magic_set *ms, struct magic *m)
! 747: {
! 748: union VALUETYPE *p = &ms->ms_value;
! 749:
! 750: switch (m->type) {
! 751: case FILE_BYTE:
! 752: cvt_8(p, m);
! 753: return 1;
! 754: case FILE_SHORT:
! 755: cvt_16(p, m);
! 756: return 1;
! 757: case FILE_LONG:
! 758: case FILE_DATE:
! 759: case FILE_LDATE:
! 760: cvt_32(p, m);
! 761: return 1;
! 762: case FILE_QUAD:
! 763: case FILE_QDATE:
! 764: case FILE_QLDATE:
! 765: cvt_64(p, m);
! 766: return 1;
! 767: case FILE_STRING:
! 768: case FILE_BESTRING16:
! 769: case FILE_LESTRING16: {
! 770: /* Null terminate and eat *trailing* return */
! 771: p->s[sizeof(p->s) - 1] = '\0';
! 772: #if 0
! 773: /* Why? breaks magic numbers that end with \xa */
! 774: len = strlen(p->s);
! 775: if (len-- && p->s[len] == '\n')
! 776: p->s[len] = '\0';
! 777: #endif
! 778: return 1;
! 779: }
! 780: case FILE_PSTRING: {
! 781: char *ptr1 = p->s, *ptr2 = ptr1 + 1;
! 782: size_t len = *p->s;
! 783: if (len >= sizeof(p->s))
! 784: len = sizeof(p->s) - 1;
! 785: while (len--)
! 786: *ptr1++ = *ptr2++;
! 787: *ptr1 = '\0';
! 788: #if 0
! 789: /* Why? breaks magic numbers that end with \xa */
! 790: len = strlen(p->s);
! 791: if (len-- && p->s[len] == '\n')
! 792: p->s[len] = '\0';
! 793: #endif
! 794: return 1;
! 795: }
! 796: case FILE_BESHORT:
! 797: p->h = (short)((p->hs[0]<<8)|(p->hs[1]));
! 798: cvt_16(p, m);
! 799: return 1;
! 800: case FILE_BELONG:
! 801: case FILE_BEDATE:
! 802: case FILE_BELDATE:
! 803: p->l = (int32_t)
! 804: ((p->hl[0]<<24)|(p->hl[1]<<16)|(p->hl[2]<<8)|(p->hl[3]));
! 805: cvt_32(p, m);
! 806: return 1;
! 807: case FILE_BEQUAD:
! 808: case FILE_BEQDATE:
! 809: case FILE_BEQLDATE:
! 810: p->q = (uint64_t)
! 811: (((uint64_t)p->hq[0]<<56)|((uint64_t)p->hq[1]<<48)|
! 812: ((uint64_t)p->hq[2]<<40)|((uint64_t)p->hq[3]<<32)|
! 813: ((uint64_t)p->hq[4]<<24)|((uint64_t)p->hq[5]<<16)|
! 814: ((uint64_t)p->hq[6]<<8)|((uint64_t)p->hq[7]));
! 815: cvt_64(p, m);
! 816: return 1;
! 817: case FILE_LESHORT:
! 818: p->h = (short)((p->hs[1]<<8)|(p->hs[0]));
! 819: cvt_16(p, m);
! 820: return 1;
! 821: case FILE_LELONG:
! 822: case FILE_LEDATE:
! 823: case FILE_LELDATE:
! 824: p->l = (int32_t)
! 825: ((p->hl[3]<<24)|(p->hl[2]<<16)|(p->hl[1]<<8)|(p->hl[0]));
! 826: cvt_32(p, m);
! 827: return 1;
! 828: case FILE_LEQUAD:
! 829: case FILE_LEQDATE:
! 830: case FILE_LEQLDATE:
! 831: p->q = (uint64_t)
! 832: (((uint64_t)p->hq[7]<<56)|((uint64_t)p->hq[6]<<48)|
! 833: ((uint64_t)p->hq[5]<<40)|((uint64_t)p->hq[4]<<32)|
! 834: ((uint64_t)p->hq[3]<<24)|((uint64_t)p->hq[2]<<16)|
! 835: ((uint64_t)p->hq[1]<<8)|((uint64_t)p->hq[0]));
! 836: cvt_64(p, m);
! 837: return 1;
! 838: case FILE_MELONG:
! 839: case FILE_MEDATE:
! 840: case FILE_MELDATE:
! 841: p->l = (int32_t)
! 842: ((p->hl[1]<<24)|(p->hl[0]<<16)|(p->hl[3]<<8)|(p->hl[2]));
! 843: cvt_32(p, m);
! 844: return 1;
! 845: case FILE_FLOAT:
! 846: cvt_float(p, m);
! 847: return 1;
! 848: case FILE_BEFLOAT:
! 849: p->l = ((uint32_t)p->hl[0]<<24)|((uint32_t)p->hl[1]<<16)|
! 850: ((uint32_t)p->hl[2]<<8) |((uint32_t)p->hl[3]);
! 851: cvt_float(p, m);
! 852: return 1;
! 853: case FILE_LEFLOAT:
! 854: p->l = ((uint32_t)p->hl[3]<<24)|((uint32_t)p->hl[2]<<16)|
! 855: ((uint32_t)p->hl[1]<<8) |((uint32_t)p->hl[0]);
! 856: cvt_float(p, m);
! 857: return 1;
! 858: case FILE_DOUBLE:
! 859: cvt_double(p, m);
! 860: return 1;
! 861: case FILE_BEDOUBLE:
! 862: p->q = ((uint64_t)p->hq[0]<<56)|((uint64_t)p->hq[1]<<48)|
! 863: ((uint64_t)p->hq[2]<<40)|((uint64_t)p->hq[3]<<32)|
! 864: ((uint64_t)p->hq[4]<<24)|((uint64_t)p->hq[5]<<16)|
! 865: ((uint64_t)p->hq[6]<<8) |((uint64_t)p->hq[7]);
! 866: cvt_double(p, m);
! 867: return 1;
! 868: case FILE_LEDOUBLE:
! 869: p->q = ((uint64_t)p->hq[7]<<56)|((uint64_t)p->hq[6]<<48)|
! 870: ((uint64_t)p->hq[5]<<40)|((uint64_t)p->hq[4]<<32)|
! 871: ((uint64_t)p->hq[3]<<24)|((uint64_t)p->hq[2]<<16)|
! 872: ((uint64_t)p->hq[1]<<8) |((uint64_t)p->hq[0]);
! 873: cvt_double(p, m);
! 874: return 1;
! 875: case FILE_REGEX:
! 876: case FILE_SEARCH:
! 877: case FILE_DEFAULT:
! 878: return 1;
! 879: default:
! 880: file_magerror(ms, "invalid type %d in mconvert()", m->type);
! 881: return 0;
! 882: }
! 883: }
! 884:
! 885:
! 886: private void
! 887: mdebug(uint32_t offset, const char *str, size_t len)
! 888: {
! 889: (void) fprintf(stderr, "mget @%d: ", offset);
! 890: file_showstr(stderr, str, len);
! 891: (void) fputc('\n', stderr);
! 892: (void) fputc('\n', stderr);
! 893: }
! 894:
! 895: private int
! 896: mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
! 897: const unsigned char *s, uint32_t offset, size_t nbytes, size_t linecnt)
! 898: {
! 899: /*
! 900: * Note: FILE_SEARCH and FILE_REGEX do not actually copy
! 901: * anything, but setup pointers into the source
! 902: */
! 903: if (indir == 0) {
! 904: switch (type) {
! 905: case FILE_SEARCH:
! 906: ms->search.s = (const char *)s + offset;
! 907: ms->search.s_len = nbytes - offset;
! 908: ms->search.offset = offset;
! 909: return 0;
! 910:
! 911: case FILE_REGEX: {
! 912: const char *b;
! 913: const char *c;
! 914: const char *last; /* end of search region */
! 915: const char *buf; /* start of search region */
! 916: const char *end;
! 917: size_t lines;
! 918:
! 919: if (s == NULL) {
! 920: ms->search.s_len = 0;
! 921: ms->search.s = NULL;
! 922: return 0;
! 923: }
! 924: buf = (const char *)s + offset;
! 925: end = last = (const char *)s + nbytes;
! 926: /* mget() guarantees buf <= last */
! 927: for (lines = linecnt, b = buf;
! 928: lines && ((b = memchr(c = b, '\n', end - b)) || (b = memchr(c, '\r', end - c)));
! 929: lines--, b++) {
! 930: last = b;
! 931: if (b[0] == '\r' && b[1] == '\n')
! 932: b++;
! 933: }
! 934: if (lines)
! 935: last = (const char *)s + nbytes;
! 936:
! 937: ms->search.s = buf;
! 938: ms->search.s_len = last - buf;
! 939: ms->search.offset = offset;
! 940: ms->search.rm_len = 0;
! 941: return 0;
! 942: }
! 943: case FILE_BESTRING16:
! 944: case FILE_LESTRING16: {
! 945: const unsigned char *src = s + offset;
! 946: const unsigned char *esrc = s + nbytes;
! 947: char *dst = p->s;
! 948: char *edst = &p->s[sizeof(p->s) - 1];
! 949:
! 950: if (type == FILE_BESTRING16)
! 951: src++;
! 952:
! 953: /* check for pointer overflow */
! 954: if (src < s) {
! 955: file_magerror(ms, "invalid offset %u in mcopy()",
! 956: offset);
! 957: return -1;
! 958: }
! 959: for (/*EMPTY*/; src < esrc; src += 2, dst++) {
! 960: if (dst < edst)
! 961: *dst = *src;
! 962: else
! 963: break;
! 964: if (*dst == '\0') {
! 965: if (type == FILE_BESTRING16 ?
! 966: *(src - 1) != '\0' :
! 967: *(src + 1) != '\0')
! 968: *dst = ' ';
! 969: }
! 970: }
! 971: *edst = '\0';
! 972: return 0;
! 973: }
! 974: case FILE_STRING: /* XXX - these two should not need */
! 975: case FILE_PSTRING: /* to copy anything, but do anyway. */
! 976: default:
! 977: break;
! 978: }
! 979: }
! 980:
! 981: if (offset >= nbytes) {
! 982: (void)memset(p, '\0', sizeof(*p));
! 983: return 0;
! 984: }
! 985: if (nbytes - offset < sizeof(*p))
! 986: nbytes = nbytes - offset;
! 987: else
! 988: nbytes = sizeof(*p);
! 989:
! 990: (void)memcpy(p, s + offset, nbytes);
! 991:
! 992: /*
! 993: * the usefulness of padding with zeroes eludes me, it
! 994: * might even cause problems
! 995: */
! 996: if (nbytes < sizeof(*p))
! 997: (void)memset(((char *)(void *)p) + nbytes, '\0',
! 998: sizeof(*p) - nbytes);
! 999: return 0;
! 1000: }
! 1001:
! 1002: private int
! 1003: mget(struct magic_set *ms, const unsigned char *s,
! 1004: struct magic *m, size_t nbytes, unsigned int cont_level)
! 1005: {
! 1006: uint32_t offset = ms->offset;
! 1007: uint32_t count = m->str_range;
! 1008: union VALUETYPE *p = &ms->ms_value;
! 1009:
! 1010: if (mcopy(ms, p, m->type, m->flag & INDIR, s, offset, nbytes, count) == -1)
! 1011: return -1;
! 1012:
! 1013: if ((ms->flags & MAGIC_DEBUG) != 0) {
! 1014: mdebug(offset, (char *)(void *)p, sizeof(union VALUETYPE));
! 1015: }
! 1016:
! 1017: if (m->flag & INDIR) {
! 1018: int off = m->in_offset;
! 1019: if (m->in_op & FILE_OPINDIRECT) {
! 1020: const union VALUETYPE *q =
! 1021: ((const void *)(s + offset + off));
! 1022: switch (m->in_type) {
! 1023: case FILE_BYTE:
! 1024: off = q->b;
! 1025: break;
! 1026: case FILE_SHORT:
! 1027: off = q->h;
! 1028: break;
! 1029: case FILE_BESHORT:
! 1030: off = (short)((q->hs[0]<<8)|(q->hs[1]));
! 1031: break;
! 1032: case FILE_LESHORT:
! 1033: off = (short)((q->hs[1]<<8)|(q->hs[0]));
! 1034: break;
! 1035: case FILE_LONG:
! 1036: off = q->l;
! 1037: break;
! 1038: case FILE_BELONG:
! 1039: case FILE_BEID3:
! 1040: off = (int32_t)((q->hl[0]<<24)|(q->hl[1]<<16)|
! 1041: (q->hl[2]<<8)|(q->hl[3]));
! 1042: break;
! 1043: case FILE_LEID3:
! 1044: case FILE_LELONG:
! 1045: off = (int32_t)((q->hl[3]<<24)|(q->hl[2]<<16)|
! 1046: (q->hl[1]<<8)|(q->hl[0]));
! 1047: break;
! 1048: case FILE_MELONG:
! 1049: off = (int32_t)((q->hl[1]<<24)|(q->hl[0]<<16)|
! 1050: (q->hl[3]<<8)|(q->hl[2]));
! 1051: break;
! 1052: }
! 1053: }
! 1054: switch (m->in_type) {
! 1055: case FILE_BYTE:
! 1056: if (nbytes < (offset + 1))
! 1057: return 0;
! 1058: if (off) {
! 1059: switch (m->in_op & FILE_OPS_MASK) {
! 1060: case FILE_OPAND:
! 1061: offset = p->b & off;
! 1062: break;
! 1063: case FILE_OPOR:
! 1064: offset = p->b | off;
! 1065: break;
! 1066: case FILE_OPXOR:
! 1067: offset = p->b ^ off;
! 1068: break;
! 1069: case FILE_OPADD:
! 1070: offset = p->b + off;
! 1071: break;
! 1072: case FILE_OPMINUS:
! 1073: offset = p->b - off;
! 1074: break;
! 1075: case FILE_OPMULTIPLY:
! 1076: offset = p->b * off;
! 1077: break;
! 1078: case FILE_OPDIVIDE:
! 1079: offset = p->b / off;
! 1080: break;
! 1081: case FILE_OPMODULO:
! 1082: offset = p->b % off;
! 1083: break;
! 1084: }
! 1085: } else
! 1086: offset = p->b;
! 1087: if (m->in_op & FILE_OPINVERSE)
! 1088: offset = ~offset;
! 1089: break;
! 1090: case FILE_BESHORT:
! 1091: if (nbytes < (offset + 2))
! 1092: return 0;
! 1093: if (off) {
! 1094: switch (m->in_op & FILE_OPS_MASK) {
! 1095: case FILE_OPAND:
! 1096: offset = (short)((p->hs[0]<<8)|
! 1097: (p->hs[1])) &
! 1098: off;
! 1099: break;
! 1100: case FILE_OPOR:
! 1101: offset = (short)((p->hs[0]<<8)|
! 1102: (p->hs[1])) |
! 1103: off;
! 1104: break;
! 1105: case FILE_OPXOR:
! 1106: offset = (short)((p->hs[0]<<8)|
! 1107: (p->hs[1])) ^
! 1108: off;
! 1109: break;
! 1110: case FILE_OPADD:
! 1111: offset = (short)((p->hs[0]<<8)|
! 1112: (p->hs[1])) +
! 1113: off;
! 1114: break;
! 1115: case FILE_OPMINUS:
! 1116: offset = (short)((p->hs[0]<<8)|
! 1117: (p->hs[1])) -
! 1118: off;
! 1119: break;
! 1120: case FILE_OPMULTIPLY:
! 1121: offset = (short)((p->hs[0]<<8)|
! 1122: (p->hs[1])) *
! 1123: off;
! 1124: break;
! 1125: case FILE_OPDIVIDE:
! 1126: offset = (short)((p->hs[0]<<8)|
! 1127: (p->hs[1])) /
! 1128: off;
! 1129: break;
! 1130: case FILE_OPMODULO:
! 1131: offset = (short)((p->hs[0]<<8)|
! 1132: (p->hs[1])) %
! 1133: off;
! 1134: break;
! 1135: }
! 1136: } else
! 1137: offset = (short)((p->hs[0]<<8)|
! 1138: (p->hs[1]));
! 1139: if (m->in_op & FILE_OPINVERSE)
! 1140: offset = ~offset;
! 1141: break;
! 1142: case FILE_LESHORT:
! 1143: if (nbytes < (offset + 2))
! 1144: return 0;
! 1145: if (off) {
! 1146: switch (m->in_op & FILE_OPS_MASK) {
! 1147: case FILE_OPAND:
! 1148: offset = (short)((p->hs[1]<<8)|
! 1149: (p->hs[0])) &
! 1150: off;
! 1151: break;
! 1152: case FILE_OPOR:
! 1153: offset = (short)((p->hs[1]<<8)|
! 1154: (p->hs[0])) |
! 1155: off;
! 1156: break;
! 1157: case FILE_OPXOR:
! 1158: offset = (short)((p->hs[1]<<8)|
! 1159: (p->hs[0])) ^
! 1160: off;
! 1161: break;
! 1162: case FILE_OPADD:
! 1163: offset = (short)((p->hs[1]<<8)|
! 1164: (p->hs[0])) +
! 1165: off;
! 1166: break;
! 1167: case FILE_OPMINUS:
! 1168: offset = (short)((p->hs[1]<<8)|
! 1169: (p->hs[0])) -
! 1170: off;
! 1171: break;
! 1172: case FILE_OPMULTIPLY:
! 1173: offset = (short)((p->hs[1]<<8)|
! 1174: (p->hs[0])) *
! 1175: off;
! 1176: break;
! 1177: case FILE_OPDIVIDE:
! 1178: offset = (short)((p->hs[1]<<8)|
! 1179: (p->hs[0])) /
! 1180: off;
! 1181: break;
! 1182: case FILE_OPMODULO:
! 1183: offset = (short)((p->hs[1]<<8)|
! 1184: (p->hs[0])) %
! 1185: off;
! 1186: break;
! 1187: }
! 1188: } else
! 1189: offset = (short)((p->hs[1]<<8)|
! 1190: (p->hs[0]));
! 1191: if (m->in_op & FILE_OPINVERSE)
! 1192: offset = ~offset;
! 1193: break;
! 1194: case FILE_SHORT:
! 1195: if (nbytes < (offset + 2))
! 1196: return 0;
! 1197: if (off) {
! 1198: switch (m->in_op & FILE_OPS_MASK) {
! 1199: case FILE_OPAND:
! 1200: offset = p->h & off;
! 1201: break;
! 1202: case FILE_OPOR:
! 1203: offset = p->h | off;
! 1204: break;
! 1205: case FILE_OPXOR:
! 1206: offset = p->h ^ off;
! 1207: break;
! 1208: case FILE_OPADD:
! 1209: offset = p->h + off;
! 1210: break;
! 1211: case FILE_OPMINUS:
! 1212: offset = p->h - off;
! 1213: break;
! 1214: case FILE_OPMULTIPLY:
! 1215: offset = p->h * off;
! 1216: break;
! 1217: case FILE_OPDIVIDE:
! 1218: offset = p->h / off;
! 1219: break;
! 1220: case FILE_OPMODULO:
! 1221: offset = p->h % off;
! 1222: break;
! 1223: }
! 1224: }
! 1225: else
! 1226: offset = p->h;
! 1227: if (m->in_op & FILE_OPINVERSE)
! 1228: offset = ~offset;
! 1229: break;
! 1230: case FILE_BELONG:
! 1231: case FILE_BEID3:
! 1232: if (nbytes < (offset + 4))
! 1233: return 0;
! 1234: if (off) {
! 1235: switch (m->in_op & FILE_OPS_MASK) {
! 1236: case FILE_OPAND:
! 1237: offset = (int32_t)((p->hl[0]<<24)|
! 1238: (p->hl[1]<<16)|
! 1239: (p->hl[2]<<8)|
! 1240: (p->hl[3])) &
! 1241: off;
! 1242: break;
! 1243: case FILE_OPOR:
! 1244: offset = (int32_t)((p->hl[0]<<24)|
! 1245: (p->hl[1]<<16)|
! 1246: (p->hl[2]<<8)|
! 1247: (p->hl[3])) |
! 1248: off;
! 1249: break;
! 1250: case FILE_OPXOR:
! 1251: offset = (int32_t)((p->hl[0]<<24)|
! 1252: (p->hl[1]<<16)|
! 1253: (p->hl[2]<<8)|
! 1254: (p->hl[3])) ^
! 1255: off;
! 1256: break;
! 1257: case FILE_OPADD:
! 1258: offset = (int32_t)((p->hl[0]<<24)|
! 1259: (p->hl[1]<<16)|
! 1260: (p->hl[2]<<8)|
! 1261: (p->hl[3])) +
! 1262: off;
! 1263: break;
! 1264: case FILE_OPMINUS:
! 1265: offset = (int32_t)((p->hl[0]<<24)|
! 1266: (p->hl[1]<<16)|
! 1267: (p->hl[2]<<8)|
! 1268: (p->hl[3])) -
! 1269: off;
! 1270: break;
! 1271: case FILE_OPMULTIPLY:
! 1272: offset = (int32_t)((p->hl[0]<<24)|
! 1273: (p->hl[1]<<16)|
! 1274: (p->hl[2]<<8)|
! 1275: (p->hl[3])) *
! 1276: off;
! 1277: break;
! 1278: case FILE_OPDIVIDE:
! 1279: offset = (int32_t)((p->hl[0]<<24)|
! 1280: (p->hl[1]<<16)|
! 1281: (p->hl[2]<<8)|
! 1282: (p->hl[3])) /
! 1283: off;
! 1284: break;
! 1285: case FILE_OPMODULO:
! 1286: offset = (int32_t)((p->hl[0]<<24)|
! 1287: (p->hl[1]<<16)|
! 1288: (p->hl[2]<<8)|
! 1289: (p->hl[3])) %
! 1290: off;
! 1291: break;
! 1292: }
! 1293: } else
! 1294: offset = (int32_t)((p->hl[0]<<24)|
! 1295: (p->hl[1]<<16)|
! 1296: (p->hl[2]<<8)|
! 1297: (p->hl[3]));
! 1298: if (m->in_op & FILE_OPINVERSE)
! 1299: offset = ~offset;
! 1300: break;
! 1301: case FILE_LELONG:
! 1302: case FILE_LEID3:
! 1303: if (nbytes < (offset + 4))
! 1304: return 0;
! 1305: if (off) {
! 1306: switch (m->in_op & FILE_OPS_MASK) {
! 1307: case FILE_OPAND:
! 1308: offset = (int32_t)((p->hl[3]<<24)|
! 1309: (p->hl[2]<<16)|
! 1310: (p->hl[1]<<8)|
! 1311: (p->hl[0])) &
! 1312: off;
! 1313: break;
! 1314: case FILE_OPOR:
! 1315: offset = (int32_t)((p->hl[3]<<24)|
! 1316: (p->hl[2]<<16)|
! 1317: (p->hl[1]<<8)|
! 1318: (p->hl[0])) |
! 1319: off;
! 1320: break;
! 1321: case FILE_OPXOR:
! 1322: offset = (int32_t)((p->hl[3]<<24)|
! 1323: (p->hl[2]<<16)|
! 1324: (p->hl[1]<<8)|
! 1325: (p->hl[0])) ^
! 1326: off;
! 1327: break;
! 1328: case FILE_OPADD:
! 1329: offset = (int32_t)((p->hl[3]<<24)|
! 1330: (p->hl[2]<<16)|
! 1331: (p->hl[1]<<8)|
! 1332: (p->hl[0])) +
! 1333: off;
! 1334: break;
! 1335: case FILE_OPMINUS:
! 1336: offset = (int32_t)((p->hl[3]<<24)|
! 1337: (p->hl[2]<<16)|
! 1338: (p->hl[1]<<8)|
! 1339: (p->hl[0])) -
! 1340: off;
! 1341: break;
! 1342: case FILE_OPMULTIPLY:
! 1343: offset = (int32_t)((p->hl[3]<<24)|
! 1344: (p->hl[2]<<16)|
! 1345: (p->hl[1]<<8)|
! 1346: (p->hl[0])) *
! 1347: off;
! 1348: break;
! 1349: case FILE_OPDIVIDE:
! 1350: offset = (int32_t)((p->hl[3]<<24)|
! 1351: (p->hl[2]<<16)|
! 1352: (p->hl[1]<<8)|
! 1353: (p->hl[0])) /
! 1354: off;
! 1355: break;
! 1356: case FILE_OPMODULO:
! 1357: offset = (int32_t)((p->hl[3]<<24)|
! 1358: (p->hl[2]<<16)|
! 1359: (p->hl[1]<<8)|
! 1360: (p->hl[0])) %
! 1361: off;
! 1362: break;
! 1363: }
! 1364: } else
! 1365: offset = (int32_t)((p->hl[3]<<24)|
! 1366: (p->hl[2]<<16)|
! 1367: (p->hl[1]<<8)|
! 1368: (p->hl[0]));
! 1369: if (m->in_op & FILE_OPINVERSE)
! 1370: offset = ~offset;
! 1371: break;
! 1372: case FILE_MELONG:
! 1373: if (nbytes < (offset + 4))
! 1374: return 0;
! 1375: if (off) {
! 1376: switch (m->in_op & FILE_OPS_MASK) {
! 1377: case FILE_OPAND:
! 1378: offset = (int32_t)((p->hl[1]<<24)|
! 1379: (p->hl[0]<<16)|
! 1380: (p->hl[3]<<8)|
! 1381: (p->hl[2])) &
! 1382: off;
! 1383: break;
! 1384: case FILE_OPOR:
! 1385: offset = (int32_t)((p->hl[1]<<24)|
! 1386: (p->hl[0]<<16)|
! 1387: (p->hl[3]<<8)|
! 1388: (p->hl[2])) |
! 1389: off;
! 1390: break;
! 1391: case FILE_OPXOR:
! 1392: offset = (int32_t)((p->hl[1]<<24)|
! 1393: (p->hl[0]<<16)|
! 1394: (p->hl[3]<<8)|
! 1395: (p->hl[2])) ^
! 1396: off;
! 1397: break;
! 1398: case FILE_OPADD:
! 1399: offset = (int32_t)((p->hl[1]<<24)|
! 1400: (p->hl[0]<<16)|
! 1401: (p->hl[3]<<8)|
! 1402: (p->hl[2])) +
! 1403: off;
! 1404: break;
! 1405: case FILE_OPMINUS:
! 1406: offset = (int32_t)((p->hl[1]<<24)|
! 1407: (p->hl[0]<<16)|
! 1408: (p->hl[3]<<8)|
! 1409: (p->hl[2])) -
! 1410: off;
! 1411: break;
! 1412: case FILE_OPMULTIPLY:
! 1413: offset = (int32_t)((p->hl[1]<<24)|
! 1414: (p->hl[0]<<16)|
! 1415: (p->hl[3]<<8)|
! 1416: (p->hl[2])) *
! 1417: off;
! 1418: break;
! 1419: case FILE_OPDIVIDE:
! 1420: offset = (int32_t)((p->hl[1]<<24)|
! 1421: (p->hl[0]<<16)|
! 1422: (p->hl[3]<<8)|
! 1423: (p->hl[2])) /
! 1424: off;
! 1425: break;
! 1426: case FILE_OPMODULO:
! 1427: offset = (int32_t)((p->hl[1]<<24)|
! 1428: (p->hl[0]<<16)|
! 1429: (p->hl[3]<<8)|
! 1430: (p->hl[2])) %
! 1431: off;
! 1432: break;
! 1433: }
! 1434: } else
! 1435: offset = (int32_t)((p->hl[1]<<24)|
! 1436: (p->hl[0]<<16)|
! 1437: (p->hl[3]<<8)|
! 1438: (p->hl[2]));
! 1439: if (m->in_op & FILE_OPINVERSE)
! 1440: offset = ~offset;
! 1441: break;
! 1442: case FILE_LONG:
! 1443: if (nbytes < (offset + 4))
! 1444: return 0;
! 1445: if (off) {
! 1446: switch (m->in_op & FILE_OPS_MASK) {
! 1447: case FILE_OPAND:
! 1448: offset = p->l & off;
! 1449: break;
! 1450: case FILE_OPOR:
! 1451: offset = p->l | off;
! 1452: break;
! 1453: case FILE_OPXOR:
! 1454: offset = p->l ^ off;
! 1455: break;
! 1456: case FILE_OPADD:
! 1457: offset = p->l + off;
! 1458: break;
! 1459: case FILE_OPMINUS:
! 1460: offset = p->l - off;
! 1461: break;
! 1462: case FILE_OPMULTIPLY:
! 1463: offset = p->l * off;
! 1464: break;
! 1465: case FILE_OPDIVIDE:
! 1466: offset = p->l / off;
! 1467: break;
! 1468: case FILE_OPMODULO:
! 1469: offset = p->l % off;
! 1470: break;
! 1471: }
! 1472: } else
! 1473: offset = p->l;
! 1474: if (m->in_op & FILE_OPINVERSE)
! 1475: offset = ~offset;
! 1476: break;
! 1477: }
! 1478:
! 1479: switch (m->in_type) {
! 1480: case FILE_LEID3:
! 1481: case FILE_BEID3:
! 1482: offset = ((((offset >> 0) & 0x7f) << 0) |
! 1483: (((offset >> 8) & 0x7f) << 7) |
! 1484: (((offset >> 16) & 0x7f) << 14) |
! 1485: (((offset >> 24) & 0x7f) << 21)) + 10;
! 1486: break;
! 1487: default:
! 1488: break;
! 1489: }
! 1490:
! 1491: if (m->flag & INDIROFFADD) {
! 1492: offset += ms->c.li[cont_level-1].off;
! 1493: }
! 1494: if (mcopy(ms, p, m->type, 0, s, offset, nbytes, count) == -1)
! 1495: return -1;
! 1496: ms->offset = offset;
! 1497:
! 1498: if ((ms->flags & MAGIC_DEBUG) != 0) {
! 1499: mdebug(offset, (char *)(void *)p,
! 1500: sizeof(union VALUETYPE));
! 1501: }
! 1502: }
! 1503:
! 1504: /* Verify we have enough data to match magic type */
! 1505: switch (m->type) {
! 1506: case FILE_BYTE:
! 1507: if (nbytes < (offset + 1)) /* should alway be true */
! 1508: return 0;
! 1509: break;
! 1510:
! 1511: case FILE_SHORT:
! 1512: case FILE_BESHORT:
! 1513: case FILE_LESHORT:
! 1514: if (nbytes < (offset + 2))
! 1515: return 0;
! 1516: break;
! 1517:
! 1518: case FILE_LONG:
! 1519: case FILE_BELONG:
! 1520: case FILE_LELONG:
! 1521: case FILE_MELONG:
! 1522: case FILE_DATE:
! 1523: case FILE_BEDATE:
! 1524: case FILE_LEDATE:
! 1525: case FILE_MEDATE:
! 1526: case FILE_LDATE:
! 1527: case FILE_BELDATE:
! 1528: case FILE_LELDATE:
! 1529: case FILE_MELDATE:
! 1530: case FILE_FLOAT:
! 1531: case FILE_BEFLOAT:
! 1532: case FILE_LEFLOAT:
! 1533: if (nbytes < (offset + 4))
! 1534: return 0;
! 1535: break;
! 1536:
! 1537: case FILE_DOUBLE:
! 1538: case FILE_BEDOUBLE:
! 1539: case FILE_LEDOUBLE:
! 1540: if (nbytes < (offset + 8))
! 1541: return 0;
! 1542: break;
! 1543:
! 1544: case FILE_STRING:
! 1545: case FILE_PSTRING:
! 1546: case FILE_SEARCH:
! 1547: if (nbytes < (offset + m->vallen))
! 1548: return 0;
! 1549: break;
! 1550:
! 1551: case FILE_REGEX:
! 1552: if (nbytes < offset)
! 1553: return 0;
! 1554: break;
! 1555:
! 1556: case FILE_INDIRECT:
! 1557: if ((ms->flags & (MAGIC_MIME|MAGIC_APPLE)) == 0 &&
! 1558: file_printf(ms, m->desc) == -1)
! 1559: return -1;
! 1560: if (nbytes < offset)
! 1561: return 0;
! 1562: return file_softmagic(ms, s + offset, nbytes - offset,
! 1563: BINTEST);
! 1564:
! 1565: case FILE_DEFAULT: /* nothing to check */
! 1566: default:
! 1567: break;
! 1568: }
! 1569: if (!mconvert(ms, m))
! 1570: return 0;
! 1571: return 1;
! 1572: }
! 1573:
! 1574: private uint64_t
! 1575: file_strncmp(const char *s1, const char *s2, size_t len, uint32_t flags)
! 1576: {
! 1577: /*
! 1578: * Convert the source args to unsigned here so that (1) the
! 1579: * compare will be unsigned as it is in strncmp() and (2) so
! 1580: * the ctype functions will work correctly without extra
! 1581: * casting.
! 1582: */
! 1583: const unsigned char *a = (const unsigned char *)s1;
! 1584: const unsigned char *b = (const unsigned char *)s2;
! 1585: uint64_t v;
! 1586:
! 1587: /*
! 1588: * What we want here is v = strncmp(s1, s2, len),
! 1589: * but ignoring any nulls.
! 1590: */
! 1591: v = 0;
! 1592: if (0L == flags) { /* normal string: do it fast */
! 1593: while (len-- > 0)
! 1594: if ((v = *b++ - *a++) != '\0')
! 1595: break;
! 1596: }
! 1597: else { /* combine the others */
! 1598: while (len-- > 0) {
! 1599: if ((flags & STRING_IGNORE_LOWERCASE) &&
! 1600: islower(*a)) {
! 1601: if ((v = tolower(*b++) - *a++) != '\0')
! 1602: break;
! 1603: }
! 1604: else if ((flags & STRING_IGNORE_UPPERCASE) &&
! 1605: isupper(*a)) {
! 1606: if ((v = toupper(*b++) - *a++) != '\0')
! 1607: break;
! 1608: }
! 1609: else if ((flags & STRING_COMPACT_BLANK) &&
! 1610: isspace(*a)) {
! 1611: a++;
! 1612: if (isspace(*b++)) {
! 1613: while (isspace(*b))
! 1614: b++;
! 1615: }
! 1616: else {
! 1617: v = 1;
! 1618: break;
! 1619: }
! 1620: }
! 1621: else if ((flags & STRING_COMPACT_OPTIONAL_BLANK) &&
! 1622: isspace(*a)) {
! 1623: a++;
! 1624: while (isspace(*b))
! 1625: b++;
! 1626: }
! 1627: else {
! 1628: if ((v = *b++ - *a++) != '\0')
! 1629: break;
! 1630: }
! 1631: }
! 1632: }
! 1633: return v;
! 1634: }
! 1635:
! 1636: private uint64_t
! 1637: file_strncmp16(const char *a, const char *b, size_t len, uint32_t flags)
! 1638: {
! 1639: /*
! 1640: * XXX - The 16-bit string compare probably needs to be done
! 1641: * differently, especially if the flags are to be supported.
! 1642: * At the moment, I am unsure.
! 1643: */
! 1644: flags = 0;
! 1645: return file_strncmp(a, b, len, flags);
! 1646: }
! 1647:
! 1648: private void
! 1649: convert_libmagic_pattern(zval *pattern, int options)
! 1650: {
! 1651: int i, j=0;
! 1652: char *t;
! 1653:
! 1654: t = (char *) safe_emalloc(Z_STRLEN_P(pattern), 2, 5);
! 1655:
! 1656: t[j++] = '~';
! 1657:
! 1658: for (i=0; i<Z_STRLEN_P(pattern); i++, j++) {
! 1659: switch (Z_STRVAL_P(pattern)[i]) {
! 1660: case '?':
! 1661: t[j] = '.';
! 1662: break;
! 1663: case '*':
! 1664: t[j++] = '.';
! 1665: t[j] = '*';
! 1666: break;
! 1667: case '.':
! 1668: t[j++] = '\\';
! 1669: t[j] = '.';
! 1670: break;
! 1671: case '\\':
! 1672: t[j++] = '\\';
! 1673: t[j] = '\\';
! 1674: break;
! 1675: case '(':
! 1676: t[j++] = '\\';
! 1677: t[j] = '(';
! 1678: break;
! 1679: case ')':
! 1680: t[j++] = '\\';
! 1681: t[j] = ')';
! 1682: break;
! 1683: case '~':
! 1684: t[j++] = '\\';
! 1685: t[j] = '~';
! 1686: break;
! 1687: default:
! 1688: t[j] = Z_STRVAL_P(pattern)[i];
! 1689: break;
! 1690: }
! 1691: }
! 1692: t[j++] = '~';
! 1693:
! 1694: if (options & PCRE_CASELESS)
! 1695: t[j++] = 'm';
! 1696:
! 1697: if (options & PCRE_MULTILINE)
! 1698: t[j++] = 'i';
! 1699:
! 1700: t[j]=0;
! 1701:
! 1702: Z_STRVAL_P(pattern) = t;
! 1703: Z_STRLEN_P(pattern) = j;
! 1704:
! 1705: }
! 1706:
! 1707: private int
! 1708: magiccheck(struct magic_set *ms, struct magic *m)
! 1709: {
! 1710: uint64_t l = m->value.q;
! 1711: uint64_t v;
! 1712: float fl, fv;
! 1713: double dl, dv;
! 1714: int matched;
! 1715: union VALUETYPE *p = &ms->ms_value;
! 1716:
! 1717: switch (m->type) {
! 1718: case FILE_BYTE:
! 1719: v = p->b;
! 1720: break;
! 1721:
! 1722: case FILE_SHORT:
! 1723: case FILE_BESHORT:
! 1724: case FILE_LESHORT:
! 1725: v = p->h;
! 1726: break;
! 1727:
! 1728: case FILE_LONG:
! 1729: case FILE_BELONG:
! 1730: case FILE_LELONG:
! 1731: case FILE_MELONG:
! 1732: case FILE_DATE:
! 1733: case FILE_BEDATE:
! 1734: case FILE_LEDATE:
! 1735: case FILE_MEDATE:
! 1736: case FILE_LDATE:
! 1737: case FILE_BELDATE:
! 1738: case FILE_LELDATE:
! 1739: case FILE_MELDATE:
! 1740: v = p->l;
! 1741: break;
! 1742:
! 1743: case FILE_QUAD:
! 1744: case FILE_LEQUAD:
! 1745: case FILE_BEQUAD:
! 1746: case FILE_QDATE:
! 1747: case FILE_BEQDATE:
! 1748: case FILE_LEQDATE:
! 1749: case FILE_QLDATE:
! 1750: case FILE_BEQLDATE:
! 1751: case FILE_LEQLDATE:
! 1752: v = p->q;
! 1753: break;
! 1754:
! 1755: case FILE_FLOAT:
! 1756: case FILE_BEFLOAT:
! 1757: case FILE_LEFLOAT:
! 1758: fl = m->value.f;
! 1759: fv = p->f;
! 1760: switch (m->reln) {
! 1761: case 'x':
! 1762: matched = 1;
! 1763: break;
! 1764:
! 1765: case '!':
! 1766: matched = fv != fl;
! 1767: break;
! 1768:
! 1769: case '=':
! 1770: matched = fv == fl;
! 1771: break;
! 1772:
! 1773: case '>':
! 1774: matched = fv > fl;
! 1775: break;
! 1776:
! 1777: case '<':
! 1778: matched = fv < fl;
! 1779: break;
! 1780:
! 1781: default:
! 1782: matched = 0;
! 1783: file_magerror(ms, "cannot happen with float: invalid relation `%c'",
! 1784: m->reln);
! 1785: return -1;
! 1786: }
! 1787: return matched;
! 1788:
! 1789: case FILE_DOUBLE:
! 1790: case FILE_BEDOUBLE:
! 1791: case FILE_LEDOUBLE:
! 1792: dl = m->value.d;
! 1793: dv = p->d;
! 1794: switch (m->reln) {
! 1795: case 'x':
! 1796: matched = 1;
! 1797: break;
! 1798:
! 1799: case '!':
! 1800: matched = dv != dl;
! 1801: break;
! 1802:
! 1803: case '=':
! 1804: matched = dv == dl;
! 1805: break;
! 1806:
! 1807: case '>':
! 1808: matched = dv > dl;
! 1809: break;
! 1810:
! 1811: case '<':
! 1812: matched = dv < dl;
! 1813: break;
! 1814:
! 1815: default:
! 1816: matched = 0;
! 1817: file_magerror(ms, "cannot happen with double: invalid relation `%c'", m->reln);
! 1818: return -1;
! 1819: }
! 1820: return matched;
! 1821:
! 1822: case FILE_DEFAULT:
! 1823: l = 0;
! 1824: v = 0;
! 1825: break;
! 1826:
! 1827: case FILE_STRING:
! 1828: case FILE_PSTRING:
! 1829: l = 0;
! 1830: v = file_strncmp(m->value.s, p->s, (size_t)m->vallen, m->str_flags);
! 1831: break;
! 1832:
! 1833: case FILE_BESTRING16:
! 1834: case FILE_LESTRING16:
! 1835: l = 0;
! 1836: v = file_strncmp16(m->value.s, p->s, (size_t)m->vallen, m->str_flags);
! 1837: break;
! 1838:
! 1839: case FILE_SEARCH: { /* search ms->search.s for the string m->value.s */
! 1840: size_t slen;
! 1841: size_t idx;
! 1842:
! 1843: if (ms->search.s == NULL)
! 1844: return 0;
! 1845:
! 1846: slen = MIN(m->vallen, sizeof(m->value.s));
! 1847: l = 0;
! 1848: v = 0;
! 1849:
! 1850: for (idx = 0; m->str_range == 0 || idx < m->str_range; idx++) {
! 1851: if (slen + idx > ms->search.s_len)
! 1852: break;
! 1853:
! 1854: v = file_strncmp(m->value.s, ms->search.s + idx, slen, m->str_flags);
! 1855: if (v == 0) { /* found match */
! 1856: ms->search.offset += idx;
! 1857: break;
! 1858: }
! 1859: }
! 1860: break;
! 1861: }
! 1862: case FILE_REGEX: {
! 1863: zval *pattern;
! 1864: int options = 0;
! 1865: pcre_cache_entry *pce;
! 1866: TSRMLS_FETCH();
! 1867:
! 1868: MAKE_STD_ZVAL(pattern);
! 1869: ZVAL_STRINGL(pattern, (char *)m->value.s, m->vallen, 0);
! 1870:
! 1871: options |= PCRE_MULTILINE;
! 1872:
! 1873: if (m->str_flags & STRING_IGNORE_CASE) {
! 1874: options |= PCRE_CASELESS;
! 1875: }
! 1876:
! 1877: convert_libmagic_pattern(pattern, options);
! 1878:
! 1879: #if (PHP_MAJOR_VERSION < 6)
! 1880: if ((pce = pcre_get_compiled_regex_cache(Z_STRVAL_P(pattern), Z_STRLEN_P(pattern) TSRMLS_CC)) == NULL) {
! 1881: #else
! 1882: if ((pce = pcre_get_compiled_regex_cache(IS_STRING, Z_STRVAL_P(pattern), Z_STRLEN_P(pattern) TSRMLS_CC)) == NULL) {
! 1883: #endif
! 1884: zval_dtor(pattern);
! 1885: FREE_ZVAL(pattern);
! 1886: return -1;
! 1887: } else {
! 1888: /* pce now contains the compiled regex */
! 1889: zval *retval;
! 1890: zval *subpats;
! 1891: char *haystack;
! 1892:
! 1893: MAKE_STD_ZVAL(retval);
! 1894: ALLOC_INIT_ZVAL(subpats);
! 1895:
! 1896: /* Cut the search len from haystack, equals to REG_STARTEND */
! 1897: haystack = estrndup(ms->search.s, ms->search.s_len);
! 1898:
! 1899: /* match v = 0, no match v = 1 */
! 1900: #if (PHP_MAJOR_VERSION < 6)
! 1901: php_pcre_match_impl(pce, haystack, ms->search.s_len, retval, subpats, 1, 1, PREG_OFFSET_CAPTURE, 0 TSRMLS_CC);
! 1902: #else
! 1903: php_pcre_match_impl(pce, IS_STRING, haystack, ms->search.s_len, retval, subpats, 1, 1, PREG_OFFSET_CAPTURE, 0 TSRMLS_CC);
! 1904: #endif
! 1905: /* Free haystack */
! 1906: efree(haystack);
! 1907:
! 1908: if (Z_LVAL_P(retval) < 0) {
! 1909: zval_ptr_dtor(&subpats);
! 1910: FREE_ZVAL(retval);
! 1911: zval_dtor(pattern);
! 1912: FREE_ZVAL(pattern);
! 1913: return -1;
! 1914: } else if ((Z_LVAL_P(retval) > 0) && (Z_TYPE_P(subpats) == IS_ARRAY)) {
! 1915:
! 1916: /* Need to fetch global match which equals pmatch[0] */
! 1917: HashTable *ht = Z_ARRVAL_P(subpats);
! 1918: HashPosition outer_pos;
! 1919: zval *pattern_match = NULL, *pattern_offset = NULL;
! 1920:
! 1921: zend_hash_internal_pointer_reset_ex(ht, &outer_pos);
! 1922:
! 1923: if (zend_hash_has_more_elements_ex(ht, &outer_pos) == SUCCESS &&
! 1924: zend_hash_move_forward_ex(ht, &outer_pos)) {
! 1925:
! 1926: zval **ppzval;
! 1927:
! 1928: /* The first element (should be) is the global match
! 1929: Need to move to the inner array to get the global match */
! 1930:
! 1931: if (zend_hash_get_current_data_ex(ht, (void**)&ppzval, &outer_pos) != FAILURE) {
! 1932:
! 1933: HashTable *inner_ht;
! 1934: HashPosition inner_pos;
! 1935: zval **match, **offset;
! 1936: zval tmpcopy = **ppzval, matchcopy, offsetcopy;
! 1937:
! 1938: zval_copy_ctor(&tmpcopy);
! 1939: INIT_PZVAL(&tmpcopy);
! 1940:
! 1941: inner_ht = Z_ARRVAL(tmpcopy);
! 1942:
! 1943: /* If everything goes according to the master plan
! 1944: tmpcopy now contains two elements:
! 1945: 0 = the match
! 1946: 1 = starting position of the match */
! 1947: zend_hash_internal_pointer_reset_ex(inner_ht, &inner_pos);
! 1948:
! 1949: if (zend_hash_has_more_elements_ex(inner_ht, &inner_pos) == SUCCESS &&
! 1950: zend_hash_move_forward_ex(inner_ht, &inner_pos)) {
! 1951:
! 1952: if (zend_hash_get_current_data_ex(inner_ht, (void**)&match, &inner_pos) != FAILURE) {
! 1953:
! 1954: matchcopy = **match;
! 1955: zval_copy_ctor(&matchcopy);
! 1956: INIT_PZVAL(&matchcopy);
! 1957: convert_to_string(&matchcopy);
! 1958:
! 1959: MAKE_STD_ZVAL(pattern_match);
! 1960: Z_STRVAL_P(pattern_match) = (char *)Z_STRVAL(matchcopy);
! 1961: Z_STRLEN_P(pattern_match) = Z_STRLEN(matchcopy);
! 1962: Z_TYPE_P(pattern_match) = IS_STRING;
! 1963:
! 1964: zval_dtor(&matchcopy);
! 1965: }
! 1966: }
! 1967:
! 1968: if (zend_hash_has_more_elements_ex(inner_ht, &inner_pos) == SUCCESS &&
! 1969: zend_hash_move_forward_ex(inner_ht, &inner_pos)) {
! 1970:
! 1971: if (zend_hash_get_current_data_ex(inner_ht, (void**)&offset, &inner_pos) != FAILURE) {
! 1972:
! 1973: offsetcopy = **offset;
! 1974: zval_copy_ctor(&offsetcopy);
! 1975: INIT_PZVAL(&offsetcopy);
! 1976: convert_to_long(&offsetcopy);
! 1977:
! 1978: MAKE_STD_ZVAL(pattern_offset);
! 1979: Z_LVAL_P(pattern_offset) = Z_LVAL(offsetcopy);
! 1980: Z_TYPE_P(pattern_offset) = IS_LONG;
! 1981:
! 1982: zval_dtor(&offsetcopy);
! 1983: }
! 1984: }
! 1985: zval_dtor(&tmpcopy);
! 1986: }
! 1987:
! 1988: if ((pattern_match != NULL) && (pattern_offset != NULL)) {
! 1989: ms->search.s += (int)Z_LVAL_P(pattern_offset); /* this is where the match starts */
! 1990: ms->search.offset += (size_t)Z_LVAL_P(pattern_offset); /* this is where the match starts as size_t */
! 1991: ms->search.rm_len = Z_STRLEN_P(pattern_match) /* This is the length of the matched pattern */;
! 1992: v = 0;
! 1993:
! 1994: efree(pattern_match);
! 1995: efree(pattern_offset);
! 1996:
! 1997: } else {
! 1998: zval_ptr_dtor(&subpats);
! 1999: FREE_ZVAL(retval);
! 2000: zval_dtor(pattern);
! 2001: FREE_ZVAL(pattern);
! 2002: return -1;
! 2003: }
! 2004: }
! 2005:
! 2006:
! 2007: } else {
! 2008: v = 1;
! 2009: }
! 2010: zval_ptr_dtor(&subpats);
! 2011: FREE_ZVAL(retval);
! 2012: }
! 2013: zval_dtor(pattern);
! 2014: FREE_ZVAL(pattern);
! 2015: break;
! 2016: }
! 2017: case FILE_INDIRECT:
! 2018: return 1;
! 2019: default:
! 2020: file_magerror(ms, "invalid type %d in magiccheck()", m->type);
! 2021: return -1;
! 2022: }
! 2023:
! 2024: v = file_signextend(ms, m, v);
! 2025:
! 2026: switch (m->reln) {
! 2027: case 'x':
! 2028: if ((ms->flags & MAGIC_DEBUG) != 0)
! 2029: (void) fprintf(stderr, "%llu == *any* = 1\n",
! 2030: (uint64_t)v);
! 2031: matched = 1;
! 2032: break;
! 2033:
! 2034: case '!':
! 2035: matched = v != l;
! 2036: if ((ms->flags & MAGIC_DEBUG) != 0)
! 2037: (void) fprintf(stderr, "%llu != %llu = %d\n",
! 2038: (uint64_t)v, (uint64_t)l,
! 2039: matched);
! 2040: break;
! 2041:
! 2042: case '=':
! 2043: matched = v == l;
! 2044: if ((ms->flags & MAGIC_DEBUG) != 0)
! 2045: (void) fprintf(stderr, "%llu == %llu = %d\n",
! 2046: (uint64_t)v, (uint64_t)l,
! 2047: matched);
! 2048: break;
! 2049:
! 2050: case '>':
! 2051: if (m->flag & UNSIGNED) {
! 2052: matched = v > l;
! 2053: if ((ms->flags & MAGIC_DEBUG) != 0)
! 2054: (void) fprintf(stderr, "%llu > %llu = %d\n",
! 2055: (uint64_t)v,
! 2056: (uint64_t)l, matched);
! 2057: }
! 2058: else {
! 2059: matched = (int64_t) v > (int64_t) l;
! 2060: if ((ms->flags & MAGIC_DEBUG) != 0)
! 2061: (void) fprintf(stderr, "%lld > %lld = %d\n",
! 2062: (uint64_t)v, (uint64_t)l, matched);
! 2063: }
! 2064: break;
! 2065:
! 2066: case '<':
! 2067: if (m->flag & UNSIGNED) {
! 2068: matched = v < l;
! 2069: if ((ms->flags & MAGIC_DEBUG) != 0)
! 2070: (void) fprintf(stderr, "%llu < %llu = %d\n",
! 2071: (uint64_t)v,
! 2072: (uint64_t)l, matched);
! 2073: }
! 2074: else {
! 2075: matched = (int64_t) v < (int64_t) l;
! 2076: if ((ms->flags & MAGIC_DEBUG) != 0)
! 2077: (void) fprintf(stderr, "%lld < %lld = %d\n",
! 2078: (int64_t)v, (int64_t)l, matched);
! 2079: }
! 2080: break;
! 2081:
! 2082: case '&':
! 2083: matched = (v & l) == l;
! 2084: if ((ms->flags & MAGIC_DEBUG) != 0)
! 2085: (void) fprintf(stderr, "((%llx & %llx) == %llx) = %d\n",
! 2086: (uint64_t)v, (uint64_t)l,
! 2087: (uint64_t)l, matched);
! 2088: break;
! 2089:
! 2090: case '^':
! 2091: matched = (v & l) != l;
! 2092: if ((ms->flags & MAGIC_DEBUG) != 0)
! 2093: (void) fprintf(stderr, "((%llx & %llx) != %llx) = %d\n",
! 2094: (uint64_t)v, (uint64_t)l,
! 2095: (uint64_t)l, matched);
! 2096: break;
! 2097:
! 2098: default:
! 2099: matched = 0;
! 2100: file_magerror(ms, "cannot happen: invalid relation `%c'",
! 2101: m->reln);
! 2102: return -1;
! 2103: }
! 2104:
! 2105: return matched;
! 2106: }
! 2107:
! 2108: private int
! 2109: handle_annotation(struct magic_set *ms, struct magic *m)
! 2110: {
! 2111: if (ms->flags & MAGIC_APPLE) {
! 2112: if (file_printf(ms, "%.8s", m->apple) == -1)
! 2113: return -1;
! 2114: return 1;
! 2115: }
! 2116: if ((ms->flags & MAGIC_MIME_TYPE) && m->mimetype[0]) {
! 2117: if (file_printf(ms, "%s", m->mimetype) == -1)
! 2118: return -1;
! 2119: return 1;
! 2120: }
! 2121: return 0;
! 2122: }
! 2123:
! 2124: private int
! 2125: print_sep(struct magic_set *ms, int firstline)
! 2126: {
! 2127: if (ms->flags & MAGIC_MIME)
! 2128: return 0;
! 2129: if (firstline)
! 2130: return 0;
! 2131: /*
! 2132: * we found another match
! 2133: * put a newline and '-' to do some simple formatting
! 2134: */
! 2135: return file_printf(ms, "\n- ");
! 2136: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>