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