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