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