Rizin
unix-like reverse engineering framework and cli tools
softmagic.c
Go to the documentation of this file.
1 /* $OpenBSD: softmagic.c,v 1.16 2010/01/17 20:36:21 chl Exp $ */
2 /*
3  * Copyright (c) Ian F. Darwin 1986-1995.
4  * Software written by Ian F. Darwin and others;
5  * maintained 1995-present by Christos Zoulas and others.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  * notice immediately at the beginning of the file, without modification,
12  * this list of conditions, and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in the
15  * documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
21  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 /*
30  * softmagic - interpret variable magic from MAGIC
31  */
32 #include <rz_userconf.h>
33 
34 #if !USE_LIB_MAGIC
35 
36 #include "file.h"
37 #include "rz_regex.h"
38 #include <string.h>
39 #include <ctype.h>
40 #include <stdlib.h>
41 #include "rz_util/rz_time.h"
42 
43 static int match(RzMagic *, struct rz_magic *, ut32,
44  const ut8 *, size_t, int);
45 static int mget(RzMagic *, const ut8 *,
46  struct rz_magic *, size_t, unsigned int);
47 static int magiccheck(RzMagic *, struct rz_magic *);
48 static st32 mprint(RzMagic *, struct rz_magic *);
49 static void mdebug(ut32, const char *, size_t);
50 static int mcopy(RzMagic *, union VALUETYPE *, int, int,
51  const ut8 *, ut32, size_t, size_t);
52 static int mconvert(RzMagic *, struct rz_magic *);
53 static int print_sep(RzMagic *, int);
54 static void cvt_8(union VALUETYPE *, const struct rz_magic *);
55 static void cvt_16(union VALUETYPE *, const struct rz_magic *);
56 static void cvt_32(union VALUETYPE *, const struct rz_magic *);
57 static void cvt_64(union VALUETYPE *, const struct rz_magic *);
58 
59 /*
60  * Macro to give description string according to whether we want plain
61  * text or MIME type
62  */
63 #define RZ_MAGIC_DESC ((ms->flags & RZ_MAGIC_MIME) ? m->mimetype : m->desc)
64 
65 /*
66  * softmagic - lookup one file in parsed, in-memory copy of database
67  * Passed the name and FILE * of one file to be typed.
68  */
69 /*ARGSUSED1*/ /* nbytes passed for regularity, maybe need later */
70 int file_softmagic(RzMagic *ms, const ut8 *buf, size_t nbytes, int mode) {
71  struct mlist *ml;
72  int rv;
73  for (ml = ms->mlist->next; ml != ms->mlist; ml = ml->next) {
74  if ((rv = match(ms, ml->magic, ml->nmagic, buf, nbytes, mode)) != 0) {
75  return rv;
76  }
77  }
78  return 0;
79 }
80 
81 /*
82  * Go through the whole list, stopping if you find a match. Process all
83  * the continuations of that match before returning.
84  *
85  * We support multi-level continuations:
86  *
87  * At any time when processing a successful top-level match, there is a
88  * current continuation level; it represents the level of the last
89  * successfully matched continuation.
90  *
91  * Continuations above that level are skipped as, if we see one, it
92  * means that the continuation that controls them - i.e, the
93  * lower-level continuation preceding them - failed to match.
94  *
95  * Continuations below that level are processed as, if we see one,
96  * it means we've finished processing or skipping higher-level
97  * continuations under the control of a successful or unsuccessful
98  * lower-level continuation, and are now seeing the next lower-level
99  * continuation and should process it. The current continuation
100  * level reverts to the level of the one we're seeing.
101  *
102  * Continuations at the current level are processed as, if we see
103  * one, there's no lower-level continuation that may have failed.
104  *
105  * If a continuation matches, we bump the current continuation level
106  * so that higher-level continuations are processed.
107  */
108 static int match(RzMagic *ms, struct rz_magic *magic, ut32 nmagic, const ut8 *s, size_t nbytes, int mode) {
109  ut32 magindex = 0;
110  unsigned int cont_level = 0;
111  int need_separator = 0;
112  int returnval = 0; /* if a match is found it is set to 1*/
113  int firstline = 1; /* a flag to print X\n X\n- X */
114  int printed_something = 0;
115 
116  if (file_check_mem(ms, cont_level) == -1) {
117  return -1;
118  }
119  for (magindex = 0; magindex < nmagic; magindex++) {
120  int flush;
121  struct rz_magic *m = &magic[magindex];
122 
123  if ((m->flag & BINTEST) != mode) {
124  /* Skip sub-tests */
125  while (magic[magindex + 1].cont_level != 0 && ++magindex < nmagic - 1) {
126  continue;
127  }
128  continue; /* Skip to next top-level test*/
129  }
130 
131  ms->offset = m->offset;
132  ms->line = m->lineno;
133 
134  /* if main entry matches, print it... */
135  flush = !mget(ms, s, m, nbytes, cont_level);
136  if (flush) {
137  if (m->reln == '!') {
138  flush = 0;
139  }
140  } else {
141  int ret = magiccheck(ms, m);
142  if (ret == -1) {
143  return -1;
144  }
145  if (!ret) {
146  flush++;
147  }
148  }
149  if (flush) {
150  /*
151  * main entry didn't match,
152  * flush its continuations
153  */
154  while (magindex < nmagic - 1 && magic[magindex + 1].cont_level) {
155  magindex++;
156  }
157  continue;
158  }
159 
160  /*
161  * If we are going to print something, we'll need to print
162  * a blank before we print something else.
163  */
164  if (*RZ_MAGIC_DESC) {
165  need_separator = 1;
166  printed_something = 1;
167  if (print_sep(ms, firstline) == -1) {
168  return -1;
169  }
170  }
171 
172  if ((ms->c.li[cont_level].off = mprint(ms, m)) == -1) {
173  return -1;
174  }
175 
176  /* and any continuations that match */
177  if (file_check_mem(ms, ++cont_level) == -1) {
178  return -1;
179  }
180 
181  while (++magindex < nmagic - 1 && magic[magindex].cont_level != 0) {
182  m = &magic[magindex];
183  ms->line = m->lineno; /* for messages */
184 
185  if (cont_level < m->cont_level) {
186  continue;
187  }
188  if (cont_level > m->cont_level) {
189  /*
190  * We're at the end of the level
191  * "cont_level" continuations.
192  */
193  cont_level = m->cont_level;
194  }
195  ms->offset = m->offset;
196  if (m->flag & OFFADD) {
197  ms->offset += ms->c.li[cont_level - 1].off;
198  }
199 
200  if (m->cond == COND_ELSE || m->cond == COND_ELIF) {
201  if (ms->c.li[cont_level].last_match == 1) {
202  continue;
203  }
204  }
205  flush = !mget(ms, s, m, nbytes, cont_level);
206  if (flush && m->reln != '!') {
207  continue;
208  }
209 
210  switch (flush ? 1 : magiccheck(ms, m)) {
211  case -1:
212  return -1;
213  case 0:
214  ms->c.li[cont_level].last_match = 0;
215  break;
216  default:
217  ms->c.li[cont_level].last_match = 1;
218  if (m->type != FILE_DEFAULT) {
219  ms->c.li[cont_level].got_match = 1;
220  } else if (ms->c.li[cont_level].got_match) {
221  ms->c.li[cont_level].got_match = 0;
222  break;
223  }
224  /*
225  * If we are going to print something,
226  * make sure that we have a separator first.
227  */
228  if (*RZ_MAGIC_DESC) {
229  printed_something = 1;
230  if (print_sep(ms, firstline) == -1) {
231  return -1;
232  }
233  }
234  /*
235  * This continuation matched. Print
236  * its message, with a blank before it
237  * if the previous item printed and
238  * this item isn't empty.
239  */
240  /* space if previous printed */
241  if (need_separator && ((m->flag & NOSPACE) == 0) && *RZ_MAGIC_DESC) {
242  if (file_printf(ms, " ") == -1) {
243  return -1;
244  }
245  need_separator = 0;
246  }
247  if ((ms->c.li[cont_level].off = mprint(ms, m)) == -1) {
248  return -1;
249  }
250  if (*RZ_MAGIC_DESC) {
251  need_separator = 1;
252  }
253 
254  /*
255  * If we see any continuations
256  * at a higher level,
257  * process them.
258  */
259  if (file_check_mem(ms, ++cont_level) == -1) {
260  return -1;
261  }
262  break;
263  }
264  }
265  if (printed_something) {
266  firstline = 0;
267  returnval = 1;
268  }
269  if ((ms->flags & RZ_MAGIC_CONTINUE) == 0 && printed_something) {
270  return 1; /* don't keep searching */
271  }
272  }
273  return returnval; /* This is hit if -k is set or there is no match */
274 }
275 
276 static int check_fmt(RzMagic *ms, struct rz_magic *m) {
277  RzRegex rx;
278  int rc;
279 
280  if (!strchr(RZ_MAGIC_DESC, '%')) {
281  return 0;
282  }
283 
284  rc = rz_regex_comp(&rx, "%[-0-9\\.]*s", RZ_REGEX_EXTENDED | RZ_REGEX_NOSUB);
285  if (rc) {
286  char errmsg[512];
287  rz_regex_error(rc, &rx, errmsg, sizeof(errmsg) - 1);
288  file_magerror(ms, "regex error %d, (%s)", rc, errmsg);
289  return -1;
290  } else {
291  rc = rz_regex_exec(&rx, RZ_MAGIC_DESC, 0, 0, 0);
292  rz_regex_fini(&rx);
293  return !rc;
294  }
295 }
296 
297 char *strdupn(const char *str, size_t n) {
298  size_t len;
299  char *copy;
300 
301  for (len = 0; len < n && str[len]; len++) {
302  }
303  if (!(copy = malloc(len + 1))) {
304  return NULL;
305  }
306  (void)memcpy(copy, str, len);
307  copy[len] = '\0';
308  return copy;
309 }
310 
311 static st32 mprint(RzMagic *ms, struct rz_magic *m) {
312  ut64 v;
313  float vf;
314  double vd;
315  ut64 t = 0;
316  char *buf = NULL;
317  union VALUETYPE *p = &ms->ms_value;
318  char pp[ASCTIME_BUF_MINLEN];
319 
320  switch (m->type) {
321  case FILE_BYTE:
322  v = file_signextend(ms, m, (ut64)p->b);
323  switch (check_fmt(ms, m)) {
324  case -1:
325  return -1;
326  case 1:
327  buf = malloc(2);
328  if (snprintf(buf, 2, "%c", (ut8)v) < 0) {
329  free(buf);
330  return -1;
331  }
332  if (file_printf(ms, RZ_MAGIC_DESC, buf) == -1) {
333  free(buf);
334  return -1;
335  }
336  break;
337  default:
338  if (file_printf(ms, RZ_MAGIC_DESC, (ut8)v) == -1) {
339  return -1;
340  }
341  break;
342  }
343  t = ms->offset + sizeof(char);
344  break;
345  case FILE_SHORT:
346  case FILE_BESHORT:
347  case FILE_LESHORT:
348  v = file_signextend(ms, m, (ut64)p->h);
349  switch (check_fmt(ms, m)) {
350  case -1:
351  return -1;
352  case 1:
353  buf = malloc(32);
354  if (snprintf(buf, 32, "%hu", (unsigned short)v) < 0) {
355  free(buf);
356  return -1;
357  }
358  if (file_printf(ms, RZ_MAGIC_DESC, buf) == -1) {
359  free(buf);
360  return -1;
361  }
362  break;
363  default:
364  if (file_printf(ms, RZ_MAGIC_DESC, (unsigned short)v) == -1) {
365  return -1;
366  }
367  break;
368  }
369  t = ms->offset + sizeof(short);
370  break;
371  case FILE_LONG:
372  case FILE_BELONG:
373  case FILE_LELONG:
374  case FILE_MELONG:
375  v = file_signextend(ms, m, (ut64)p->l);
376  switch (check_fmt(ms, m)) {
377  case -1:
378  return -1;
379  case 1:
380  buf = malloc(32);
381  if (snprintf(buf, 32, "%u", (ut32)v) < 0) {
382  free(buf);
383  return -1;
384  }
385  if (file_printf(ms, RZ_MAGIC_DESC, buf) == -1) {
386  free(buf);
387  return -1;
388  }
389  break;
390  default:
391  if (file_printf(ms, RZ_MAGIC_DESC, (ut32)v) == -1) {
392  return -1;
393  }
394  break;
395  }
396  t = ms->offset + sizeof(st32);
397  break;
398  case FILE_QUAD:
399  case FILE_BEQUAD:
400  case FILE_LEQUAD:
401  v = file_signextend(ms, m, p->q);
402  if (file_printf(ms, RZ_MAGIC_DESC, (ut64)v) == -1) {
403  return -1;
404  }
405  t = ms->offset + sizeof(ut64);
406  break;
407 
408  case FILE_STRING:
409  case FILE_PSTRING:
410  case FILE_BESTRING16:
411  case FILE_LESTRING16:
412  if (m->reln == '=' || m->reln == '!') {
413  if (file_printf(ms, RZ_MAGIC_DESC, m->value.s) == -1) {
414  return -1;
415  }
416  t = ms->offset + m->vallen;
417  } else {
418  if (*m->value.s == '\0') {
419  p->s[strcspn(p->s, "\n")] = '\0';
420  }
421  if (file_printf(ms, RZ_MAGIC_DESC, p->s) == -1) {
422  return -1;
423  }
424  t = ms->offset + strlen(p->s);
425  if (m->type == FILE_PSTRING) {
426  t++;
427  }
428  }
429  break;
430  case FILE_DATE:
431  case FILE_BEDATE:
432  case FILE_LEDATE:
433  case FILE_MEDATE:
434  if (file_printf(ms, RZ_MAGIC_DESC, file_fmttime(p->l, 1, pp)) == -1) {
435  return -1;
436  }
437  t = ms->offset + sizeof(time_t);
438  break;
439  case FILE_LDATE:
440  case FILE_BELDATE:
441  case FILE_LELDATE:
442  case FILE_MELDATE:
443  if (file_printf(ms, RZ_MAGIC_DESC, file_fmttime(p->l, 0, pp)) == -1) {
444  return -1;
445  }
446  t = ms->offset + sizeof(time_t);
447  break;
448  case FILE_QDATE:
449  case FILE_BEQDATE:
450  case FILE_LEQDATE:
451  if (file_printf(ms, RZ_MAGIC_DESC, file_fmttime((ut32)p->q, 1, pp)) == -1) {
452  return -1;
453  }
454  t = ms->offset + sizeof(ut64);
455  break;
456  case FILE_QLDATE:
457  case FILE_BEQLDATE:
458  case FILE_LEQLDATE:
459  if (file_printf(ms, RZ_MAGIC_DESC, file_fmttime((ut32)p->q, 0, pp)) == -1) {
460  return -1;
461  }
462  t = ms->offset + sizeof(ut64);
463  break;
464  case FILE_FLOAT:
465  case FILE_BEFLOAT:
466  case FILE_LEFLOAT:
467  vf = p->f;
468  switch (check_fmt(ms, m)) {
469  case -1:
470  return -1;
471  case 1:
472  buf = malloc(32);
473  if (snprintf(buf, 32, "%g", vf) < 0) {
474  free(buf);
475  return -1;
476  }
477  if (file_printf(ms, RZ_MAGIC_DESC, buf) == -1) {
478  free(buf);
479  return -1;
480  }
481  break;
482  default:
483  if (file_printf(ms, RZ_MAGIC_DESC, vf) == -1) {
484  return -1;
485  }
486  break;
487  }
488  t = ms->offset + sizeof(float);
489  break;
490  case FILE_DOUBLE:
491  case FILE_BEDOUBLE:
492  case FILE_LEDOUBLE:
493  vd = p->d;
494  switch (check_fmt(ms, m)) {
495  case -1:
496  return -1;
497  case 1:
498  buf = malloc(32);
499  if (snprintf(buf, 32, "%g", vd) < 0) {
500  free(buf);
501  return -1;
502  }
503  if (file_printf(ms, RZ_MAGIC_DESC, buf) == -1) {
504  free(buf);
505  return -1;
506  }
507  break;
508  default:
509  if (file_printf(ms, RZ_MAGIC_DESC, vd) == -1) {
510  return -1;
511  }
512  break;
513  }
514  t = ms->offset + sizeof(double);
515  break;
516  case FILE_REGEX: {
517  char *cp;
518  int rval;
519 
520  cp = strdupn((const char *)ms->search.s, ms->search.rm_len);
521  if (!cp) {
522  file_oomem(ms, ms->search.rm_len);
523  return -1;
524  }
525  rval = file_printf(ms, RZ_MAGIC_DESC, cp);
526  free(cp);
527 
528  if (rval == -1) {
529  return -1;
530  }
531 
532  if ((m->str_flags & REGEX_OFFSET_START)) {
533  t = ms->search.offset;
534  } else {
535  t = ms->search.offset + ms->search.rm_len;
536  }
537  break;
538  }
539 
540  case FILE_SEARCH:
541  if (file_printf(ms, RZ_MAGIC_DESC, m->value.s) == -1) {
542  return -1;
543  }
544  if ((m->str_flags & REGEX_OFFSET_START)) {
545  t = ms->search.offset;
546  } else {
547  t = ms->search.offset + m->vallen;
548  }
549  break;
550  case FILE_DEFAULT:
551  if (file_printf(ms, RZ_MAGIC_DESC, m->value.s) == -1) {
552  return -1;
553  }
554  t = ms->offset;
555  break;
556  default:
557  file_magerror(ms, "invalid m->type (%d) in mprint()", m->type);
558  return -1;
559  }
560  free(buf);
561  return t;
562 }
563 
564 #define DO_CVT(fld, cast) \
565  if (m->num_mask) \
566  switch (m->mask_op & FILE_OPS_MASK) { \
567  case FILE_OPAND: \
568  p->fld &= cast m->num_mask; \
569  break; \
570  case FILE_OPOR: \
571  p->fld |= cast m->num_mask; \
572  break; \
573  case FILE_OPXOR: \
574  p->fld ^= cast m->num_mask; \
575  break; \
576  case FILE_OPADD: \
577  p->fld += cast m->num_mask; \
578  break; \
579  case FILE_OPMINUS: \
580  p->fld -= cast m->num_mask; \
581  break; \
582  case FILE_OPMULTIPLY: \
583  p->fld *= cast m->num_mask; \
584  break; \
585  case FILE_OPDIVIDE: \
586  p->fld /= cast m->num_mask; \
587  break; \
588  case FILE_OPMODULO: \
589  p->fld %= cast m->num_mask; \
590  break; \
591  } \
592  if (m->mask_op & FILE_OPINVERSE) \
593  p->fld = ~p->fld
594 
595 static void cvt_8(union VALUETYPE *p, const struct rz_magic *m) {
596  DO_CVT(b, (ut8));
597 }
598 
599 static void cvt_16(union VALUETYPE *p, const struct rz_magic *m) {
600  DO_CVT(h, (ut16));
601 }
602 
603 static void cvt_32(union VALUETYPE *p, const struct rz_magic *m) {
604  DO_CVT(l, (ut32));
605 }
606 
607 static void cvt_64(union VALUETYPE *p, const struct rz_magic *m) {
608  DO_CVT(q, (ut64));
609 }
610 
611 #define DO_CVT2(fld, cast) \
612  if (m->num_mask) \
613  switch (m->mask_op & FILE_OPS_MASK) { \
614  case FILE_OPADD: \
615  p->fld += cast m->num_mask; \
616  break; \
617  case FILE_OPMINUS: \
618  p->fld -= cast m->num_mask; \
619  break; \
620  case FILE_OPMULTIPLY: \
621  p->fld *= cast m->num_mask; \
622  break; \
623  case FILE_OPDIVIDE: \
624  p->fld /= cast m->num_mask; \
625  break; \
626  }
627 
628 static void cvt_float(union VALUETYPE *p, const struct rz_magic *m) {
629  DO_CVT2(f, (float));
630 }
631 
632 static void cvt_double(union VALUETYPE *p, const struct rz_magic *m) {
633  DO_CVT2(d, (double));
634 }
635 
636 /*
637  * Convert the byte order of the data we are looking at
638  * While we're here, let's apply the mask operation
639  * (unless you have a better idea)
640  */
641 static int mconvert(RzMagic *ms, struct rz_magic *m) {
642  union VALUETYPE *p = &ms->ms_value;
643 
644  switch (m->type) {
645  case FILE_BYTE:
646  cvt_8(p, m);
647  return 1;
648  case FILE_SHORT:
649  cvt_16(p, m);
650  return 1;
651  case FILE_LONG:
652  case FILE_DATE:
653  case FILE_LDATE:
654  cvt_32(p, m);
655  return 1;
656  case FILE_QUAD:
657  case FILE_QDATE:
658  case FILE_QLDATE:
659  cvt_64(p, m);
660  return 1;
661  case FILE_STRING:
662  case FILE_BESTRING16:
663  case FILE_LESTRING16: {
664  size_t len;
665 
666  /* Null terminate and eat *trailing* return */
667  p->s[sizeof(p->s) - 1] = '\0';
668  len = strlen(p->s);
669  if (len-- && p->s[len] == '\n') {
670  p->s[len] = '\0';
671  }
672  return 1;
673  }
674  case FILE_PSTRING: {
675  char *ptr1 = p->s, *ptr2 = ptr1 + 1;
676  size_t len = *p->s;
677  if (len >= sizeof(p->s)) {
678  len = sizeof(p->s) - 1;
679  }
680  while (len--) {
681  *ptr1++ = *ptr2++;
682  }
683  *ptr1 = '\0';
684  len = strlen(p->s);
685  if (len-- && p->s[len] == '\n') {
686  p->s[len] = '\0';
687  }
688  return 1;
689  }
690  case FILE_BESHORT:
691  p->h = (short)((p->hs[0] << 8) | (p->hs[1]));
692  cvt_16(p, m);
693  return 1;
694  case FILE_BELONG:
695  case FILE_BEDATE:
696  case FILE_BELDATE:
697  p->l = (st32)rz_read_be32(p->hl);
698  cvt_32(p, m);
699  return 1;
700  case FILE_BEQUAD:
701  case FILE_BEQDATE:
702  case FILE_BEQLDATE:
703  p->q = (ut64)(((ut64)p->hq[0] << 56) | ((ut64)p->hq[1] << 48) |
704  ((ut64)p->hq[2] << 40) | ((ut64)p->hq[3] << 32) |
705  ((ut64)p->hq[4] << 24) | ((ut64)p->hq[5] << 16) |
706  ((ut64)p->hq[6] << 8) | ((ut64)p->hq[7]));
707  cvt_64(p, m);
708  return 1;
709  case FILE_LESHORT:
710  p->h = (short)((p->hs[1] << 8) | (p->hs[0]));
711  cvt_16(p, m);
712  return 1;
713  case FILE_LELONG:
714  case FILE_LEDATE:
715  case FILE_LELDATE:
716  p->l = (st32)rz_read_le32(p->hl);
717  cvt_32(p, m);
718  return 1;
719  case FILE_LEQUAD:
720  case FILE_LEQDATE:
721  case FILE_LEQLDATE:
722  p->q = (ut64)(((ut64)p->hq[7] << 56) | ((ut64)p->hq[6] << 48) |
723  ((ut64)p->hq[5] << 40) | ((ut64)p->hq[4] << 32) |
724  ((ut64)p->hq[3] << 24) | ((ut64)p->hq[2] << 16) |
725  ((ut64)p->hq[1] << 8) | ((ut64)p->hq[0]));
726  cvt_64(p, m);
727  return 1;
728  case FILE_MELONG:
729  case FILE_MEDATE:
730  case FILE_MELDATE:
731  p->l = (st32)((p->hl[1] << 24) | (p->hl[0] << 16) | (p->hl[3] << 8) | (p->hl[2]));
732  cvt_32(p, m);
733  return 1;
734  case FILE_FLOAT:
735  cvt_float(p, m);
736  return 1;
737  case FILE_BEFLOAT:
738  p->l = ((ut32)p->hl[0] << 24) | ((ut32)p->hl[1] << 16) |
739  ((ut32)p->hl[2] << 8) | ((ut32)p->hl[3]);
740  cvt_float(p, m);
741  return 1;
742  case FILE_LEFLOAT:
743  p->l = ((ut32)p->hl[3] << 24) | ((ut32)p->hl[2] << 16) |
744  ((ut32)p->hl[1] << 8) | ((ut32)p->hl[0]);
745  cvt_float(p, m);
746  return 1;
747  case FILE_DOUBLE:
748  cvt_double(p, m);
749  return 1;
750  case FILE_BEDOUBLE:
751  p->q = ((ut64)p->hq[0] << 56) | ((ut64)p->hq[1] << 48) |
752  ((ut64)p->hq[2] << 40) | ((ut64)p->hq[3] << 32) |
753  ((ut64)p->hq[4] << 24) | ((ut64)p->hq[5] << 16) |
754  ((ut64)p->hq[6] << 8) | ((ut64)p->hq[7]);
755  cvt_double(p, m);
756  return 1;
757  case FILE_LEDOUBLE:
758  p->q = ((ut64)p->hq[7] << 56) | ((ut64)p->hq[6] << 48) |
759  ((ut64)p->hq[5] << 40) | ((ut64)p->hq[4] << 32) |
760  ((ut64)p->hq[3] << 24) | ((ut64)p->hq[2] << 16) |
761  ((ut64)p->hq[1] << 8) | ((ut64)p->hq[0]);
762  cvt_double(p, m);
763  return 1;
764  case FILE_REGEX:
765  case FILE_SEARCH:
766  case FILE_DEFAULT:
767  return 1;
768  default:
769  file_magerror(ms, "invalid type %d in mconvert()", m->type);
770  return 0;
771  }
772 }
773 
774 static void mdebug(ut32 offset, const char *str, size_t len) {
775  eprintf("mget @%d: ", offset);
776  file_showstr(stderr, str, len);
777  (void)fputc('\n', stderr);
778  (void)fputc('\n', stderr);
779 }
780 
781 static int mcopy(RzMagic *ms, union VALUETYPE *p, int type, int indir, const ut8 *s, ut32 offset, size_t nbytes, size_t linecnt) {
782  /*
783  * Note: FILE_SEARCH and FILE_REGEX do not actually copy
784  * anything, but setup pointers into the source
785  */
786  if (indir == 0) {
787  switch (type) {
788  case FILE_SEARCH:
789  ms->search.s = (const char *)s + offset;
790  ms->search.s_len = nbytes - offset;
791  ms->search.offset = offset;
792  return 0;
793  case FILE_REGEX: {
794  const char *b;
795  const char *c;
796  const char *last; /* end of search region */
797  const char *buf; /* start of search region */
798  size_t lines;
799 
800  if (!s) {
801  ms->search.s_len = 0;
802  ms->search.s = NULL;
803  return 0;
804  }
805  buf = (const char *)s + offset;
806  last = (const char *)s + nbytes;
807  /* mget() guarantees buf <= last */
808  for (lines = linecnt, b = buf;
809  lines && ((b = strchr(c = b, '\n')) || (b = strchr(c, '\r')));
810  lines--, b++) {
811  last = b;
812  if (b[0] == '\r' && b[1] == '\n') {
813  b++;
814  }
815  }
816  if (lines) {
817  last = (const char *)s + nbytes;
818  }
819 
820  ms->search.s = buf;
821  ms->search.s_len = last - buf;
822  ms->search.offset = offset;
823  ms->search.rm_len = 0;
824  return 0;
825  }
826  case FILE_BESTRING16:
827  case FILE_LESTRING16: {
828  const ut8 *src = s + offset;
829  const ut8 *esrc = s + nbytes;
830  char *dst = p->s;
831  char *edst = &p->s[sizeof(p->s) - 1];
832 
833  if (type == FILE_BESTRING16) {
834  src++;
835  }
836 
837  /* check for pointer overflow */
838  if (src < s) {
839  file_magerror(ms, "invalid offset %u in mcopy()",
840  offset);
841  return -1;
842  }
843  for (/*EMPTY*/; src < esrc; src += 2, dst++) {
844  if (dst < edst) {
845  *dst = *src;
846  } else {
847  break;
848  }
849  if (*dst == '\0') {
850  if (type == FILE_BESTRING16 ? *(src - 1) != '\0' : *(src + 1) != '\0') {
851  *dst = ' ';
852  }
853  }
854  }
855  *edst = '\0';
856  return 0;
857  }
858  case FILE_STRING: /* XXX - these two should not need */
859  case FILE_PSTRING: /* to copy anything, but do anyway. */
860  default:
861  break;
862  }
863  }
864 
865  if (offset >= nbytes) {
866  (void)memset(p, '\0', sizeof(*p));
867  return 0;
868  }
869  nbytes = (nbytes - offset < sizeof(*p)) ? nbytes - offset : sizeof(*p);
870 
871  (void)memcpy(p, s + offset, nbytes);
872 
873  /*
874  * the usefulness of padding with zeroes eludes me, it
875  * might even cause problems
876  */
877  if (nbytes < sizeof(*p)) {
878  (void)memset(((char *)(void *)p) + nbytes, '\0',
879  sizeof(*p) - nbytes);
880  }
881  return 0;
882 }
883 
884 static int mget(RzMagic *ms, const ut8 *s, struct rz_magic *m, size_t nbytes, unsigned int cont_level) {
885  ut32 offset = ms->offset;
886  ut32 count = m->str_range;
887  union VALUETYPE *p = &ms->ms_value;
888 
889  if (mcopy(ms, p, m->type, m->flag & INDIR, s, offset, nbytes, count) == -1) {
890  return -1;
891  }
892 
893  if ((ms->flags & RZ_MAGIC_DEBUG) != 0) {
894  mdebug(offset, (char *)(void *)p, sizeof(union VALUETYPE));
895  file_mdump(m);
896  }
897 
898  if (m->flag & INDIR) {
899  int off = m->in_offset;
900  if (m->in_op & FILE_OPINDIRECT) {
901  const union VALUETYPE *q =
902  ((const void *)(s + offset + off));
903  switch (m->in_type) {
904  case FILE_BYTE:
905  off = q->b;
906  break;
907  case FILE_SHORT:
908  off = q->h;
909  break;
910  case FILE_BESHORT:
911  off = (short)((q->hs[0] << 8) | (q->hs[1]));
912  break;
913  case FILE_LESHORT:
914  off = (short)((q->hs[1] << 8) | (q->hs[0]));
915  break;
916  case FILE_LONG:
917  off = q->l;
918  break;
919  case FILE_BELONG:
920  off = (st32)((q->hl[0] << 24) | (q->hl[1] << 16) | (q->hl[2] << 8) | (q->hl[3]));
921  break;
922  case FILE_LELONG:
923  off = (st32)((q->hl[3] << 24) | (q->hl[2] << 16) | (q->hl[1] << 8) | (q->hl[0]));
924  break;
925  case FILE_MELONG:
926  off = (st32)((q->hl[1] << 24) | (q->hl[0] << 16) | (q->hl[3] << 8) | (q->hl[2]));
927  break;
928  }
929  }
930  switch (m->in_type) {
931  case FILE_BYTE:
932  if (nbytes < (offset + 1)) {
933  return 0;
934  }
935  if (off) {
936  switch (m->in_op & FILE_OPS_MASK) {
937  case FILE_OPAND: offset = p->b & off; break;
938  case FILE_OPOR: offset = p->b | off; break;
939  case FILE_OPXOR: offset = p->b ^ off; break;
940  case FILE_OPADD: offset = p->b + off; break;
941  case FILE_OPMINUS: offset = p->b - off; break;
942  case FILE_OPMULTIPLY: offset = p->b * off; break;
943  case FILE_OPDIVIDE: offset = p->b / off; break;
944  case FILE_OPMODULO: offset = p->b % off; break;
945  }
946  } else {
947  offset = p->b;
948  }
949  if (m->in_op & FILE_OPINVERSE) {
950  offset = ~offset;
951  }
952  break;
953  case FILE_BESHORT:
954  if (nbytes < (offset + 2)) {
955  return 0;
956  }
957  if (off) {
958  switch (m->in_op & FILE_OPS_MASK) {
959  case FILE_OPAND: offset = (short)((p->hs[0] << 8) | (p->hs[1])) & off; break;
960  case FILE_OPOR: offset = (short)((p->hs[0] << 8) | (p->hs[1])) | off; break;
961  case FILE_OPXOR: offset = (short)((p->hs[0] << 8) | (p->hs[1])) ^ off; break;
962  case FILE_OPADD: offset = (short)((p->hs[0] << 8) | (p->hs[1])) + off; break;
963  case FILE_OPMINUS: offset = (short)((p->hs[0] << 8) | (p->hs[1])) - off; break;
964  case FILE_OPMULTIPLY: offset = (short)((p->hs[0] << 8) | (p->hs[1])) * off; break;
965  case FILE_OPDIVIDE: offset = (short)((p->hs[0] << 8) | (p->hs[1])) / off; break;
966  case FILE_OPMODULO: offset = (short)((p->hs[0] << 8) | (p->hs[1])) % off; break;
967  }
968  } else {
969  offset = (short)((p->hs[0] << 8) |
970  (p->hs[1]));
971  }
972  if (m->in_op & FILE_OPINVERSE) {
973  offset = ~offset;
974  }
975  break;
976  case FILE_LESHORT:
977  if (nbytes < (offset + 2)) {
978  return 0;
979  }
980  if (off) {
981  switch (m->in_op & FILE_OPS_MASK) {
982  case FILE_OPAND: offset = (short)((p->hs[1] << 8) | (p->hs[0])) & off; break;
983  case FILE_OPOR: offset = (short)((p->hs[1] << 8) | (p->hs[0])) | off; break;
984  case FILE_OPXOR: offset = (short)((p->hs[1] << 8) | (p->hs[0])) ^ off; break;
985  case FILE_OPADD: offset = (short)((p->hs[1] << 8) | (p->hs[0])) + off; break;
986  case FILE_OPMINUS: offset = (short)((p->hs[1] << 8) | (p->hs[0])) - off; break;
987  case FILE_OPMULTIPLY: offset = (short)((p->hs[1] << 8) | (p->hs[0])) * off; break;
988  case FILE_OPDIVIDE: offset = (short)((p->hs[1] << 8) | (p->hs[0])) / off; break;
989  case FILE_OPMODULO: offset = (short)((p->hs[1] << 8) | (p->hs[0])) % off; break;
990  }
991  } else {
992  offset = (short)((p->hs[1] << 8) | (p->hs[0]));
993  }
994  if (m->in_op & FILE_OPINVERSE) {
995  offset = ~offset;
996  }
997  break;
998  case FILE_SHORT:
999  if (nbytes < (offset + 2)) {
1000  return 0;
1001  }
1002  if (off) {
1003  switch (m->in_op & FILE_OPS_MASK) {
1004  case FILE_OPAND: offset = p->h & off; break;
1005  case FILE_OPOR: offset = p->h | off; break;
1006  case FILE_OPXOR: offset = p->h ^ off; break;
1007  case FILE_OPADD: offset = p->h + off; break;
1008  case FILE_OPMINUS: offset = p->h - off; break;
1009  case FILE_OPMULTIPLY: offset = p->h * off; break;
1010  case FILE_OPDIVIDE: offset = p->h / off; break;
1011  case FILE_OPMODULO: offset = p->h % off; break;
1012  }
1013  } else {
1014  offset = p->h;
1015  }
1016  if (m->in_op & FILE_OPINVERSE) {
1017  offset = ~offset;
1018  }
1019  break;
1020  case FILE_BELONG:
1021  if (nbytes < (offset + 4)) {
1022  return 0;
1023  }
1024  if (off) {
1025  switch (m->in_op & FILE_OPS_MASK) {
1026  case FILE_OPAND:
1027  offset = (st32)((p->hl[0] << 24) | (p->hl[1] << 16) | (p->hl[2] << 8) | (p->hl[3])) & off;
1028  break;
1029  case FILE_OPOR:
1030  offset = (st32)((p->hl[0] << 24) | (p->hl[1] << 16) | (p->hl[2] << 8) | (p->hl[3])) | off;
1031  break;
1032  case FILE_OPXOR:
1033  offset = (st32)((p->hl[0] << 24) | (p->hl[1] << 16) | (p->hl[2] << 8) | (p->hl[3])) ^ off;
1034  break;
1035  case FILE_OPADD:
1036  offset = (st32)((p->hl[0] << 24) | (p->hl[1] << 16) | (p->hl[2] << 8) | (p->hl[3])) + off;
1037  break;
1038  case FILE_OPMINUS:
1039  offset = (st32)((p->hl[0] << 24) | (p->hl[1] << 16) | (p->hl[2] << 8) | (p->hl[3])) - off;
1040  break;
1041  case FILE_OPMULTIPLY:
1042  offset = (st32)((p->hl[0] << 24) | (p->hl[1] << 16) | (p->hl[2] << 8) | (p->hl[3])) * off;
1043  break;
1044  case FILE_OPDIVIDE:
1045  offset = (st32)((p->hl[0] << 24) | (p->hl[1] << 16) | (p->hl[2] << 8) | (p->hl[3])) / off;
1046  break;
1047  case FILE_OPMODULO:
1048  offset = (st32)((p->hl[0] << 24) | (p->hl[1] << 16) | (p->hl[2] << 8) | (p->hl[3])) % off;
1049  break;
1050  }
1051  } else {
1052  offset = (st32)((p->hl[0] << 24) | (p->hl[1] << 16) | (p->hl[2] << 8) | (p->hl[3]));
1053  }
1054  if (m->in_op & FILE_OPINVERSE) {
1055  offset = ~offset;
1056  }
1057  break;
1058  case FILE_LELONG:
1059  if (nbytes < (offset + 4)) {
1060  return 0;
1061  }
1062  if (off) {
1063  switch (m->in_op & FILE_OPS_MASK) {
1064  case FILE_OPAND:
1065  offset = (st32)((p->hl[3] << 24) | (p->hl[2] << 16) | (p->hl[1] << 8) | (p->hl[0])) & off;
1066  break;
1067  case FILE_OPOR:
1068  offset = (st32)((p->hl[3] << 24) | (p->hl[2] << 16) | (p->hl[1] << 8) | (p->hl[0])) | off;
1069  break;
1070  case FILE_OPXOR:
1071  offset = (st32)((p->hl[3] << 24) | (p->hl[2] << 16) | (p->hl[1] << 8) | (p->hl[0])) ^ off;
1072  break;
1073  case FILE_OPADD:
1074  offset = (st32)((p->hl[3] << 24) | (p->hl[2] << 16) | (p->hl[1] << 8) | (p->hl[0])) + off;
1075  break;
1076  case FILE_OPMINUS:
1077  offset = (st32)((p->hl[3] << 24) | (p->hl[2] << 16) | (p->hl[1] << 8) | (p->hl[0])) - off;
1078  break;
1079  case FILE_OPMULTIPLY:
1080  offset = (st32)((p->hl[3] << 24) | (p->hl[2] << 16) | (p->hl[1] << 8) | (p->hl[0])) * off;
1081  break;
1082  case FILE_OPDIVIDE:
1083  offset = (st32)((p->hl[3] << 24) | (p->hl[2] << 16) | (p->hl[1] << 8) | (p->hl[0])) / off;
1084  break;
1085  case FILE_OPMODULO:
1086  offset = (st32)((p->hl[3] << 24) | (p->hl[2] << 16) | (p->hl[1] << 8) | (p->hl[0])) % off;
1087  break;
1088  }
1089  } else {
1090  offset = (st32)(((ut32)p->hl[3] << 24) | (p->hl[2] << 16) | (p->hl[1] << 8) | (p->hl[0]));
1091  }
1092  if (m->in_op & FILE_OPINVERSE) {
1093  offset = ~offset;
1094  }
1095  break;
1096  case FILE_MELONG:
1097  if (nbytes < (offset + 4)) {
1098  return 0;
1099  }
1100  if (off) {
1101  switch (m->in_op & FILE_OPS_MASK) {
1102  case FILE_OPAND:
1103  offset = (st32)((p->hl[1] << 24) | (p->hl[0] << 16) | (p->hl[3] << 8) | (p->hl[2])) & off;
1104  break;
1105  case FILE_OPOR:
1106  offset = (st32)((p->hl[1] << 24) | (p->hl[0] << 16) | (p->hl[3] << 8) | (p->hl[2])) | off;
1107  break;
1108  case FILE_OPXOR:
1109  offset = (st32)((p->hl[1] << 24) | (p->hl[0] << 16) | (p->hl[3] << 8) | (p->hl[2])) ^ off;
1110  break;
1111  case FILE_OPADD:
1112  offset = (st32)((p->hl[1] << 24) | (p->hl[0] << 16) | (p->hl[3] << 8) | (p->hl[2])) + off;
1113  break;
1114  case FILE_OPMINUS:
1115  offset = (st32)((p->hl[1] << 24) | (p->hl[0] << 16) | (p->hl[3] << 8) | (p->hl[2])) - off;
1116  break;
1117  case FILE_OPMULTIPLY:
1118  offset = (st32)((p->hl[1] << 24) | (p->hl[0] << 16) | (p->hl[3] << 8) | (p->hl[2])) * off;
1119  break;
1120  case FILE_OPDIVIDE:
1121  offset = (st32)((p->hl[1] << 24) | (p->hl[0] << 16) | (p->hl[3] << 8) | (p->hl[2])) / off;
1122  break;
1123  case FILE_OPMODULO:
1124  offset = (st32)((p->hl[1] << 24) | (p->hl[0] << 16) | (p->hl[3] << 8) | (p->hl[2])) % off;
1125  break;
1126  }
1127  } else {
1128  offset = (st32)((p->hl[1] << 24) | (p->hl[0] << 16) | (p->hl[3] << 8) | (p->hl[2]));
1129  }
1130  if (m->in_op & FILE_OPINVERSE) {
1131  offset = ~offset;
1132  }
1133  break;
1134  case FILE_LONG:
1135  if (nbytes < (offset + 4)) {
1136  return 0;
1137  }
1138  if (off) {
1139  switch (m->in_op & FILE_OPS_MASK) {
1140  case FILE_OPAND: offset = p->l & off; break;
1141  case FILE_OPOR: offset = p->l | off; break;
1142  case FILE_OPXOR: offset = p->l ^ off; break;
1143  case FILE_OPADD: offset = p->l + off; break;
1144  case FILE_OPMINUS: offset = p->l - off; break;
1145  case FILE_OPMULTIPLY: offset = p->l * off; break;
1146  case FILE_OPDIVIDE: offset = p->l / off; break;
1147  case FILE_OPMODULO: offset = p->l % off; break;
1148  }
1149  } else {
1150  offset = p->l;
1151  }
1152  if (m->in_op & FILE_OPINVERSE) {
1153  offset = ~offset;
1154  }
1155  break;
1156  }
1157 
1158  if (m->flag & INDIROFFADD) {
1159  offset += ms->c.li[cont_level - 1].off;
1160  }
1161  if (mcopy(ms, p, m->type, 0, s, offset, nbytes, count) == -1) {
1162  return -1;
1163  }
1164  ms->offset = offset;
1165 
1166  if ((ms->flags & RZ_MAGIC_DEBUG) != 0) {
1167  mdebug(offset, (char *)(void *)p,
1168  sizeof(union VALUETYPE));
1169  file_mdump(m);
1170  }
1171  }
1172 
1173  /* Verify we have enough data to match magic type */
1174  switch (m->type) {
1175  case FILE_BYTE:
1176  if (nbytes < (offset + 1)) { /* should alway be true */
1177  return 0;
1178  }
1179  break;
1180  case FILE_SHORT:
1181  case FILE_BESHORT:
1182  case FILE_LESHORT:
1183  if (nbytes < (offset + 2)) {
1184  return 0;
1185  }
1186  break;
1187  case FILE_LONG:
1188  case FILE_BELONG:
1189  case FILE_LELONG:
1190  case FILE_MELONG:
1191  case FILE_DATE:
1192  case FILE_BEDATE:
1193  case FILE_LEDATE:
1194  case FILE_MEDATE:
1195  case FILE_LDATE:
1196  case FILE_BELDATE:
1197  case FILE_LELDATE:
1198  case FILE_MELDATE:
1199  case FILE_FLOAT:
1200  case FILE_BEFLOAT:
1201  case FILE_LEFLOAT:
1202  if (nbytes < (offset + 4)) {
1203  return 0;
1204  }
1205  break;
1206  case FILE_DOUBLE:
1207  case FILE_BEDOUBLE:
1208  case FILE_LEDOUBLE:
1209  if (nbytes < (offset + 8)) {
1210  return 0;
1211  }
1212  break;
1213  case FILE_STRING:
1214  case FILE_PSTRING:
1215  case FILE_SEARCH:
1216  if (nbytes < (offset + m->vallen)) {
1217  return 0;
1218  }
1219  break;
1220  case FILE_REGEX:
1221  if (nbytes < offset) {
1222  return 0;
1223  }
1224  break;
1225  case FILE_DEFAULT: /* nothing to check */
1226  default:
1227  break;
1228  }
1229  return mconvert(ms, m);
1230 }
1231 
1232 static ut64 file_strncmp(const char *s1, const char *s2, size_t len, ut32 flags) {
1233  /*
1234  * Convert the source args to unsigned here so that (1) the
1235  * compare will be unsigned as it is in strncmp() and (2) so
1236  * the ctype functions will work correctly without extra
1237  * casting.
1238  */
1239  const ut8 *a = (const ut8 *)s1;
1240  const ut8 *b = (const ut8 *)s2;
1241  ut64 v;
1242 
1243  /*
1244  * What we want here is v = strncmp(s1, s2, len),
1245  * but ignoring any nulls.
1246  */
1247  v = 0;
1248  if (0L == flags) { /* normal string: do it fast */
1249  while (len-- > 0) {
1250  if ((v = *b++ - *a++) != '\0') {
1251  break;
1252  }
1253  }
1254  } else { /* combine the others */
1255  while (len-- > 0) {
1256  if ((flags & STRING_IGNORE_LOWERCASE) &&
1257  islower(*a)) {
1258  if ((v = tolower(*b++) - *a++) != '\0') {
1259  break;
1260  }
1261  } else if ((flags & STRING_IGNORE_UPPERCASE) && isupper(*a)) {
1262  if ((v = toupper(*b++) - *a++) != '\0') {
1263  break;
1264  }
1265  } else if ((flags & STRING_COMPACT_BLANK) && isspace(*a)) {
1266  a++;
1267  if (isspace(*b++)) {
1268  while (isspace(*b)) {
1269  b++;
1270  }
1271  } else {
1272  v = 1;
1273  break;
1274  }
1275  } else if ((flags & STRING_COMPACT_OPTIONAL_BLANK) && isspace(*a)) {
1276  a++;
1277  while (isspace(*b)) {
1278  b++;
1279  }
1280  } else {
1281  if ((v = *b++ - *a++) != '\0') {
1282  break;
1283  }
1284  }
1285  }
1286  }
1287  return v;
1288 }
1289 
1290 static ut64 file_strncmp16(const char *a, const char *b, size_t len, ut32 flags) {
1291  /*
1292  * XXX - The 16-bit string compare probably needs to be done
1293  * differently, especially if the flags are to be supported.
1294  * At the moment, I am unsure.
1295  */
1296  flags = 0;
1297  return file_strncmp(a, b, len, flags);
1298 }
1299 
1300 static int magiccheck(RzMagic *ms, struct rz_magic *m) {
1301  ut64 l = m->value.q;
1302  ut64 v;
1303  float fl, fv;
1304  double dl, dv;
1305  int matched;
1306  union VALUETYPE *p = &ms->ms_value;
1307 
1308  switch (m->type) {
1309  case FILE_BYTE:
1310  v = p->b;
1311  break;
1312  case FILE_SHORT:
1313  case FILE_BESHORT:
1314  case FILE_LESHORT:
1315  v = p->h;
1316  break;
1317  case FILE_LONG:
1318  case FILE_BELONG:
1319  case FILE_LELONG:
1320  case FILE_MELONG:
1321  case FILE_DATE:
1322  case FILE_BEDATE:
1323  case FILE_LEDATE:
1324  case FILE_MEDATE:
1325  case FILE_LDATE:
1326  case FILE_BELDATE:
1327  case FILE_LELDATE:
1328  case FILE_MELDATE:
1329  v = p->l;
1330  break;
1331  case FILE_QUAD:
1332  case FILE_LEQUAD:
1333  case FILE_BEQUAD:
1334  case FILE_QDATE:
1335  case FILE_BEQDATE:
1336  case FILE_LEQDATE:
1337  case FILE_QLDATE:
1338  case FILE_BEQLDATE:
1339  case FILE_LEQLDATE:
1340  v = p->q;
1341  break;
1342  case FILE_FLOAT:
1343  case FILE_BEFLOAT:
1344  case FILE_LEFLOAT:
1345  fl = m->value.f;
1346  fv = p->f;
1347  switch (m->reln) {
1348  case 'x': matched = 1; break;
1349  case '!': matched = fv != fl; break;
1350  case '=': matched = fv == fl; break;
1351  case '>': matched = fv > fl; break;
1352  case '<': matched = fv < fl; break;
1353  default:
1354  file_magerror(ms, "cannot happen with float: invalid relation `%c'", m->reln);
1355  return -1;
1356  }
1357  return matched;
1358  case FILE_DOUBLE:
1359  case FILE_BEDOUBLE:
1360  case FILE_LEDOUBLE:
1361  dl = m->value.d;
1362  dv = p->d;
1363  switch (m->reln) {
1364  case 'x': matched = 1; break;
1365  case '!': matched = dv != dl; break;
1366  case '=': matched = dv == dl; break;
1367  case '>': matched = dv > dl; break;
1368  case '<': matched = dv < dl; break;
1369  default:
1370  file_magerror(ms, "cannot happen with double: invalid relation `%c'", m->reln);
1371  return -1;
1372  }
1373  return matched;
1374  case FILE_DEFAULT:
1375  l = 0;
1376  v = 0;
1377  break;
1378  case FILE_STRING:
1379  case FILE_PSTRING:
1380  l = 0;
1381  v = file_strncmp(m->value.s, p->s, (size_t)m->vallen, m->str_flags);
1382  break;
1383  case FILE_BESTRING16:
1384  case FILE_LESTRING16:
1385  l = 0;
1386  v = file_strncmp16(m->value.s, p->s, (size_t)m->vallen, m->str_flags);
1387  break;
1388  case FILE_SEARCH: { /* search ms->search.s for the string m->value.s */
1389  size_t slen, idx;
1390 
1391  if (!ms->search.s) {
1392  return 0;
1393  }
1394 
1395  slen = RZ_MIN(m->vallen, sizeof(m->value.s));
1396  l = 0;
1397  v = 0;
1398 
1399  for (idx = 0; m->str_range == 0 || idx < m->str_range; idx++) {
1400  if ((int)ms->search.offset < 0) {
1401  break;
1402  }
1403  if (slen + idx > ms->search.s_len) {
1404  break;
1405  }
1406  v = file_strncmp(m->value.s, ms->search.s + idx, slen, m->str_flags);
1407  if (v == 0) { /* found match */
1408  ms->search.offset += idx;
1409  break;
1410  }
1411  }
1412  break;
1413  }
1414  case FILE_REGEX: {
1415  int rc;
1416  RzRegex rx;
1417  char errmsg[512];
1418 
1419  if (!ms->search.s) {
1420  return 0;
1421  }
1422 
1423  l = 0;
1424  rc = rz_regex_comp(&rx, m->value.s,
1426  ((m->str_flags & STRING_IGNORE_CASE) ? RZ_REGEX_ICASE : 0));
1427  if (rc) {
1428  (void)rz_regex_error(rc, &rx, errmsg, sizeof(errmsg) - 1);
1429  file_magerror(ms, "regex error %d, (%s)",
1430  rc, errmsg);
1431  v = (ut64)-1;
1432  } else {
1433  RzRegexMatch pmatch[1];
1434 #ifndef RZ_REGEX_STARTEND
1435 #define RZ_REGEX_STARTEND 0
1436  size_t l = ms->search.s_len - 1;
1437  char c = ms->search.s[l];
1438  ((char *)(intptr_t)ms->search.s)[l] = '\0';
1439 #else
1440  pmatch[0].rm_so = 0;
1441  pmatch[0].rm_eo = ms->search.s_len;
1442 #endif
1443  rc = rz_regex_exec(&rx, (const char *)ms->search.s, 1, pmatch, RZ_REGEX_STARTEND);
1444 #if RZ_REGEX_STARTEND == 0
1445  ((char *)(intptr_t)ms->search.s)[l] = c;
1446 #endif
1447  switch (rc) {
1448  case 0:
1449  ms->search.s += (int)pmatch[0].rm_so;
1450  ms->search.offset += (size_t)pmatch[0].rm_so;
1451  ms->search.rm_len = (size_t)(pmatch[0].rm_eo - pmatch[0].rm_so);
1452  v = 0;
1453  break;
1454  case RZ_REGEX_NOMATCH:
1455  v = 1;
1456  break;
1457  default:
1458  (void)rz_regex_error(rc, &rx, errmsg, sizeof(errmsg) - 1);
1459  file_magerror(ms, "regexec error %d, (%s)", rc, errmsg);
1460  v = UT64_MAX;
1461  break;
1462  }
1463  rz_regex_fini(&rx);
1464  }
1465  if (v == (ut64)-1) {
1466  return -1;
1467  }
1468  break;
1469  }
1470  default:
1471  file_magerror(ms, "invalid type %d in magiccheck()", m->type);
1472  return -1;
1473  }
1474 
1475  v = file_signextend(ms, m, v);
1476  switch (m->reln) {
1477  case 'x':
1478  if ((ms->flags & RZ_MAGIC_DEBUG) != 0) {
1479  (void)fprintf(stderr, "%" PFMT64u " == *any* = 1\n", (ut64)v);
1480  }
1481  matched = 1;
1482  break;
1483  case '!':
1484  matched = v != l;
1485  if ((ms->flags & RZ_MAGIC_DEBUG) != 0) {
1486  fprintf(stderr, "%" PFMT64u " != %" PFMT64u " = %d\n", (ut64)v, (ut64)l, matched);
1487  }
1488  break;
1489  case '=':
1490  matched = v == l;
1491  if ((ms->flags & RZ_MAGIC_DEBUG) != 0) {
1492  eprintf("%" PFMT64u " == %" PFMT64u " = %d\n", (ut64)v, (ut64)l, matched);
1493  }
1494  break;
1495  case '>':
1496  if (m->flag & UNSIGNED) {
1497  matched = v > l;
1498  if ((ms->flags & RZ_MAGIC_DEBUG) != 0) {
1499  eprintf("%" PFMT64u " > %" PFMT64u " = %d\n", (ut64)v, (ut64)l, matched);
1500  }
1501  } else {
1502  matched = (ut64)v > (ut64)l;
1503  if ((ms->flags & RZ_MAGIC_DEBUG) != 0) {
1504  eprintf("%" PFMT64u " > %" PFMT64u " = %d\n", (st64)v, (st64)l, matched);
1505  }
1506  }
1507  break;
1508  case '<':
1509  if (m->flag & UNSIGNED) {
1510  matched = v < l;
1511  if ((ms->flags & RZ_MAGIC_DEBUG) != 0) {
1512  eprintf("%" PFMT64u " < %" PFMT64u " = %d\n", (ut64)v, (ut64)l, matched);
1513  }
1514  } else {
1515  matched = (ut64)v < (ut64)l;
1516  if ((ms->flags & RZ_MAGIC_DEBUG) != 0) {
1517  eprintf("%" PFMT64d " < %" PFMT64d " = %d\n", (st64)v, (st64)l, matched);
1518  }
1519  }
1520  break;
1521  case '&':
1522  matched = (v & l) == l;
1523  if ((ms->flags & RZ_MAGIC_DEBUG) != 0) {
1524  eprintf("((%" PFMT64x " & %" PFMT64x ") == %" PFMT64x ") = %d\n", (ut64)v, (ut64)l, (ut64)l, matched);
1525  }
1526  break;
1527  case '^':
1528  matched = (v & l) != l;
1529  if ((ms->flags & RZ_MAGIC_DEBUG) != 0) {
1530  eprintf("((%" PFMT64x " & %" PFMT64x ") != %" PFMT64x ") = %d\n", (ut64)v, (ut64)l, (ut64)l, matched);
1531  }
1532  break;
1533  default:
1534  file_magerror(ms, "cannot happen: invalid relation `%c'", m->reln);
1535  return -1;
1536  }
1537  return matched;
1538 }
1539 
1540 static int print_sep(RzMagic *ms, int firstline) {
1541  return firstline ? 0 : file_printf(ms, "\n- ");
1542 }
1543 #endif
size_t len
Definition: 6502dis.c:15
lzma_index * src
Definition: index.h:567
void file_showstr(FILE *fp, const char *s, size_t len)
Definition: apprentice.c:1778
ut64 file_signextend(RzMagic *ms, struct rz_magic *m, ut64 v)
Definition: apprentice.c:757
static RzBinSourceLineInfo * lines(RzBinFile *bf)
Definition: bin_symbols.c:427
#define NULL
Definition: cris-opc.c:27
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void nbytes
Definition: sflib.h:113
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
uint16_t ut16
uint32_t ut32
const char * v
Definition: dsignal.c:12
void file_oomem(struct rz_magic_set *, size_t)
void file_magerror(struct rz_magic_set *, const char *,...)
void file_mdump(struct rz_magic *)
Definition: mdump.c:47
int file_printf(struct rz_magic_set *, const char *,...)
int file_check_mem(struct rz_magic_set *, unsigned int)
const char * file_fmttime(unsigned int, int, char *)
Definition: mdump.c:188
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf uLong offset
Definition: ioapi.h:144
const char int mode
Definition: ioapi.h:137
voidpf void * buf
Definition: ioapi.h:138
snprintf
Definition: kernel.h:364
uint8_t ut8
Definition: lh5801.h:11
return memset(p, 0, total)
void * p
Definition: libc.cpp:67
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
void * malloc(size_t size)
Definition: malloc.c:123
char * dst
Definition: lz4.h:724
int n
Definition: mipsasm.c:19
int type
Definition: mipsasm.c:17
int idx
Definition: setup.py:197
int off
Definition: pal.c:13
#define eprintf(x, y...)
Definition: rlcc.c:7
static RzSocket * s
Definition: rtr.c:28
static ut32 rz_read_le32(const void *src)
Definition: rz_endian.h:239
static ut32 rz_read_be32(const void *src)
Definition: rz_endian.h:87
#define UNSIGNED(n, x)
RZ_API int rz_regex_exec(const RzRegex *preg, const char *string, size_t nmatch, RzRegexMatch __pmatch[], int eflags)
Definition: regexec.c:149
#define RZ_REGEX_ICASE
Definition: rz_regex.h:24
#define RZ_REGEX_NEWLINE
Definition: rz_regex.h:26
RZ_API void rz_regex_fini(RzRegex *)
Definition: regcomp.c:226
#define RZ_REGEX_EXTENDED
Definition: rz_regex.h:23
RZ_API int rz_regex_comp(RzRegex *, const char *, int)
Definition: regcomp.c:258
#define RZ_REGEX_NOSUB
Definition: rz_regex.h:25
RZ_API size_t rz_regex_error(int, const RzRegex *, char *, size_t)
Definition: regerror.c:78
#define RZ_REGEX_NOMATCH
Definition: rz_regex.h:33
#define ASCTIME_BUF_MINLEN
Definition: rz_time.h:13
#define PFMT64d
Definition: rz_types.h:394
#define PFMT64u
Definition: rz_types.h:395
#define PFMT64x
Definition: rz_types.h:393
#define RZ_MIN(x, y)
#define st64
Definition: rz_types_base.h:10
#define UT64_MAX
Definition: rz_types_base.h:86
#define st32
Definition: rz_types_base.h:12
#define isspace(c)
Definition: safe-ctype.h:141
#define islower(c)
Definition: safe-ctype.h:135
#define tolower(c)
Definition: safe-ctype.h:149
#define isupper(c)
Definition: safe-ctype.h:143
#define toupper(c)
Definition: safe-ctype.h:147
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123
static int
Definition: sfsocketcall.h:114
int size_t
Definition: sftypes.h:40
int time_t
Definition: sftypes.h:66
#define d(i)
Definition: sha256.c:44
#define b(i)
Definition: sha256.c:42
#define f(i)
Definition: sha256.c:46
#define c(i)
Definition: sha256.c:43
#define a(i)
Definition: sha256.c:41
#define s1(x)
Definition: sha256.c:60
#define h(i)
Definition: sha256.c:48
static int mget(RzMagic *, const ut8 *, struct rz_magic *, size_t, unsigned int)
Definition: softmagic.c:884
static int match(RzMagic *, struct rz_magic *, ut32, const ut8 *, size_t, int)
Definition: softmagic.c:108
static int mcopy(RzMagic *, union VALUETYPE *, int, int, const ut8 *, ut32, size_t, size_t)
Definition: softmagic.c:781
static int check_fmt(RzMagic *ms, struct rz_magic *m)
Definition: softmagic.c:276
#define RZ_REGEX_STARTEND
char * strdupn(const char *str, size_t n)
Definition: softmagic.c:297
static void cvt_16(union VALUETYPE *, const struct rz_magic *)
Definition: softmagic.c:599
static void cvt_32(union VALUETYPE *, const struct rz_magic *)
Definition: softmagic.c:603
static st32 mprint(RzMagic *, struct rz_magic *)
Definition: softmagic.c:311
static void cvt_float(union VALUETYPE *p, const struct rz_magic *m)
Definition: softmagic.c:628
static int mconvert(RzMagic *, struct rz_magic *)
Definition: softmagic.c:641
static void cvt_64(union VALUETYPE *, const struct rz_magic *)
Definition: softmagic.c:607
#define DO_CVT2(fld, cast)
Definition: softmagic.c:611
static void mdebug(ut32, const char *, size_t)
Definition: softmagic.c:774
static int magiccheck(RzMagic *, struct rz_magic *)
Definition: softmagic.c:1300
static void cvt_double(union VALUETYPE *p, const struct rz_magic *m)
Definition: softmagic.c:632
static ut64 file_strncmp16(const char *a, const char *b, size_t len, ut32 flags)
Definition: softmagic.c:1290
static int print_sep(RzMagic *, int)
Definition: softmagic.c:1540
static ut64 file_strncmp(const char *s1, const char *s2, size_t len, ut32 flags)
Definition: softmagic.c:1232
#define RZ_MAGIC_DESC
Definition: softmagic.c:63
int file_softmagic(RzMagic *ms, const ut8 *buf, size_t nbytes, int mode)
Definition: softmagic.c:70
static void cvt_8(union VALUETYPE *, const struct rz_magic *)
Definition: softmagic.c:595
#define DO_CVT(fld, cast)
Definition: softmagic.c:564
_W64 signed int intptr_t
st64 rm_so
Definition: rz_regex.h:17
st64 rm_eo
Definition: rz_regex.h:18
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
#define L
Definition: zip_err_str.c:7