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