Annotation of embedaddon/php/ext/fileinfo/libmagic/softmagic.c, revision 1.1.1.2

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>