168349Sobrien/* 2133359Sobrien * Copyright (c) Ian F. Darwin 1986-1995. 3133359Sobrien * Software written by Ian F. Darwin and others; 4133359Sobrien * maintained 1995-present by Christos Zoulas and others. 5191736Sobrien * 6133359Sobrien * Redistribution and use in source and binary forms, with or without 7133359Sobrien * modification, are permitted provided that the following conditions 8133359Sobrien * are met: 9133359Sobrien * 1. Redistributions of source code must retain the above copyright 10133359Sobrien * notice immediately at the beginning of the file, without modification, 11133359Sobrien * this list of conditions, and the following disclaimer. 12133359Sobrien * 2. Redistributions in binary form must reproduce the above copyright 13133359Sobrien * notice, this list of conditions and the following disclaimer in the 14133359Sobrien * documentation and/or other materials provided with the distribution. 15191736Sobrien * 16133359Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17133359Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18133359Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19133359Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 20133359Sobrien * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21133359Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22133359Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23133359Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24133359Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25133359Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26133359Sobrien * SUCH DAMAGE. 27133359Sobrien */ 28133359Sobrien/* 2975937Sobrien * softmagic - interpret variable magic from MAGIC 3068349Sobrien */ 3168349Sobrien 32103373Sobrien#include "file.h" 33191736Sobrien 34191736Sobrien#ifndef lint 35284193SdelphijFILE_RCSID("@(#)$File: softmagic.c,v 1.206 2015/01/01 17:07:34 christos Exp $") 36191736Sobrien#endif /* lint */ 37191736Sobrien 38133359Sobrien#include "magic.h" 39267843Sdelphij#include <assert.h> 4068349Sobrien#include <string.h> 4168349Sobrien#include <ctype.h> 4268349Sobrien#include <stdlib.h> 4368349Sobrien#include <time.h> 4468349Sobrien 45133359Sobrienprivate int match(struct magic_set *, struct magic *, uint32_t, 46284193Sdelphij const unsigned char *, size_t, size_t, int, int, int, uint16_t, 47284193Sdelphij uint16_t *, int *, int *, int *); 48169962Sobrienprivate int mget(struct magic_set *, const unsigned char *, 49284193Sdelphij struct magic *, size_t, size_t, unsigned int, int, int, int, uint16_t, 50284193Sdelphij uint16_t *, int *, int *, int *); 51169962Sobrienprivate int magiccheck(struct magic_set *, struct magic *); 52169962Sobrienprivate int32_t mprint(struct magic_set *, struct magic *); 53191736Sobrienprivate int32_t moffset(struct magic_set *, struct magic *); 54133359Sobrienprivate void mdebug(uint32_t, const char *, size_t); 55139368Sobrienprivate int mcopy(struct magic_set *, union VALUETYPE *, int, int, 56267843Sdelphij const unsigned char *, uint32_t, size_t, struct magic *); 57267843Sdelphijprivate int mconvert(struct magic_set *, struct magic *, int); 58169942Sobrienprivate int print_sep(struct magic_set *, int); 59191736Sobrienprivate int handle_annotation(struct magic_set *, struct magic *); 60169942Sobrienprivate void cvt_8(union VALUETYPE *, const struct magic *); 61169942Sobrienprivate void cvt_16(union VALUETYPE *, const struct magic *); 62169942Sobrienprivate void cvt_32(union VALUETYPE *, const struct magic *); 63169942Sobrienprivate void cvt_64(union VALUETYPE *, const struct magic *); 6468349Sobrien 65267843Sdelphij#define OFFSET_OOB(n, o, i) ((n) < (o) || (i) > ((n) - (o))) 66275670Sdelphij 6768349Sobrien/* 68169942Sobrien * softmagic - lookup one file in parsed, in-memory copy of database 6968349Sobrien * Passed the name and FILE * of one file to be typed. 7068349Sobrien */ 7168349Sobrien/*ARGSUSED1*/ /* nbytes passed for regularity, maybe need later */ 72133359Sobrienprotected int 73234250Sobrienfile_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes, 74284193Sdelphij uint16_t indir_level, uint16_t *name_count, int mode, int text) 7568349Sobrien{ 7674784Sobrien struct mlist *ml; 77267843Sdelphij int rv, printed_something = 0, need_separator = 0; 78284193Sdelphij uint16_t nc; 79284193Sdelphij 80284193Sdelphij if (name_count == NULL) { 81284193Sdelphij nc = 0; 82284193Sdelphij name_count = &nc; 83284193Sdelphij } 84284193Sdelphij 85267843Sdelphij for (ml = ms->mlist[0]->next; ml != ms->mlist[0]; ml = ml->next) 86267843Sdelphij if ((rv = match(ms, ml->magic, ml->nmagic, buf, nbytes, 0, mode, 87284193Sdelphij text, 0, indir_level, name_count, 88284193Sdelphij &printed_something, &need_separator, NULL)) != 0) 89169942Sobrien return rv; 9074784Sobrien 9168349Sobrien return 0; 9268349Sobrien} 9368349Sobrien 94267843Sdelphij#define FILE_FMTDEBUG 95267843Sdelphij#ifdef FILE_FMTDEBUG 96267843Sdelphij#define F(a, b, c) file_fmtcheck((a), (b), (c), __FILE__, __LINE__) 97267843Sdelphij 98267843Sdelphijprivate const char * __attribute__((__format_arg__(3))) 99267843Sdelphijfile_fmtcheck(struct magic_set *ms, const struct magic *m, const char *def, 100267843Sdelphij const char *file, size_t line) 101267843Sdelphij{ 102267843Sdelphij const char *ptr = fmtcheck(m->desc, def); 103267843Sdelphij if (ptr == def) 104267843Sdelphij file_magerror(ms, 105284193Sdelphij "%s, %" SIZE_T_FORMAT "u: format `%s' does not match" 106284193Sdelphij " with `%s'", file, line, m->desc, def); 107267843Sdelphij return ptr; 108267843Sdelphij} 109267843Sdelphij#else 110267843Sdelphij#define F(a, b, c) fmtcheck((b)->desc, (c)) 111267843Sdelphij#endif 112267843Sdelphij 11368349Sobrien/* 11468349Sobrien * Go through the whole list, stopping if you find a match. Process all 11568349Sobrien * the continuations of that match before returning. 11668349Sobrien * 11768349Sobrien * We support multi-level continuations: 11868349Sobrien * 11968349Sobrien * At any time when processing a successful top-level match, there is a 12068349Sobrien * current continuation level; it represents the level of the last 12168349Sobrien * successfully matched continuation. 12268349Sobrien * 12368349Sobrien * Continuations above that level are skipped as, if we see one, it 12468349Sobrien * means that the continuation that controls them - i.e, the 12568349Sobrien * lower-level continuation preceding them - failed to match. 12668349Sobrien * 12768349Sobrien * Continuations below that level are processed as, if we see one, 12868349Sobrien * it means we've finished processing or skipping higher-level 12968349Sobrien * continuations under the control of a successful or unsuccessful 13068349Sobrien * lower-level continuation, and are now seeing the next lower-level 13168349Sobrien * continuation and should process it. The current continuation 13268349Sobrien * level reverts to the level of the one we're seeing. 13368349Sobrien * 13468349Sobrien * Continuations at the current level are processed as, if we see 13568349Sobrien * one, there's no lower-level continuation that may have failed. 13668349Sobrien * 13768349Sobrien * If a continuation matches, we bump the current continuation level 13868349Sobrien * so that higher-level continuations are processed. 13968349Sobrien */ 140133359Sobrienprivate int 141133359Sobrienmatch(struct magic_set *ms, struct magic *magic, uint32_t nmagic, 142267843Sdelphij const unsigned char *s, size_t nbytes, size_t offset, int mode, int text, 143284193Sdelphij int flip, uint16_t indir_level, uint16_t *name_count, 144284193Sdelphij int *printed_something, int *need_separator, int *returnval) 14568349Sobrien{ 146133359Sobrien uint32_t magindex = 0; 147133359Sobrien unsigned int cont_level = 0; 148267843Sdelphij int returnvalv = 0, e; /* if a match is found it is set to 1*/ 14968349Sobrien int firstline = 1; /* a flag to print X\n X\n- X */ 150191736Sobrien int print = (ms->flags & (MAGIC_MIME|MAGIC_APPLE)) == 0; 15168349Sobrien 152267843Sdelphij if (returnval == NULL) 153267843Sdelphij returnval = &returnvalv; 154267843Sdelphij 155169962Sobrien if (file_check_mem(ms, cont_level) == -1) 156133359Sobrien return -1; 15768349Sobrien 15868349Sobrien for (magindex = 0; magindex < nmagic; magindex++) { 159191736Sobrien int flush = 0; 160186690Sobrien struct magic *m = &magic[magindex]; 161169962Sobrien 162267843Sdelphij if (m->type != FILE_NAME) 163234250Sobrien if ((IS_STRING(m->type) && 164267843Sdelphij#define FLT (STRING_BINTEST | STRING_TEXTTEST) 165267843Sdelphij ((text && (m->str_flags & FLT) == STRING_BINTEST) || 166267843Sdelphij (!text && (m->str_flags & FLT) == STRING_TEXTTEST))) || 167234250Sobrien (m->flag & mode) != mode) { 168186690Sobrien /* Skip sub-tests */ 169267843Sdelphij while (magindex + 1 < nmagic && 170267843Sdelphij magic[magindex + 1].cont_level != 0 && 171267843Sdelphij ++magindex) 172186690Sobrien continue; 173186690Sobrien continue; /* Skip to next top-level test*/ 174186690Sobrien } 175169962Sobrien 176186690Sobrien ms->offset = m->offset; 177186690Sobrien ms->line = m->lineno; 178186690Sobrien 17968349Sobrien /* if main entry matches, print it... */ 180267843Sdelphij switch (mget(ms, s, m, nbytes, offset, cont_level, mode, text, 181284193Sdelphij flip, indir_level, name_count, 182284193Sdelphij printed_something, need_separator, returnval)) { 183191736Sobrien case -1: 184191736Sobrien return -1; 185191736Sobrien case 0: 186191736Sobrien flush = m->reln != '!'; 187191736Sobrien break; 188191736Sobrien default: 189191736Sobrien if (m->type == FILE_INDIRECT) 190267843Sdelphij *returnval = 1; 191226048Sobrien 192186690Sobrien switch (magiccheck(ms, m)) { 193159764Sobrien case -1: 194159764Sobrien return -1; 195159764Sobrien case 0: 196159764Sobrien flush++; 197159764Sobrien break; 198159764Sobrien default: 199191736Sobrien flush = 0; 200159764Sobrien break; 201159764Sobrien } 202191736Sobrien break; 20368349Sobrien } 204133359Sobrien if (flush) { 205191736Sobrien /* 206133359Sobrien * main entry didn't match, 207133359Sobrien * flush its continuations 208133359Sobrien */ 209133359Sobrien while (magindex < nmagic - 1 && 210169962Sobrien magic[magindex + 1].cont_level != 0) 211169962Sobrien magindex++; 212133359Sobrien continue; 213133359Sobrien } 21468349Sobrien 215267843Sdelphij if ((e = handle_annotation(ms, m)) != 0) { 216267843Sdelphij *need_separator = 1; 217267843Sdelphij *printed_something = 1; 218267843Sdelphij *returnval = 1; 219226048Sobrien return e; 220267843Sdelphij } 221169942Sobrien /* 222169942Sobrien * If we are going to print something, we'll need to print 223169942Sobrien * a blank before we print something else. 224169942Sobrien */ 225191736Sobrien if (*m->desc) { 226267843Sdelphij *need_separator = 1; 227267843Sdelphij *printed_something = 1; 228169942Sobrien if (print_sep(ms, firstline) == -1) 229133359Sobrien return -1; 23068349Sobrien } 23168349Sobrien 232191736Sobrien 233191736Sobrien if (print && mprint(ms, m) == -1) 234133359Sobrien return -1; 235169942Sobrien 236191736Sobrien ms->c.li[cont_level].off = moffset(ms, m); 237191736Sobrien 23868349Sobrien /* and any continuations that match */ 239169962Sobrien if (file_check_mem(ms, ++cont_level) == -1) 240133359Sobrien return -1; 241133359Sobrien 242284193Sdelphij while (magindex + 1 < nmagic && 243284193Sdelphij magic[magindex + 1].cont_level != 0) { 244284193Sdelphij m = &magic[++magindex]; 245186690Sobrien ms->line = m->lineno; /* for messages */ 246169962Sobrien 247186690Sobrien if (cont_level < m->cont_level) 248133359Sobrien continue; 249186690Sobrien if (cont_level > m->cont_level) { 250133359Sobrien /* 251133359Sobrien * We're at the end of the level 252133359Sobrien * "cont_level" continuations. 253133359Sobrien */ 254186690Sobrien cont_level = m->cont_level; 255133359Sobrien } 256186690Sobrien ms->offset = m->offset; 257186690Sobrien if (m->flag & OFFADD) { 258169942Sobrien ms->offset += 259169962Sobrien ms->c.li[cont_level - 1].off; 260133359Sobrien } 261159764Sobrien 262169962Sobrien#ifdef ENABLE_CONDITIONALS 263186690Sobrien if (m->cond == COND_ELSE || 264186690Sobrien m->cond == COND_ELIF) { 265169962Sobrien if (ms->c.li[cont_level].last_match == 1) 266169962Sobrien continue; 267169962Sobrien } 268169962Sobrien#endif 269267843Sdelphij switch (mget(ms, s, m, nbytes, offset, cont_level, mode, 270284193Sdelphij text, flip, indir_level, name_count, 271284193Sdelphij printed_something, need_separator, returnval)) { 272191736Sobrien case -1: 273191736Sobrien return -1; 274191736Sobrien case 0: 275191736Sobrien if (m->reln != '!') 276191736Sobrien continue; 277191736Sobrien flush = 1; 278191736Sobrien break; 279191736Sobrien default: 280191736Sobrien if (m->type == FILE_INDIRECT) 281267843Sdelphij *returnval = 1; 282191736Sobrien flush = 0; 283191736Sobrien break; 284191736Sobrien } 285191736Sobrien 286186690Sobrien switch (flush ? 1 : magiccheck(ms, m)) { 287133359Sobrien case -1: 288133359Sobrien return -1; 289133359Sobrien case 0: 290169962Sobrien#ifdef ENABLE_CONDITIONALS 291169962Sobrien ms->c.li[cont_level].last_match = 0; 292169962Sobrien#endif 293133359Sobrien break; 294133359Sobrien default: 295169962Sobrien#ifdef ENABLE_CONDITIONALS 296169962Sobrien ms->c.li[cont_level].last_match = 1; 297169962Sobrien#endif 298267843Sdelphij if (m->type == FILE_CLEAR) 299267843Sdelphij ms->c.li[cont_level].got_match = 0; 300267843Sdelphij else if (ms->c.li[cont_level].got_match) { 301267843Sdelphij if (m->type == FILE_DEFAULT) 302267843Sdelphij break; 303267843Sdelphij } else 304169962Sobrien ms->c.li[cont_level].got_match = 1; 305267843Sdelphij if ((e = handle_annotation(ms, m)) != 0) { 306267843Sdelphij *need_separator = 1; 307267843Sdelphij *printed_something = 1; 308267843Sdelphij *returnval = 1; 309267843Sdelphij return e; 310169962Sobrien } 311133359Sobrien /* 312169942Sobrien * If we are going to print something, 313169942Sobrien * make sure that we have a separator first. 314169942Sobrien */ 315191736Sobrien if (*m->desc) { 316267843Sdelphij if (!*printed_something) { 317267843Sdelphij *printed_something = 1; 318192348Sdelphij if (print_sep(ms, firstline) 319192348Sdelphij == -1) 320192348Sdelphij return -1; 321192348Sdelphij } 322169942Sobrien } 323169942Sobrien /* 324169962Sobrien * This continuation matched. Print 325169962Sobrien * its message, with a blank before it 326169962Sobrien * if the previous item printed and 327169962Sobrien * this item isn't empty. 328133359Sobrien */ 329133359Sobrien /* space if previous printed */ 330267843Sdelphij if (*need_separator 331186690Sobrien && ((m->flag & NOSPACE) == 0) 332191736Sobrien && *m->desc) { 333191736Sobrien if (print && 334191736Sobrien file_printf(ms, " ") == -1) 335133359Sobrien return -1; 336267843Sdelphij *need_separator = 0; 33768349Sobrien } 338191736Sobrien if (print && mprint(ms, m) == -1) 339133359Sobrien return -1; 340191736Sobrien 341191736Sobrien ms->c.li[cont_level].off = moffset(ms, m); 342191736Sobrien 343191736Sobrien if (*m->desc) 344267843Sdelphij *need_separator = 1; 34568349Sobrien 346133359Sobrien /* 347133359Sobrien * If we see any continuations 348133359Sobrien * at a higher level, 349133359Sobrien * process them. 350133359Sobrien */ 351169962Sobrien if (file_check_mem(ms, ++cont_level) == -1) 352133359Sobrien return -1; 353169962Sobrien break; 35468349Sobrien } 35568349Sobrien } 356267843Sdelphij if (*printed_something) { 357175296Sobrien firstline = 0; 358191736Sobrien if (print) 359267843Sdelphij *returnval = 1; 360175296Sobrien } 361267843Sdelphij if ((ms->flags & MAGIC_CONTINUE) == 0 && *printed_something) { 362267843Sdelphij return *returnval; /* don't keep searching */ 363191736Sobrien } 36468349Sobrien } 365267843Sdelphij return *returnval; /* This is hit if -k is set or there is no match */ 36668349Sobrien} 36768349Sobrien 368133359Sobrienprivate int 369169942Sobriencheck_fmt(struct magic_set *ms, struct magic *m) 370169942Sobrien{ 371267843Sdelphij file_regex_t rx; 372267843Sdelphij int rc, rv = -1; 373169942Sobrien 374191736Sobrien if (strchr(m->desc, '%') == NULL) 375169942Sobrien return 0; 376169942Sobrien 377267843Sdelphij rc = file_regcomp(&rx, "%[-0-9\\.]*s", REG_EXTENDED|REG_NOSUB); 378169942Sobrien if (rc) { 379267843Sdelphij file_regerror(&rx, rc, ms); 380169942Sobrien } else { 381267843Sdelphij rc = file_regexec(&rx, m->desc, 0, 0, 0); 382267843Sdelphij rv = !rc; 383169942Sobrien } 384267843Sdelphij file_regfree(&rx); 385267843Sdelphij return rv; 386169942Sobrien} 387169942Sobrien 388169962Sobrien#ifndef HAVE_STRNDUP 389169962Sobrienchar * strndup(const char *, size_t); 390169962Sobrien 391169962Sobrienchar * 392169962Sobrienstrndup(const char *str, size_t n) 393169962Sobrien{ 394169962Sobrien size_t len; 395169962Sobrien char *copy; 396169962Sobrien 397192348Sdelphij for (len = 0; len < n && str[len]; len++) 398192348Sdelphij continue; 399192348Sdelphij if ((copy = malloc(len + 1)) == NULL) 400192348Sdelphij return NULL; 401192348Sdelphij (void)memcpy(copy, str, len); 402169962Sobrien copy[len] = '\0'; 403192348Sdelphij return copy; 404169962Sobrien} 405169962Sobrien#endif /* HAVE_STRNDUP */ 406169962Sobrien 407133359Sobrienprivate int32_t 408169962Sobrienmprint(struct magic_set *ms, struct magic *m) 409133359Sobrien{ 410169942Sobrien uint64_t v; 411175296Sobrien float vf; 412175296Sobrien double vd; 413169962Sobrien int64_t t = 0; 414284193Sdelphij char buf[128], tbuf[26], sbuf[512]; 415169962Sobrien union VALUETYPE *p = &ms->ms_value; 41668349Sobrien 41768349Sobrien switch (m->type) { 418133359Sobrien case FILE_BYTE: 419169942Sobrien v = file_signextend(ms, m, (uint64_t)p->b); 420169942Sobrien switch (check_fmt(ms, m)) { 421169942Sobrien case -1: 422133359Sobrien return -1; 423169942Sobrien case 1: 424267843Sdelphij (void)snprintf(buf, sizeof(buf), "%d", 425191736Sobrien (unsigned char)v); 426267843Sdelphij if (file_printf(ms, F(ms, m, "%s"), buf) == -1) 427169942Sobrien return -1; 428169942Sobrien break; 429169942Sobrien default: 430267843Sdelphij if (file_printf(ms, F(ms, m, "%d"), 431267843Sdelphij (unsigned char) v) == -1) 432169942Sobrien return -1; 433169942Sobrien break; 434169942Sobrien } 435169942Sobrien t = ms->offset + sizeof(char); 43668349Sobrien break; 43768349Sobrien 438133359Sobrien case FILE_SHORT: 439133359Sobrien case FILE_BESHORT: 440133359Sobrien case FILE_LESHORT: 441169942Sobrien v = file_signextend(ms, m, (uint64_t)p->h); 442169942Sobrien switch (check_fmt(ms, m)) { 443169942Sobrien case -1: 444133359Sobrien return -1; 445169942Sobrien case 1: 446267843Sdelphij (void)snprintf(buf, sizeof(buf), "%u", 447191736Sobrien (unsigned short)v); 448267843Sdelphij if (file_printf(ms, F(ms, m, "%s"), buf) == -1) 449169942Sobrien return -1; 450169942Sobrien break; 451169942Sobrien default: 452267843Sdelphij if (file_printf(ms, F(ms, m, "%u"), 453267843Sdelphij (unsigned short) v) == -1) 454169942Sobrien return -1; 455169942Sobrien break; 456169942Sobrien } 457169942Sobrien t = ms->offset + sizeof(short); 45868349Sobrien break; 45968349Sobrien 460133359Sobrien case FILE_LONG: 461133359Sobrien case FILE_BELONG: 462133359Sobrien case FILE_LELONG: 463159764Sobrien case FILE_MELONG: 464169942Sobrien v = file_signextend(ms, m, (uint64_t)p->l); 465169942Sobrien switch (check_fmt(ms, m)) { 466169942Sobrien case -1: 467133359Sobrien return -1; 468169942Sobrien case 1: 469267843Sdelphij (void)snprintf(buf, sizeof(buf), "%u", (uint32_t) v); 470267843Sdelphij if (file_printf(ms, F(ms, m, "%s"), buf) == -1) 471169942Sobrien return -1; 472169942Sobrien break; 473169942Sobrien default: 474267843Sdelphij if (file_printf(ms, F(ms, m, "%u"), (uint32_t) v) == -1) 475169942Sobrien return -1; 476169942Sobrien break; 477169942Sobrien } 478169942Sobrien t = ms->offset + sizeof(int32_t); 47968349Sobrien break; 48068349Sobrien 481169942Sobrien case FILE_QUAD: 482169942Sobrien case FILE_BEQUAD: 483169942Sobrien case FILE_LEQUAD: 484169942Sobrien v = file_signextend(ms, m, p->q); 485267843Sdelphij switch (check_fmt(ms, m)) { 486267843Sdelphij case -1: 487169942Sobrien return -1; 488267843Sdelphij case 1: 489267843Sdelphij (void)snprintf(buf, sizeof(buf), "%" INT64_T_FORMAT "u", 490267843Sdelphij (unsigned long long)v); 491267843Sdelphij if (file_printf(ms, F(ms, m, "%s"), buf) == -1) 492267843Sdelphij return -1; 493267843Sdelphij break; 494267843Sdelphij default: 495267843Sdelphij if (file_printf(ms, F(ms, m, "%" INT64_T_FORMAT "u"), 496267843Sdelphij (unsigned long long) v) == -1) 497267843Sdelphij return -1; 498267843Sdelphij break; 499267843Sdelphij } 500169942Sobrien t = ms->offset + sizeof(int64_t); 501169942Sobrien break; 502169962Sobrien 503133359Sobrien case FILE_STRING: 504133359Sobrien case FILE_PSTRING: 505139368Sobrien case FILE_BESTRING16: 506139368Sobrien case FILE_LESTRING16: 507159764Sobrien if (m->reln == '=' || m->reln == '!') { 508284193Sdelphij if (file_printf(ms, F(ms, m, "%s"), 509284193Sdelphij file_printable(sbuf, sizeof(sbuf), m->value.s)) 510284193Sdelphij == -1) 511133359Sobrien return -1; 512169942Sobrien t = ms->offset + m->vallen; 51368349Sobrien } 51468349Sobrien else { 515267843Sdelphij char *str = p->s; 516267843Sdelphij 517267843Sdelphij /* compute t before we mangle the string? */ 518267843Sdelphij t = ms->offset + strlen(str); 519267843Sdelphij 520175296Sobrien if (*m->value.s == '\0') 521267843Sdelphij str[strcspn(str, "\n")] = '\0'; 522267843Sdelphij 523267843Sdelphij if (m->str_flags & STRING_TRIM) { 524267843Sdelphij char *last; 525267843Sdelphij while (isspace((unsigned char)*str)) 526267843Sdelphij str++; 527267843Sdelphij last = str; 528267843Sdelphij while (*last) 529267843Sdelphij last++; 530267843Sdelphij --last; 531267843Sdelphij while (isspace((unsigned char)*last)) 532267843Sdelphij last--; 533267843Sdelphij *++last = '\0'; 534267843Sdelphij } 535267843Sdelphij 536284193Sdelphij if (file_printf(ms, F(ms, m, "%s"), 537284193Sdelphij file_printable(sbuf, sizeof(sbuf), str)) == -1) 538133359Sobrien return -1; 539267843Sdelphij 540186690Sobrien if (m->type == FILE_PSTRING) 541226048Sobrien t += file_pstring_length_size(m); 54268349Sobrien } 54368349Sobrien break; 54468349Sobrien 545133359Sobrien case FILE_DATE: 546133359Sobrien case FILE_BEDATE: 547133359Sobrien case FILE_LEDATE: 548159764Sobrien case FILE_MEDATE: 549267843Sdelphij if (file_printf(ms, F(ms, m, "%s"), 550267843Sdelphij file_fmttime(p->l + m->num_mask, FILE_T_LOCAL, tbuf)) == -1) 551133359Sobrien return -1; 552267843Sdelphij t = ms->offset + sizeof(uint32_t); 55368349Sobrien break; 55468349Sobrien 555133359Sobrien case FILE_LDATE: 556133359Sobrien case FILE_BELDATE: 557133359Sobrien case FILE_LELDATE: 558159764Sobrien case FILE_MELDATE: 559267843Sdelphij if (file_printf(ms, F(ms, m, "%s"), 560267843Sdelphij file_fmttime(p->l + m->num_mask, 0, tbuf)) == -1) 561133359Sobrien return -1; 562267843Sdelphij t = ms->offset + sizeof(uint32_t); 56380588Sobrien break; 564169942Sobrien 565169942Sobrien case FILE_QDATE: 566169942Sobrien case FILE_BEQDATE: 567169942Sobrien case FILE_LEQDATE: 568267843Sdelphij if (file_printf(ms, F(ms, m, "%s"), 569267843Sdelphij file_fmttime(p->q + m->num_mask, FILE_T_LOCAL, tbuf)) == -1) 570169942Sobrien return -1; 571169942Sobrien t = ms->offset + sizeof(uint64_t); 572169942Sobrien break; 573169942Sobrien 574169942Sobrien case FILE_QLDATE: 575169942Sobrien case FILE_BEQLDATE: 576169942Sobrien case FILE_LEQLDATE: 577267843Sdelphij if (file_printf(ms, F(ms, m, "%s"), 578267843Sdelphij file_fmttime(p->q + m->num_mask, 0, tbuf)) == -1) 579169942Sobrien return -1; 580169942Sobrien t = ms->offset + sizeof(uint64_t); 581169942Sobrien break; 582169942Sobrien 583267843Sdelphij case FILE_QWDATE: 584267843Sdelphij case FILE_BEQWDATE: 585267843Sdelphij case FILE_LEQWDATE: 586267843Sdelphij if (file_printf(ms, F(ms, m, "%s"), 587267843Sdelphij file_fmttime(p->q + m->num_mask, FILE_T_WINDOWS, tbuf)) == -1) 588267843Sdelphij return -1; 589267843Sdelphij t = ms->offset + sizeof(uint64_t); 590267843Sdelphij break; 591267843Sdelphij 592175296Sobrien case FILE_FLOAT: 593175296Sobrien case FILE_BEFLOAT: 594175296Sobrien case FILE_LEFLOAT: 595175296Sobrien vf = p->f; 596175296Sobrien switch (check_fmt(ms, m)) { 597175296Sobrien case -1: 598175296Sobrien return -1; 599175296Sobrien case 1: 600191736Sobrien (void)snprintf(buf, sizeof(buf), "%g", vf); 601267843Sdelphij if (file_printf(ms, F(ms, m, "%s"), buf) == -1) 602175296Sobrien return -1; 603175296Sobrien break; 604175296Sobrien default: 605267843Sdelphij if (file_printf(ms, F(ms, m, "%g"), vf) == -1) 606175296Sobrien return -1; 607175296Sobrien break; 608175296Sobrien } 609175296Sobrien t = ms->offset + sizeof(float); 610175296Sobrien break; 611175296Sobrien 612175296Sobrien case FILE_DOUBLE: 613175296Sobrien case FILE_BEDOUBLE: 614175296Sobrien case FILE_LEDOUBLE: 615175296Sobrien vd = p->d; 616175296Sobrien switch (check_fmt(ms, m)) { 617175296Sobrien case -1: 618175296Sobrien return -1; 619175296Sobrien case 1: 620191736Sobrien (void)snprintf(buf, sizeof(buf), "%g", vd); 621267843Sdelphij if (file_printf(ms, F(ms, m, "%s"), buf) == -1) 622175296Sobrien return -1; 623175296Sobrien break; 624175296Sobrien default: 625267843Sdelphij if (file_printf(ms, F(ms, m, "%g"), vd) == -1) 626175296Sobrien return -1; 627175296Sobrien break; 628175296Sobrien } 629175296Sobrien t = ms->offset + sizeof(double); 630175296Sobrien break; 631175296Sobrien 632169962Sobrien case FILE_REGEX: { 633169962Sobrien char *cp; 634169962Sobrien int rval; 635169962Sobrien 636169962Sobrien cp = strndup((const char *)ms->search.s, ms->search.rm_len); 637169962Sobrien if (cp == NULL) { 638169962Sobrien file_oomem(ms, ms->search.rm_len); 639133359Sobrien return -1; 640169962Sobrien } 641284193Sdelphij rval = file_printf(ms, F(ms, m, "%s"), 642284193Sdelphij file_printable(sbuf, sizeof(sbuf), cp)); 643169962Sobrien free(cp); 644169962Sobrien 645169962Sobrien if (rval == -1) 646169962Sobrien return -1; 647169962Sobrien 648169962Sobrien if ((m->str_flags & REGEX_OFFSET_START)) 649169962Sobrien t = ms->search.offset; 650169962Sobrien else 651169962Sobrien t = ms->search.offset + ms->search.rm_len; 652103373Sobrien break; 653169962Sobrien } 654169942Sobrien 655159764Sobrien case FILE_SEARCH: 656284193Sdelphij if (file_printf(ms, F(ms, m, "%s"), 657284193Sdelphij file_printable(sbuf, sizeof(sbuf), m->value.s)) == -1) 658159764Sobrien return -1; 659169962Sobrien if ((m->str_flags & REGEX_OFFSET_START)) 660169962Sobrien t = ms->search.offset; 661169962Sobrien else 662169962Sobrien t = ms->search.offset + m->vallen; 663159764Sobrien break; 66480588Sobrien 665169962Sobrien case FILE_DEFAULT: 666267843Sdelphij case FILE_CLEAR: 667267843Sdelphij if (file_printf(ms, "%s", m->desc) == -1) 668169962Sobrien return -1; 669169962Sobrien t = ms->offset; 670169962Sobrien break; 671169962Sobrien 672191736Sobrien case FILE_INDIRECT: 673267843Sdelphij case FILE_USE: 674267843Sdelphij case FILE_NAME: 675191736Sobrien t = ms->offset; 676191736Sobrien break; 677191736Sobrien 67868349Sobrien default: 679169962Sobrien file_magerror(ms, "invalid m->type (%d) in mprint()", m->type); 680133359Sobrien return -1; 68168349Sobrien } 682191736Sobrien return (int32_t)t; 68368349Sobrien} 68468349Sobrien 685191736Sobrienprivate int32_t 686191736Sobrienmoffset(struct magic_set *ms, struct magic *m) 687191736Sobrien{ 688191736Sobrien switch (m->type) { 689191736Sobrien case FILE_BYTE: 690226048Sobrien return CAST(int32_t, (ms->offset + sizeof(char))); 691169942Sobrien 692191736Sobrien case FILE_SHORT: 693191736Sobrien case FILE_BESHORT: 694191736Sobrien case FILE_LESHORT: 695226048Sobrien return CAST(int32_t, (ms->offset + sizeof(short))); 696191736Sobrien 697191736Sobrien case FILE_LONG: 698191736Sobrien case FILE_BELONG: 699191736Sobrien case FILE_LELONG: 700191736Sobrien case FILE_MELONG: 701226048Sobrien return CAST(int32_t, (ms->offset + sizeof(int32_t))); 702191736Sobrien 703191736Sobrien case FILE_QUAD: 704191736Sobrien case FILE_BEQUAD: 705191736Sobrien case FILE_LEQUAD: 706226048Sobrien return CAST(int32_t, (ms->offset + sizeof(int64_t))); 707191736Sobrien 708191736Sobrien case FILE_STRING: 709191736Sobrien case FILE_PSTRING: 710191736Sobrien case FILE_BESTRING16: 711191736Sobrien case FILE_LESTRING16: 712191736Sobrien if (m->reln == '=' || m->reln == '!') 713191736Sobrien return ms->offset + m->vallen; 714191736Sobrien else { 715191736Sobrien union VALUETYPE *p = &ms->ms_value; 716191736Sobrien uint32_t t; 717191736Sobrien 718191736Sobrien if (*m->value.s == '\0') 719191736Sobrien p->s[strcspn(p->s, "\n")] = '\0'; 720226048Sobrien t = CAST(uint32_t, (ms->offset + strlen(p->s))); 721191736Sobrien if (m->type == FILE_PSTRING) 722267843Sdelphij t += (uint32_t)file_pstring_length_size(m); 723191736Sobrien return t; 724191736Sobrien } 725191736Sobrien 726191736Sobrien case FILE_DATE: 727191736Sobrien case FILE_BEDATE: 728191736Sobrien case FILE_LEDATE: 729191736Sobrien case FILE_MEDATE: 730267843Sdelphij return CAST(int32_t, (ms->offset + sizeof(uint32_t))); 731191736Sobrien 732191736Sobrien case FILE_LDATE: 733191736Sobrien case FILE_BELDATE: 734191736Sobrien case FILE_LELDATE: 735191736Sobrien case FILE_MELDATE: 736267843Sdelphij return CAST(int32_t, (ms->offset + sizeof(uint32_t))); 737191736Sobrien 738191736Sobrien case FILE_QDATE: 739191736Sobrien case FILE_BEQDATE: 740191736Sobrien case FILE_LEQDATE: 741226048Sobrien return CAST(int32_t, (ms->offset + sizeof(uint64_t))); 742191736Sobrien 743191736Sobrien case FILE_QLDATE: 744191736Sobrien case FILE_BEQLDATE: 745191736Sobrien case FILE_LEQLDATE: 746226048Sobrien return CAST(int32_t, (ms->offset + sizeof(uint64_t))); 747191736Sobrien 748191736Sobrien case FILE_FLOAT: 749191736Sobrien case FILE_BEFLOAT: 750191736Sobrien case FILE_LEFLOAT: 751226048Sobrien return CAST(int32_t, (ms->offset + sizeof(float))); 752191736Sobrien 753191736Sobrien case FILE_DOUBLE: 754191736Sobrien case FILE_BEDOUBLE: 755191736Sobrien case FILE_LEDOUBLE: 756226048Sobrien return CAST(int32_t, (ms->offset + sizeof(double))); 757191736Sobrien 758191736Sobrien case FILE_REGEX: 759191736Sobrien if ((m->str_flags & REGEX_OFFSET_START) != 0) 760226048Sobrien return CAST(int32_t, ms->search.offset); 761191736Sobrien else 762226048Sobrien return CAST(int32_t, (ms->search.offset + 763226048Sobrien ms->search.rm_len)); 764191736Sobrien 765191736Sobrien case FILE_SEARCH: 766191736Sobrien if ((m->str_flags & REGEX_OFFSET_START) != 0) 767226048Sobrien return CAST(int32_t, ms->search.offset); 768191736Sobrien else 769226048Sobrien return CAST(int32_t, (ms->search.offset + m->vallen)); 770191736Sobrien 771267843Sdelphij case FILE_CLEAR: 772191736Sobrien case FILE_DEFAULT: 773191736Sobrien case FILE_INDIRECT: 774191736Sobrien return ms->offset; 775191736Sobrien 776191736Sobrien default: 777191736Sobrien return 0; 778191736Sobrien } 779191736Sobrien} 780191736Sobrien 781267843Sdelphijprivate int 782267843Sdelphijcvt_flip(int type, int flip) 783267843Sdelphij{ 784267843Sdelphij if (flip == 0) 785267843Sdelphij return type; 786267843Sdelphij switch (type) { 787267843Sdelphij case FILE_BESHORT: 788267843Sdelphij return FILE_LESHORT; 789267843Sdelphij case FILE_BELONG: 790267843Sdelphij return FILE_LELONG; 791267843Sdelphij case FILE_BEDATE: 792267843Sdelphij return FILE_LEDATE; 793267843Sdelphij case FILE_BELDATE: 794267843Sdelphij return FILE_LELDATE; 795267843Sdelphij case FILE_BEQUAD: 796267843Sdelphij return FILE_LEQUAD; 797267843Sdelphij case FILE_BEQDATE: 798267843Sdelphij return FILE_LEQDATE; 799267843Sdelphij case FILE_BEQLDATE: 800267843Sdelphij return FILE_LEQLDATE; 801267843Sdelphij case FILE_BEQWDATE: 802267843Sdelphij return FILE_LEQWDATE; 803267843Sdelphij case FILE_LESHORT: 804267843Sdelphij return FILE_BESHORT; 805267843Sdelphij case FILE_LELONG: 806267843Sdelphij return FILE_BELONG; 807267843Sdelphij case FILE_LEDATE: 808267843Sdelphij return FILE_BEDATE; 809267843Sdelphij case FILE_LELDATE: 810267843Sdelphij return FILE_BELDATE; 811267843Sdelphij case FILE_LEQUAD: 812267843Sdelphij return FILE_BEQUAD; 813267843Sdelphij case FILE_LEQDATE: 814267843Sdelphij return FILE_BEQDATE; 815267843Sdelphij case FILE_LEQLDATE: 816267843Sdelphij return FILE_BEQLDATE; 817267843Sdelphij case FILE_LEQWDATE: 818267843Sdelphij return FILE_BEQWDATE; 819267843Sdelphij case FILE_BEFLOAT: 820267843Sdelphij return FILE_LEFLOAT; 821267843Sdelphij case FILE_LEFLOAT: 822267843Sdelphij return FILE_BEFLOAT; 823267843Sdelphij case FILE_BEDOUBLE: 824267843Sdelphij return FILE_LEDOUBLE; 825267843Sdelphij case FILE_LEDOUBLE: 826267843Sdelphij return FILE_BEDOUBLE; 827267843Sdelphij default: 828267843Sdelphij return type; 829267843Sdelphij } 830267843Sdelphij} 831169942Sobrien#define DO_CVT(fld, cast) \ 832169962Sobrien if (m->num_mask) \ 833169962Sobrien switch (m->mask_op & FILE_OPS_MASK) { \ 834169942Sobrien case FILE_OPAND: \ 835169962Sobrien p->fld &= cast m->num_mask; \ 836169942Sobrien break; \ 837169942Sobrien case FILE_OPOR: \ 838169962Sobrien p->fld |= cast m->num_mask; \ 839169942Sobrien break; \ 840169942Sobrien case FILE_OPXOR: \ 841169962Sobrien p->fld ^= cast m->num_mask; \ 842169942Sobrien break; \ 843169942Sobrien case FILE_OPADD: \ 844169962Sobrien p->fld += cast m->num_mask; \ 845169942Sobrien break; \ 846169942Sobrien case FILE_OPMINUS: \ 847169962Sobrien p->fld -= cast m->num_mask; \ 848169942Sobrien break; \ 849169942Sobrien case FILE_OPMULTIPLY: \ 850169962Sobrien p->fld *= cast m->num_mask; \ 851169942Sobrien break; \ 852169942Sobrien case FILE_OPDIVIDE: \ 853169962Sobrien p->fld /= cast m->num_mask; \ 854169942Sobrien break; \ 855169942Sobrien case FILE_OPMODULO: \ 856169962Sobrien p->fld %= cast m->num_mask; \ 857169942Sobrien break; \ 858169942Sobrien } \ 859169942Sobrien if (m->mask_op & FILE_OPINVERSE) \ 860169942Sobrien p->fld = ~p->fld \ 861169942Sobrien 862169942Sobrienprivate void 863169942Sobriencvt_8(union VALUETYPE *p, const struct magic *m) 864169942Sobrien{ 865169942Sobrien DO_CVT(b, (uint8_t)); 866169942Sobrien} 867169942Sobrien 868169942Sobrienprivate void 869169942Sobriencvt_16(union VALUETYPE *p, const struct magic *m) 870169942Sobrien{ 871169942Sobrien DO_CVT(h, (uint16_t)); 872169942Sobrien} 873169942Sobrien 874169942Sobrienprivate void 875169942Sobriencvt_32(union VALUETYPE *p, const struct magic *m) 876169942Sobrien{ 877169942Sobrien DO_CVT(l, (uint32_t)); 878169942Sobrien} 879169942Sobrien 880169942Sobrienprivate void 881169942Sobriencvt_64(union VALUETYPE *p, const struct magic *m) 882169942Sobrien{ 883169942Sobrien DO_CVT(q, (uint64_t)); 884169942Sobrien} 885169942Sobrien 886175296Sobrien#define DO_CVT2(fld, cast) \ 887175296Sobrien if (m->num_mask) \ 888175296Sobrien switch (m->mask_op & FILE_OPS_MASK) { \ 889175296Sobrien case FILE_OPADD: \ 890175296Sobrien p->fld += cast m->num_mask; \ 891175296Sobrien break; \ 892175296Sobrien case FILE_OPMINUS: \ 893175296Sobrien p->fld -= cast m->num_mask; \ 894175296Sobrien break; \ 895175296Sobrien case FILE_OPMULTIPLY: \ 896175296Sobrien p->fld *= cast m->num_mask; \ 897175296Sobrien break; \ 898175296Sobrien case FILE_OPDIVIDE: \ 899175296Sobrien p->fld /= cast m->num_mask; \ 900175296Sobrien break; \ 901175296Sobrien } \ 902175296Sobrien 903175296Sobrienprivate void 904175296Sobriencvt_float(union VALUETYPE *p, const struct magic *m) 905175296Sobrien{ 906175296Sobrien DO_CVT2(f, (float)); 907175296Sobrien} 908175296Sobrien 909175296Sobrienprivate void 910175296Sobriencvt_double(union VALUETYPE *p, const struct magic *m) 911175296Sobrien{ 912175296Sobrien DO_CVT2(d, (double)); 913175296Sobrien} 914175296Sobrien 91568349Sobrien/* 91668349Sobrien * Convert the byte order of the data we are looking at 91780588Sobrien * While we're here, let's apply the mask operation 91880588Sobrien * (unless you have a better idea) 91968349Sobrien */ 920133359Sobrienprivate int 921267843Sdelphijmconvert(struct magic_set *ms, struct magic *m, int flip) 92268349Sobrien{ 923169962Sobrien union VALUETYPE *p = &ms->ms_value; 924267843Sdelphij uint8_t type; 925169962Sobrien 926267843Sdelphij switch (type = cvt_flip(m->type, flip)) { 927133359Sobrien case FILE_BYTE: 928169942Sobrien cvt_8(p, m); 92980588Sobrien return 1; 930133359Sobrien case FILE_SHORT: 931169942Sobrien cvt_16(p, m); 93280588Sobrien return 1; 933133359Sobrien case FILE_LONG: 934133359Sobrien case FILE_DATE: 935133359Sobrien case FILE_LDATE: 936169942Sobrien cvt_32(p, m); 93768349Sobrien return 1; 938169942Sobrien case FILE_QUAD: 939169942Sobrien case FILE_QDATE: 940169942Sobrien case FILE_QLDATE: 941267843Sdelphij case FILE_QWDATE: 942169942Sobrien cvt_64(p, m); 943169942Sobrien return 1; 944133359Sobrien case FILE_STRING: 945139368Sobrien case FILE_BESTRING16: 946169962Sobrien case FILE_LESTRING16: { 947169962Sobrien /* Null terminate and eat *trailing* return */ 948169962Sobrien p->s[sizeof(p->s) - 1] = '\0'; 949169962Sobrien return 1; 950169962Sobrien } 951169962Sobrien case FILE_PSTRING: { 952267843Sdelphij size_t sz = file_pstring_length_size(m); 953267843Sdelphij char *ptr1 = p->s, *ptr2 = ptr1 + sz; 954226048Sobrien size_t len = file_pstring_get_length(m, ptr1); 955284193Sdelphij sz = sizeof(p->s) - sz; /* maximum length of string */ 956284193Sdelphij if (len >= sz) { 957267843Sdelphij /* 958267843Sdelphij * The size of the pascal string length (sz) 959267843Sdelphij * is 1, 2, or 4. We need at least 1 byte for NUL 960267843Sdelphij * termination, but we've already truncated the 961267843Sdelphij * string by p->s, so we need to deduct sz. 962284193Sdelphij * Because we can use one of the bytes of the length 963284193Sdelphij * after we shifted as NUL termination. 964267843Sdelphij */ 965284193Sdelphij len = sz; 966267843Sdelphij } 967169962Sobrien while (len--) 968169962Sobrien *ptr1++ = *ptr2++; 969169962Sobrien *ptr1 = '\0'; 970169962Sobrien return 1; 971169962Sobrien } 972133359Sobrien case FILE_BESHORT: 97368349Sobrien p->h = (short)((p->hs[0]<<8)|(p->hs[1])); 974169942Sobrien cvt_16(p, m); 97568349Sobrien return 1; 976133359Sobrien case FILE_BELONG: 977133359Sobrien case FILE_BEDATE: 978133359Sobrien case FILE_BELDATE: 979103373Sobrien p->l = (int32_t) 98068349Sobrien ((p->hl[0]<<24)|(p->hl[1]<<16)|(p->hl[2]<<8)|(p->hl[3])); 981267843Sdelphij if (type == FILE_BELONG) 982267843Sdelphij cvt_32(p, m); 98368349Sobrien return 1; 984169942Sobrien case FILE_BEQUAD: 985169942Sobrien case FILE_BEQDATE: 986169942Sobrien case FILE_BEQLDATE: 987267843Sdelphij case FILE_BEQWDATE: 988186690Sobrien p->q = (uint64_t) 989186690Sobrien (((uint64_t)p->hq[0]<<56)|((uint64_t)p->hq[1]<<48)| 990186690Sobrien ((uint64_t)p->hq[2]<<40)|((uint64_t)p->hq[3]<<32)| 991186690Sobrien ((uint64_t)p->hq[4]<<24)|((uint64_t)p->hq[5]<<16)| 992186690Sobrien ((uint64_t)p->hq[6]<<8)|((uint64_t)p->hq[7])); 993267843Sdelphij if (type == FILE_BEQUAD) 994267843Sdelphij cvt_64(p, m); 995169942Sobrien return 1; 996133359Sobrien case FILE_LESHORT: 99768349Sobrien p->h = (short)((p->hs[1]<<8)|(p->hs[0])); 998169942Sobrien cvt_16(p, m); 99968349Sobrien return 1; 1000133359Sobrien case FILE_LELONG: 1001133359Sobrien case FILE_LEDATE: 1002133359Sobrien case FILE_LELDATE: 1003103373Sobrien p->l = (int32_t) 100468349Sobrien ((p->hl[3]<<24)|(p->hl[2]<<16)|(p->hl[1]<<8)|(p->hl[0])); 1005267843Sdelphij if (type == FILE_LELONG) 1006267843Sdelphij cvt_32(p, m); 100768349Sobrien return 1; 1008169942Sobrien case FILE_LEQUAD: 1009169942Sobrien case FILE_LEQDATE: 1010169942Sobrien case FILE_LEQLDATE: 1011267843Sdelphij case FILE_LEQWDATE: 1012186690Sobrien p->q = (uint64_t) 1013186690Sobrien (((uint64_t)p->hq[7]<<56)|((uint64_t)p->hq[6]<<48)| 1014186690Sobrien ((uint64_t)p->hq[5]<<40)|((uint64_t)p->hq[4]<<32)| 1015186690Sobrien ((uint64_t)p->hq[3]<<24)|((uint64_t)p->hq[2]<<16)| 1016186690Sobrien ((uint64_t)p->hq[1]<<8)|((uint64_t)p->hq[0])); 1017267843Sdelphij if (type == FILE_LEQUAD) 1018267843Sdelphij cvt_64(p, m); 1019169942Sobrien return 1; 1020159764Sobrien case FILE_MELONG: 1021159764Sobrien case FILE_MEDATE: 1022159764Sobrien case FILE_MELDATE: 1023159764Sobrien p->l = (int32_t) 1024159764Sobrien ((p->hl[1]<<24)|(p->hl[0]<<16)|(p->hl[3]<<8)|(p->hl[2])); 1025267843Sdelphij if (type == FILE_MELONG) 1026267843Sdelphij cvt_32(p, m); 1027159764Sobrien return 1; 1028175296Sobrien case FILE_FLOAT: 1029175296Sobrien cvt_float(p, m); 1030175296Sobrien return 1; 1031175296Sobrien case FILE_BEFLOAT: 1032175296Sobrien p->l = ((uint32_t)p->hl[0]<<24)|((uint32_t)p->hl[1]<<16)| 1033175296Sobrien ((uint32_t)p->hl[2]<<8) |((uint32_t)p->hl[3]); 1034175296Sobrien cvt_float(p, m); 1035175296Sobrien return 1; 1036175296Sobrien case FILE_LEFLOAT: 1037175296Sobrien p->l = ((uint32_t)p->hl[3]<<24)|((uint32_t)p->hl[2]<<16)| 1038175296Sobrien ((uint32_t)p->hl[1]<<8) |((uint32_t)p->hl[0]); 1039175296Sobrien cvt_float(p, m); 1040175296Sobrien return 1; 1041175296Sobrien case FILE_DOUBLE: 1042175296Sobrien cvt_double(p, m); 1043175296Sobrien return 1; 1044175296Sobrien case FILE_BEDOUBLE: 1045175296Sobrien p->q = ((uint64_t)p->hq[0]<<56)|((uint64_t)p->hq[1]<<48)| 1046175296Sobrien ((uint64_t)p->hq[2]<<40)|((uint64_t)p->hq[3]<<32)| 1047175296Sobrien ((uint64_t)p->hq[4]<<24)|((uint64_t)p->hq[5]<<16)| 1048175296Sobrien ((uint64_t)p->hq[6]<<8) |((uint64_t)p->hq[7]); 1049175296Sobrien cvt_double(p, m); 1050175296Sobrien return 1; 1051175296Sobrien case FILE_LEDOUBLE: 1052175296Sobrien p->q = ((uint64_t)p->hq[7]<<56)|((uint64_t)p->hq[6]<<48)| 1053175296Sobrien ((uint64_t)p->hq[5]<<40)|((uint64_t)p->hq[4]<<32)| 1054175296Sobrien ((uint64_t)p->hq[3]<<24)|((uint64_t)p->hq[2]<<16)| 1055175296Sobrien ((uint64_t)p->hq[1]<<8) |((uint64_t)p->hq[0]); 1056175296Sobrien cvt_double(p, m); 1057175296Sobrien return 1; 1058133359Sobrien case FILE_REGEX: 1059159764Sobrien case FILE_SEARCH: 1060169962Sobrien case FILE_DEFAULT: 1061267843Sdelphij case FILE_CLEAR: 1062267843Sdelphij case FILE_NAME: 1063267843Sdelphij case FILE_USE: 1064103373Sobrien return 1; 106568349Sobrien default: 1066169962Sobrien file_magerror(ms, "invalid type %d in mconvert()", m->type); 106768349Sobrien return 0; 106868349Sobrien } 106968349Sobrien} 107068349Sobrien 107168349Sobrien 1072133359Sobrienprivate void 1073133359Sobrienmdebug(uint32_t offset, const char *str, size_t len) 107468349Sobrien{ 1075284193Sdelphij (void) fprintf(stderr, "mget/%" SIZE_T_FORMAT "u @%d: ", len, offset); 1076133359Sobrien file_showstr(stderr, str, len); 107768349Sobrien (void) fputc('\n', stderr); 107868349Sobrien (void) fputc('\n', stderr); 107968349Sobrien} 108068349Sobrien 1081133359Sobrienprivate int 1082139368Sobrienmcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir, 1083267843Sdelphij const unsigned char *s, uint32_t offset, size_t nbytes, struct magic *m) 108468349Sobrien{ 1085169962Sobrien /* 1086169962Sobrien * Note: FILE_SEARCH and FILE_REGEX do not actually copy 1087169962Sobrien * anything, but setup pointers into the source 1088169962Sobrien */ 1089169962Sobrien if (indir == 0) { 1090169962Sobrien switch (type) { 1091169962Sobrien case FILE_SEARCH: 1092226048Sobrien ms->search.s = RCAST(const char *, s) + offset; 1093169962Sobrien ms->search.s_len = nbytes - offset; 1094186690Sobrien ms->search.offset = offset; 1095159764Sobrien return 0; 109668349Sobrien 1097169962Sobrien case FILE_REGEX: { 1098169962Sobrien const char *b; 1099169962Sobrien const char *c; 1100169962Sobrien const char *last; /* end of search region */ 1101169962Sobrien const char *buf; /* start of search region */ 1102191736Sobrien const char *end; 1103267843Sdelphij size_t lines, linecnt, bytecnt; 1104139368Sobrien 1105169962Sobrien if (s == NULL) { 1106169962Sobrien ms->search.s_len = 0; 1107169962Sobrien ms->search.s = NULL; 1108169962Sobrien return 0; 1109169962Sobrien } 1110267843Sdelphij 1111267843Sdelphij if (m->str_flags & REGEX_LINE_COUNT) { 1112267843Sdelphij linecnt = m->str_range; 1113267843Sdelphij bytecnt = linecnt * 80; 1114267843Sdelphij } else { 1115267843Sdelphij linecnt = 0; 1116267843Sdelphij bytecnt = m->str_range; 1117267843Sdelphij } 1118267843Sdelphij 1119267843Sdelphij if (bytecnt == 0) 1120267843Sdelphij bytecnt = 8192; 1121267843Sdelphij if (bytecnt > nbytes) 1122267843Sdelphij bytecnt = nbytes; 1123267843Sdelphij 1124226048Sobrien buf = RCAST(const char *, s) + offset; 1125267843Sdelphij end = last = RCAST(const char *, s) + bytecnt; 1126169962Sobrien /* mget() guarantees buf <= last */ 1127226048Sobrien for (lines = linecnt, b = buf; lines && b < end && 1128226048Sobrien ((b = CAST(const char *, 1129226048Sobrien memchr(c = b, '\n', CAST(size_t, (end - b))))) 1130226048Sobrien || (b = CAST(const char *, 1131226048Sobrien memchr(c, '\r', CAST(size_t, (end - c)))))); 1132169962Sobrien lines--, b++) { 1133169962Sobrien last = b; 1134169962Sobrien if (b[0] == '\r' && b[1] == '\n') 1135169962Sobrien b++; 1136169962Sobrien } 1137169962Sobrien if (lines) 1138267843Sdelphij last = RCAST(const char *, s) + bytecnt; 1139191736Sobrien 1140169962Sobrien ms->search.s = buf; 1141169962Sobrien ms->search.s_len = last - buf; 1142169962Sobrien ms->search.offset = offset; 1143169962Sobrien ms->search.rm_len = 0; 1144169962Sobrien return 0; 1145169942Sobrien } 1146169962Sobrien case FILE_BESTRING16: 1147169962Sobrien case FILE_LESTRING16: { 1148169962Sobrien const unsigned char *src = s + offset; 1149169962Sobrien const unsigned char *esrc = s + nbytes; 1150169962Sobrien char *dst = p->s; 1151169962Sobrien char *edst = &p->s[sizeof(p->s) - 1]; 1152191736Sobrien 1153169962Sobrien if (type == FILE_BESTRING16) 1154169962Sobrien src++; 1155191736Sobrien 1156267843Sdelphij /* check that offset is within range */ 1157267843Sdelphij if (offset >= nbytes) 1158267843Sdelphij break; 1159175296Sobrien for (/*EMPTY*/; src < esrc; src += 2, dst++) { 1160169962Sobrien if (dst < edst) 1161175296Sobrien *dst = *src; 1162169962Sobrien else 1163169962Sobrien break; 1164175296Sobrien if (*dst == '\0') { 1165175296Sobrien if (type == FILE_BESTRING16 ? 1166175296Sobrien *(src - 1) != '\0' : 1167175296Sobrien *(src + 1) != '\0') 1168175296Sobrien *dst = ' '; 1169175296Sobrien } 1170169962Sobrien } 1171169962Sobrien *edst = '\0'; 1172169962Sobrien return 0; 1173139368Sobrien } 1174169962Sobrien case FILE_STRING: /* XXX - these two should not need */ 1175169962Sobrien case FILE_PSTRING: /* to copy anything, but do anyway. */ 1176169962Sobrien default: 1177169962Sobrien break; 1178169962Sobrien } 1179139368Sobrien } 1180139368Sobrien 1181139368Sobrien if (offset >= nbytes) { 1182139368Sobrien (void)memset(p, '\0', sizeof(*p)); 1183139368Sobrien return 0; 1184139368Sobrien } 1185139368Sobrien if (nbytes - offset < sizeof(*p)) 1186139368Sobrien nbytes = nbytes - offset; 1187139368Sobrien else 1188139368Sobrien nbytes = sizeof(*p); 1189139368Sobrien 1190139368Sobrien (void)memcpy(p, s + offset, nbytes); 1191139368Sobrien 1192139368Sobrien /* 1193139368Sobrien * the usefulness of padding with zeroes eludes me, it 1194139368Sobrien * might even cause problems 1195139368Sobrien */ 1196139368Sobrien if (nbytes < sizeof(*p)) 1197159764Sobrien (void)memset(((char *)(void *)p) + nbytes, '\0', 1198159764Sobrien sizeof(*p) - nbytes); 1199139368Sobrien return 0; 1200139368Sobrien} 1201139368Sobrien 1202139368Sobrienprivate int 1203267843Sdelphijmget(struct magic_set *ms, const unsigned char *s, struct magic *m, 1204267843Sdelphij size_t nbytes, size_t o, unsigned int cont_level, int mode, int text, 1205284193Sdelphij int flip, uint16_t indir_level, uint16_t *name_count, 1206284193Sdelphij int *printed_something, int *need_separator, int *returnval) 1207139368Sobrien{ 1208275670Sdelphij uint32_t offset = ms->offset; 1209267843Sdelphij uint32_t lhs; 1210275670Sdelphij file_pushbuf_t *pb; 1211267843Sdelphij int rv, oneed_separator, in_type; 1212275670Sdelphij char *rbuf; 1213169962Sobrien union VALUETYPE *p = &ms->ms_value; 1214267843Sdelphij struct mlist ml; 1215139368Sobrien 1216284193Sdelphij if (indir_level >= ms->indir_max) { 1217284193Sdelphij file_error(ms, 0, "indirect recursion nesting (%hu) exceeded", 1218284193Sdelphij indir_level); 1219139368Sobrien return -1; 1220267843Sdelphij } 1221139368Sobrien 1222284193Sdelphij if (*name_count >= ms->name_max) { 1223284193Sdelphij file_error(ms, 0, "name use count (%hu) exceeded", 1224284193Sdelphij *name_count); 1225284193Sdelphij return -1; 1226284193Sdelphij } 1227284193Sdelphij 1228267843Sdelphij if (mcopy(ms, p, m->type, m->flag & INDIR, s, (uint32_t)(offset + o), 1229267843Sdelphij (uint32_t)nbytes, m) == -1) 1230267843Sdelphij return -1; 1231267843Sdelphij 1232133359Sobrien if ((ms->flags & MAGIC_DEBUG) != 0) { 1233284193Sdelphij fprintf(stderr, "mget(type=%d, flag=%x, offset=%u, o=%" 1234284193Sdelphij SIZE_T_FORMAT "u, " "nbytes=%" SIZE_T_FORMAT 1235284193Sdelphij "u, il=%hu, nc=%hu)\n", 1236284193Sdelphij m->type, m->flag, offset, o, nbytes, 1237284193Sdelphij indir_level, *name_count); 1238133359Sobrien mdebug(offset, (char *)(void *)p, sizeof(union VALUETYPE)); 1239191736Sobrien#ifndef COMPILE_ONLY 1240133359Sobrien file_mdump(m); 1241191736Sobrien#endif 1242133359Sobrien } 1243133359Sobrien 124468349Sobrien if (m->flag & INDIR) { 1245159764Sobrien int off = m->in_offset; 1246159764Sobrien if (m->in_op & FILE_OPINDIRECT) { 1247186690Sobrien const union VALUETYPE *q = CAST(const union VALUETYPE *, 1248186690Sobrien ((const void *)(s + offset + off))); 1249267843Sdelphij switch (cvt_flip(m->in_type, flip)) { 1250159764Sobrien case FILE_BYTE: 1251159764Sobrien off = q->b; 1252159764Sobrien break; 1253159764Sobrien case FILE_SHORT: 1254159764Sobrien off = q->h; 1255159764Sobrien break; 1256159764Sobrien case FILE_BESHORT: 1257159764Sobrien off = (short)((q->hs[0]<<8)|(q->hs[1])); 1258159764Sobrien break; 1259159764Sobrien case FILE_LESHORT: 1260159764Sobrien off = (short)((q->hs[1]<<8)|(q->hs[0])); 1261159764Sobrien break; 1262159764Sobrien case FILE_LONG: 1263159764Sobrien off = q->l; 1264159764Sobrien break; 1265159764Sobrien case FILE_BELONG: 1266191736Sobrien case FILE_BEID3: 1267159764Sobrien off = (int32_t)((q->hl[0]<<24)|(q->hl[1]<<16)| 1268159764Sobrien (q->hl[2]<<8)|(q->hl[3])); 1269159764Sobrien break; 1270191736Sobrien case FILE_LEID3: 1271159764Sobrien case FILE_LELONG: 1272159764Sobrien off = (int32_t)((q->hl[3]<<24)|(q->hl[2]<<16)| 1273159764Sobrien (q->hl[1]<<8)|(q->hl[0])); 1274159764Sobrien break; 1275159764Sobrien case FILE_MELONG: 1276159764Sobrien off = (int32_t)((q->hl[1]<<24)|(q->hl[0]<<16)| 1277159764Sobrien (q->hl[3]<<8)|(q->hl[2])); 1278159764Sobrien break; 1279159764Sobrien } 1280267843Sdelphij if ((ms->flags & MAGIC_DEBUG) != 0) 1281267843Sdelphij fprintf(stderr, "indirect offs=%u\n", off); 1282159764Sobrien } 1283267843Sdelphij switch (in_type = cvt_flip(m->in_type, flip)) { 1284133359Sobrien case FILE_BYTE: 1285267843Sdelphij if (OFFSET_OOB(nbytes, offset, 1)) 1286169962Sobrien return 0; 1287159764Sobrien if (off) { 1288169962Sobrien switch (m->in_op & FILE_OPS_MASK) { 1289133359Sobrien case FILE_OPAND: 1290159764Sobrien offset = p->b & off; 129180588Sobrien break; 1292133359Sobrien case FILE_OPOR: 1293159764Sobrien offset = p->b | off; 129480588Sobrien break; 1295133359Sobrien case FILE_OPXOR: 1296159764Sobrien offset = p->b ^ off; 129780588Sobrien break; 1298133359Sobrien case FILE_OPADD: 1299159764Sobrien offset = p->b + off; 130080588Sobrien break; 1301133359Sobrien case FILE_OPMINUS: 1302159764Sobrien offset = p->b - off; 130380588Sobrien break; 1304133359Sobrien case FILE_OPMULTIPLY: 1305159764Sobrien offset = p->b * off; 130680588Sobrien break; 1307133359Sobrien case FILE_OPDIVIDE: 1308159764Sobrien offset = p->b / off; 130980588Sobrien break; 1310133359Sobrien case FILE_OPMODULO: 1311159764Sobrien offset = p->b % off; 131280588Sobrien break; 131380588Sobrien } 1314133359Sobrien } else 1315133359Sobrien offset = p->b; 1316133359Sobrien if (m->in_op & FILE_OPINVERSE) 131780588Sobrien offset = ~offset; 131868349Sobrien break; 1319133359Sobrien case FILE_BESHORT: 1320267843Sdelphij if (OFFSET_OOB(nbytes, offset, 2)) 1321159764Sobrien return 0; 1322267843Sdelphij lhs = (p->hs[0] << 8) | p->hs[1]; 1323159764Sobrien if (off) { 1324169962Sobrien switch (m->in_op & FILE_OPS_MASK) { 1325133359Sobrien case FILE_OPAND: 1326267843Sdelphij offset = lhs & off; 132780588Sobrien break; 1328133359Sobrien case FILE_OPOR: 1329267843Sdelphij offset = lhs | off; 133080588Sobrien break; 1331133359Sobrien case FILE_OPXOR: 1332267843Sdelphij offset = lhs ^ off; 133380588Sobrien break; 1334133359Sobrien case FILE_OPADD: 1335267843Sdelphij offset = lhs + off; 133680588Sobrien break; 1337133359Sobrien case FILE_OPMINUS: 1338267843Sdelphij offset = lhs - off; 133980588Sobrien break; 1340133359Sobrien case FILE_OPMULTIPLY: 1341267843Sdelphij offset = lhs * off; 134280588Sobrien break; 1343133359Sobrien case FILE_OPDIVIDE: 1344267843Sdelphij offset = lhs / off; 134580588Sobrien break; 1346133359Sobrien case FILE_OPMODULO: 1347267843Sdelphij offset = lhs % off; 134880588Sobrien break; 134980588Sobrien } 1350133359Sobrien } else 1351267843Sdelphij offset = lhs; 1352133359Sobrien if (m->in_op & FILE_OPINVERSE) 135380588Sobrien offset = ~offset; 135468349Sobrien break; 1355133359Sobrien case FILE_LESHORT: 1356267843Sdelphij if (OFFSET_OOB(nbytes, offset, 2)) 1357159764Sobrien return 0; 1358267843Sdelphij lhs = (p->hs[1] << 8) | p->hs[0]; 1359159764Sobrien if (off) { 1360169962Sobrien switch (m->in_op & FILE_OPS_MASK) { 1361133359Sobrien case FILE_OPAND: 1362267843Sdelphij offset = lhs & off; 136380588Sobrien break; 1364133359Sobrien case FILE_OPOR: 1365267843Sdelphij offset = lhs | off; 136680588Sobrien break; 1367133359Sobrien case FILE_OPXOR: 1368267843Sdelphij offset = lhs ^ off; 136980588Sobrien break; 1370133359Sobrien case FILE_OPADD: 1371267843Sdelphij offset = lhs + off; 137280588Sobrien break; 1373133359Sobrien case FILE_OPMINUS: 1374267843Sdelphij offset = lhs - off; 137580588Sobrien break; 1376133359Sobrien case FILE_OPMULTIPLY: 1377267843Sdelphij offset = lhs * off; 137880588Sobrien break; 1379133359Sobrien case FILE_OPDIVIDE: 1380267843Sdelphij offset = lhs / off; 138180588Sobrien break; 1382133359Sobrien case FILE_OPMODULO: 1383267843Sdelphij offset = lhs % off; 138480588Sobrien break; 138580588Sobrien } 1386133359Sobrien } else 1387267843Sdelphij offset = lhs; 1388133359Sobrien if (m->in_op & FILE_OPINVERSE) 138980588Sobrien offset = ~offset; 139068349Sobrien break; 1391133359Sobrien case FILE_SHORT: 1392267843Sdelphij if (OFFSET_OOB(nbytes, offset, 2)) 1393159764Sobrien return 0; 1394159764Sobrien if (off) { 1395169962Sobrien switch (m->in_op & FILE_OPS_MASK) { 1396133359Sobrien case FILE_OPAND: 1397159764Sobrien offset = p->h & off; 139880588Sobrien break; 1399133359Sobrien case FILE_OPOR: 1400159764Sobrien offset = p->h | off; 140180588Sobrien break; 1402133359Sobrien case FILE_OPXOR: 1403159764Sobrien offset = p->h ^ off; 140480588Sobrien break; 1405133359Sobrien case FILE_OPADD: 1406159764Sobrien offset = p->h + off; 140780588Sobrien break; 1408133359Sobrien case FILE_OPMINUS: 1409159764Sobrien offset = p->h - off; 141080588Sobrien break; 1411133359Sobrien case FILE_OPMULTIPLY: 1412159764Sobrien offset = p->h * off; 141380588Sobrien break; 1414133359Sobrien case FILE_OPDIVIDE: 1415159764Sobrien offset = p->h / off; 141680588Sobrien break; 1417133359Sobrien case FILE_OPMODULO: 1418159764Sobrien offset = p->h % off; 141980588Sobrien break; 142080588Sobrien } 1421133359Sobrien } 1422133359Sobrien else 1423133359Sobrien offset = p->h; 1424133359Sobrien if (m->in_op & FILE_OPINVERSE) 142580588Sobrien offset = ~offset; 142668349Sobrien break; 1427133359Sobrien case FILE_BELONG: 1428191736Sobrien case FILE_BEID3: 1429267843Sdelphij if (OFFSET_OOB(nbytes, offset, 4)) 1430159764Sobrien return 0; 1431267843Sdelphij lhs = (p->hl[0] << 24) | (p->hl[1] << 16) | 1432267843Sdelphij (p->hl[2] << 8) | p->hl[3]; 1433159764Sobrien if (off) { 1434169962Sobrien switch (m->in_op & FILE_OPS_MASK) { 1435133359Sobrien case FILE_OPAND: 1436267843Sdelphij offset = lhs & off; 143780588Sobrien break; 1438133359Sobrien case FILE_OPOR: 1439267843Sdelphij offset = lhs | off; 144080588Sobrien break; 1441133359Sobrien case FILE_OPXOR: 1442267843Sdelphij offset = lhs ^ off; 144380588Sobrien break; 1444133359Sobrien case FILE_OPADD: 1445267843Sdelphij offset = lhs + off; 144680588Sobrien break; 1447133359Sobrien case FILE_OPMINUS: 1448267843Sdelphij offset = lhs - off; 144980588Sobrien break; 1450133359Sobrien case FILE_OPMULTIPLY: 1451267843Sdelphij offset = lhs * off; 145280588Sobrien break; 1453133359Sobrien case FILE_OPDIVIDE: 1454267843Sdelphij offset = lhs / off; 145580588Sobrien break; 1456133359Sobrien case FILE_OPMODULO: 1457267843Sdelphij offset = lhs % off; 145880588Sobrien break; 145980588Sobrien } 1460133359Sobrien } else 1461267843Sdelphij offset = lhs; 1462133359Sobrien if (m->in_op & FILE_OPINVERSE) 146380588Sobrien offset = ~offset; 146468349Sobrien break; 1465133359Sobrien case FILE_LELONG: 1466191736Sobrien case FILE_LEID3: 1467267843Sdelphij if (OFFSET_OOB(nbytes, offset, 4)) 1468159764Sobrien return 0; 1469267843Sdelphij lhs = (p->hl[3] << 24) | (p->hl[2] << 16) | 1470267843Sdelphij (p->hl[1] << 8) | p->hl[0]; 1471159764Sobrien if (off) { 1472169962Sobrien switch (m->in_op & FILE_OPS_MASK) { 1473133359Sobrien case FILE_OPAND: 1474267843Sdelphij offset = lhs & off; 147580588Sobrien break; 1476133359Sobrien case FILE_OPOR: 1477267843Sdelphij offset = lhs | off; 147880588Sobrien break; 1479133359Sobrien case FILE_OPXOR: 1480267843Sdelphij offset = lhs ^ off; 148180588Sobrien break; 1482133359Sobrien case FILE_OPADD: 1483267843Sdelphij offset = lhs + off; 148480588Sobrien break; 1485133359Sobrien case FILE_OPMINUS: 1486267843Sdelphij offset = lhs - off; 148780588Sobrien break; 1488133359Sobrien case FILE_OPMULTIPLY: 1489267843Sdelphij offset = lhs * off; 149080588Sobrien break; 1491133359Sobrien case FILE_OPDIVIDE: 1492267843Sdelphij offset = lhs / off; 149380588Sobrien break; 1494133359Sobrien case FILE_OPMODULO: 1495267843Sdelphij offset = lhs % off; 149680588Sobrien break; 149780588Sobrien } 1498133359Sobrien } else 1499267843Sdelphij offset = lhs; 1500133359Sobrien if (m->in_op & FILE_OPINVERSE) 150180588Sobrien offset = ~offset; 150268349Sobrien break; 1503159764Sobrien case FILE_MELONG: 1504267843Sdelphij if (OFFSET_OOB(nbytes, offset, 4)) 1505159764Sobrien return 0; 1506267843Sdelphij lhs = (p->hl[1] << 24) | (p->hl[0] << 16) | 1507267843Sdelphij (p->hl[3] << 8) | p->hl[2]; 1508159764Sobrien if (off) { 1509169962Sobrien switch (m->in_op & FILE_OPS_MASK) { 1510159764Sobrien case FILE_OPAND: 1511267843Sdelphij offset = lhs & off; 1512159764Sobrien break; 1513159764Sobrien case FILE_OPOR: 1514267843Sdelphij offset = lhs | off; 1515159764Sobrien break; 1516159764Sobrien case FILE_OPXOR: 1517267843Sdelphij offset = lhs ^ off; 1518159764Sobrien break; 1519159764Sobrien case FILE_OPADD: 1520267843Sdelphij offset = lhs + off; 1521159764Sobrien break; 1522159764Sobrien case FILE_OPMINUS: 1523267843Sdelphij offset = lhs - off; 1524159764Sobrien break; 1525159764Sobrien case FILE_OPMULTIPLY: 1526267843Sdelphij offset = lhs * off; 1527159764Sobrien break; 1528159764Sobrien case FILE_OPDIVIDE: 1529267843Sdelphij offset = lhs / off; 1530159764Sobrien break; 1531159764Sobrien case FILE_OPMODULO: 1532267843Sdelphij offset = lhs % off; 1533159764Sobrien break; 1534159764Sobrien } 1535159764Sobrien } else 1536267843Sdelphij offset = lhs; 1537159764Sobrien if (m->in_op & FILE_OPINVERSE) 1538159764Sobrien offset = ~offset; 1539159764Sobrien break; 1540133359Sobrien case FILE_LONG: 1541267843Sdelphij if (OFFSET_OOB(nbytes, offset, 4)) 1542159764Sobrien return 0; 1543159764Sobrien if (off) { 1544169962Sobrien switch (m->in_op & FILE_OPS_MASK) { 1545133359Sobrien case FILE_OPAND: 1546159764Sobrien offset = p->l & off; 154780588Sobrien break; 1548133359Sobrien case FILE_OPOR: 1549159764Sobrien offset = p->l | off; 155080588Sobrien break; 1551133359Sobrien case FILE_OPXOR: 1552159764Sobrien offset = p->l ^ off; 155380588Sobrien break; 1554133359Sobrien case FILE_OPADD: 1555159764Sobrien offset = p->l + off; 155680588Sobrien break; 1557133359Sobrien case FILE_OPMINUS: 1558159764Sobrien offset = p->l - off; 155980588Sobrien break; 1560133359Sobrien case FILE_OPMULTIPLY: 1561159764Sobrien offset = p->l * off; 156280588Sobrien break; 1563133359Sobrien case FILE_OPDIVIDE: 1564159764Sobrien offset = p->l / off; 156580588Sobrien break; 1566133359Sobrien case FILE_OPMODULO: 1567159764Sobrien offset = p->l % off; 156880588Sobrien break; 156980588Sobrien } 1570133359Sobrien } else 1571133359Sobrien offset = p->l; 1572133359Sobrien if (m->in_op & FILE_OPINVERSE) 157380588Sobrien offset = ~offset; 157468349Sobrien break; 1575267843Sdelphij default: 1576267843Sdelphij break; 157768349Sobrien } 157868349Sobrien 1579267843Sdelphij switch (in_type) { 1580191736Sobrien case FILE_LEID3: 1581191736Sobrien case FILE_BEID3: 1582191736Sobrien offset = ((((offset >> 0) & 0x7f) << 0) | 1583191736Sobrien (((offset >> 8) & 0x7f) << 7) | 1584191736Sobrien (((offset >> 16) & 0x7f) << 14) | 1585191736Sobrien (((offset >> 24) & 0x7f) << 21)) + 10; 1586191736Sobrien break; 1587191736Sobrien default: 1588191736Sobrien break; 1589191736Sobrien } 1590191736Sobrien 1591191736Sobrien if (m->flag & INDIROFFADD) { 1592169962Sobrien offset += ms->c.li[cont_level-1].off; 1593267843Sdelphij if (offset == 0) { 1594267843Sdelphij if ((ms->flags & MAGIC_DEBUG) != 0) 1595267843Sdelphij fprintf(stderr, 1596267843Sdelphij "indirect *zero* offset\n"); 1597267843Sdelphij return 0; 1598267843Sdelphij } 1599267843Sdelphij if ((ms->flags & MAGIC_DEBUG) != 0) 1600267843Sdelphij fprintf(stderr, "indirect +offs=%u\n", offset); 1601191736Sobrien } 1602267843Sdelphij if (mcopy(ms, p, m->type, 0, s, offset, nbytes, m) == -1) 1603139368Sobrien return -1; 1604169942Sobrien ms->offset = offset; 160568349Sobrien 1606133359Sobrien if ((ms->flags & MAGIC_DEBUG) != 0) { 1607133359Sobrien mdebug(offset, (char *)(void *)p, 1608133359Sobrien sizeof(union VALUETYPE)); 1609191736Sobrien#ifndef COMPILE_ONLY 1610133359Sobrien file_mdump(m); 1611191736Sobrien#endif 161268349Sobrien } 161368349Sobrien } 1614159764Sobrien 1615159764Sobrien /* Verify we have enough data to match magic type */ 1616159764Sobrien switch (m->type) { 1617169962Sobrien case FILE_BYTE: 1618267843Sdelphij if (OFFSET_OOB(nbytes, offset, 1)) 1619169962Sobrien return 0; 1620169962Sobrien break; 1621191736Sobrien 1622169962Sobrien case FILE_SHORT: 1623169962Sobrien case FILE_BESHORT: 1624169962Sobrien case FILE_LESHORT: 1625267843Sdelphij if (OFFSET_OOB(nbytes, offset, 2)) 1626169962Sobrien return 0; 1627169962Sobrien break; 1628191736Sobrien 1629169962Sobrien case FILE_LONG: 1630169962Sobrien case FILE_BELONG: 1631169962Sobrien case FILE_LELONG: 1632169962Sobrien case FILE_MELONG: 1633169962Sobrien case FILE_DATE: 1634169962Sobrien case FILE_BEDATE: 1635169962Sobrien case FILE_LEDATE: 1636169962Sobrien case FILE_MEDATE: 1637169962Sobrien case FILE_LDATE: 1638169962Sobrien case FILE_BELDATE: 1639169962Sobrien case FILE_LELDATE: 1640169962Sobrien case FILE_MELDATE: 1641175296Sobrien case FILE_FLOAT: 1642175296Sobrien case FILE_BEFLOAT: 1643175296Sobrien case FILE_LEFLOAT: 1644267843Sdelphij if (OFFSET_OOB(nbytes, offset, 4)) 1645169962Sobrien return 0; 1646169962Sobrien break; 1647191736Sobrien 1648175296Sobrien case FILE_DOUBLE: 1649175296Sobrien case FILE_BEDOUBLE: 1650175296Sobrien case FILE_LEDOUBLE: 1651267843Sdelphij if (OFFSET_OOB(nbytes, offset, 8)) 1652175296Sobrien return 0; 1653175296Sobrien break; 1654175296Sobrien 1655169962Sobrien case FILE_STRING: 1656169962Sobrien case FILE_PSTRING: 1657169962Sobrien case FILE_SEARCH: 1658267843Sdelphij if (OFFSET_OOB(nbytes, offset, m->vallen)) 1659169962Sobrien return 0; 1660169962Sobrien break; 1661159764Sobrien 1662169962Sobrien case FILE_REGEX: 1663169962Sobrien if (nbytes < offset) 1664169962Sobrien return 0; 1665169962Sobrien break; 1666159764Sobrien 1667191736Sobrien case FILE_INDIRECT: 1668284193Sdelphij if (m->str_flags & INDIRECT_RELATIVE) 1669284193Sdelphij offset += o; 1670267843Sdelphij if (offset == 0) 1671267843Sdelphij return 0; 1672275670Sdelphij 1673191736Sobrien if (nbytes < offset) 1674191736Sobrien return 0; 1675275670Sdelphij 1676275670Sdelphij if ((pb = file_push_buffer(ms)) == NULL) 1677275670Sdelphij return -1; 1678275670Sdelphij 1679267843Sdelphij rv = file_softmagic(ms, s + offset, nbytes - offset, 1680284193Sdelphij indir_level + 1, name_count, BINTEST, text); 1681275670Sdelphij 1682267843Sdelphij if ((ms->flags & MAGIC_DEBUG) != 0) 1683267843Sdelphij fprintf(stderr, "indirect @offs=%u[%d]\n", offset, rv); 1684275670Sdelphij 1685275670Sdelphij rbuf = file_pop_buffer(ms, pb); 1686275670Sdelphij if (rbuf == NULL && ms->event_flags & EVENT_HAD_ERR) 1687275670Sdelphij return -1; 1688275670Sdelphij 1689267843Sdelphij if (rv == 1) { 1690267843Sdelphij if ((ms->flags & (MAGIC_MIME|MAGIC_APPLE)) == 0 && 1691267843Sdelphij file_printf(ms, F(ms, m, "%u"), offset) == -1) { 1692267843Sdelphij free(rbuf); 1693267843Sdelphij return -1; 1694267843Sdelphij } 1695267843Sdelphij if (file_printf(ms, "%s", rbuf) == -1) { 1696267843Sdelphij free(rbuf); 1697267843Sdelphij return -1; 1698267843Sdelphij } 1699267843Sdelphij } 1700267843Sdelphij free(rbuf); 1701267843Sdelphij return rv; 1702191736Sobrien 1703267843Sdelphij case FILE_USE: 1704267843Sdelphij if (nbytes < offset) 1705267843Sdelphij return 0; 1706275670Sdelphij rbuf = m->value.s; 1707275670Sdelphij if (*rbuf == '^') { 1708275670Sdelphij rbuf++; 1709267843Sdelphij flip = !flip; 1710267843Sdelphij } 1711275670Sdelphij if (file_magicfind(ms, rbuf, &ml) == -1) { 1712275670Sdelphij file_error(ms, 0, "cannot find entry `%s'", rbuf); 1713267843Sdelphij return -1; 1714267843Sdelphij } 1715284193Sdelphij (*name_count)++; 1716267843Sdelphij oneed_separator = *need_separator; 1717267843Sdelphij if (m->flag & NOSPACE) 1718267843Sdelphij *need_separator = 0; 1719267843Sdelphij rv = match(ms, ml.magic, ml.nmagic, s, nbytes, offset + o, 1720284193Sdelphij mode, text, flip, indir_level, name_count, 1721284193Sdelphij printed_something, need_separator, returnval); 1722267843Sdelphij if (rv != 1) 1723267843Sdelphij *need_separator = oneed_separator; 1724267843Sdelphij return rv; 1725267843Sdelphij 1726267843Sdelphij case FILE_NAME: 1727267843Sdelphij if (file_printf(ms, "%s", m->desc) == -1) 1728267843Sdelphij return -1; 1729267843Sdelphij return 1; 1730169962Sobrien case FILE_DEFAULT: /* nothing to check */ 1731267843Sdelphij case FILE_CLEAR: 1732169962Sobrien default: 1733169962Sobrien break; 1734169962Sobrien } 1735267843Sdelphij if (!mconvert(ms, m, flip)) 1736169962Sobrien return 0; 1737169962Sobrien return 1; 1738169962Sobrien} 1739159764Sobrien 1740169962Sobrienprivate uint64_t 1741169962Sobrienfile_strncmp(const char *s1, const char *s2, size_t len, uint32_t flags) 1742169962Sobrien{ 1743169962Sobrien /* 1744169962Sobrien * Convert the source args to unsigned here so that (1) the 1745169962Sobrien * compare will be unsigned as it is in strncmp() and (2) so 1746169962Sobrien * the ctype functions will work correctly without extra 1747169962Sobrien * casting. 1748169962Sobrien */ 1749169962Sobrien const unsigned char *a = (const unsigned char *)s1; 1750169962Sobrien const unsigned char *b = (const unsigned char *)s2; 1751169962Sobrien uint64_t v; 1752169962Sobrien 1753169962Sobrien /* 1754186690Sobrien * What we want here is v = strncmp(s1, s2, len), 1755186690Sobrien * but ignoring any nulls. 1756169962Sobrien */ 1757169962Sobrien v = 0; 1758169962Sobrien if (0L == flags) { /* normal string: do it fast */ 1759169962Sobrien while (len-- > 0) 1760169962Sobrien if ((v = *b++ - *a++) != '\0') 1761191736Sobrien break; 1762159764Sobrien } 1763169962Sobrien else { /* combine the others */ 1764169962Sobrien while (len-- > 0) { 1765169962Sobrien if ((flags & STRING_IGNORE_LOWERCASE) && 1766169962Sobrien islower(*a)) { 1767169962Sobrien if ((v = tolower(*b++) - *a++) != '\0') 1768169962Sobrien break; 1769169962Sobrien } 1770169962Sobrien else if ((flags & STRING_IGNORE_UPPERCASE) && 1771169962Sobrien isupper(*a)) { 1772169962Sobrien if ((v = toupper(*b++) - *a++) != '\0') 1773169962Sobrien break; 1774169962Sobrien } 1775226048Sobrien else if ((flags & STRING_COMPACT_WHITESPACE) && 1776191736Sobrien isspace(*a)) { 1777169962Sobrien a++; 1778169962Sobrien if (isspace(*b++)) { 1779226048Sobrien if (!isspace(*a)) 1780226048Sobrien while (isspace(*b)) 1781226048Sobrien b++; 1782169962Sobrien } 1783169962Sobrien else { 1784169962Sobrien v = 1; 1785169962Sobrien break; 1786169962Sobrien } 1787169962Sobrien } 1788226048Sobrien else if ((flags & STRING_COMPACT_OPTIONAL_WHITESPACE) && 1789169962Sobrien isspace(*a)) { 1790169962Sobrien a++; 1791169962Sobrien while (isspace(*b)) 1792169962Sobrien b++; 1793169962Sobrien } 1794169962Sobrien else { 1795169962Sobrien if ((v = *b++ - *a++) != '\0') 1796169962Sobrien break; 1797169962Sobrien } 1798159764Sobrien } 1799159764Sobrien } 1800169962Sobrien return v; 180168349Sobrien} 180268349Sobrien 1803169962Sobrienprivate uint64_t 1804169962Sobrienfile_strncmp16(const char *a, const char *b, size_t len, uint32_t flags) 1805169962Sobrien{ 1806169962Sobrien /* 1807169962Sobrien * XXX - The 16-bit string compare probably needs to be done 1808169962Sobrien * differently, especially if the flags are to be supported. 1809169962Sobrien * At the moment, I am unsure. 1810169962Sobrien */ 1811169962Sobrien flags = 0; 1812169962Sobrien return file_strncmp(a, b, len, flags); 1813169962Sobrien} 1814169962Sobrien 1815133359Sobrienprivate int 1816169962Sobrienmagiccheck(struct magic_set *ms, struct magic *m) 181768349Sobrien{ 1818169942Sobrien uint64_t l = m->value.q; 1819169942Sobrien uint64_t v; 1820175296Sobrien float fl, fv; 1821175296Sobrien double dl, dv; 182268349Sobrien int matched; 1823169962Sobrien union VALUETYPE *p = &ms->ms_value; 182468349Sobrien 182568349Sobrien switch (m->type) { 1826133359Sobrien case FILE_BYTE: 182768349Sobrien v = p->b; 182868349Sobrien break; 182968349Sobrien 1830133359Sobrien case FILE_SHORT: 1831133359Sobrien case FILE_BESHORT: 1832133359Sobrien case FILE_LESHORT: 183368349Sobrien v = p->h; 183468349Sobrien break; 183568349Sobrien 1836133359Sobrien case FILE_LONG: 1837133359Sobrien case FILE_BELONG: 1838133359Sobrien case FILE_LELONG: 1839159764Sobrien case FILE_MELONG: 1840133359Sobrien case FILE_DATE: 1841133359Sobrien case FILE_BEDATE: 1842133359Sobrien case FILE_LEDATE: 1843159764Sobrien case FILE_MEDATE: 1844133359Sobrien case FILE_LDATE: 1845133359Sobrien case FILE_BELDATE: 1846133359Sobrien case FILE_LELDATE: 1847159764Sobrien case FILE_MELDATE: 184868349Sobrien v = p->l; 184968349Sobrien break; 185068349Sobrien 1851169942Sobrien case FILE_QUAD: 1852169942Sobrien case FILE_LEQUAD: 1853169942Sobrien case FILE_BEQUAD: 1854169942Sobrien case FILE_QDATE: 1855169942Sobrien case FILE_BEQDATE: 1856169942Sobrien case FILE_LEQDATE: 1857169942Sobrien case FILE_QLDATE: 1858169942Sobrien case FILE_BEQLDATE: 1859169942Sobrien case FILE_LEQLDATE: 1860267843Sdelphij case FILE_QWDATE: 1861267843Sdelphij case FILE_BEQWDATE: 1862267843Sdelphij case FILE_LEQWDATE: 1863169942Sobrien v = p->q; 1864169942Sobrien break; 1865169942Sobrien 1866175296Sobrien case FILE_FLOAT: 1867175296Sobrien case FILE_BEFLOAT: 1868175296Sobrien case FILE_LEFLOAT: 1869175296Sobrien fl = m->value.f; 1870175296Sobrien fv = p->f; 1871175296Sobrien switch (m->reln) { 1872175296Sobrien case 'x': 1873175296Sobrien matched = 1; 1874175296Sobrien break; 1875191736Sobrien 1876175296Sobrien case '!': 1877175296Sobrien matched = fv != fl; 1878175296Sobrien break; 1879191736Sobrien 1880175296Sobrien case '=': 1881175296Sobrien matched = fv == fl; 1882175296Sobrien break; 1883191736Sobrien 1884175296Sobrien case '>': 1885175296Sobrien matched = fv > fl; 1886175296Sobrien break; 1887191736Sobrien 1888175296Sobrien case '<': 1889175296Sobrien matched = fv < fl; 1890175296Sobrien break; 1891191736Sobrien 1892175296Sobrien default: 1893191736Sobrien file_magerror(ms, "cannot happen with float: invalid relation `%c'", 1894191736Sobrien m->reln); 1895175296Sobrien return -1; 1896175296Sobrien } 1897175296Sobrien return matched; 1898175296Sobrien 1899175296Sobrien case FILE_DOUBLE: 1900175296Sobrien case FILE_BEDOUBLE: 1901175296Sobrien case FILE_LEDOUBLE: 1902175296Sobrien dl = m->value.d; 1903175296Sobrien dv = p->d; 1904175296Sobrien switch (m->reln) { 1905175296Sobrien case 'x': 1906175296Sobrien matched = 1; 1907175296Sobrien break; 1908191736Sobrien 1909175296Sobrien case '!': 1910175296Sobrien matched = dv != dl; 1911175296Sobrien break; 1912191736Sobrien 1913175296Sobrien case '=': 1914175296Sobrien matched = dv == dl; 1915175296Sobrien break; 1916191736Sobrien 1917175296Sobrien case '>': 1918175296Sobrien matched = dv > dl; 1919175296Sobrien break; 1920191736Sobrien 1921175296Sobrien case '<': 1922175296Sobrien matched = dv < dl; 1923175296Sobrien break; 1924191736Sobrien 1925175296Sobrien default: 1926175296Sobrien file_magerror(ms, "cannot happen with double: invalid relation `%c'", m->reln); 1927175296Sobrien return -1; 1928175296Sobrien } 1929175296Sobrien return matched; 1930175296Sobrien 1931169962Sobrien case FILE_DEFAULT: 1932267843Sdelphij case FILE_CLEAR: 1933169962Sobrien l = 0; 1934169962Sobrien v = 0; 1935169962Sobrien break; 1936169962Sobrien 1937133359Sobrien case FILE_STRING: 1938169962Sobrien case FILE_PSTRING: 1939169962Sobrien l = 0; 1940169962Sobrien v = file_strncmp(m->value.s, p->s, (size_t)m->vallen, m->str_flags); 1941169962Sobrien break; 1942169962Sobrien 1943139368Sobrien case FILE_BESTRING16: 1944139368Sobrien case FILE_LESTRING16: 194568349Sobrien l = 0; 1946169962Sobrien v = file_strncmp16(m->value.s, p->s, (size_t)m->vallen, m->str_flags); 1947169962Sobrien break; 1948169962Sobrien 1949169962Sobrien case FILE_SEARCH: { /* search ms->search.s for the string m->value.s */ 1950169962Sobrien size_t slen; 1951169962Sobrien size_t idx; 1952169962Sobrien 1953169962Sobrien if (ms->search.s == NULL) 1954169962Sobrien return 0; 1955169962Sobrien 1956169962Sobrien slen = MIN(m->vallen, sizeof(m->value.s)); 1957169962Sobrien l = 0; 195868349Sobrien v = 0; 1959169962Sobrien 1960186690Sobrien for (idx = 0; m->str_range == 0 || idx < m->str_range; idx++) { 1961169962Sobrien if (slen + idx > ms->search.s_len) 1962169962Sobrien break; 1963169962Sobrien 1964267843Sdelphij v = file_strncmp(m->value.s, ms->search.s + idx, slen, 1965267843Sdelphij m->str_flags); 1966169962Sobrien if (v == 0) { /* found match */ 1967186690Sobrien ms->search.offset += idx; 1968169962Sobrien break; 196968349Sobrien } 197068349Sobrien } 197168349Sobrien break; 197268349Sobrien } 1973169962Sobrien case FILE_REGEX: { 1974103373Sobrien int rc; 1975267843Sdelphij file_regex_t rx; 1976284193Sdelphij const char *search; 1977103373Sobrien 1978169962Sobrien if (ms->search.s == NULL) 1979159764Sobrien return 0; 1980159764Sobrien 1981169962Sobrien l = 0; 1982267843Sdelphij rc = file_regcomp(&rx, m->value.s, 1983169962Sobrien REG_EXTENDED|REG_NEWLINE| 1984169962Sobrien ((m->str_flags & STRING_IGNORE_CASE) ? REG_ICASE : 0)); 1985103373Sobrien if (rc) { 1986267843Sdelphij file_regerror(&rx, rc, ms); 1987169962Sobrien v = (uint64_t)-1; 1988267843Sdelphij } else { 1989169962Sobrien regmatch_t pmatch[1]; 1990267843Sdelphij size_t slen = ms->search.s_len; 1991169962Sobrien#ifndef REG_STARTEND 1992169962Sobrien#define REG_STARTEND 0 1993284193Sdelphij char *copy; 1994284193Sdelphij if (slen != 0) { 1995284193Sdelphij copy = malloc(slen); 1996284193Sdelphij if (copy == NULL) { 1997284193Sdelphij file_error(ms, errno, 1998284193Sdelphij "can't allocate %" SIZE_T_FORMAT "u bytes", 1999284193Sdelphij slen); 2000284193Sdelphij return -1; 2001284193Sdelphij } 2002284193Sdelphij memcpy(copy, ms->search.s, slen); 2003284193Sdelphij copy[--slen] = '\0'; 2004284193Sdelphij search = copy; 2005284193Sdelphij } else { 2006284193Sdelphij search = ms->search.s; 2007284193Sdelphij copy = NULL; 2008284193Sdelphij } 2009169962Sobrien#else 2010284193Sdelphij search = ms->search.s; 2011169962Sobrien pmatch[0].rm_so = 0; 2012267843Sdelphij pmatch[0].rm_eo = slen; 2013169962Sobrien#endif 2014284193Sdelphij rc = file_regexec(&rx, (const char *)search, 2015169962Sobrien 1, pmatch, REG_STARTEND); 2016169962Sobrien#if REG_STARTEND == 0 2017284193Sdelphij free(copy); 2018169962Sobrien#endif 2019169962Sobrien switch (rc) { 2020169962Sobrien case 0: 2021169962Sobrien ms->search.s += (int)pmatch[0].rm_so; 2022169962Sobrien ms->search.offset += (size_t)pmatch[0].rm_so; 2023169962Sobrien ms->search.rm_len = 2024169962Sobrien (size_t)(pmatch[0].rm_eo - pmatch[0].rm_so); 2025169962Sobrien v = 0; 2026159764Sobrien break; 2027169962Sobrien 2028169962Sobrien case REG_NOMATCH: 2029169942Sobrien v = 1; 2030159764Sobrien break; 2031169962Sobrien 2032169962Sobrien default: 2033267843Sdelphij file_regerror(&rx, rc, ms); 2034169962Sobrien v = (uint64_t)-1; 2035169962Sobrien break; 2036169942Sobrien } 2037159764Sobrien } 2038267843Sdelphij file_regfree(&rx); 2039169962Sobrien if (v == (uint64_t)-1) 2040169962Sobrien return -1; 2041159764Sobrien break; 2042159764Sobrien } 2043191736Sobrien case FILE_INDIRECT: 2044267843Sdelphij case FILE_USE: 2045267843Sdelphij case FILE_NAME: 2046191736Sobrien return 1; 204768349Sobrien default: 2048169962Sobrien file_magerror(ms, "invalid type %d in magiccheck()", m->type); 2049133359Sobrien return -1; 205068349Sobrien } 205168349Sobrien 2052169962Sobrien v = file_signextend(ms, m, v); 205368349Sobrien 205468349Sobrien switch (m->reln) { 205568349Sobrien case 'x': 2056133359Sobrien if ((ms->flags & MAGIC_DEBUG) != 0) 2057226048Sobrien (void) fprintf(stderr, "%" INT64_T_FORMAT 2058226048Sobrien "u == *any* = 1\n", (unsigned long long)v); 205968349Sobrien matched = 1; 206068349Sobrien break; 206168349Sobrien 206268349Sobrien case '!': 206368349Sobrien matched = v != l; 2064133359Sobrien if ((ms->flags & MAGIC_DEBUG) != 0) 2065226048Sobrien (void) fprintf(stderr, "%" INT64_T_FORMAT "u != %" 2066226048Sobrien INT64_T_FORMAT "u = %d\n", (unsigned long long)v, 2067226048Sobrien (unsigned long long)l, matched); 206868349Sobrien break; 206968349Sobrien 207068349Sobrien case '=': 207168349Sobrien matched = v == l; 2072133359Sobrien if ((ms->flags & MAGIC_DEBUG) != 0) 2073226048Sobrien (void) fprintf(stderr, "%" INT64_T_FORMAT "u == %" 2074226048Sobrien INT64_T_FORMAT "u = %d\n", (unsigned long long)v, 2075226048Sobrien (unsigned long long)l, matched); 207668349Sobrien break; 207768349Sobrien 207868349Sobrien case '>': 207968349Sobrien if (m->flag & UNSIGNED) { 208068349Sobrien matched = v > l; 2081133359Sobrien if ((ms->flags & MAGIC_DEBUG) != 0) 2082226048Sobrien (void) fprintf(stderr, "%" INT64_T_FORMAT 2083226048Sobrien "u > %" INT64_T_FORMAT "u = %d\n", 2084169942Sobrien (unsigned long long)v, 2085169942Sobrien (unsigned long long)l, matched); 208668349Sobrien } 208768349Sobrien else { 2088169962Sobrien matched = (int64_t) v > (int64_t) l; 2089133359Sobrien if ((ms->flags & MAGIC_DEBUG) != 0) 2090226048Sobrien (void) fprintf(stderr, "%" INT64_T_FORMAT 2091226048Sobrien "d > %" INT64_T_FORMAT "d = %d\n", 2092169942Sobrien (long long)v, (long long)l, matched); 209368349Sobrien } 209468349Sobrien break; 209568349Sobrien 209668349Sobrien case '<': 209768349Sobrien if (m->flag & UNSIGNED) { 209868349Sobrien matched = v < l; 2099133359Sobrien if ((ms->flags & MAGIC_DEBUG) != 0) 2100226048Sobrien (void) fprintf(stderr, "%" INT64_T_FORMAT 2101226048Sobrien "u < %" INT64_T_FORMAT "u = %d\n", 2102169942Sobrien (unsigned long long)v, 2103169942Sobrien (unsigned long long)l, matched); 210468349Sobrien } 210568349Sobrien else { 2106169962Sobrien matched = (int64_t) v < (int64_t) l; 2107133359Sobrien if ((ms->flags & MAGIC_DEBUG) != 0) 2108226048Sobrien (void) fprintf(stderr, "%" INT64_T_FORMAT 2109226048Sobrien "d < %" INT64_T_FORMAT "d = %d\n", 2110226048Sobrien (long long)v, (long long)l, matched); 211168349Sobrien } 211268349Sobrien break; 211368349Sobrien 211468349Sobrien case '&': 211568349Sobrien matched = (v & l) == l; 2116133359Sobrien if ((ms->flags & MAGIC_DEBUG) != 0) 2117226048Sobrien (void) fprintf(stderr, "((%" INT64_T_FORMAT "x & %" 2118226048Sobrien INT64_T_FORMAT "x) == %" INT64_T_FORMAT 2119226048Sobrien "x) = %d\n", (unsigned long long)v, 2120226048Sobrien (unsigned long long)l, (unsigned long long)l, 2121226048Sobrien matched); 212268349Sobrien break; 212368349Sobrien 212468349Sobrien case '^': 212568349Sobrien matched = (v & l) != l; 2126133359Sobrien if ((ms->flags & MAGIC_DEBUG) != 0) 2127226048Sobrien (void) fprintf(stderr, "((%" INT64_T_FORMAT "x & %" 2128226048Sobrien INT64_T_FORMAT "x) != %" INT64_T_FORMAT 2129226048Sobrien "x) = %d\n", (unsigned long long)v, 2130226048Sobrien (unsigned long long)l, (unsigned long long)l, 2131226048Sobrien matched); 213268349Sobrien break; 213368349Sobrien 213468349Sobrien default: 2135169962Sobrien file_magerror(ms, "cannot happen: invalid relation `%c'", 2136133359Sobrien m->reln); 2137133359Sobrien return -1; 213868349Sobrien } 213968349Sobrien 214068349Sobrien return matched; 214168349Sobrien} 2142169942Sobrien 2143169942Sobrienprivate int 2144191736Sobrienhandle_annotation(struct magic_set *ms, struct magic *m) 2145191736Sobrien{ 2146191736Sobrien if (ms->flags & MAGIC_APPLE) { 2147191736Sobrien if (file_printf(ms, "%.8s", m->apple) == -1) 2148191736Sobrien return -1; 2149191736Sobrien return 1; 2150191736Sobrien } 2151191736Sobrien if ((ms->flags & MAGIC_MIME_TYPE) && m->mimetype[0]) { 2152191736Sobrien if (file_printf(ms, "%s", m->mimetype) == -1) 2153191736Sobrien return -1; 2154191736Sobrien return 1; 2155191736Sobrien } 2156191736Sobrien return 0; 2157191736Sobrien} 2158191736Sobrien 2159191736Sobrienprivate int 2160169942Sobrienprint_sep(struct magic_set *ms, int firstline) 2161169942Sobrien{ 2162191736Sobrien if (ms->flags & MAGIC_MIME) 2163191736Sobrien return 0; 2164169942Sobrien if (firstline) 2165169942Sobrien return 0; 2166169942Sobrien /* 2167191736Sobrien * we found another match 2168169942Sobrien * put a newline and '-' to do some simple formatting 2169169942Sobrien */ 2170169942Sobrien return file_printf(ms, "\n- "); 2171169942Sobrien} 2172