"Fossies" - the Fresh Open Source Software Archive

Member "file-5.35/src/softmagic.c" (15 Oct 2018, 51281 Bytes) of package /linux/misc/file-5.35.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "softmagic.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 5.34_vs_5.35.

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