1 /*        $NetBSD: softmagic.c,v 1.26 2023/08/18 19:00:11 christos Exp $        */
2 
3 /*
4  * Copyright (c) Ian F. Darwin 1986-1995.
5  * Software written by Ian F. Darwin and others;
6  * maintained 1995-present by Christos Zoulas and others.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice immediately at the beginning of the file, without modification,
13  *    this list of conditions, and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
22  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 /*
31  * softmagic - interpret variable magic from MAGIC
32  */
33 
34 #include "file.h"
35 
36 #ifndef   lint
37 #if 0
38 FILE_RCSID("@(#)$File: softmagic.c,v 1.345 2023/07/02 12:48:39 christos Exp $")
39 #else
40 __RCSID("$NetBSD: softmagic.c,v 1.26 2023/08/18 19:00:11 christos Exp $");
41 #endif
42 #endif    /* lint */
43 
44 #include "magic.h"
45 #include <assert.h>
46 #include <math.h>
47 #include <string.h>
48 #include <ctype.h>
49 #include <stdlib.h>
50 #include <limits.h>
51 #include <time.h>
52 #include "der.h"
53 
54 file_private int match(struct magic_set *, struct magic *, file_regex_t **, size_t,
55     const struct buffer *, size_t, int, int, int, uint16_t *,
56     uint16_t *, int *, int *, int *, int *, int *);
57 file_private int mget(struct magic_set *, struct magic *, const struct buffer *,
58     const unsigned char *, size_t,
59     size_t, unsigned int, int, int, int, uint16_t *,
60     uint16_t *, int *, int *, int *, int *, int *);
61 file_private int msetoffset(struct magic_set *, struct magic *, struct buffer *,
62     const struct buffer *, size_t, unsigned int);
63 file_private int magiccheck(struct magic_set *, struct magic *, file_regex_t **);
64 file_private int mprint(struct magic_set *, struct magic *);
65 file_private int moffset(struct magic_set *, struct magic *, const struct buffer *,
66     int32_t *);
67 file_private void mdebug(uint32_t, const char *, size_t);
68 file_private int mcopy(struct magic_set *, union VALUETYPE *, int, int,
69     const unsigned char *, uint32_t, size_t, struct magic *);
70 file_private int mconvert(struct magic_set *, struct magic *, int);
71 file_private int print_sep(struct magic_set *, int);
72 file_private int handle_annotation(struct magic_set *, struct magic *, int);
73 file_private int cvt_8(union VALUETYPE *, const struct magic *);
74 file_private int cvt_16(union VALUETYPE *, const struct magic *);
75 file_private int cvt_32(union VALUETYPE *, const struct magic *);
76 file_private int cvt_64(union VALUETYPE *, const struct magic *);
77 
78 #define OFFSET_OOB(n, o, i)   ((n) < CAST(uint32_t, (o)) || (i) > ((n) - (o)))
79 #define BE64(p) ( \
80     (CAST(uint64_t, (p)->hq[0])<<56)| \
81     (CAST(uint64_t, (p)->hq[1])<<48)| \
82     (CAST(uint64_t, (p)->hq[2])<<40)| \
83     (CAST(uint64_t, (p)->hq[3])<<32)| \
84     (CAST(uint64_t, (p)->hq[4])<<24)| \
85     (CAST(uint64_t, (p)->hq[5])<<16)| \
86     (CAST(uint64_t, (p)->hq[6])<<8)| \
87     (CAST(uint64_t, (p)->hq[7])))
88 #define LE64(p) ( \
89     (CAST(uint64_t, (p)->hq[7])<<56)| \
90     (CAST(uint64_t, (p)->hq[6])<<48)| \
91     (CAST(uint64_t, (p)->hq[5])<<40)| \
92     (CAST(uint64_t, (p)->hq[4])<<32)| \
93     (CAST(uint64_t, (p)->hq[3])<<24)| \
94     (CAST(uint64_t, (p)->hq[2])<<16)| \
95     (CAST(uint64_t, (p)->hq[1])<<8)| \
96     (CAST(uint64_t, (p)->hq[0])))
97 #define LE32(p) ( \
98     (CAST(uint32_t, (p)->hl[3])<<24)| \
99     (CAST(uint32_t, (p)->hl[2])<<16)| \
100     (CAST(uint32_t, (p)->hl[1])<<8)| \
101     (CAST(uint32_t, (p)->hl[0])))
102 #define BE32(p) ( \
103     (CAST(uint32_t, (p)->hl[0])<<24)| \
104     (CAST(uint32_t, (p)->hl[1])<<16)| \
105     (CAST(uint32_t, (p)->hl[2])<<8)| \
106     (CAST(uint32_t, (p)->hl[3])))
107 #define ME32(p) ( \
108     (CAST(uint32_t, (p)->hl[1])<<24)| \
109     (CAST(uint32_t, (p)->hl[0])<<16)| \
110     (CAST(uint32_t, (p)->hl[3])<<8)| \
111     (CAST(uint32_t, (p)->hl[2])))
112 
113 #define BE16(p) ((CAST(uint16_t, (p)->hs[0])<<8)|(CAST(uint16_t, (p)->hs[1])))
114 #define LE16(p) ((CAST(uint16_t, (p)->hs[1])<<8)|(CAST(uint16_t, (p)->hs[0])))
115 #define SEXT(s,v,p) ((s) ? \
116           CAST(intmax_t, CAST(int##v##_t, p)) : \
117           CAST(intmax_t, CAST(uint##v##_t, p)))
118 
119 /*
120  * softmagic - lookup one file in parsed, in-memory copy of database
121  * Passed the name and FILE * of one file to be typed.
122  */
123 /*ARGSUSED1*/                 /* nbytes passed for regularity, maybe need later */
124 file_protected int
file_softmagic(struct magic_set * ms,const struct buffer * b,uint16_t * indir_count,uint16_t * name_count,int mode,int text)125 file_softmagic(struct magic_set *ms, const struct buffer *b,
126     uint16_t *indir_count, uint16_t *name_count, int mode, int text)
127 {
128           struct mlist *ml;
129           int rv = 0, printed_something = 0, need_separator = 0, firstline = 1;
130           uint16_t nc, ic;
131 
132           if (name_count == NULL) {
133                     nc = 0;
134                     name_count = &nc;
135           }
136           if (indir_count == NULL) {
137                     ic = 0;
138                     indir_count = &ic;
139           }
140 
141           for (ml = ms->mlist[0]->next; ml != ms->mlist[0]; ml = ml->next) {
142                     int ret = match(ms, ml->magic, ml->magic_rxcomp, ml->nmagic, b,
143                         0, mode, text, 0, indir_count, name_count,
144                         &printed_something, &need_separator, &firstline,
145                         NULL, NULL);
146                     switch (ret) {
147                     case -1:
148                               return ret;
149                     case 0:
150                               continue;
151                     default:
152                               if ((ms->flags & MAGIC_CONTINUE) == 0)
153                                         return ret;
154                               rv = ret;
155                               break;
156                     }
157           }
158 
159           return rv;
160 }
161 
162 #define FILE_FMTDEBUG
163 #ifdef FILE_FMTDEBUG
164 #define F(a, b, c) file_fmtcheck((a), (b), (c), __FILE__, __LINE__)
165 
166 file_private const char * __attribute__((__format_arg__(3)))
file_fmtcheck(struct magic_set * ms,const char * desc,const char * def,const char * file,size_t line)167 file_fmtcheck(struct magic_set *ms, const char *desc, const char *def,
168           const char *file, size_t line)
169 {
170           const char *ptr;
171 
172           if (strchr(desc, '%') == NULL)
173                     return desc;
174 
175           ptr = fmtcheck(desc, def);
176           if (ptr == def)
177                     file_magerror(ms,
178                         "%s, %" SIZE_T_FORMAT "u: format `%s' does not match"
179                         " with `%s'", file, line, desc, def);
180           return ptr;
181 }
182 #else
183 #define F(a, b, c) fmtcheck((b), (c))
184 #endif
185 
186 /*
187  * Go through the whole list, stopping if you find a match.  Process all
188  * the continuations of that match before returning.
189  *
190  * We support multi-level continuations:
191  *
192  *        At any time when processing a successful top-level match, there is a
193  *        current continuation level; it represents the level of the last
194  *        successfully matched continuation.
195  *
196  *        Continuations above that level are skipped as, if we see one, it
197  *        means that the continuation that controls them - i.e, the
198  *        lower-level continuation preceding them - failed to match.
199  *
200  *        Continuations below that level are processed as, if we see one,
201  *        it means we've finished processing or skipping higher-level
202  *        continuations under the control of a successful or unsuccessful
203  *        lower-level continuation, and are now seeing the next lower-level
204  *        continuation and should process it.  The current continuation
205  *        level reverts to the level of the one we're seeing.
206  *
207  *        Continuations at the current level are processed as, if we see
208  *        one, there's no lower-level continuation that may have failed.
209  *
210  *        If a continuation matches, we bump the current continuation level
211  *        so that higher-level continuations are processed.
212  */
213 file_private int
match(struct magic_set * ms,struct magic * magic,file_regex_t ** magic_rxcomp,size_t nmagic,const struct buffer * b,size_t offset,int mode,int text,int flip,uint16_t * indir_count,uint16_t * name_count,int * printed_something,int * need_separator,int * firstline,int * returnval,int * found_match)214 match(struct magic_set *ms, struct magic *magic, file_regex_t **magic_rxcomp,
215     size_t nmagic, const struct buffer *b, size_t offset, int mode, int text,
216     int flip, uint16_t *indir_count, uint16_t *name_count,
217     int *printed_something, int *need_separator, int *firstline,
218     int *returnval, int *found_match)
219 {
220           uint32_t magindex = 0;
221           unsigned int cont_level = 0;
222           int found_matchv = 0; /* if a match is found it is set to 1*/
223           int returnvalv = 0, e;
224           struct buffer bb;
225           int print = (ms->flags & MAGIC_NODESC) == 0;
226 
227           /*
228            * returnval can be 0 if a match is found, but there was no
229            * annotation to be printed.
230            */
231           if (returnval == NULL)
232                     returnval = &returnvalv;
233           if (found_match == NULL)
234                     found_match = &found_matchv;
235 
236           if (file_check_mem(ms, cont_level) == -1)
237                     return -1;
238 
239           for (magindex = 0; magindex < nmagic; magindex++) {
240                     int flush = 0;
241                     struct magic *m = &magic[magindex];
242                     file_regex_t **m_rxcomp = &magic_rxcomp[magindex];
243 
244                     if (m->type != FILE_NAME)
245                     if ((IS_STRING(m->type) &&
246 #define FLT (STRING_BINTEST | STRING_TEXTTEST)
247                          ((text && (m->str_flags & FLT) == STRING_BINTEST) ||
248                           (!text && (m->str_flags & FLT) == STRING_TEXTTEST))) ||
249                         (m->flag & mode) != mode) {
250 flush:
251                               /* Skip sub-tests */
252                               while (magindex < nmagic - 1 &&
253                                   magic[magindex + 1].cont_level != 0)
254                                         magindex++;
255                               cont_level = 0;
256                               continue; /* Skip to next top-level test*/
257                     }
258 
259                     if (msetoffset(ms, m, &bb, b, offset, cont_level) == -1)
260                               goto flush;
261                     ms->line = m->lineno;
262 
263                     /* if main entry matches, print it... */
264                     switch (mget(ms, m, b, CAST(const unsigned char *, bb.fbuf),
265                         bb.flen, offset, cont_level,
266                         mode, text, flip, indir_count, name_count,
267                         printed_something, need_separator, firstline, returnval,
268                         found_match))
269                     {
270                     case -1:
271                               return -1;
272                     case 0:
273                               flush = m->reln != '!';
274                               break;
275                     default:
276                               if (m->type == FILE_INDIRECT) {
277                                         *found_match = 1;
278                                         *returnval = 1;
279                               }
280 
281                               switch (magiccheck(ms, m, m_rxcomp)) {
282                               case -1:
283                                         return -1;
284                               case 0:
285                                         flush++;
286                                         break;
287                               default:
288                                         flush = 0;
289                                         break;
290                               }
291                               break;
292                     }
293                     if (flush) {
294                               /*
295                                * main entry didn't match,
296                                * flush its continuations
297                                */
298                               goto flush;
299                     }
300 
301                     if ((e = handle_annotation(ms, m, *firstline)) != 0)
302                     {
303                               *found_match = 1;
304                               *need_separator = 1;
305                               *printed_something = 1;
306                               *returnval = 1;
307                               *firstline = 0;
308                               return e;
309                     }
310 
311                     /*
312                      * If we are going to print something, we'll need to print
313                      * a blank before we print something else.
314                      */
315                     if (*m->desc) {
316                               *found_match = 1;
317                               if (print) {
318                                         *returnval = 1;
319                                         *need_separator = 1;
320                                         *printed_something = 1;
321                                         if (print_sep(ms, *firstline) == -1)
322                                                   return -1;
323                                         if (mprint(ms, m) == -1)
324                                                   return -1;
325                               }
326                     }
327 
328                     switch (moffset(ms, m, &bb, &ms->c.li[cont_level].off)) {
329                     case -1:
330                     case 0:
331                               goto flush;
332                     default:
333                               break;
334                     }
335 
336                     /* and any continuations that match */
337                     if (file_check_mem(ms, ++cont_level) == -1)
338                               return -1;
339 
340                     while (magindex + 1 < nmagic &&
341                         magic[magindex + 1].cont_level != 0) {
342                               m = &magic[++magindex];
343                               m_rxcomp = &magic_rxcomp[magindex];
344                               ms->line = m->lineno; /* for messages */
345 
346                               if (cont_level < m->cont_level)
347                                         continue;
348                               if (cont_level > m->cont_level) {
349                                         /*
350                                          * We're at the end of the level
351                                          * "cont_level" continuations.
352                                          */
353                                         cont_level = m->cont_level;
354                               }
355                               if (msetoffset(ms, m, &bb, b, offset, cont_level) == -1)
356                                         goto flush;
357                               if (m->flag & OFFADD) {
358                                         if (cont_level == 0) {
359                                                   if ((ms->flags & MAGIC_DEBUG) != 0)
360                                                             fprintf(stderr,
361                                                                 "direct *zero*"
362                                                                 " cont_level\n");
363                                                   return 0;
364                                         }
365                                         ms->offset +=
366                                             ms->c.li[cont_level - 1].off;
367                               }
368 
369 #ifdef ENABLE_CONDITIONALS
370                               if (m->cond == COND_ELSE ||
371                                   m->cond == COND_ELIF) {
372                                         if (ms->c.li[cont_level].last_match == 1)
373                                                   continue;
374                               }
375 #endif
376                               switch (mget(ms, m, b, CAST(const unsigned char *,
377                                   bb.fbuf), bb.flen, offset,
378                                   cont_level, mode, text, flip, indir_count,
379                                   name_count, printed_something, need_separator,
380                                   firstline, returnval, found_match)) {
381                               case -1:
382                                         return -1;
383                               case 0:
384                                         if (m->reln != '!')
385                                                   continue;
386                                         flush = 1;
387                                         break;
388                               default:
389                                         if (m->type == FILE_INDIRECT) {
390                                                   *found_match = 1;
391                                                   *returnval = 1;
392                                         }
393                                         flush = 0;
394                                         break;
395                               }
396 
397                               switch (flush ? 1 : magiccheck(ms, m, m_rxcomp)) {
398                               case -1:
399                                         return -1;
400                               case 0:
401 #ifdef ENABLE_CONDITIONALS
402                                         ms->c.li[cont_level].last_match = 0;
403 #endif
404                                         break;
405                               default:
406 #ifdef ENABLE_CONDITIONALS
407                                         ms->c.li[cont_level].last_match = 1;
408 #endif
409                                         if (m->type == FILE_CLEAR)
410                                                   ms->c.li[cont_level].got_match = 0;
411                                         else if (ms->c.li[cont_level].got_match) {
412                                                   if (m->type == FILE_DEFAULT)
413                                                             break;
414                                         } else
415                                                   ms->c.li[cont_level].got_match = 1;
416 
417                                         if ((e = handle_annotation(ms, m, *firstline))
418                                             != 0) {
419                                                   *found_match = 1;
420                                                   *need_separator = 1;
421                                                   *printed_something = 1;
422                                                   *returnval = 1;
423                                                   return e;
424                                         }
425                                         if (*m->desc) {
426                                                   *found_match = 1;
427                                         }
428                                         if (print && *m->desc) {
429                                                   *returnval = 1;
430                                                   /*
431                                                    * This continuation matched.  Print
432                                                    * its message, with a blank before it
433                                                    * if the previous item printed and
434                                                    * this item isn't empty.
435                                                    */
436                                                   /*
437                                                    * If we are going to print something,
438                                                    * make sure that we have a separator
439                                                    * first.
440                                                    */
441                                                   if (!*printed_something) {
442                                                             *printed_something = 1;
443                                                             if (print_sep(ms, *firstline)
444                                                                 == -1)
445                                                                       return -1;
446                                                   }
447                                                   /* space if previous printed */
448                                                   if (*need_separator
449                                                       && (m->flag & NOSPACE) == 0) {
450                                                             if (file_printf(ms, " ") == -1)
451                                                                       return -1;
452                                                   }
453                                                   if (mprint(ms, m) == -1)
454                                                             return -1;
455                                                   *need_separator = 1;
456                                         }
457 
458                                         switch (moffset(ms, m, &bb,
459                                             &ms->c.li[cont_level].off)) {
460                                         case -1:
461                                         case 0:
462                                                   cont_level--;
463                                                   break;
464                                         default:
465                                                   break;
466                                         }
467 
468                                         /*
469                                          * If we see any continuations
470                                          * at a higher level,
471                                          * process them.
472                                          */
473                                         if (file_check_mem(ms, ++cont_level) == -1)
474                                                   return -1;
475                                         break;
476                               }
477                     }
478                     if (*printed_something) {
479                               *firstline = 0;
480                     }
481                     if (*found_match) {
482                               if ((ms->flags & MAGIC_CONTINUE) == 0)
483                                         return *returnval;
484                               // So that we print a separator
485                               *printed_something = 0;
486                               *firstline = 0;
487                     }
488                     cont_level = 0;
489           }
490           return *returnval;
491 }
492 
493 file_private int
check_fmt(struct magic_set * ms,const char * fmt)494 check_fmt(struct magic_set *ms, const char *fmt)
495 {
496           file_regex_t rx;
497           int rc, rv = -1;
498         const char* pat = "%[-0-9\\.]*s";
499 
500           if (strchr(fmt, '%') == NULL)
501                     return 0;
502 
503           rc = file_regcomp(ms, &rx, pat, REG_EXTENDED|REG_NOSUB);
504           if (rc == 0) {
505                     rc = file_regexec(ms, &rx, fmt, 0, 0, 0);
506                     rv = !rc;
507           }
508           file_regfree(&rx);
509           return rv;
510 }
511 
512 #if !defined(HAVE_STRNDUP) || defined(__aiws__) || defined(_AIX)
513 # if defined(__aiws__) || defined(_AIX)
514 #  define strndup aix_strndup /* aix is broken */
515 # endif
516 char *strndup(const char *, size_t);
517 
518 char *
strndup(const char * str,size_t n)519 strndup(const char *str, size_t n)
520 {
521           size_t len;
522           char *copy;
523 
524           for (len = 0; len < n && str[len]; len++)
525                     continue;
526           if ((copy = CAST(char *, malloc(len + 1))) == NULL)
527                     return NULL;
528           (void)memcpy(copy, str, len);
529           copy[len] = '\0';
530           return copy;
531 }
532 #endif /* HAVE_STRNDUP */
533 
534 static int
varexpand(struct magic_set * ms,char * buf,size_t len,const char * str)535 varexpand(struct magic_set *ms, char *buf, size_t len, const char *str)
536 {
537           const char *ptr, *sptr, *e, *t, *ee, *et;
538           size_t l;
539 
540           for (sptr = str; (ptr = strstr(sptr, "${")) != NULL;) {
541                     l = CAST(size_t, ptr - sptr);
542                     if (l >= len)
543                               return -1;
544                     memcpy(buf, sptr, l);
545                     buf += l;
546                     len -= l;
547                     ptr += 2;
548                     if (!*ptr || ptr[1] != '?')
549                               return -1;
550                     for (et = t = ptr + 2; *et && *et != ':'; et++)
551                               continue;
552                     if (*et != ':')
553                               return -1;
554                     for (ee = e = et + 1; *ee && *ee != '}'; ee++)
555                               continue;
556                     if (*ee != '}')
557                               return -1;
558                     switch (*ptr) {
559                     case 'x':
560                               if (ms->mode & 0111) {
561                                         ptr = t;
562                                         l = et - t;
563                               } else {
564                                         ptr = e;
565                                         l = ee - e;
566                               }
567                               break;
568                     default:
569                               return -1;
570                     }
571                     if (l >= len)
572                               return -1;
573                     memcpy(buf, ptr, l);
574                     buf += l;
575                     len -= l;
576                     sptr = ee + 1;
577           }
578 
579           l = strlen(sptr);
580           if (l >= len)
581                     return -1;
582 
583           memcpy(buf, sptr, l);
584           buf[l] = '\0';
585           return 0;
586 }
587 
588 
589 file_private int
mprint(struct magic_set * ms,struct magic * m)590 mprint(struct magic_set *ms, struct magic *m)
591 {
592           uint64_t v;
593           float vf;
594           double vd;
595           char buf[128], tbuf[26], sbuf[512], ebuf[512];
596           const char *desc;
597           union VALUETYPE *p = &ms->ms_value;
598 
599           if (varexpand(ms, ebuf, sizeof(ebuf), m->desc) == -1)
600                     desc = m->desc;
601           else
602                     desc = ebuf;
603 
604 #define   PRINTER(value, format, stype, utype)    \
605           v = file_signextend(ms, m, CAST(uint64_t, value)); \
606           switch (check_fmt(ms, desc)) { \
607           case -1: \
608                     return -1; \
609           case 1: \
610                     if (m->flag & UNSIGNED) { \
611                               (void)snprintf(buf, sizeof(buf), "%" format "u", \
612                                   CAST(utype, v)); \
613                     } else { \
614                               (void)snprintf(buf, sizeof(buf), "%" format "d", \
615                                   CAST(stype, v)); \
616                     } \
617                     if (file_printf(ms, F(ms, desc, "%s"), buf) == -1) \
618                               return -1; \
619                     break; \
620           default: \
621                     if (m->flag & UNSIGNED) { \
622                            if (file_printf(ms, F(ms, desc, "%" format "u"), \
623                                  CAST(utype, v)) == -1) \
624                                  return -1; \
625                     } else { \
626                            if (file_printf(ms, F(ms, desc, "%" format "d"), \
627                                  CAST(stype, v)) == -1) \
628                                  return -1; \
629                     } \
630                     break; \
631           } \
632           break
633 
634           switch (m->type) {
635           case FILE_BYTE:
636                     PRINTER(p->b, "", int8_t, uint8_t);
637 
638           case FILE_SHORT:
639           case FILE_BESHORT:
640           case FILE_LESHORT:
641                     PRINTER(p->h, "", int16_t, uint16_t);
642 
643           case FILE_LONG:
644           case FILE_BELONG:
645           case FILE_LELONG:
646           case FILE_MELONG:
647                     PRINTER(p->l, "", int32_t, uint32_t);
648 
649           case FILE_QUAD:
650           case FILE_BEQUAD:
651           case FILE_LEQUAD:
652           case FILE_OFFSET:
653                     PRINTER(p->q, INT64_T_FORMAT, long long, unsigned long long);
654 
655           case FILE_STRING:
656           case FILE_PSTRING:
657           case FILE_BESTRING16:
658           case FILE_LESTRING16:
659                     if (m->reln == '=' || m->reln == '!') {
660                               if (file_printf(ms, F(ms, desc, "%s"),
661                                   file_printable(ms, sbuf, sizeof(sbuf), m->value.s,
662                                   sizeof(m->value.s))) == -1)
663                                         return -1;
664                     }
665                     else {
666                               char *str = p->s;
667 
668                               /* compute t before we mangle the string? */
669 
670                               if (*m->value.s == '\0')
671                                         str[strcspn(str, "\r\n")] = '\0';
672 
673                               if (m->str_flags & STRING_TRIM)
674                                         str = file_strtrim(str);
675 
676                               if (file_printf(ms, F(ms, desc, "%s"),
677                                   file_printable(ms, sbuf, sizeof(sbuf), str,
678                                         sizeof(p->s) - (str - p->s))) == -1)
679                                         return -1;
680 
681                               if (m->type == FILE_PSTRING) {
682                                         size_t l = file_pstring_length_size(ms, m);
683                                         if (l == FILE_BADSIZE)
684                                                   return -1;
685                               }
686                     }
687                     break;
688 
689           case FILE_DATE:
690           case FILE_BEDATE:
691           case FILE_LEDATE:
692           case FILE_MEDATE:
693                     if (file_printf(ms, F(ms, desc, "%s"),
694                         file_fmtdatetime(tbuf, sizeof(tbuf), p->l, 0)) == -1)
695                               return -1;
696                     break;
697 
698           case FILE_LDATE:
699           case FILE_BELDATE:
700           case FILE_LELDATE:
701           case FILE_MELDATE:
702                     if (file_printf(ms, F(ms, desc, "%s"),
703                         file_fmtdatetime(tbuf, sizeof(tbuf), p->l, FILE_T_LOCAL))
704                               == -1)
705                               return -1;
706                     break;
707 
708           case FILE_QDATE:
709           case FILE_BEQDATE:
710           case FILE_LEQDATE:
711                     if (file_printf(ms, F(ms, desc, "%s"),
712                         file_fmtdatetime(tbuf, sizeof(tbuf), p->q, 0)) == -1)
713                               return -1;
714                     break;
715 
716           case FILE_QLDATE:
717           case FILE_BEQLDATE:
718           case FILE_LEQLDATE:
719                     if (file_printf(ms, F(ms, desc, "%s"),
720                         file_fmtdatetime(tbuf, sizeof(tbuf), p->q, FILE_T_LOCAL)) == -1)
721                               return -1;
722                     break;
723 
724           case FILE_QWDATE:
725           case FILE_BEQWDATE:
726           case FILE_LEQWDATE:
727                     if (file_printf(ms, F(ms, desc, "%s"),
728                         file_fmtdatetime(tbuf, sizeof(tbuf), p->q, FILE_T_WINDOWS))
729                         == -1)
730                               return -1;
731                     break;
732 
733           case FILE_FLOAT:
734           case FILE_BEFLOAT:
735           case FILE_LEFLOAT:
736                     vf = p->f;
737                     switch (check_fmt(ms, desc)) {
738                     case -1:
739                               return -1;
740                     case 1:
741                               (void)snprintf(buf, sizeof(buf), "%g", vf);
742                               if (file_printf(ms, F(ms, desc, "%s"), buf) == -1)
743                                         return -1;
744                               break;
745                     default:
746                               if (file_printf(ms, F(ms, desc, "%g"), vf) == -1)
747                                         return -1;
748                               break;
749                     }
750                     break;
751 
752           case FILE_DOUBLE:
753           case FILE_BEDOUBLE:
754           case FILE_LEDOUBLE:
755                     vd = p->d;
756                     switch (check_fmt(ms, desc)) {
757                     case -1:
758                               return -1;
759                     case 1:
760                               (void)snprintf(buf, sizeof(buf), "%g", vd);
761                               if (file_printf(ms, F(ms, desc, "%s"), buf) == -1)
762                                         return -1;
763                               break;
764                     default:
765                               if (file_printf(ms, F(ms, desc, "%g"), vd) == -1)
766                                         return -1;
767                               break;
768                     }
769                     break;
770 
771           case FILE_SEARCH:
772           case FILE_REGEX: {
773                     char *cp, *scp;
774                     int rval;
775 
776                     cp = strndup(RCAST(const char *, ms->search.s),
777                         ms->search.rm_len);
778                     if (cp == NULL) {
779                               file_oomem(ms, ms->search.rm_len);
780                               return -1;
781                     }
782                     scp = (m->str_flags & STRING_TRIM) ? file_strtrim(cp) : cp;
783 
784                     rval = file_printf(ms, F(ms, desc, "%s"), file_printable(ms,
785                         sbuf, sizeof(sbuf), scp, ms->search.rm_len));
786                     free(cp);
787 
788                     if (rval == -1)
789                               return -1;
790                     break;
791           }
792 
793           case FILE_DEFAULT:
794           case FILE_CLEAR:
795                     if (file_printf(ms, "%s", m->desc) == -1)
796                               return -1;
797                     break;
798 
799           case FILE_INDIRECT:
800           case FILE_USE:
801           case FILE_NAME:
802                     break;
803           case FILE_DER:
804                     if (file_printf(ms, F(ms, desc, "%s"),
805                         file_printable(ms, sbuf, sizeof(sbuf), ms->ms_value.s,
806                               sizeof(ms->ms_value.s))) == -1)
807                               return -1;
808                     break;
809           case FILE_GUID:
810                     (void) file_print_guid(buf, sizeof(buf), ms->ms_value.guid);
811                     if (file_printf(ms, F(ms, desc, "%s"), buf) == -1)
812                               return -1;
813                     break;
814           case FILE_MSDOSDATE:
815           case FILE_BEMSDOSDATE:
816           case FILE_LEMSDOSDATE:
817                     if (file_printf(ms, F(ms, desc, "%s"),
818                         file_fmtdate(tbuf, sizeof(tbuf), p->h)) == -1)
819                               return -1;
820                     break;
821           case FILE_MSDOSTIME:
822           case FILE_BEMSDOSTIME:
823           case FILE_LEMSDOSTIME:
824                     if (file_printf(ms, F(ms, desc, "%s"),
825                         file_fmttime(tbuf, sizeof(tbuf), p->h)) == -1)
826                               return -1;
827                     break;
828           case FILE_OCTAL:
829                     file_fmtnum(buf, sizeof(buf), m->value.s, 8);
830                     if (file_printf(ms, F(ms, desc, "%s"), buf) == -1)
831                               return -1;
832                     break;
833           default:
834                     file_magerror(ms, "invalid m->type (%d) in mprint()", m->type);
835                     return -1;
836           }
837           return 0;
838 }
839 
840 file_private int
moffset(struct magic_set * ms,struct magic * m,const struct buffer * b,int32_t * op)841 moffset(struct magic_set *ms, struct magic *m, const struct buffer *b,
842     int32_t *op)
843 {
844           size_t nbytes = b->flen;
845           int32_t o;
846 
847           switch (m->type) {
848           case FILE_BYTE:
849                     o = CAST(int32_t, (ms->offset + sizeof(char)));
850                     break;
851 
852           case FILE_SHORT:
853           case FILE_BESHORT:
854           case FILE_LESHORT:
855           case FILE_MSDOSDATE:
856           case FILE_LEMSDOSDATE:
857           case FILE_BEMSDOSDATE:
858           case FILE_MSDOSTIME:
859           case FILE_LEMSDOSTIME:
860           case FILE_BEMSDOSTIME:
861                     o = CAST(int32_t, (ms->offset + sizeof(short)));
862                     break;
863 
864           case FILE_LONG:
865           case FILE_BELONG:
866           case FILE_LELONG:
867           case FILE_MELONG:
868                     o = CAST(int32_t, (ms->offset + sizeof(int32_t)));
869                     break;
870 
871           case FILE_QUAD:
872           case FILE_BEQUAD:
873           case FILE_LEQUAD:
874                     o = CAST(int32_t, (ms->offset + sizeof(int64_t)));
875                     break;
876 
877           case FILE_STRING:
878           case FILE_PSTRING:
879           case FILE_BESTRING16:
880           case FILE_LESTRING16:
881           case FILE_OCTAL:
882                     if (m->reln == '=' || m->reln == '!') {
883                               o = ms->offset + m->vallen;
884                     } else {
885                               union VALUETYPE *p = &ms->ms_value;
886 
887                               if (*m->value.s == '\0')
888                                         p->s[strcspn(p->s, "\r\n")] = '\0';
889                               o = CAST(uint32_t, (ms->offset + strlen(p->s)));
890                               if (m->type == FILE_PSTRING) {
891                                         size_t l = file_pstring_length_size(ms, m);
892                                         if (l == FILE_BADSIZE)
893                                                   return -1;
894                                         o += CAST(uint32_t, l);
895                               }
896                     }
897                     break;
898 
899           case FILE_DATE:
900           case FILE_BEDATE:
901           case FILE_LEDATE:
902           case FILE_MEDATE:
903                     o = CAST(int32_t, (ms->offset + sizeof(uint32_t)));
904                     break;
905 
906           case FILE_LDATE:
907           case FILE_BELDATE:
908           case FILE_LELDATE:
909           case FILE_MELDATE:
910                     o = CAST(int32_t, (ms->offset + sizeof(uint32_t)));
911                     break;
912 
913           case FILE_QDATE:
914           case FILE_BEQDATE:
915           case FILE_LEQDATE:
916                     o = CAST(int32_t, (ms->offset + sizeof(uint64_t)));
917                     break;
918 
919           case FILE_QLDATE:
920           case FILE_BEQLDATE:
921           case FILE_LEQLDATE:
922                     o = CAST(int32_t, (ms->offset + sizeof(uint64_t)));
923                     break;
924 
925           case FILE_FLOAT:
926           case FILE_BEFLOAT:
927           case FILE_LEFLOAT:
928                     o = CAST(int32_t, (ms->offset + sizeof(float)));
929                     break;
930 
931           case FILE_DOUBLE:
932           case FILE_BEDOUBLE:
933           case FILE_LEDOUBLE:
934                     o = CAST(int32_t, (ms->offset + sizeof(double)));
935                     break;
936 
937           case FILE_REGEX:
938                     if ((m->str_flags & REGEX_OFFSET_START) != 0)
939                               o = CAST(int32_t, ms->search.offset);
940                     else
941                               o = CAST(int32_t,
942                                   (ms->search.offset + ms->search.rm_len));
943                     break;
944 
945           case FILE_SEARCH:
946                     if ((m->str_flags & REGEX_OFFSET_START) != 0)
947                               o = CAST(int32_t, ms->search.offset);
948                     else
949                               o = CAST(int32_t, (ms->search.offset + m->vallen));
950                     break;
951 
952           case FILE_CLEAR:
953           case FILE_DEFAULT:
954           case FILE_INDIRECT:
955           case FILE_OFFSET:
956           case FILE_USE:
957                     o = ms->offset;
958                     break;
959 
960           case FILE_DER:
961                     o = der_offs(ms, m, nbytes);
962                     if (o == -1 || CAST(size_t, o) > nbytes) {
963                               if ((ms->flags & MAGIC_DEBUG) != 0) {
964                                         (void)fprintf(stderr,
965                                             "Bad DER offset %d nbytes=%"
966                                             SIZE_T_FORMAT "u", o, nbytes);
967                               }
968                               *op = 0;
969                               return 0;
970                     }
971                     break;
972 
973           case FILE_GUID:
974                     o = CAST(int32_t, (ms->offset + 2 * sizeof(uint64_t)));
975                     break;
976 
977           default:
978                     o = 0;
979                     break;
980           }
981 
982           if (CAST(size_t, o) > nbytes) {
983 #if 0
984                     file_error(ms, 0, "Offset out of range %" SIZE_T_FORMAT
985                         "u > %" SIZE_T_FORMAT "u", (size_t)o, nbytes);
986 #endif
987                     return -1;
988           }
989           *op = o;
990           return 1;
991 }
992 
993 file_private uint32_t
cvt_id3(struct magic_set * ms,uint32_t v)994 cvt_id3(struct magic_set *ms, uint32_t v)
995 {
996           v = ((((v >>  0) & 0x7f) <<  0) |
997                (((v >>  8) & 0x7f) <<  7) |
998                (((v >> 16) & 0x7f) << 14) |
999                (((v >> 24) & 0x7f) << 21));
1000           if ((ms->flags & MAGIC_DEBUG) != 0)
1001                     fprintf(stderr, "id3 offs=%u\n", v);
1002           return v;
1003 }
1004 
1005 file_private int
cvt_flip(int type,int flip)1006 cvt_flip(int type, int flip)
1007 {
1008           if (flip == 0)
1009                     return type;
1010           switch (type) {
1011           case FILE_BESHORT:
1012                     return FILE_LESHORT;
1013           case FILE_BELONG:
1014                     return FILE_LELONG;
1015           case FILE_BEDATE:
1016                     return FILE_LEDATE;
1017           case FILE_BELDATE:
1018                     return FILE_LELDATE;
1019           case FILE_BEQUAD:
1020                     return FILE_LEQUAD;
1021           case FILE_BEQDATE:
1022                     return FILE_LEQDATE;
1023           case FILE_BEQLDATE:
1024                     return FILE_LEQLDATE;
1025           case FILE_BEQWDATE:
1026                     return FILE_LEQWDATE;
1027           case FILE_LESHORT:
1028                     return FILE_BESHORT;
1029           case FILE_LELONG:
1030                     return FILE_BELONG;
1031           case FILE_LEDATE:
1032                     return FILE_BEDATE;
1033           case FILE_LELDATE:
1034                     return FILE_BELDATE;
1035           case FILE_LEQUAD:
1036                     return FILE_BEQUAD;
1037           case FILE_LEQDATE:
1038                     return FILE_BEQDATE;
1039           case FILE_LEQLDATE:
1040                     return FILE_BEQLDATE;
1041           case FILE_LEQWDATE:
1042                     return FILE_BEQWDATE;
1043           case FILE_BEFLOAT:
1044                     return FILE_LEFLOAT;
1045           case FILE_LEFLOAT:
1046                     return FILE_BEFLOAT;
1047           case FILE_BEDOUBLE:
1048                     return FILE_LEDOUBLE;
1049           case FILE_LEDOUBLE:
1050                     return FILE_BEDOUBLE;
1051           default:
1052                     return type;
1053           }
1054 }
1055 #define DO_CVT(fld, type) \
1056           if (m->num_mask) \
1057                     switch (m->mask_op & FILE_OPS_MASK) { \
1058                     case FILE_OPAND: \
1059                               p->fld &= CAST(type, m->num_mask); \
1060                               break; \
1061                     case FILE_OPOR: \
1062                               p->fld |= CAST(type, m->num_mask); \
1063                               break; \
1064                     case FILE_OPXOR: \
1065                               p->fld ^= CAST(type, m->num_mask); \
1066                               break; \
1067                     case FILE_OPADD: \
1068                               p->fld += CAST(type, m->num_mask); \
1069                               break; \
1070                     case FILE_OPMINUS: \
1071                               p->fld -= CAST(type, m->num_mask); \
1072                               break; \
1073                     case FILE_OPMULTIPLY: \
1074                               p->fld *= CAST(type, m->num_mask); \
1075                               break; \
1076                     case FILE_OPDIVIDE: \
1077                               if (CAST(type, m->num_mask) == 0) \
1078                                         return -1; \
1079                               p->fld /= CAST(type, m->num_mask); \
1080                               break; \
1081                     case FILE_OPMODULO: \
1082                               if (CAST(type, m->num_mask) == 0) \
1083                                         return -1; \
1084                               p->fld %= CAST(type, m->num_mask); \
1085                               break; \
1086                     } \
1087           if (m->mask_op & FILE_OPINVERSE) \
1088                     p->fld = ~p->fld \
1089 
1090 file_private int
cvt_8(union VALUETYPE * p,const struct magic * m)1091 cvt_8(union VALUETYPE *p, const struct magic *m)
1092 {
1093           DO_CVT(b, uint8_t);
1094           return 0;
1095 }
1096 
1097 file_private int
cvt_16(union VALUETYPE * p,const struct magic * m)1098 cvt_16(union VALUETYPE *p, const struct magic *m)
1099 {
1100           DO_CVT(h, uint16_t);
1101           return 0;
1102 }
1103 
1104 file_private int
cvt_32(union VALUETYPE * p,const struct magic * m)1105 cvt_32(union VALUETYPE *p, const struct magic *m)
1106 {
1107           DO_CVT(l, uint32_t);
1108           return 0;
1109 }
1110 
1111 file_private int
cvt_64(union VALUETYPE * p,const struct magic * m)1112 cvt_64(union VALUETYPE *p, const struct magic *m)
1113 {
1114           DO_CVT(q, uint64_t);
1115           return 0;
1116 }
1117 
1118 #define DO_CVT2(fld, type) \
1119           if (m->num_mask) \
1120                     switch (m->mask_op & FILE_OPS_MASK) { \
1121                     case FILE_OPADD: \
1122                               p->fld += CAST(type, m->num_mask); \
1123                               break; \
1124                     case FILE_OPMINUS: \
1125                               p->fld -= CAST(type, m->num_mask); \
1126                               break; \
1127                     case FILE_OPMULTIPLY: \
1128                               p->fld *= CAST(type, m->num_mask); \
1129                               break; \
1130                     case FILE_OPDIVIDE: \
1131                               if (CAST(type, m->num_mask) == 0) \
1132                                         return -1; \
1133                               p->fld /= CAST(type, m->num_mask); \
1134                               break; \
1135                     } \
1136 
1137 file_private int
cvt_float(union VALUETYPE * p,const struct magic * m)1138 cvt_float(union VALUETYPE *p, const struct magic *m)
1139 {
1140           DO_CVT2(f, float);
1141           return 0;
1142 }
1143 
1144 file_private int
cvt_double(union VALUETYPE * p,const struct magic * m)1145 cvt_double(union VALUETYPE *p, const struct magic *m)
1146 {
1147           DO_CVT2(d, double);
1148           return 0;
1149 }
1150 
1151 /*
1152  * Convert the byte order of the data we are looking at
1153  * While we're here, let's apply the mask operation
1154  * (unless you have a better idea)
1155  */
1156 file_private int
mconvert(struct magic_set * ms,struct magic * m,int flip)1157 mconvert(struct magic_set *ms, struct magic *m, int flip)
1158 {
1159           union VALUETYPE *p = &ms->ms_value;
1160 
1161           switch (cvt_flip(m->type, flip)) {
1162           case FILE_BYTE:
1163                     if (cvt_8(p, m) == -1)
1164                               goto out;
1165                     return 1;
1166           case FILE_SHORT:
1167           case FILE_MSDOSDATE:
1168           case FILE_LEMSDOSDATE:
1169           case FILE_BEMSDOSDATE:
1170           case FILE_MSDOSTIME:
1171           case FILE_LEMSDOSTIME:
1172           case FILE_BEMSDOSTIME:
1173                     if (cvt_16(p, m) == -1)
1174                               goto out;
1175                     return 1;
1176           case FILE_LONG:
1177           case FILE_DATE:
1178           case FILE_LDATE:
1179                     if (cvt_32(p, m) == -1)
1180                               goto out;
1181                     return 1;
1182           case FILE_QUAD:
1183           case FILE_QDATE:
1184           case FILE_QLDATE:
1185           case FILE_QWDATE:
1186           case FILE_OFFSET:
1187                     if (cvt_64(p, m) == -1)
1188                               goto out;
1189                     return 1;
1190           case FILE_STRING:
1191           case FILE_BESTRING16:
1192           case FILE_LESTRING16:
1193           case FILE_OCTAL: {
1194                     /* Null terminate and eat *trailing* return */
1195                     p->s[sizeof(p->s) - 1] = '\0';
1196                     return 1;
1197           }
1198           case FILE_PSTRING: {
1199                     char *ptr1, *ptr2;
1200                     size_t len, sz = file_pstring_length_size(ms, m);
1201                     if (sz == FILE_BADSIZE)
1202                               return 0;
1203                     ptr1 = p->s;
1204                     ptr2 = ptr1 + sz;
1205                     len = file_pstring_get_length(ms, m, ptr1);
1206                     if (len == FILE_BADSIZE)
1207                               return 0;
1208                     sz = sizeof(p->s) - sz; /* maximum length of string */
1209                     if (len >= sz) {
1210                               /*
1211                                * The size of the pascal string length (sz)
1212                                * is 1, 2, or 4. We need at least 1 byte for NUL
1213                                * termination, but we've already truncated the
1214                                * string by p->s, so we need to deduct sz.
1215                                * Because we can use one of the bytes of the length
1216                                * after we shifted as NUL termination.
1217                                */
1218                               len = sz;
1219                     }
1220                     while (len--)
1221                               *ptr1++ = *ptr2++;
1222                     *ptr1 = '\0';
1223                     return 1;
1224           }
1225           case FILE_BESHORT:
1226                     p->h = CAST(short, BE16(p));
1227                     if (cvt_16(p, m) == -1)
1228                               goto out;
1229                     return 1;
1230           case FILE_BELONG:
1231           case FILE_BEDATE:
1232           case FILE_BELDATE:
1233                     p->l = CAST(int32_t, BE32(p));
1234                     if (cvt_32(p, m) == -1)
1235                               goto out;
1236                     return 1;
1237           case FILE_BEQUAD:
1238           case FILE_BEQDATE:
1239           case FILE_BEQLDATE:
1240           case FILE_BEQWDATE:
1241                     p->q = CAST(uint64_t, BE64(p));
1242                     if (cvt_64(p, m) == -1)
1243                               goto out;
1244                     return 1;
1245           case FILE_LESHORT:
1246                     p->h = CAST(short, LE16(p));
1247                     if (cvt_16(p, m) == -1)
1248                               goto out;
1249                     return 1;
1250           case FILE_LELONG:
1251           case FILE_LEDATE:
1252           case FILE_LELDATE:
1253                     p->l = CAST(int32_t, LE32(p));
1254                     if (cvt_32(p, m) == -1)
1255                               goto out;
1256                     return 1;
1257           case FILE_LEQUAD:
1258           case FILE_LEQDATE:
1259           case FILE_LEQLDATE:
1260           case FILE_LEQWDATE:
1261                     p->q = CAST(uint64_t, LE64(p));
1262                     if (cvt_64(p, m) == -1)
1263                               goto out;
1264                     return 1;
1265           case FILE_MELONG:
1266           case FILE_MEDATE:
1267           case FILE_MELDATE:
1268                     p->l = CAST(int32_t, ME32(p));
1269                     if (cvt_32(p, m) == -1)
1270                               goto out;
1271                     return 1;
1272           case FILE_FLOAT:
1273                     if (cvt_float(p, m) == -1)
1274                               goto out;
1275                     return 1;
1276           case FILE_BEFLOAT:
1277                     p->l = BE32(p);
1278                     if (cvt_float(p, m) == -1)
1279                               goto out;
1280                     return 1;
1281           case FILE_LEFLOAT:
1282                     p->l = LE32(p);
1283                     if (cvt_float(p, m) == -1)
1284                               goto out;
1285                     return 1;
1286           case FILE_DOUBLE:
1287                     if (cvt_double(p, m) == -1)
1288                               goto out;
1289                     return 1;
1290           case FILE_BEDOUBLE:
1291                     p->q = BE64(p);
1292                     if (cvt_double(p, m) == -1)
1293                               goto out;
1294                     return 1;
1295           case FILE_LEDOUBLE:
1296                     p->q = LE64(p);
1297                     if (cvt_double(p, m) == -1)
1298                               goto out;
1299                     return 1;
1300           case FILE_REGEX:
1301           case FILE_SEARCH:
1302           case FILE_DEFAULT:
1303           case FILE_CLEAR:
1304           case FILE_NAME:
1305           case FILE_USE:
1306           case FILE_DER:
1307           case FILE_GUID:
1308                     return 1;
1309           default:
1310                     file_magerror(ms, "invalid type %d in mconvert()", m->type);
1311                     return 0;
1312           }
1313 out:
1314           file_magerror(ms, "zerodivide in mconvert()");
1315           return 0;
1316 }
1317 
1318 
1319 file_private void
mdebug(uint32_t offset,const char * str,size_t len)1320 mdebug(uint32_t offset, const char *str, size_t len)
1321 {
1322           (void) fprintf(stderr, "mget/%" SIZE_T_FORMAT "u @%d: ", len, offset);
1323           file_showstr(stderr, str, len);
1324           (void) fputc('\n', stderr);
1325           (void) fputc('\n', stderr);
1326 }
1327 
1328 file_private int
mcopy(struct magic_set * ms,union VALUETYPE * p,int type,int indir,const unsigned char * s,uint32_t offset,size_t nbytes,struct magic * m)1329 mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
1330     const unsigned char *s, uint32_t offset, size_t nbytes, struct magic *m)
1331 {
1332           size_t size = sizeof(*p);
1333           /*
1334            * Note: FILE_SEARCH and FILE_REGEX do not actually copy
1335            * anything, but setup pointers into the source
1336            */
1337           if (indir == 0) {
1338                     switch (type) {
1339                     case FILE_DER:
1340                     case FILE_SEARCH:
1341                               if (offset > nbytes)
1342                                         offset = CAST(uint32_t, nbytes);
1343                               ms->search.s = RCAST(const char *, s) + offset;
1344                               ms->search.s_len = nbytes - offset;
1345                               ms->search.offset = offset;
1346                               return 0;
1347 
1348                     case FILE_REGEX: {
1349                               const char *b;
1350                               const char *c;
1351                               const char *last;   /* end of search region */
1352                               const char *buf;    /* start of search region */
1353                               const char *end;
1354                               size_t lines, linecnt, bytecnt;
1355 
1356                               if (s == NULL || nbytes < offset) {
1357                                         ms->search.s_len = 0;
1358                                         ms->search.s = NULL;
1359                                         return 0;
1360                               }
1361 
1362                               if (m->str_flags & REGEX_LINE_COUNT) {
1363                                         linecnt = m->str_range;
1364                                         bytecnt = linecnt * 80;
1365                               } else {
1366                                         linecnt = 0;
1367                                         bytecnt = m->str_range;
1368                               }
1369 
1370                               if (bytecnt == 0 || bytecnt > nbytes - offset)
1371                                         bytecnt = nbytes - offset;
1372                               if (bytecnt > ms->regex_max)
1373                                         bytecnt = ms->regex_max;
1374 
1375                               buf = RCAST(const char *, s) + offset;
1376                               end = last = RCAST(const char *, s) + bytecnt + offset;
1377                               /* mget() guarantees buf <= last */
1378                               for (lines = linecnt, b = buf; lines && b < end &&
1379                                    ((b = CAST(const char *,
1380                                          memchr(c = b, '\n', CAST(size_t, (end - b)))))
1381                                    || (b = CAST(const char *,
1382                                          memchr(c, '\r', CAST(size_t, (end - c))))));
1383                                    lines--, b++) {
1384                                         if (b < end - 1 && b[0] == '\r' && b[1] == '\n')
1385                                                   b++;
1386                                         if (b < end - 1 && b[0] == '\n')
1387                                                   b++;
1388                                         last = b;
1389                               }
1390                               if (lines)
1391                                         last = end;
1392 
1393                               ms->search.s = buf;
1394                               ms->search.s_len = last - buf;
1395                               ms->search.offset = offset;
1396                               ms->search.rm_len = 0;
1397                               return 0;
1398                     }
1399                     case FILE_BESTRING16:
1400                     case FILE_LESTRING16: {
1401                               const unsigned char *src = s + offset;
1402                               const unsigned char *esrc = s + nbytes;
1403                               char *dst = p->s;
1404                               char *edst = &p->s[sizeof(p->s) - 1];
1405 
1406                               if (type == FILE_BESTRING16)
1407                                         src++;
1408 
1409                               /* check that offset is within range */
1410                               if (offset >= nbytes)
1411                                         break;
1412                               for (/*EMPTY*/; src < esrc; src += 2, dst++) {
1413                                         if (dst < edst)
1414                                                   *dst = *src;
1415                                         else
1416                                                   break;
1417                                         if (*dst == '\0') {
1418                                                   if (type == FILE_BESTRING16 ?
1419                                                       *(src - 1) != '\0' :
1420                                                       ((src + 1 < esrc) &&
1421                                                       *(src + 1) != '\0'))
1422                                                             *dst = ' ';
1423                                         }
1424                               }
1425                               *edst = '\0';
1426                               return 0;
1427                     }
1428                     case FILE_STRING:   /* XXX - these two should not need */
1429                     case FILE_PSTRING:  /* to copy anything, but do anyway. */
1430                               if (m->str_range != 0 && m->str_range < sizeof(*p))
1431                                         size = m->str_range;
1432                               break;
1433                     default:
1434                               break;
1435                     }
1436           }
1437 
1438           if (type == FILE_OFFSET) {
1439                     (void)memset(p, '\0', sizeof(*p));
1440                     p->q = offset;
1441                     return 0;
1442           }
1443 
1444           if (offset >= nbytes) {
1445                     (void)memset(p, '\0', sizeof(*p));
1446                     return 0;
1447           }
1448           if (nbytes - offset < size)
1449                     nbytes = nbytes - offset;
1450           else
1451                     nbytes = size;
1452 
1453           (void)memcpy(p, s + offset, nbytes);
1454 
1455           /*
1456            * the usefulness of padding with zeroes eludes me, it
1457            * might even cause problems
1458            */
1459           if (nbytes < sizeof(*p))
1460                     (void)memset(RCAST(char *, RCAST(void *, p)) + nbytes, '\0',
1461                         sizeof(*p) - nbytes);
1462           return 0;
1463 }
1464 
1465 file_private int
do_ops(struct magic_set * ms,struct magic * m,uint32_t * rv,intmax_t lhs,intmax_t off)1466 do_ops(struct magic_set *ms, struct magic *m, uint32_t *rv, intmax_t lhs,
1467     intmax_t off)
1468 {
1469           intmax_t offset;
1470           // On purpose not INTMAX_MAX
1471           if (lhs >= UINT_MAX || lhs <= INT_MIN ||
1472               off >= UINT_MAX || off <= INT_MIN) {
1473                     if ((ms->flags & MAGIC_DEBUG) != 0)
1474                               fprintf(stderr, "lhs/off overflow %jd %jd\n", lhs, off);
1475                     return 1;
1476           }
1477 
1478           if (off) {
1479                     switch (m->in_op & FILE_OPS_MASK) {
1480                     case FILE_OPAND:
1481                               offset = lhs & off;
1482                               break;
1483                     case FILE_OPOR:
1484                               offset = lhs | off;
1485                               break;
1486                     case FILE_OPXOR:
1487                               offset = lhs ^ off;
1488                               break;
1489                     case FILE_OPADD:
1490                               offset = lhs + off;
1491                               break;
1492                     case FILE_OPMINUS:
1493                               offset = lhs - off;
1494                               break;
1495                     case FILE_OPMULTIPLY:
1496                               offset = lhs * off;
1497                               break;
1498                     case FILE_OPDIVIDE:
1499                               offset = lhs / off;
1500                               break;
1501                     case FILE_OPMODULO:
1502                               offset = lhs % off;
1503                               break;
1504                     }
1505           } else
1506                     offset = lhs;
1507           if (m->in_op & FILE_OPINVERSE)
1508                     offset = ~offset;
1509           if (offset >= UINT_MAX) {
1510                     if ((ms->flags & MAGIC_DEBUG) != 0)
1511                               fprintf(stderr, "offset overflow %jd\n", offset);
1512                     return 1;
1513           }
1514           *rv = CAST(uint32_t, offset);
1515           return 0;
1516 }
1517 
1518 file_private int
msetoffset(struct magic_set * ms,struct magic * m,struct buffer * bb,const struct buffer * b,size_t o,unsigned int cont_level)1519 msetoffset(struct magic_set *ms, struct magic *m, struct buffer *bb,
1520     const struct buffer *b, size_t o, unsigned int cont_level)
1521 {
1522           int32_t offset;
1523           if (m->flag & OFFNEGATIVE) {
1524                     offset = -m->offset;
1525                     if (cont_level > 0) {
1526                               if (m->flag & (OFFADD|INDIROFFADD))
1527                                         goto normal;
1528 #if 0
1529                               file_error(ms, 0, "negative offset %d at continuation"
1530                                   "level %u", m->offset, cont_level);
1531                               return -1;
1532 #endif
1533                     }
1534                     if (buffer_fill(b) == -1)
1535                               return -1;
1536                     if (o != 0) {
1537                               // Not yet!
1538                               file_magerror(ms, "non zero offset %" SIZE_T_FORMAT
1539                                   "u at level %u", o, cont_level);
1540                               return -1;
1541                     }
1542                     if (CAST(size_t, m->offset) > b->elen)
1543                               return -1;
1544                     buffer_init(bb, -1, NULL, b->ebuf, b->elen);
1545                     ms->eoffset = ms->offset = CAST(int32_t, b->elen - m->offset);
1546           } else {
1547                     offset = m->offset;
1548                     if (cont_level == 0) {
1549 normal:
1550                               // XXX: Pass real fd, then who frees bb?
1551                               buffer_init(bb, -1, NULL, b->fbuf, b->flen);
1552                               ms->offset = offset;
1553                               ms->eoffset = 0;
1554                     } else {
1555                               ms->offset = ms->eoffset + offset;
1556                     }
1557           }
1558           if ((ms->flags & MAGIC_DEBUG) != 0) {
1559                     fprintf(stderr, "bb=[%p,%" SIZE_T_FORMAT "u,%"
1560                         SIZE_T_FORMAT "u], %d [b=%p,%"
1561                         SIZE_T_FORMAT "u,%" SIZE_T_FORMAT "u], [o=%#x, c=%d]\n",
1562                         bb->fbuf, bb->flen, bb->elen, ms->offset, b->fbuf,
1563                         b->flen, b->elen, offset, cont_level);
1564           }
1565           return 0;
1566 }
1567 
1568 file_private int
save_cont(struct magic_set * ms,struct cont * c)1569 save_cont(struct magic_set *ms, struct cont *c)
1570 {
1571           size_t len;
1572           *c = ms->c;
1573           len = c->len * sizeof(*c->li);
1574           ms->c.li = CAST(struct level_info *, malloc(len));
1575           if (ms->c.li == NULL) {
1576                     ms->c = *c;
1577                     return -1;
1578           }
1579           memcpy(ms->c.li, c->li, len);
1580           return 0;
1581 }
1582 
1583 file_private void
restore_cont(struct magic_set * ms,struct cont * c)1584 restore_cont(struct magic_set *ms, struct cont *c)
1585 {
1586           free(ms->c.li);
1587           ms->c = *c;
1588 }
1589 
1590 file_private int
mget(struct magic_set * ms,struct magic * m,const struct buffer * b,const unsigned char * s,size_t nbytes,size_t o,unsigned int cont_level,int mode,int text,int flip,uint16_t * indir_count,uint16_t * name_count,int * printed_something,int * need_separator,int * firstline,int * returnval,int * found_match)1591 mget(struct magic_set *ms, struct magic *m, const struct buffer *b,
1592     const unsigned char *s, size_t nbytes, size_t o, unsigned int cont_level,
1593     int mode, int text, int flip, uint16_t *indir_count, uint16_t *name_count,
1594     int *printed_something, int *need_separator, int *firstline, int *returnval,
1595     int *found_match)
1596 {
1597           uint32_t eoffset, offset = ms->offset;
1598           struct buffer bb;
1599           intmax_t lhs;
1600           file_pushbuf_t *pb;
1601           int rv, oneed_separator, in_type, nfound_match;
1602           char *rbuf;
1603           union VALUETYPE *p = &ms->ms_value;
1604           struct mlist ml, *mlp;
1605           struct cont c;
1606 
1607           if (*indir_count >= ms->indir_max) {
1608                     file_error(ms, 0, "indirect count (%hu) exceeded",
1609                         *indir_count);
1610                     return -1;
1611           }
1612 
1613           if (*name_count >= ms->name_max) {
1614                     file_error(ms, 0, "name use count (%hu) exceeded",
1615                         *name_count);
1616                     return -1;
1617           }
1618 
1619 
1620 
1621           if (mcopy(ms, p, m->type, m->flag & INDIR, s,
1622               CAST(uint32_t, offset + o), CAST(uint32_t, nbytes), m) == -1)
1623                     return -1;
1624 
1625           if ((ms->flags & MAGIC_DEBUG) != 0) {
1626                     fprintf(stderr, "mget(type=%d, flag=%#x, offset=%u, o=%"
1627                         SIZE_T_FORMAT "u, " "nbytes=%" SIZE_T_FORMAT
1628                         "u, il=%hu, nc=%hu)\n",
1629                         m->type, m->flag, offset, o, nbytes,
1630                         *indir_count, *name_count);
1631                     mdebug(offset, RCAST(char *, RCAST(void *, p)),
1632                         sizeof(union VALUETYPE));
1633 #ifndef COMPILE_ONLY
1634                     file_mdump(m);
1635 #endif
1636           }
1637 
1638           if (m->flag & INDIR) {
1639                     intmax_t off = m->in_offset;
1640                     const int sgn = m->in_op & FILE_OPSIGNED;
1641                     if (m->in_op & FILE_OPINDIRECT) {
1642                               const union VALUETYPE *q = CAST(const union VALUETYPE *,
1643                                   RCAST(const void *, s + offset + off));
1644                               int op;
1645                               switch (op = cvt_flip(m->in_type, flip)) {
1646                               case FILE_BYTE:
1647                                         if (OFFSET_OOB(nbytes, offset + off, 1))
1648                                                   return 0;
1649                                         off = SEXT(sgn,8,q->b);
1650                                         break;
1651                               case FILE_SHORT:
1652                                         if (OFFSET_OOB(nbytes, offset + off, 2))
1653                                                   return 0;
1654                                         off = SEXT(sgn,16,q->h);
1655                                         break;
1656                               case FILE_BESHORT:
1657                                         if (OFFSET_OOB(nbytes, offset + off, 2))
1658                                                   return 0;
1659                                         off = SEXT(sgn,16,BE16(q));
1660                                         break;
1661                               case FILE_LESHORT:
1662                                         if (OFFSET_OOB(nbytes, offset + off, 2))
1663                                                   return 0;
1664                                         off = SEXT(sgn,16,LE16(q));
1665                                         break;
1666                               case FILE_LONG:
1667                                         if (OFFSET_OOB(nbytes, offset + off, 4))
1668                                                   return 0;
1669                                         off = SEXT(sgn,32,q->l);
1670                                         break;
1671                               case FILE_BELONG:
1672                               case FILE_BEID3:
1673                                         if (OFFSET_OOB(nbytes, offset + off, 4))
1674                                                   return 0;
1675                                         off = SEXT(sgn,32,BE32(q));
1676                                         break;
1677                               case FILE_LEID3:
1678                               case FILE_LELONG:
1679                                         if (OFFSET_OOB(nbytes, offset + off, 4))
1680                                                   return 0;
1681                                         off = SEXT(sgn,32,LE32(q));
1682                                         break;
1683                               case FILE_MELONG:
1684                                         if (OFFSET_OOB(nbytes, offset + off, 4))
1685                                                   return 0;
1686                                         off = SEXT(sgn,32,ME32(q));
1687                                         break;
1688                               case FILE_BEQUAD:
1689                                         if (OFFSET_OOB(nbytes, offset + off, 8))
1690                                                   return 0;
1691                                         off = SEXT(sgn,64,BE64(q));
1692                                         break;
1693                               case FILE_LEQUAD:
1694                                         if (OFFSET_OOB(nbytes, offset + off, 8))
1695                                                   return 0;
1696                                         off = SEXT(sgn,64,LE64(q));
1697                                         break;
1698                               case FILE_OCTAL:
1699                                         if (OFFSET_OOB(nbytes, offset, m->vallen))
1700                                                   return 0;
1701                                         off = SEXT(sgn,64,strtoull(p->s, NULL, 8));
1702                                         break;
1703                               default:
1704                                         if ((ms->flags & MAGIC_DEBUG) != 0)
1705                                                   fprintf(stderr, "bad op=%d\n", op);
1706                                         return 0;
1707                               }
1708                               if ((ms->flags & MAGIC_DEBUG) != 0)
1709                                         fprintf(stderr, "indirect offs=%jd\n", off);
1710                     }
1711                     switch (in_type = cvt_flip(m->in_type, flip)) {
1712                     case FILE_BYTE:
1713                               if (OFFSET_OOB(nbytes, offset, 1))
1714                                         return 0;
1715                               if (do_ops(ms, m, &offset, SEXT(sgn,8,p->b), off))
1716                                         return 0;
1717                               break;
1718                     case FILE_BESHORT:
1719                               if (OFFSET_OOB(nbytes, offset, 2))
1720                                         return 0;
1721                               if (do_ops(ms, m, &offset, SEXT(sgn,16,BE16(p)), off))
1722                                         return 0;
1723                               break;
1724                     case FILE_LESHORT:
1725                               if (OFFSET_OOB(nbytes, offset, 2))
1726                                         return 0;
1727                               if (do_ops(ms, m, &offset, SEXT(sgn,16,LE16(p)), off))
1728                                         return 0;
1729                               break;
1730                     case FILE_SHORT:
1731                               if (OFFSET_OOB(nbytes, offset, 2))
1732                                         return 0;
1733                               if (do_ops(ms, m, &offset, SEXT(sgn,16,p->h), off))
1734                                         return 0;
1735                               break;
1736                     case FILE_BELONG:
1737                     case FILE_BEID3:
1738                               if (OFFSET_OOB(nbytes, offset, 4))
1739                                         return 0;
1740                               lhs = BE32(p);
1741                               if (in_type == FILE_BEID3)
1742                                         lhs = cvt_id3(ms, CAST(uint32_t, lhs));
1743                               if (do_ops(ms, m, &offset, SEXT(sgn,32,lhs), off))
1744                                         return 0;
1745                               break;
1746                     case FILE_LELONG:
1747                     case FILE_LEID3:
1748                               if (OFFSET_OOB(nbytes, offset, 4))
1749                                         return 0;
1750                               lhs = LE32(p);
1751                               if (in_type == FILE_LEID3)
1752                                         lhs = cvt_id3(ms, CAST(uint32_t, lhs));
1753                               if (do_ops(ms, m, &offset, SEXT(sgn,32,lhs), off))
1754                                         return 0;
1755                               break;
1756                     case FILE_MELONG:
1757                               if (OFFSET_OOB(nbytes, offset, 4))
1758                                         return 0;
1759                               if (do_ops(ms, m, &offset, SEXT(sgn,32,ME32(p)), off))
1760                                         return 0;
1761                               break;
1762                     case FILE_LONG:
1763                               if (OFFSET_OOB(nbytes, offset, 4))
1764                                         return 0;
1765                               if (do_ops(ms, m, &offset, SEXT(sgn,32,p->l), off))
1766                                         return 0;
1767                               break;
1768                     case FILE_LEQUAD:
1769                               if (OFFSET_OOB(nbytes, offset, 8))
1770                                         return 0;
1771                               if (do_ops(ms, m, &offset, SEXT(sgn,64,LE64(p)), off))
1772                                         return 0;
1773                               break;
1774                     case FILE_BEQUAD:
1775                               if (OFFSET_OOB(nbytes, offset, 8))
1776                                         return 0;
1777                               if (do_ops(ms, m, &offset, SEXT(sgn,64,BE64(p)), off))
1778                                         return 0;
1779                               break;
1780                     case FILE_OCTAL:
1781                               if (OFFSET_OOB(nbytes, offset, m->vallen))
1782                                         return 0;
1783                               if(do_ops(ms, m, &offset,
1784                                   SEXT(sgn,64,strtoull(p->s, NULL, 8)), off))
1785                                         return 0;
1786                               break;
1787                     default:
1788                               if ((ms->flags & MAGIC_DEBUG) != 0)
1789                                         fprintf(stderr, "bad in_type=%d\n", in_type);
1790                               return 0;
1791                     }
1792 
1793                     if (m->flag & INDIROFFADD) {
1794                               if (cont_level == 0) {
1795                                         if ((ms->flags & MAGIC_DEBUG) != 0)
1796                                                   fprintf(stderr,
1797                                                       "indirect *zero* cont_level\n");
1798                                         return 0;
1799                               }
1800                               offset += ms->c.li[cont_level - 1].off;
1801                               if (offset == 0) {
1802                                         if ((ms->flags & MAGIC_DEBUG) != 0)
1803                                                   fprintf(stderr,
1804                                                       "indirect *zero* offset\n");
1805                                         return 0;
1806                               }
1807                               if ((ms->flags & MAGIC_DEBUG) != 0)
1808                                         fprintf(stderr, "indirect +offs=%u\n", offset);
1809                     }
1810                     if (mcopy(ms, p, m->type, 0, s, offset, nbytes, m) == -1)
1811                               return -1;
1812                     ms->offset = offset;
1813 
1814                     if ((ms->flags & MAGIC_DEBUG) != 0) {
1815                               mdebug(offset, RCAST(char *, RCAST(void *, p)),
1816                                   sizeof(union VALUETYPE));
1817 #ifndef COMPILE_ONLY
1818                               file_mdump(m);
1819 #endif
1820                     }
1821           }
1822 
1823           /* Verify we have enough data to match magic type */
1824           switch (m->type) {
1825           case FILE_BYTE:
1826                     if (OFFSET_OOB(nbytes, offset, 1))
1827                               return 0;
1828                     break;
1829 
1830           case FILE_SHORT:
1831           case FILE_BESHORT:
1832           case FILE_LESHORT:
1833                     if (OFFSET_OOB(nbytes, offset, 2))
1834                               return 0;
1835                     break;
1836 
1837           case FILE_LONG:
1838           case FILE_BELONG:
1839           case FILE_LELONG:
1840           case FILE_MELONG:
1841           case FILE_DATE:
1842           case FILE_BEDATE:
1843           case FILE_LEDATE:
1844           case FILE_MEDATE:
1845           case FILE_LDATE:
1846           case FILE_BELDATE:
1847           case FILE_LELDATE:
1848           case FILE_MELDATE:
1849           case FILE_FLOAT:
1850           case FILE_BEFLOAT:
1851           case FILE_LEFLOAT:
1852                     if (OFFSET_OOB(nbytes, offset, 4))
1853                               return 0;
1854                     break;
1855 
1856           case FILE_DOUBLE:
1857           case FILE_BEDOUBLE:
1858           case FILE_LEDOUBLE:
1859                     if (OFFSET_OOB(nbytes, offset, 8))
1860                               return 0;
1861                     break;
1862 
1863           case FILE_GUID:
1864                     if (OFFSET_OOB(nbytes, offset, 16))
1865                               return 0;
1866                     break;
1867 
1868           case FILE_STRING:
1869           case FILE_PSTRING:
1870           case FILE_SEARCH:
1871           case FILE_OCTAL:
1872                     if (OFFSET_OOB(nbytes, offset, m->vallen))
1873                               return 0;
1874                     break;
1875 
1876           case FILE_REGEX:
1877                     if (nbytes < offset)
1878                               return 0;
1879                     break;
1880 
1881           case FILE_INDIRECT:
1882                     if (m->str_flags & INDIRECT_RELATIVE)
1883                               offset += CAST(uint32_t, o);
1884                     if (offset == 0)
1885                               return 0;
1886 
1887                     if (nbytes < offset)
1888                               return 0;
1889 
1890                     if ((pb = file_push_buffer(ms)) == NULL)
1891                               return -1;
1892 
1893                     (*indir_count)++;
1894                     bb = *b;
1895                     bb.fbuf = s + offset;
1896                     bb.flen = nbytes - offset;
1897                     bb.ebuf = NULL;
1898                     bb.elen = 0;
1899                     rv = -1;
1900                     for (mlp = ms->mlist[0]->next; mlp != ms->mlist[0];
1901                         mlp = mlp->next)
1902                     {
1903                               if ((rv = match(ms, mlp->magic, mlp->magic_rxcomp,
1904                                   mlp->nmagic, &bb, 0, BINTEST, text, 0, indir_count,
1905                                   name_count, printed_something, need_separator,
1906                                   firstline, NULL, NULL)) != 0)
1907                                         break;
1908                     }
1909                     buffer_fini(&bb);
1910 
1911                     if ((ms->flags & MAGIC_DEBUG) != 0)
1912                               fprintf(stderr, "indirect @offs=%u[%d]\n", offset, rv);
1913 
1914                     rbuf = file_pop_buffer(ms, pb);
1915                     if (rbuf == NULL && ms->event_flags & EVENT_HAD_ERR)
1916                               return -1;
1917 
1918                     if (rv == 1) {
1919                               if ((ms->flags & MAGIC_NODESC) == 0 &&
1920                                   file_printf(ms, F(ms, m->desc, "%u"), offset) == -1)
1921                               {
1922                                         free(rbuf);
1923                                         return -1;
1924                               }
1925                               if (file_printf(ms, "%s", rbuf) == -1) {
1926                                         free(rbuf);
1927                                         return -1;
1928                               }
1929                     }
1930                     free(rbuf);
1931                     return rv;
1932 
1933           case FILE_USE:
1934                     if (nbytes < offset)
1935                               return 0;
1936                     rbuf = m->value.s;
1937                     if (*rbuf == '^') {
1938                               rbuf++;
1939                               flip = !flip;
1940                     }
1941                     if (file_magicfind(ms, rbuf, &ml) == -1) {
1942                               file_error(ms, 0, "cannot find entry `%s'", rbuf);
1943                               return -1;
1944                     }
1945                     if (save_cont(ms, &c) == -1) {
1946                               file_error(ms, errno, "can't allocate continuation");
1947                               return -1;
1948                     }
1949 
1950                     oneed_separator = *need_separator;
1951                     if (m->flag & NOSPACE)
1952                               *need_separator = 0;
1953 
1954                     nfound_match = 0;
1955                     (*name_count)++;
1956                     eoffset = ms->eoffset;
1957                     rv = match(ms, ml.magic, ml.magic_rxcomp, ml.nmagic, b,
1958                         offset + o, mode, text, flip, indir_count, name_count,
1959                         printed_something, need_separator, firstline, returnval,
1960                         &nfound_match);
1961                     ms->ms_value.q = nfound_match;
1962                     (*name_count)--;
1963                     *found_match |= nfound_match;
1964 
1965                     restore_cont(ms, &c);
1966 
1967                     if (rv != 1)
1968                         *need_separator = oneed_separator;
1969                     ms->offset = offset;
1970                     ms->eoffset = eoffset;
1971                     return rv || *found_match;
1972 
1973           case FILE_NAME:
1974                     if (ms->flags & MAGIC_NODESC)
1975                               return 1;
1976                     if (file_printf(ms, "%s", m->desc) == -1)
1977                               return -1;
1978                     return 1;
1979           case FILE_DER:
1980           case FILE_DEFAULT:  /* nothing to check */
1981           case FILE_CLEAR:
1982           default:
1983                     break;
1984           }
1985           if (!mconvert(ms, m, flip))
1986                     return 0;
1987           return 1;
1988 }
1989 
1990 file_private uint64_t
file_strncmp(const char * s1,const char * s2,size_t len,size_t maxlen,uint32_t flags)1991 file_strncmp(const char *s1, const char *s2, size_t len, size_t maxlen,
1992     uint32_t flags)
1993 {
1994           /*
1995            * Convert the source args to unsigned here so that (1) the
1996            * compare will be unsigned as it is in strncmp() and (2) so
1997            * the ctype functions will work correctly without extra
1998            * casting.
1999            */
2000           const unsigned char *a = RCAST(const unsigned char *, s1);
2001           const unsigned char *b = RCAST(const unsigned char *, s2);
2002           uint32_t ws = flags & (STRING_COMPACT_WHITESPACE |
2003               STRING_COMPACT_OPTIONAL_WHITESPACE);
2004           const unsigned char *eb = b + (ws ? maxlen : len);
2005           uint64_t v;
2006 
2007           /*
2008            * What we want here is v = strncmp(s1, s2, len),
2009            * but ignoring any nulls.
2010            */
2011           v = 0;
2012           len++;
2013           if (0L == flags) { /* normal string: do it fast */
2014                     while (--len > 0)
2015                               if ((v = *b++ - *a++) != '\0')
2016                                         break;
2017           }
2018           else { /* combine the others */
2019                     while (--len > 0) {
2020                               if (b >= eb) {
2021                                         v = 1;
2022                                         break;
2023                               }
2024                               if ((flags & STRING_IGNORE_LOWERCASE) &&
2025                                   islower(*a)) {
2026                                         if ((v = tolower(*b++) - *a++) != '\0')
2027                                                   break;
2028                               }
2029                               else if ((flags & STRING_IGNORE_UPPERCASE) &&
2030                                   isupper(*a)) {
2031                                         if ((v = toupper(*b++) - *a++) != '\0')
2032                                                   break;
2033                               }
2034                               else if ((flags & STRING_COMPACT_WHITESPACE) &&
2035                                   isspace(*a)) {
2036                                         a++;
2037                                         if (isspace(*b)) {
2038                                                   b++;
2039                                                   if (!isspace(*a))
2040                                                             while (b < eb && isspace(*b))
2041                                                                       b++;
2042                                         }
2043                                         else {
2044                                                   v = 1;
2045                                                   break;
2046                                         }
2047                               }
2048                               else if ((flags & STRING_COMPACT_OPTIONAL_WHITESPACE) &&
2049                                   isspace(*a)) {
2050                                         a++;
2051                                         while (b < eb && isspace(*b))
2052                                                   b++;
2053                               }
2054                               else {
2055                                         if ((v = *b++ - *a++) != '\0')
2056                                                   break;
2057                               }
2058                     }
2059                     if (len == 0 && v == 0 && (flags & STRING_FULL_WORD)) {
2060                               if (*b && !isspace(*b))
2061                                         v = 1;
2062                     }
2063           }
2064           return v;
2065 }
2066 
2067 file_private uint64_t
file_strncmp16(const char * a,const char * b,size_t len,size_t maxlen,uint32_t flags)2068 file_strncmp16(const char *a, const char *b, size_t len, size_t maxlen,
2069     uint32_t flags)
2070 {
2071           /*
2072            * XXX - The 16-bit string compare probably needs to be done
2073            * differently, especially if the flags are to be supported.
2074            * At the moment, I am unsure.
2075            */
2076           flags = 0;
2077           return file_strncmp(a, b, len, maxlen, flags);
2078 }
2079 
2080 file_private file_regex_t *
alloc_regex(struct magic_set * ms,struct magic * m)2081 alloc_regex(struct magic_set *ms, struct magic *m)
2082 {
2083           int rc;
2084           file_regex_t *rx = CAST(file_regex_t *, malloc(sizeof(*rx)));
2085 
2086           if (rx == NULL) {
2087                     file_error(ms, errno, "can't allocate %" SIZE_T_FORMAT
2088                         "u bytes", sizeof(*rx));
2089                     return NULL;
2090           }
2091 
2092           rc = file_regcomp(ms, rx, m->value.s, REG_EXTENDED | REG_NEWLINE |
2093               ((m->str_flags & STRING_IGNORE_CASE) ? REG_ICASE : 0));
2094           if (rc == 0)
2095                     return rx;
2096 
2097           free(rx);
2098           return NULL;
2099 }
2100 
2101 file_private int
magiccheck(struct magic_set * ms,struct magic * m,file_regex_t ** m_cache)2102 magiccheck(struct magic_set *ms, struct magic *m, file_regex_t **m_cache)
2103 {
2104           uint64_t l = m->value.q;
2105           uint64_t v;
2106           float fl, fv;
2107           double dl, dv;
2108           int matched;
2109           union VALUETYPE *p = &ms->ms_value;
2110 
2111           switch (m->type) {
2112           case FILE_BYTE:
2113                     v = p->b;
2114                     break;
2115 
2116           case FILE_SHORT:
2117           case FILE_BESHORT:
2118           case FILE_LESHORT:
2119           case FILE_MSDOSDATE:
2120           case FILE_LEMSDOSDATE:
2121           case FILE_BEMSDOSDATE:
2122           case FILE_MSDOSTIME:
2123           case FILE_LEMSDOSTIME:
2124           case FILE_BEMSDOSTIME:
2125                     v = p->h;
2126                     break;
2127 
2128           case FILE_LONG:
2129           case FILE_BELONG:
2130           case FILE_LELONG:
2131           case FILE_MELONG:
2132           case FILE_DATE:
2133           case FILE_BEDATE:
2134           case FILE_LEDATE:
2135           case FILE_MEDATE:
2136           case FILE_LDATE:
2137           case FILE_BELDATE:
2138           case FILE_LELDATE:
2139           case FILE_MELDATE:
2140                     v = p->l;
2141                     break;
2142 
2143           case FILE_QUAD:
2144           case FILE_LEQUAD:
2145           case FILE_BEQUAD:
2146           case FILE_QDATE:
2147           case FILE_BEQDATE:
2148           case FILE_LEQDATE:
2149           case FILE_QLDATE:
2150           case FILE_BEQLDATE:
2151           case FILE_LEQLDATE:
2152           case FILE_QWDATE:
2153           case FILE_BEQWDATE:
2154           case FILE_LEQWDATE:
2155           case FILE_OFFSET:
2156                     v = p->q;
2157                     break;
2158 
2159           case FILE_FLOAT:
2160           case FILE_BEFLOAT:
2161           case FILE_LEFLOAT:
2162                     fl = m->value.f;
2163                     fv = p->f;
2164                     switch (m->reln) {
2165                     case 'x':
2166                               matched = 1;
2167                               break;
2168 
2169                     case '!':
2170                               matched = isunordered(fl, fv) ? 1 : fv != fl;
2171                               break;
2172 
2173                     case '=':
2174                               matched = isunordered(fl, fv) ? 0 : fv == fl;
2175                               break;
2176 
2177                     case '>':
2178                               matched = isgreater(fv, fl);
2179                               break;
2180 
2181                     case '<':
2182                               matched = isless(fv, fl);
2183                               break;
2184 
2185                     default:
2186                               file_magerror(ms, "cannot happen with float: "
2187                                   "invalid relation `%c'", m->reln);
2188                               return -1;
2189                     }
2190                     return matched;
2191 
2192           case FILE_DOUBLE:
2193           case FILE_BEDOUBLE:
2194           case FILE_LEDOUBLE:
2195                     dl = m->value.d;
2196                     dv = p->d;
2197                     switch (m->reln) {
2198                     case 'x':
2199                               matched = 1;
2200                               break;
2201 
2202                     case '!':
2203                               matched = isunordered(dv, dl) ? 1 : dv != dl;
2204                               break;
2205 
2206                     case '=':
2207                               matched = isunordered(dv, dl) ? 0 : dv == dl;
2208                               break;
2209 
2210                     case '>':
2211                               matched = isgreater(dv, dl);
2212                               break;
2213 
2214                     case '<':
2215                               matched = isless(dv, dl);
2216                               break;
2217 
2218                     default:
2219                               file_magerror(ms, "cannot happen with double: "
2220                                   "invalid relation `%c'", m->reln);
2221                               return -1;
2222                     }
2223                     return matched;
2224 
2225           case FILE_DEFAULT:
2226           case FILE_CLEAR:
2227                     l = 0;
2228                     v = 0;
2229                     break;
2230 
2231           case FILE_STRING:
2232           case FILE_PSTRING:
2233           case FILE_OCTAL:
2234                     l = 0;
2235                     v = file_strncmp(m->value.s, p->s, CAST(size_t, m->vallen),
2236                         sizeof(p->s), m->str_flags);
2237                     break;
2238 
2239           case FILE_BESTRING16:
2240           case FILE_LESTRING16:
2241                     l = 0;
2242                     v = file_strncmp16(m->value.s, p->s, CAST(size_t, m->vallen),
2243                         sizeof(p->s), m->str_flags);
2244                     break;
2245 
2246           case FILE_SEARCH: { /* search ms->search.s for the string m->value.s */
2247                     size_t slen;
2248                     size_t idx;
2249 
2250                     if (ms->search.s == NULL)
2251                               return 0;
2252 
2253                     slen = MIN(m->vallen, sizeof(m->value.s));
2254                     l = 0;
2255                     v = 0;
2256                     if ((ms->flags & MAGIC_DEBUG) != 0) {
2257                               size_t xlen = ms->search.s_len > 100 ? 100
2258                                   : ms->search.s_len;
2259 
2260                               fprintf(stderr, "search: [");
2261                               file_showstr(stderr, ms->search.s, xlen);
2262                               fprintf(stderr, "%s] for [", ms->search.s_len == xlen
2263                                   ? "" : "...");
2264                               file_showstr(stderr, m->value.s, slen);
2265                     }
2266 #ifdef HAVE_MEMMEM
2267                     if (slen > 0 && m->str_flags == 0) {
2268                               const char *found;
2269                               idx = m->str_range + slen;
2270                               if (m->str_range == 0 || ms->search.s_len < idx)
2271                                         idx = ms->search.s_len;
2272                               found = CAST(const char *, memmem(ms->search.s, idx,
2273                                   m->value.s, slen));
2274                               if ((ms->flags & MAGIC_DEBUG) != 0) {
2275                                         fprintf(stderr, "] %sfound\n",
2276                                             found ? "" : "not ");
2277                               }
2278                               if (!found) {
2279                                         v = 1;
2280                                         break;
2281                               }
2282                               idx = found - ms->search.s;
2283                               ms->search.offset += idx;
2284                               ms->search.rm_len = ms->search.s_len - idx;
2285                               break;
2286                     }
2287 #endif
2288 
2289                     for (idx = 0; m->str_range == 0 || idx < m->str_range; idx++) {
2290                               if (slen + idx > ms->search.s_len) {
2291                                         v = 1;
2292                                         break;
2293                               }
2294 
2295                               v = file_strncmp(m->value.s, ms->search.s + idx, slen,
2296                                   ms->search.s_len - idx, m->str_flags);
2297                               if (v == 0) {       /* found match */
2298                                         ms->search.offset += idx;
2299                                         ms->search.rm_len = ms->search.s_len - idx;
2300                                         break;
2301                               }
2302                     }
2303                     if ((ms->flags & MAGIC_DEBUG) != 0) {
2304                               fprintf(stderr, "] %sfound\n", v == 0 ? "" : "not ");
2305                     }
2306                     break;
2307           }
2308           case FILE_REGEX: {
2309                     int rc;
2310                     file_regex_t *rx = *m_cache;
2311                     const char *search;
2312                     regmatch_t pmatch;
2313                     size_t slen = ms->search.s_len;
2314                     char *copy;
2315 
2316                     if (ms->search.s == NULL)
2317                               return 0;
2318 
2319                     if (rx == NULL) {
2320                               rx = *m_cache = alloc_regex(ms, m);
2321                               if (rx == NULL)
2322                                         return -1;
2323                     }
2324                     l = 0;
2325                     if (slen != 0) {
2326                         copy = CAST(char *, malloc(slen));
2327                         if (copy == NULL)  {
2328                               file_error(ms, errno,
2329                                   "can't allocate %" SIZE_T_FORMAT "u bytes",
2330                                   slen);
2331                               return -1;
2332                         }
2333                         memcpy(copy, ms->search.s, slen);
2334                         copy[--slen] = '\0';
2335                         search = copy;
2336                     } else {
2337                         search = CCAST(char *, "");
2338                         copy = NULL;
2339                     }
2340                     rc = file_regexec(ms, rx, RCAST(const char *, search),
2341                         1, &pmatch, 0);
2342                     free(copy);
2343                     switch (rc) {
2344                     case 0:
2345                               ms->search.s += CAST(int, pmatch.rm_so);
2346                               ms->search.offset += CAST(size_t, pmatch.rm_so);
2347                               ms->search.rm_len = CAST(size_t,
2348                                   pmatch.rm_eo - pmatch.rm_so);
2349                               v = 0;
2350                               break;
2351 
2352                     case REG_NOMATCH:
2353                               v = 1;
2354                               break;
2355 
2356                     default:
2357                               return -1;
2358                     }
2359                     break;
2360           }
2361           case FILE_USE:
2362                     return ms->ms_value.q != 0;
2363           case FILE_NAME:
2364           case FILE_INDIRECT:
2365                     return 1;
2366           case FILE_DER:
2367                     matched = der_cmp(ms, m);
2368                     if (matched == -1) {
2369                               if ((ms->flags & MAGIC_DEBUG) != 0) {
2370                                         (void) fprintf(stderr,
2371                                             "EOF comparing DER entries\n");
2372                               }
2373                               return 0;
2374                     }
2375                     return matched;
2376           case FILE_GUID:
2377                     l = 0;
2378                     v = memcmp(m->value.guid, p->guid, sizeof(p->guid));
2379                     break;
2380           default:
2381                     file_magerror(ms, "invalid type %d in magiccheck()", m->type);
2382                     return -1;
2383           }
2384 
2385           v = file_signextend(ms, m, v);
2386 
2387           switch (m->reln) {
2388           case 'x':
2389                     if ((ms->flags & MAGIC_DEBUG) != 0)
2390                               (void) fprintf(stderr, "%" INT64_T_FORMAT
2391                                   "u == *any* = 1", CAST(unsigned long long, v));
2392                     matched = 1;
2393                     break;
2394 
2395           case '!':
2396                     matched = v != l;
2397                     if ((ms->flags & MAGIC_DEBUG) != 0)
2398                               (void) fprintf(stderr, "%" INT64_T_FORMAT "u != %"
2399                                   INT64_T_FORMAT "u = %d",
2400                                   CAST(unsigned long long, v),
2401                                   CAST(unsigned long long, l), matched);
2402                     break;
2403 
2404           case '=':
2405                     matched = v == l;
2406                     if ((ms->flags & MAGIC_DEBUG) != 0)
2407                               (void) fprintf(stderr, "%" INT64_T_FORMAT "u == %"
2408                                   INT64_T_FORMAT "u = %d",
2409                                   CAST(unsigned long long, v),
2410                                   CAST(unsigned long long, l), matched);
2411                     break;
2412 
2413           case '>':
2414                     if (m->flag & UNSIGNED) {
2415                               matched = v > l;
2416                               if ((ms->flags & MAGIC_DEBUG) != 0)
2417                                         (void) fprintf(stderr, "%" INT64_T_FORMAT
2418                                             "u > %" INT64_T_FORMAT "u = %d",
2419                                             CAST(unsigned long long, v),
2420                                             CAST(unsigned long long, l), matched);
2421                     }
2422                     else {
2423                               matched = CAST(int64_t, v) > CAST(int64_t, l);
2424                               if ((ms->flags & MAGIC_DEBUG) != 0)
2425                                         (void) fprintf(stderr, "%" INT64_T_FORMAT
2426                                             "d > %" INT64_T_FORMAT "d = %d",
2427                                             CAST(long long, v),
2428                                             CAST(long long, l), matched);
2429                     }
2430                     break;
2431 
2432           case '<':
2433                     if (m->flag & UNSIGNED) {
2434                               matched = v < l;
2435                               if ((ms->flags & MAGIC_DEBUG) != 0)
2436                                         (void) fprintf(stderr, "%" INT64_T_FORMAT
2437                                             "u < %" INT64_T_FORMAT "u = %d",
2438                                             CAST(unsigned long long, v),
2439                                             CAST(unsigned long long, l), matched);
2440                     }
2441                     else {
2442                               matched = CAST(int64_t, v) < CAST(int64_t, l);
2443                               if ((ms->flags & MAGIC_DEBUG) != 0)
2444                                         (void) fprintf(stderr, "%" INT64_T_FORMAT
2445                                             "d < %" INT64_T_FORMAT "d = %d",
2446                                              CAST(long long, v),
2447                                              CAST(long long, l), matched);
2448                     }
2449                     break;
2450 
2451           case '&':
2452                     matched = (v & l) == l;
2453                     if ((ms->flags & MAGIC_DEBUG) != 0)
2454                               (void) fprintf(stderr, "((%" INT64_T_FORMAT "x & %"
2455                                   INT64_T_FORMAT "x) == %" INT64_T_FORMAT
2456                                   "x) = %d", CAST(unsigned long long, v),
2457                                   CAST(unsigned long long, l),
2458                                   CAST(unsigned long long, l),
2459                                   matched);
2460                     break;
2461 
2462           case '^':
2463                     matched = (v & l) != l;
2464                     if ((ms->flags & MAGIC_DEBUG) != 0)
2465                               (void) fprintf(stderr, "((%" INT64_T_FORMAT "x & %"
2466                                   INT64_T_FORMAT "x) != %" INT64_T_FORMAT
2467                                   "x) = %d", CAST(unsigned long long, v),
2468                                   CAST(unsigned long long, l),
2469                                   CAST(unsigned long long, l), matched);
2470                     break;
2471 
2472           default:
2473                     file_magerror(ms, "cannot happen: invalid relation `%c'",
2474                         m->reln);
2475                     return -1;
2476           }
2477           if ((ms->flags & MAGIC_DEBUG) != 0) {
2478                     (void) fprintf(stderr, " strength=%zu\n",
2479                         file_magic_strength(m, 1));
2480           }
2481 
2482           return matched;
2483 }
2484 
2485 file_private int
handle_annotation(struct magic_set * ms,struct magic * m,int firstline)2486 handle_annotation(struct magic_set *ms, struct magic *m, int firstline)
2487 {
2488           if ((ms->flags & MAGIC_APPLE) && m->apple[0]) {
2489                     if (print_sep(ms, firstline) == -1)
2490                               return -1;
2491                     if (file_printf(ms, "%.8s", m->apple) == -1)
2492                               return -1;
2493                     return 1;
2494           }
2495           if ((ms->flags & MAGIC_EXTENSION) && m->ext[0]) {
2496                     if (print_sep(ms, firstline) == -1)
2497                               return -1;
2498                     if (file_printf(ms, "%s", m->ext) == -1)
2499                               return -1;
2500                     return 1;
2501           }
2502           if ((ms->flags & MAGIC_MIME_TYPE) && m->mimetype[0]) {
2503                     char buf[1024];
2504                     const char *p;
2505                     if (print_sep(ms, firstline) == -1)
2506                               return -1;
2507                     if (varexpand(ms, buf, sizeof(buf), m->mimetype) == -1)
2508                               p = m->mimetype;
2509                     else
2510                               p = buf;
2511                     if (file_printf(ms, "%s", p) == -1)
2512                               return -1;
2513                     return 1;
2514           }
2515           return 0;
2516 }
2517 
2518 file_private int
print_sep(struct magic_set * ms,int firstline)2519 print_sep(struct magic_set *ms, int firstline)
2520 {
2521           if (firstline)
2522                     return 0;
2523           /*
2524            * we found another match
2525            * put a newline and '-' to do some simple formatting
2526            */
2527           return file_separator(ms);
2528 }
2529