Bug Summary

File:src/usr.bin/file/magic-test.c
Warning:line 236, column 7
Array access (from variable 's') results in a null pointer dereference

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name magic-test.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/file/obj -resource-dir /usr/local/lib/clang/13.0.0 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/file/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/file/magic-test.c
1/* $OpenBSD: magic-test.c,v 1.27 2019/01/15 09:24:59 nicm Exp $ */
2
3/*
4 * Copyright (c) 2015 Nicholas Marriott <nicm@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/types.h>
20
21#include <ctype.h>
22#include <errno(*__errno()).h>
23#include <fcntl.h>
24#include <limits.h>
25#include <stdarg.h>
26#include <stdio.h>
27#include <stdint.h>
28#include <stdlib.h>
29#include <string.h>
30#include <time.h>
31#include <unistd.h>
32#include <vis.h>
33
34#include "magic.h"
35#include "xmalloc.h"
36
37static int magic_test_line(struct magic_line *, struct magic_state *);
38
39static struct magic_line *
40magic_get_named(struct magic *m, const char *name)
41{
42 struct magic_line ml;
43
44 ml.name = name;
45 return (RB_FIND(magic_named_tree, &m->named, &ml)magic_named_tree_RB_FIND(&m->named, &ml));
46}
47
48static enum magic_type
49magic_reverse_type(struct magic_state *ms, enum magic_type type)
50{
51 if (!ms->reverse)
52 return (type);
53 switch (type) {
54 case MAGIC_TYPE_BESHORT:
55 return (MAGIC_TYPE_LESHORT);
56 case MAGIC_TYPE_BELONG:
57 return (MAGIC_TYPE_LELONG);
58 case MAGIC_TYPE_BEQUAD:
59 return (MAGIC_TYPE_LEQUAD);
60 case MAGIC_TYPE_UBESHORT:
61 return (MAGIC_TYPE_ULESHORT);
62 case MAGIC_TYPE_UBELONG:
63 return (MAGIC_TYPE_ULELONG);
64 case MAGIC_TYPE_UBEQUAD:
65 return (MAGIC_TYPE_ULEQUAD);
66 case MAGIC_TYPE_BEFLOAT:
67 return (MAGIC_TYPE_LEFLOAT);
68 case MAGIC_TYPE_BEDOUBLE:
69 return (MAGIC_TYPE_LEDOUBLE);
70 case MAGIC_TYPE_BEDATE:
71 return (MAGIC_TYPE_LEDATE);
72 case MAGIC_TYPE_BEQDATE:
73 return (MAGIC_TYPE_LEQDATE);
74 case MAGIC_TYPE_BELDATE:
75 return (MAGIC_TYPE_LELDATE);
76 case MAGIC_TYPE_BEQLDATE:
77 return (MAGIC_TYPE_LEQLDATE);
78 case MAGIC_TYPE_UBEDATE:
79 return (MAGIC_TYPE_ULEDATE);
80 case MAGIC_TYPE_UBEQDATE:
81 return (MAGIC_TYPE_ULEQDATE);
82 case MAGIC_TYPE_UBELDATE:
83 return (MAGIC_TYPE_ULELDATE);
84 case MAGIC_TYPE_UBEQLDATE:
85 return (MAGIC_TYPE_ULEQLDATE);
86 case MAGIC_TYPE_LESHORT:
87 return (MAGIC_TYPE_BESHORT);
88 case MAGIC_TYPE_LELONG:
89 return (MAGIC_TYPE_LELONG);
90 case MAGIC_TYPE_LEQUAD:
91 return (MAGIC_TYPE_LEQUAD);
92 case MAGIC_TYPE_ULESHORT:
93 return (MAGIC_TYPE_UBESHORT);
94 case MAGIC_TYPE_ULELONG:
95 return (MAGIC_TYPE_UBELONG);
96 case MAGIC_TYPE_ULEQUAD:
97 return (MAGIC_TYPE_UBEQUAD);
98 case MAGIC_TYPE_LEFLOAT:
99 return (MAGIC_TYPE_BEFLOAT);
100 case MAGIC_TYPE_LEDOUBLE:
101 return (MAGIC_TYPE_BEDOUBLE);
102 case MAGIC_TYPE_LEDATE:
103 return (MAGIC_TYPE_BEDATE);
104 case MAGIC_TYPE_LEQDATE:
105 return (MAGIC_TYPE_BEQDATE);
106 case MAGIC_TYPE_LELDATE:
107 return (MAGIC_TYPE_BELDATE);
108 case MAGIC_TYPE_LEQLDATE:
109 return (MAGIC_TYPE_BEQLDATE);
110 case MAGIC_TYPE_ULEDATE:
111 return (MAGIC_TYPE_UBEDATE);
112 case MAGIC_TYPE_ULEQDATE:
113 return (MAGIC_TYPE_UBEQDATE);
114 case MAGIC_TYPE_ULELDATE:
115 return (MAGIC_TYPE_UBELDATE);
116 case MAGIC_TYPE_ULEQLDATE:
117 return (MAGIC_TYPE_UBEQLDATE);
118 default:
119 return (type);
120 }
121}
122
123static int
124magic_one_eq(char a, char b, int cflag)
125{
126 if (a == b)
127 return (1);
128 if (cflag && islower((u_char)b) && tolower((u_char)a) == (u_char)b)
129 return (1);
130 return (0);
131}
132
133static int
134magic_test_eq(const char *ap, size_t asize, const char *bp, size_t bsize,
135 int cflag, int bflag, int Bflag)
136{
137 size_t aoff, boff, aspaces, bspaces;
138
139 aoff = boff = 0;
140 while (aoff != asize && boff != bsize) {
141 if (Bflag && isspace((u_char)ap[aoff])) {
142 aspaces = 0;
143 while (aoff != asize && isspace((u_char)ap[aoff])) {
144 aspaces++;
145 aoff++;
146 }
147 bspaces = 0;
148 while (boff != bsize && isspace((u_char)bp[boff])) {
149 bspaces++;
150 boff++;
151 }
152 if (bspaces >= aspaces)
153 continue;
154 return (1);
155 }
156 if (magic_one_eq(ap[aoff], bp[boff], cflag)) {
157 aoff++;
158 boff++;
159 continue;
160 }
161 if (bflag && isspace((u_char)bp[boff])) {
162 boff++;
163 continue;
164 }
165 if (ap[aoff] < bp[boff])
166 return (-1);
167 return (1);
168 }
169 return (0);
170}
171
172static int
173magic_copy_from(struct magic_state *ms, ssize_t offset, void *dst, size_t size)
174{
175 if (offset < 0)
176 offset = ms->offset;
177 if (offset + size > ms->size)
178 return (-1);
179 memcpy(dst, ms->base + offset, size);
180 return (0);
181}
182
183static void
184magic_add_result(struct magic_state *ms, struct magic_line *ml,
185 const char *fmt, ...)
186{
187 va_list ap;
188 int separate;
189 char *s, *tmp, *add;
190
191 va_start(ap, fmt)__builtin_va_start(ap, fmt);
192 if (ml->stringify) {
193 if (vasprintf(&s, fmt, ap) == -1) {
194 va_end(ap)__builtin_va_end(ap);
195 return;
196 }
197 va_end(ap)__builtin_va_end(ap);
198 if (asprintf(&tmp, ml->result, s) == -1) {
199 free(s);
200 return;
201 }
202 free(s);
203 } else {
204 if (vasprintf(&tmp, ml->result, ap) == -1) {
205 va_end(ap)__builtin_va_end(ap);
206 return;
207 }
208 va_end(ap)__builtin_va_end(ap);
209 }
210
211 separate = 1;
212 if (tmp[0] == '\\' && tmp[1] == 'b') {
213 separate = 0;
214 add = tmp + 2;
215 } else
216 add = tmp;
217
218 if (separate && *ms->out != '\0')
219 strlcat(ms->out, " ", sizeof ms->out);
220 strlcat(ms->out, add, sizeof ms->out);
221
222 free(tmp);
223}
224
225static void
226magic_add_string(struct magic_state *ms, struct magic_line *ml,
227 const char *s, size_t slen)
228{
229 char *out;
230 size_t outlen, offset;
231
232 outlen = MAGIC_STRING_SIZE31;
233 if (outlen > slen)
16
Assuming 'outlen' is <= 'slen'
17
Taking false branch
234 outlen = slen;
235 for (offset = 0; offset < outlen; offset++) {
18
Loop condition is true. Entering loop body
236 if (s[offset] == '\0' || !isprint((u_char)s[offset])) {
19
Array access (from variable 's') results in a null pointer dereference
237 outlen = offset;
238 break;
239 }
240 }
241 out = xreallocarray(NULL((void *)0), 4, outlen + 1);
242 strvisx(out, s, outlen, VIS_TAB0x08|VIS_NL0x10|VIS_CSTYLE0x02|VIS_OCTAL0x01);
243 magic_add_result(ms, ml, "%s", out);
244 free(out);
245}
246
247static int
248magic_test_signed(struct magic_line *ml, int64_t value, int64_t wanted)
249{
250 switch (ml->test_operator) {
251 case 'x':
252 return (1);
253 case '<':
254 return (value < wanted);
255 case '[':
256 return (value <= wanted);
257 case '>':
258 return (value > wanted);
259 case ']':
260 return (value >= wanted);
261 case '=':
262 return (value == wanted);
263 case '&':
264 return ((value & wanted) == wanted);
265 case '^':
266 return ((~value & wanted) == wanted);
267 }
268 return (-1);
269}
270
271static int
272magic_test_unsigned(struct magic_line *ml, uint64_t value, uint64_t wanted)
273{
274 switch (ml->test_operator) {
275 case 'x':
276 return (1);
277 case '<':
278 return (value < wanted);
279 case '[':
280 return (value <= wanted);
281 case '>':
282 return (value > wanted);
283 case ']':
284 return (value >= wanted);
285 case '=':
286 return (value == wanted);
287 case '&':
288 return ((value & wanted) == wanted);
289 case '^':
290 return ((~value & wanted) == wanted);
291 }
292 return (-1);
293}
294
295static int
296magic_test_double(struct magic_line *ml, double value, double wanted)
297{
298 switch (ml->test_operator) {
299 case 'x':
300 return (1);
301 case '=':
302 return (value == wanted);
303 }
304 return (-1);
305}
306
307static int
308magic_test_type_none(__unused__attribute__((__unused__)) struct magic_line *ml,
309 __unused__attribute__((__unused__)) struct magic_state *ms)
310{
311 return (0);
312}
313
314static int
315magic_test_type_byte(struct magic_line *ml, struct magic_state *ms)
316{
317 int8_t value;
318 int result;
319
320 if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
321 return (0);
322
323 if (ml->type_operator == '&')
324 value &= (int8_t)ml->type_operand;
325 else if (ml->type_operator == '-')
326 value -= (int8_t)ml->type_operand;
327 else if (ml->type_operator == '+')
328 value += (int8_t)ml->type_operand;
329 else if (ml->type_operator == '/')
330 value /= (int8_t)ml->type_operand;
331 else if (ml->type_operator == '%')
332 value %= (int8_t)ml->type_operand;
333 else if (ml->type_operator == '*')
334 value *= (int8_t)ml->type_operand;
335 else if (ml->type_operator != ' ')
336 return (-1);
337
338 result = magic_test_signed(ml, value, (int8_t)ml->test_signed);
339 if (result == !ml->test_not && ml->result != NULL((void *)0)) {
340 magic_add_result(ms, ml, "%c", (int)value);
341 ms->offset += sizeof value;
342 }
343 return (result);
344}
345
346static int
347magic_test_type_short(struct magic_line *ml, struct magic_state *ms)
348{
349 int16_t value;
350 int result;
351
352 if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
353 return (0);
354 if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_BESHORT))
355 value = be16toh(value)(__uint16_t)(__builtin_constant_p(value) ? (__uint16_t)(((__uint16_t
)(value) & 0xffU) << 8 | ((__uint16_t)(value) &
0xff00U) >> 8) : __swap16md(value))
;
356 if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LESHORT))
357 value = le16toh(value)((__uint16_t)(value));
358
359 if (ml->type_operator == '&')
360 value &= (int16_t)ml->type_operand;
361 else if (ml->type_operator == '-')
362 value -= (int16_t)ml->type_operand;
363 else if (ml->type_operator == '+')
364 value += (int16_t)ml->type_operand;
365 else if (ml->type_operator == '/')
366 value /= (int16_t)ml->type_operand;
367 else if (ml->type_operator == '%')
368 value %= (int16_t)ml->type_operand;
369 else if (ml->type_operator == '*')
370 value *= (int16_t)ml->type_operand;
371 else if (ml->type_operator != ' ')
372 return (-1);
373
374 result = magic_test_signed(ml, value, (int16_t)ml->test_signed);
375 if (result == !ml->test_not && ml->result != NULL((void *)0)) {
376 magic_add_result(ms, ml, "%hd", (int)value);
377 ms->offset += sizeof value;
378 }
379 return (result);
380}
381
382static int
383magic_test_type_long(struct magic_line *ml, struct magic_state *ms)
384{
385 int32_t value;
386 int result;
387
388 if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
389 return (0);
390 if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_BELONG))
391 value = be32toh(value)(__uint32_t)(__builtin_constant_p(value) ? (__uint32_t)(((__uint32_t
)(value) & 0xff) << 24 | ((__uint32_t)(value) &
0xff00) << 8 | ((__uint32_t)(value) & 0xff0000) >>
8 | ((__uint32_t)(value) & 0xff000000) >> 24) : __swap32md
(value))
;
392 if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LELONG))
393 value = le32toh(value)((__uint32_t)(value));
394
395 if (ml->type_operator == '&')
396 value &= (int32_t)ml->type_operand;
397 else if (ml->type_operator == '-')
398 value -= (int32_t)ml->type_operand;
399 else if (ml->type_operator == '+')
400 value += (int32_t)ml->type_operand;
401 else if (ml->type_operator == '/')
402 value /= (int32_t)ml->type_operand;
403 else if (ml->type_operator == '%')
404 value %= (int32_t)ml->type_operand;
405 else if (ml->type_operator == '*')
406 value *= (int32_t)ml->type_operand;
407 else if (ml->type_operator != ' ')
408 return (-1);
409
410 result = magic_test_signed(ml, value, (int32_t)ml->test_signed);
411 if (result == !ml->test_not && ml->result != NULL((void *)0)) {
412 magic_add_result(ms, ml, "%d", (int)value);
413 ms->offset += sizeof value;
414 }
415 return (result);
416}
417
418static int
419magic_test_type_quad(struct magic_line *ml, struct magic_state *ms)
420{
421 int64_t value;
422 int result;
423
424 if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
425 return (0);
426 if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_BEQUAD))
427 value = be64toh(value)(__uint64_t)(__builtin_constant_p(value) ? (__uint64_t)((((__uint64_t
)(value) & 0xff) << 56) | ((__uint64_t)(value) &
0xff00ULL) << 40 | ((__uint64_t)(value) & 0xff0000ULL
) << 24 | ((__uint64_t)(value) & 0xff000000ULL) <<
8 | ((__uint64_t)(value) & 0xff00000000ULL) >> 8 |
((__uint64_t)(value) & 0xff0000000000ULL) >> 24 | (
(__uint64_t)(value) & 0xff000000000000ULL) >> 40 | (
(__uint64_t)(value) & 0xff00000000000000ULL) >> 56)
: __swap64md(value))
;
428 if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LEQUAD))
429 value = le64toh(value)((__uint64_t)(value));
430
431 if (ml->type_operator == '&')
432 value &= (int64_t)ml->type_operand;
433 else if (ml->type_operator == '-')
434 value -= (int64_t)ml->type_operand;
435 else if (ml->type_operator == '+')
436 value += (int64_t)ml->type_operand;
437 else if (ml->type_operator == '/')
438 value /= (int64_t)ml->type_operand;
439 else if (ml->type_operator == '%')
440 value %= (int64_t)ml->type_operand;
441 else if (ml->type_operator == '*')
442 value *= (int64_t)ml->type_operand;
443 else if (ml->type_operator != ' ')
444 return (-1);
445
446 result = magic_test_signed(ml, value, (int64_t)ml->test_signed);
447 if (result == !ml->test_not && ml->result != NULL((void *)0)) {
448 magic_add_result(ms, ml, "%lld", (long long)value);
449 ms->offset += sizeof value;
450 }
451 return (result);
452}
453
454static int
455magic_test_type_ubyte(struct magic_line *ml, struct magic_state *ms)
456{
457 uint8_t value;
458 int result;
459
460 if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
461 return (0);
462
463 if (ml->type_operator == '&')
464 value &= (uint8_t)ml->type_operand;
465 else if (ml->type_operator == '-')
466 value -= (uint8_t)ml->type_operand;
467 else if (ml->type_operator == '+')
468 value += (uint8_t)ml->type_operand;
469 else if (ml->type_operator == '/')
470 value /= (uint8_t)ml->type_operand;
471 else if (ml->type_operator == '%')
472 value %= (uint8_t)ml->type_operand;
473 else if (ml->type_operator == '*')
474 value *= (uint8_t)ml->type_operand;
475 else if (ml->type_operator != ' ')
476 return (-1);
477
478 result = magic_test_unsigned(ml, value, (uint8_t)ml->test_unsigned);
479 if (result == !ml->test_not && ml->result != NULL((void *)0)) {
480 magic_add_result(ms, ml, "%c", (unsigned int)value);
481 ms->offset += sizeof value;
482 }
483 return (result);
484}
485
486static int
487magic_test_type_ushort(struct magic_line *ml, struct magic_state *ms)
488{
489 uint16_t value;
490 int result;
491
492 if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
493 return (0);
494 if (ml->type == MAGIC_TYPE_UBESHORT)
495 value = be16toh(value)(__uint16_t)(__builtin_constant_p(value) ? (__uint16_t)(((__uint16_t
)(value) & 0xffU) << 8 | ((__uint16_t)(value) &
0xff00U) >> 8) : __swap16md(value))
;
496 if (ml->type == MAGIC_TYPE_ULESHORT)
497 value = le16toh(value)((__uint16_t)(value));
498
499 if (ml->type_operator == '&')
500 value &= (uint16_t)ml->type_operand;
501 else if (ml->type_operator == '-')
502 value -= (uint16_t)ml->type_operand;
503 else if (ml->type_operator == '+')
504 value += (uint16_t)ml->type_operand;
505 else if (ml->type_operator == '/')
506 value /= (uint16_t)ml->type_operand;
507 else if (ml->type_operator == '%')
508 value %= (uint16_t)ml->type_operand;
509 else if (ml->type_operator == '*')
510 value *= (uint16_t)ml->type_operand;
511 else if (ml->type_operator != ' ')
512 return (-1);
513
514 result = magic_test_unsigned(ml, value, (uint16_t)ml->test_unsigned);
515 if (result == !ml->test_not && ml->result != NULL((void *)0)) {
516 magic_add_result(ms, ml, "%hu", (unsigned int)value);
517 ms->offset += sizeof value;
518 }
519 return (result);
520}
521
522static int
523magic_test_type_ulong(struct magic_line *ml, struct magic_state *ms)
524{
525 uint32_t value;
526 int result;
527
528 if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
529 return (0);
530 if (ml->type == MAGIC_TYPE_UBELONG)
531 value = be32toh(value)(__uint32_t)(__builtin_constant_p(value) ? (__uint32_t)(((__uint32_t
)(value) & 0xff) << 24 | ((__uint32_t)(value) &
0xff00) << 8 | ((__uint32_t)(value) & 0xff0000) >>
8 | ((__uint32_t)(value) & 0xff000000) >> 24) : __swap32md
(value))
;
532 if (ml->type == MAGIC_TYPE_ULELONG)
533 value = le32toh(value)((__uint32_t)(value));
534
535 if (ml->type_operator == '&')
536 value &= (uint32_t)ml->type_operand;
537 else if (ml->type_operator == '-')
538 value -= (uint32_t)ml->type_operand;
539 else if (ml->type_operator == '+')
540 value += (uint32_t)ml->type_operand;
541 else if (ml->type_operator == '/')
542 value /= (uint32_t)ml->type_operand;
543 else if (ml->type_operator == '%')
544 value %= (uint32_t)ml->type_operand;
545 else if (ml->type_operator == '*')
546 value *= (uint32_t)ml->type_operand;
547 else if (ml->type_operator != ' ')
548 return (-1);
549
550 result = magic_test_unsigned(ml, value, (uint32_t)ml->test_unsigned);
551 if (result == !ml->test_not && ml->result != NULL((void *)0)) {
552 magic_add_result(ms, ml, "%u", (unsigned int)value);
553 ms->offset += sizeof value;
554 }
555 return (result);
556}
557
558static int
559magic_test_type_uquad(struct magic_line *ml, struct magic_state *ms)
560{
561 uint64_t value;
562 int result;
563
564 if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
565 return (0);
566 if (ml->type == MAGIC_TYPE_UBEQUAD)
567 value = be64toh(value)(__uint64_t)(__builtin_constant_p(value) ? (__uint64_t)((((__uint64_t
)(value) & 0xff) << 56) | ((__uint64_t)(value) &
0xff00ULL) << 40 | ((__uint64_t)(value) & 0xff0000ULL
) << 24 | ((__uint64_t)(value) & 0xff000000ULL) <<
8 | ((__uint64_t)(value) & 0xff00000000ULL) >> 8 |
((__uint64_t)(value) & 0xff0000000000ULL) >> 24 | (
(__uint64_t)(value) & 0xff000000000000ULL) >> 40 | (
(__uint64_t)(value) & 0xff00000000000000ULL) >> 56)
: __swap64md(value))
;
568 if (ml->type == MAGIC_TYPE_ULEQUAD)
569 value = le64toh(value)((__uint64_t)(value));
570
571 if (ml->type_operator == '&')
572 value &= (uint64_t)ml->type_operand;
573 else if (ml->type_operator == '-')
574 value -= (uint64_t)ml->type_operand;
575 else if (ml->type_operator == '+')
576 value += (uint64_t)ml->type_operand;
577 else if (ml->type_operator == '/')
578 value /= (uint64_t)ml->type_operand;
579 else if (ml->type_operator == '%')
580 value %= (uint64_t)ml->type_operand;
581 else if (ml->type_operator == '*')
582 value *= (uint64_t)ml->type_operand;
583 else if (ml->type_operator != ' ')
584 return (-1);
585
586 result = magic_test_unsigned(ml, value, (uint64_t)ml->test_unsigned);
587 if (result == !ml->test_not && ml->result != NULL((void *)0)) {
588 magic_add_result(ms, ml, "%llu", (unsigned long long)value);
589 ms->offset += sizeof value;
590 }
591 return (result);
592}
593
594static int
595magic_test_type_float(struct magic_line *ml, struct magic_state *ms)
596{
597 uint32_t value0;
598 float value;
599 int result;
600
601 if (magic_copy_from(ms, -1, &value0, sizeof value0) != 0)
602 return (0);
603 if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_BEFLOAT))
604 value0 = be32toh(value0)(__uint32_t)(__builtin_constant_p(value0) ? (__uint32_t)(((__uint32_t
)(value0) & 0xff) << 24 | ((__uint32_t)(value0) &
0xff00) << 8 | ((__uint32_t)(value0) & 0xff0000) >>
8 | ((__uint32_t)(value0) & 0xff000000) >> 24) : __swap32md
(value0))
;
605 if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LEFLOAT))
606 value0 = le32toh(value0)((__uint32_t)(value0));
607 memcpy(&value, &value0, sizeof value);
608
609 if (ml->type_operator != ' ')
610 return (-1);
611
612 result = magic_test_double(ml, value, (float)ml->test_double);
613 if (result == !ml->test_not && ml->result != NULL((void *)0)) {
614 magic_add_result(ms, ml, "%g", value);
615 ms->offset += sizeof value0;
616 }
617 return (1);
618}
619
620static int
621magic_test_type_double(struct magic_line *ml, struct magic_state *ms)
622{
623 uint64_t value0;
624 double value;
625 int result;
626
627 if (magic_copy_from(ms, -1, &value0, sizeof value0) != 0)
628 return (0);
629 if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_BEDOUBLE))
630 value0 = be64toh(value0)(__uint64_t)(__builtin_constant_p(value0) ? (__uint64_t)((((__uint64_t
)(value0) & 0xff) << 56) | ((__uint64_t)(value0) &
0xff00ULL) << 40 | ((__uint64_t)(value0) & 0xff0000ULL
) << 24 | ((__uint64_t)(value0) & 0xff000000ULL) <<
8 | ((__uint64_t)(value0) & 0xff00000000ULL) >> 8 |
((__uint64_t)(value0) & 0xff0000000000ULL) >> 24 |
((__uint64_t)(value0) & 0xff000000000000ULL) >> 40
| ((__uint64_t)(value0) & 0xff00000000000000ULL) >>
56) : __swap64md(value0))
;
631 if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LEDOUBLE))
632 value0 = le64toh(value0)((__uint64_t)(value0));
633 memcpy(&value, &value0, sizeof value);
634
635 if (ml->type_operator != ' ')
636 return (-1);
637
638 result = magic_test_double(ml, value, (double)ml->test_double);
639 if (result == !ml->test_not && ml->result != NULL((void *)0)) {
640 magic_add_result(ms, ml, "%g", value);
641 ms->offset += sizeof value0;
642 }
643 return (1);
644}
645
646static int
647magic_test_type_string(struct magic_line *ml, struct magic_state *ms)
648{
649 const char *s, *cp;
650 size_t slen;
651 int result, cflag = 0, bflag = 0, Bflag = 0;
652
653 cp = &ml->type_string[(sizeof "string") - 1];
654 if (*cp != '\0') {
655 if (*cp != '/')
656 return (-1);
657 cp++;
658 for (; *cp != '\0'; cp++) {
659 switch (*cp) {
660 case 'B':
661 case 'W':
662 Bflag = 1;
663 break;
664 case 'b':
665 case 'w':
666 bflag = 1;
667 break;
668 case 'c':
669 cflag = 1;
670 break;
671 case 't':
672 break;
673 default:
674 return (-1);
675 }
676 }
677 }
678
679 s = ms->base + ms->offset;
680 slen = ms->size - ms->offset;
681 if (slen < ml->test_string_size)
682 return (0);
683
684 result = magic_test_eq(s, slen, ml->test_string, ml->test_string_size,
685 cflag, bflag, Bflag);
686 switch (ml->test_operator) {
687 case 'x':
688 result = 1;
689 break;
690 case '<':
691 result = result < 0;
692 break;
693 case '>':
694 result = result > 0;
695 break;
696 case '=':
697 slen = ml->test_string_size; /* only print what was found */
698 result = result == 0;
699 break;
700 default:
701 result = -1;
702 break;
703 }
704 if (result == !ml->test_not) {
705 if (ml->result != NULL((void *)0))
706 magic_add_string(ms, ml, s, slen);
707 if (result && ml->test_operator == '=')
708 ms->offset = s - ms->base + ml->test_string_size;
709 }
710 return (result);
711}
712
713static int
714magic_test_type_pstring(struct magic_line *ml, struct magic_state *ms)
715{
716 const char *s, *cp;
717 size_t slen;
718 int result;
719
720 cp = &ml->type_string[(sizeof "pstring") - 1];
721 if (*cp != '\0') {
722 if (*cp != '/')
723 return (-1);
724 cp++;
725 for (; *cp != '\0'; cp++) {
726 switch (*cp) {
727 default:
728 return (-1);
729 }
730 }
731 }
732
733 s = ms->base + ms->offset;
734 if (ms->size - ms->offset < 1)
735 return (-1);
736 slen = *(u_char *)s;
737 if (slen + 1 > ms->size - ms->offset)
738 return (-1);
739 s++;
740
741 if (slen < ml->test_string_size)
742 result = -1;
743 else if (slen > ml->test_string_size)
744 result = 1;
745 else
746 result = memcmp(s, ml->test_string, ml->test_string_size);
747 switch (ml->test_operator) {
748 case 'x':
749 result = 1;
750 break;
751 case '<':
752 result = result < 0;
753 break;
754 case '>':
755 result = result > 0;
756 break;
757 case '=':
758 result = result == 0;
759 break;
760 default:
761 result = -1;
762 break;
763 }
764 if (result == !ml->test_not) {
765 if (ml->result != NULL((void *)0))
766 magic_add_string(ms, ml, s, slen);
767 if (result && ml->test_operator == '=')
768 ms->offset += slen + 1;
769 }
770 return (result);
771}
772
773static int
774magic_test_type_date(struct magic_line *ml, struct magic_state *ms)
775{
776 int32_t value;
777 int result;
778 time_t t;
779 char s[64];
780
781 if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
782 return (0);
783 if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_BEDATE) ||
784 ml->type == magic_reverse_type(ms, MAGIC_TYPE_BELDATE))
785 value = be32toh(value)(__uint32_t)(__builtin_constant_p(value) ? (__uint32_t)(((__uint32_t
)(value) & 0xff) << 24 | ((__uint32_t)(value) &
0xff00) << 8 | ((__uint32_t)(value) & 0xff0000) >>
8 | ((__uint32_t)(value) & 0xff000000) >> 24) : __swap32md
(value))
;
786 if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LEDATE) ||
787 ml->type == magic_reverse_type(ms, MAGIC_TYPE_LELDATE))
788 value = le32toh(value)((__uint32_t)(value));
789
790 if (ml->type_operator == '&')
791 value &= (int32_t)ml->type_operand;
792 else if (ml->type_operator == '-')
793 value -= (int32_t)ml->type_operand;
794 else if (ml->type_operator == '+')
795 value += (int32_t)ml->type_operand;
796 else if (ml->type_operator != ' ')
797 return (-1);
798
799 result = magic_test_signed(ml, value, (int32_t)ml->test_signed);
800 if (result == !ml->test_not && ml->result != NULL((void *)0)) {
801 t = value;
802 switch (ml->type) {
803 case MAGIC_TYPE_LDATE:
804 case MAGIC_TYPE_LELDATE:
805 case MAGIC_TYPE_BELDATE:
806 ctime_r(&t, s);
807 break;
808 default:
809 asctime_r(gmtime(&t), s);
810 break;
811 }
812 s[strcspn(s, "\n")] = '\0';
813 magic_add_result(ms, ml, "%s", s);
814 ms->offset += sizeof value;
815 }
816 return (result);
817}
818
819static int
820magic_test_type_qdate(struct magic_line *ml, struct magic_state *ms)
821{
822 int64_t value;
823 int result;
824 time_t t;
825 char s[64];
826
827 if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
828 return (0);
829 if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_BEQDATE) ||
830 ml->type == magic_reverse_type(ms, MAGIC_TYPE_BEQLDATE))
831 value = be64toh(value)(__uint64_t)(__builtin_constant_p(value) ? (__uint64_t)((((__uint64_t
)(value) & 0xff) << 56) | ((__uint64_t)(value) &
0xff00ULL) << 40 | ((__uint64_t)(value) & 0xff0000ULL
) << 24 | ((__uint64_t)(value) & 0xff000000ULL) <<
8 | ((__uint64_t)(value) & 0xff00000000ULL) >> 8 |
((__uint64_t)(value) & 0xff0000000000ULL) >> 24 | (
(__uint64_t)(value) & 0xff000000000000ULL) >> 40 | (
(__uint64_t)(value) & 0xff00000000000000ULL) >> 56)
: __swap64md(value))
;
832 if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LEQDATE) ||
833 ml->type == magic_reverse_type(ms, MAGIC_TYPE_LEQLDATE))
834 value = le64toh(value)((__uint64_t)(value));
835
836 if (ml->type_operator == '&')
837 value &= (int64_t)ml->type_operand;
838 else if (ml->type_operator == '-')
839 value -= (int64_t)ml->type_operand;
840 else if (ml->type_operator == '+')
841 value += (int64_t)ml->type_operand;
842 else if (ml->type_operator != ' ')
843 return (-1);
844
845 result = magic_test_signed(ml, value, (int64_t)ml->test_signed);
846 if (result == !ml->test_not && ml->result != NULL((void *)0)) {
847 t = value;
848 switch (ml->type) {
849 case MAGIC_TYPE_QLDATE:
850 case MAGIC_TYPE_LEQLDATE:
851 case MAGIC_TYPE_BEQLDATE:
852 ctime_r(&t, s);
853 break;
854 default:
855 asctime_r(gmtime(&t), s);
856 break;
857 }
858 s[strcspn(s, "\n")] = '\0';
859 magic_add_result(ms, ml, "%s", s);
860 ms->offset += sizeof value;
861 }
862 return (result);
863}
864
865static int
866magic_test_type_udate(struct magic_line *ml, struct magic_state *ms)
867{
868 uint32_t value;
869 int result;
870 time_t t;
871 char s[64];
872
873 if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
874 return (0);
875 if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_BEDATE) ||
876 ml->type == magic_reverse_type(ms, MAGIC_TYPE_BELDATE))
877 value = be32toh(value)(__uint32_t)(__builtin_constant_p(value) ? (__uint32_t)(((__uint32_t
)(value) & 0xff) << 24 | ((__uint32_t)(value) &
0xff00) << 8 | ((__uint32_t)(value) & 0xff0000) >>
8 | ((__uint32_t)(value) & 0xff000000) >> 24) : __swap32md
(value))
;
878 if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LEDATE) ||
879 ml->type == magic_reverse_type(ms, MAGIC_TYPE_LELDATE))
880 value = le32toh(value)((__uint32_t)(value));
881
882 if (ml->type_operator == '&')
883 value &= (uint32_t)ml->type_operand;
884 else if (ml->type_operator == '-')
885 value -= (uint32_t)ml->type_operand;
886 else if (ml->type_operator == '+')
887 value += (uint32_t)ml->type_operand;
888 else if (ml->type_operator != ' ')
889 return (-1);
890
891 result = magic_test_unsigned(ml, value, (uint32_t)ml->test_unsigned);
892 if (result == !ml->test_not && ml->result != NULL((void *)0)) {
893 t = value;
894 switch (ml->type) {
895 case MAGIC_TYPE_LDATE:
896 case MAGIC_TYPE_LELDATE:
897 case MAGIC_TYPE_BELDATE:
898 ctime_r(&t, s);
899 break;
900 default:
901 asctime_r(gmtime(&t), s);
902 break;
903 }
904 s[strcspn(s, "\n")] = '\0';
905 magic_add_result(ms, ml, "%s", s);
906 ms->offset += sizeof value;
907 }
908 return (result);
909}
910
911static int
912magic_test_type_uqdate(struct magic_line *ml, struct magic_state *ms)
913{
914 uint64_t value;
915 int result;
916 time_t t;
917 char s[64];
918
919 if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
920 return (0);
921 if (ml->type == MAGIC_TYPE_UBEQDATE ||
922 ml->type == MAGIC_TYPE_UBEQLDATE)
923 value = be64toh(value)(__uint64_t)(__builtin_constant_p(value) ? (__uint64_t)((((__uint64_t
)(value) & 0xff) << 56) | ((__uint64_t)(value) &
0xff00ULL) << 40 | ((__uint64_t)(value) & 0xff0000ULL
) << 24 | ((__uint64_t)(value) & 0xff000000ULL) <<
8 | ((__uint64_t)(value) & 0xff00000000ULL) >> 8 |
((__uint64_t)(value) & 0xff0000000000ULL) >> 24 | (
(__uint64_t)(value) & 0xff000000000000ULL) >> 40 | (
(__uint64_t)(value) & 0xff00000000000000ULL) >> 56)
: __swap64md(value))
;
924 if (ml->type == MAGIC_TYPE_ULEQDATE ||
925 ml->type == MAGIC_TYPE_ULEQLDATE)
926 value = le64toh(value)((__uint64_t)(value));
927
928 if (ml->type_operator == '&')
929 value &= (uint64_t)ml->type_operand;
930 else if (ml->type_operator == '-')
931 value -= (uint64_t)ml->type_operand;
932 else if (ml->type_operator == '+')
933 value += (uint64_t)ml->type_operand;
934 else if (ml->type_operator != ' ')
935 return (-1);
936
937 result = magic_test_unsigned(ml, value, (uint64_t)ml->test_unsigned);
938 if (result == !ml->test_not && ml->result != NULL((void *)0)) {
939 t = value;
940 switch (ml->type) {
941 case MAGIC_TYPE_UQLDATE:
942 case MAGIC_TYPE_ULEQLDATE:
943 case MAGIC_TYPE_UBEQLDATE:
944 ctime_r(&t, s);
945 break;
946 default:
947 asctime_r(gmtime(&t), s);
948 break;
949 }
950 s[strcspn(s, "\n")] = '\0';
951 magic_add_result(ms, ml, "%s", s);
952 ms->offset += sizeof value;
953 }
954 return (result);
955}
956
957static int
958magic_test_type_bestring16(__unused__attribute__((__unused__)) struct magic_line *ml,
959 __unused__attribute__((__unused__)) struct magic_state *ms)
960{
961 return (-2);
962}
963
964static int
965magic_test_type_lestring16(__unused__attribute__((__unused__)) struct magic_line *ml,
966 __unused__attribute__((__unused__)) struct magic_state *ms)
967{
968 return (-2);
969}
970
971static int
972magic_test_type_melong(__unused__attribute__((__unused__)) struct magic_line *ml,
973 __unused__attribute__((__unused__)) struct magic_state *ms)
974{
975 return (-2);
976}
977
978static int
979magic_test_type_medate(__unused__attribute__((__unused__)) struct magic_line *ml,
980 __unused__attribute__((__unused__)) struct magic_state *ms)
981{
982 return (-2);
983}
984
985static int
986magic_test_type_meldate(__unused__attribute__((__unused__)) struct magic_line *ml,
987 __unused__attribute__((__unused__)) struct magic_state *ms)
988{
989 return (-2);
990}
991
992static int
993magic_test_type_regex(struct magic_line *ml, struct magic_state *ms)
994{
995 const char *cp;
996 regex_t re;
997 regmatch_t m;
998 int result, flags = 0, sflag = 0;
999
1000 cp = &ml->type_string[(sizeof "regex") - 1];
1001 if (*cp != '\0') {
1002 if (*cp != '/')
1003 return (-1);
1004 cp++;
1005 for (; *cp != '\0'; cp++) {
1006 switch (*cp) {
1007 case 's':
1008 sflag = 1;
1009 break;
1010 case 'c':
1011 flags |= REG_ICASE0002;
1012 break;
1013 default:
1014 return (-1);
1015 }
1016 }
1017 }
1018
1019 if (regcomp(&re, ml->test_string, REG_EXTENDED0001|REG_NEWLINE0010|flags) != 0)
1020 return (-1);
1021 m.rm_so = ms->offset;
1022 m.rm_eo = ms->size;
1023
1024 result = (regexec(&re, ms->base, 1, &m, REG_STARTEND00004) == 0);
1025 if (result == !ml->test_not) {
1026 if (ml->result != NULL((void *)0)) {
1027 magic_add_string(ms, ml, ms->base + m.rm_so,
1028 m.rm_eo - m.rm_so);
1029 }
1030 if (result) {
1031 if (sflag)
1032 ms->offset = m.rm_so;
1033 else
1034 ms->offset = m.rm_eo;
1035 }
1036 }
1037 regfree(&re);
1038 return (result);
1039}
1040
1041static int
1042magic_test_type_search(struct magic_line *ml, struct magic_state *ms)
1043{
1044 const char *cp, *endptr, *start, *found;
1045 size_t size, end, i;
1046 uint64_t range;
1047 int result, n, cflag = 0, bflag = 0, Bflag = 0;
1048
1049 cp = &ml->type_string[(sizeof "search") - 1];
1050 if (*cp != '\0') {
1
Assuming the condition is false
2
Taking false branch
1051 if (*cp != '/')
1052 return (-1);
1053 cp++;
1054
1055 endptr = magic_strtoull(cp, &range);
1056 if (endptr == NULL((void *)0) || (*endptr != '/' && *endptr != '\0'))
1057 return (-1);
1058
1059 if (*endptr == '/') {
1060 for (cp = endptr + 1; *cp != '\0'; cp++) {
1061 switch (*cp) {
1062 case 'B':
1063 case 'W':
1064 Bflag = 1;
1065 break;
1066 case 'b':
1067 case 'w':
1068 bflag = 1;
1069 break;
1070 case 'c':
1071 cflag = 1;
1072 break;
1073 case 't':
1074 break;
1075 default:
1076 return (-1);
1077 }
1078 }
1079 }
1080 } else
1081 range = UINT64_MAX0xffffffffffffffffULL;
1082 if (range > (uint64_t)ms->size - ms->offset)
3
Assuming the condition is false
4
Taking false branch
1083 range = ms->size - ms->offset;
1084 size = ml->test_string_size;
1085
1086 /* Want to search every starting position from up to range + size. */
1087 end = range + size;
1088 if (end > ms->size - ms->offset) {
5
Assuming the condition is false
6
Taking false branch
1089 if (size > ms->size - ms->offset)
1090 end = 0;
1091 else
1092 end = ms->size - ms->offset - size;
1093 }
1094
1095 /*
1096 * < and > and the flags are only in /etc/magic with search/1 so don't
1097 * support them with anything else.
1098 */
1099 start = ms->base + ms->offset;
1100 if (end == 0)
7
Assuming 'end' is equal to 0
8
Taking true branch
1101 found = NULL((void *)0);
9
Null pointer value stored to 'found'
1102 else if (ml->test_operator == 'x')
1103 found = start;
1104 else if (range == 1) {
1105 n = magic_test_eq(start, ms->size - ms->offset, ml->test_string,
1106 size, cflag, bflag, Bflag);
1107 if (n == -1 && ml->test_operator == '<')
1108 found = start;
1109 else if (n == 1 && ml->test_operator == '>')
1110 found = start;
1111 else if (n == 0 && ml->test_operator == '=')
1112 found = start;
1113 else
1114 found = NULL((void *)0);
1115 } else {
1116 if (ml->test_operator != '=')
1117 return (-2);
1118 for (i = 0; i < end; i++) {
1119 n = magic_test_eq(start + i, ms->size - ms->offset - i,
1120 ml->test_string, size, cflag, bflag, Bflag);
1121 if (n == 0) {
1122 found = start + i;
1123 break;
1124 }
1125 }
1126 if (i == end)
1127 found = NULL((void *)0);
1128 }
1129 result = (found != NULL((void *)0));
1130
1131 if (result == !ml->test_not) {
10
Assuming field 'test_not' is not equal to 0
11
Taking true branch
1132 if (ml->result != NULL((void *)0))
12
Assuming field 'result' is not equal to NULL
13
Taking true branch
1133 magic_add_string(ms, ml, found, ms->size - ms->offset);
14
Passing null pointer value via 3rd parameter 's'
15
Calling 'magic_add_string'
1134 if (result && found != NULL((void *)0) && ml->test_operator == '=')
1135 ms->offset = (found + size) - ms->base;
1136 }
1137 return (result);
1138}
1139
1140static int
1141magic_test_type_default(struct magic_line *ml, struct magic_state *ms)
1142{
1143 if (!ms->matched && ml->result != NULL((void *)0))
1144 magic_add_result(ms, ml, "%s", "");
1145 return (!ms->matched);
1146}
1147
1148static int
1149magic_test_type_clear(struct magic_line *ml, struct magic_state *ms)
1150{
1151 if (ml->result != NULL((void *)0))
1152 magic_add_result(ms, ml, "%s", "");
1153 return (1);
1154}
1155
1156static int
1157magic_test_type_name(__unused__attribute__((__unused__)) struct magic_line *ml,
1158 __unused__attribute__((__unused__)) struct magic_state *ms)
1159{
1160 return (-1);
1161}
1162
1163static int
1164magic_test_type_use(__unused__attribute__((__unused__)) struct magic_line *ml,
1165 __unused__attribute__((__unused__)) struct magic_state *ms)
1166{
1167 return (1);
1168}
1169
1170static int (*magic_test_functions[])(struct magic_line *,
1171 struct magic_state *) = {
1172 magic_test_type_none,
1173 magic_test_type_byte,
1174 magic_test_type_short,
1175 magic_test_type_long,
1176 magic_test_type_quad,
1177 magic_test_type_ubyte,
1178 magic_test_type_ushort,
1179 magic_test_type_ulong,
1180 magic_test_type_uquad,
1181 magic_test_type_float,
1182 magic_test_type_double,
1183 magic_test_type_string,
1184 magic_test_type_pstring,
1185 magic_test_type_date,
1186 magic_test_type_qdate,
1187 magic_test_type_date,
1188 magic_test_type_qdate,
1189 magic_test_type_udate,
1190 magic_test_type_uqdate,
1191 magic_test_type_udate,
1192 magic_test_type_qdate,
1193 magic_test_type_short,
1194 magic_test_type_long,
1195 magic_test_type_quad,
1196 magic_test_type_ushort,
1197 magic_test_type_ulong,
1198 magic_test_type_uquad,
1199 magic_test_type_float,
1200 magic_test_type_double,
1201 magic_test_type_date,
1202 magic_test_type_qdate,
1203 magic_test_type_date,
1204 magic_test_type_qdate,
1205 magic_test_type_udate,
1206 magic_test_type_uqdate,
1207 magic_test_type_udate,
1208 magic_test_type_uqdate,
1209 magic_test_type_bestring16,
1210 magic_test_type_short,
1211 magic_test_type_long,
1212 magic_test_type_quad,
1213 magic_test_type_ushort,
1214 magic_test_type_ulong,
1215 magic_test_type_uquad,
1216 magic_test_type_float,
1217 magic_test_type_double,
1218 magic_test_type_date,
1219 magic_test_type_qdate,
1220 magic_test_type_date,
1221 magic_test_type_qdate,
1222 magic_test_type_udate,
1223 magic_test_type_uqdate,
1224 magic_test_type_udate,
1225 magic_test_type_uqdate,
1226 magic_test_type_lestring16,
1227 magic_test_type_melong,
1228 magic_test_type_medate,
1229 magic_test_type_meldate,
1230 magic_test_type_regex,
1231 magic_test_type_search,
1232 magic_test_type_default,
1233 magic_test_type_clear,
1234 magic_test_type_name,
1235 magic_test_type_use,
1236};
1237
1238static void
1239magic_test_children(struct magic_line *ml, struct magic_state *ms, size_t start,
1240 int reverse)
1241{
1242 struct magic_line *child;
1243 size_t saved_start, saved_offset;
1244 int saved_reverse;
1245
1246 saved_start = ms->start;
1247 saved_reverse = ms->reverse;
1248 saved_offset = ms->offset;
1249
1250 ms->matched = 0; /* no need to save, caller will set too */
1251
1252 TAILQ_FOREACH(child, &ml->children, entry)for((child) = ((&ml->children)->tqh_first); (child)
!= ((void *)0); (child) = ((child)->entry.tqe_next))
{
1253 ms->start = start;
1254 ms->reverse = reverse;
1255 ms->offset = saved_offset;
1256
1257 magic_test_line(child, ms);
1258 }
1259
1260 ms->start = saved_start;
1261 ms->reverse = saved_reverse;
1262 ms->offset = saved_offset;
1263}
1264
1265static int
1266magic_test_line(struct magic_line *ml, struct magic_state *ms)
1267{
1268 struct magic *m = ml->root;
1269 struct magic_line *named;
1270 int64_t offset, wanted, next;
1271 int result;
1272 uint8_t b;
1273 uint16_t s;
1274 uint32_t l;
1275
1276 if (ml->indirect_type == ' ')
1277 wanted = ms->start + ml->offset;
1278 else {
1279 wanted = ml->indirect_offset;
1280 if (ml->indirect_relative) {
1281 if (wanted < 0 && (size_t)-wanted > ms->offset)
1282 return (0);
1283 if (wanted > 0 && ms->offset + wanted > ms->size)
1284 return (0);
1285 next = ms->offset + ml->indirect_offset;
1286 } else
1287 next = wanted;
1288
1289 switch (ml->indirect_type) {
1290 case 'b':
1291 case 'B':
1292 if (magic_copy_from(ms, next, &b, sizeof b) != 0)
1293 return (0);
1294 wanted = b;
1295 break;
1296 case 's':
1297 if (magic_copy_from(ms, next, &s, sizeof s) != 0)
1298 return (0);
1299 wanted = le16toh(s)((__uint16_t)(s));
1300 break;
1301 case 'S':
1302 if (magic_copy_from(ms, next, &s, sizeof s) != 0)
1303 return (0);
1304 wanted = be16toh(s)(__uint16_t)(__builtin_constant_p(s) ? (__uint16_t)(((__uint16_t
)(s) & 0xffU) << 8 | ((__uint16_t)(s) & 0xff00U
) >> 8) : __swap16md(s))
;
1305 break;
1306 case 'l':
1307 if (magic_copy_from(ms, next, &l, sizeof l) != 0)
1308 return (0);
1309 wanted = le16toh(l)((__uint16_t)(l));
1310 break;
1311 case 'L':
1312 if (magic_copy_from(ms, next, &l, sizeof l) != 0)
1313 return (0);
1314 wanted = be16toh(l)(__uint16_t)(__builtin_constant_p(l) ? (__uint16_t)(((__uint16_t
)(l) & 0xffU) << 8 | ((__uint16_t)(l) & 0xff00U
) >> 8) : __swap16md(l))
;
1315 break;
1316 }
1317
1318 switch (ml->indirect_operator) {
1319 case '+':
1320 wanted += ml->indirect_operand;
1321 break;
1322 case '-':
1323 wanted -= ml->indirect_operand;
1324 break;
1325 case '*':
1326 wanted *= ml->indirect_operand;
1327 break;
1328 }
1329 }
1330
1331 if (ml->offset_relative) {
1332 if (wanted < 0 && (size_t)-wanted > ms->offset)
1333 return (0);
1334 if (wanted > 0 && ms->offset + wanted > ms->size)
1335 return (0);
1336 offset = ms->offset + wanted;
1337 } else
1338 offset = wanted;
1339 if (offset < 0 || (size_t)offset > ms->size)
1340 return (0);
1341 ms->offset = offset; /* test function may update */
1342
1343 result = magic_test_functions[ml->type](ml, ms);
1344 if (result == -1) {
1345 magic_warn(ml, "test %s/%c failed", ml->type_string,
1346 ml->test_operator);
1347 return (0);
1348 }
1349 if (result == -2) {
1350 magic_warn(ml, "test %s/%c not implemented", ml->type_string,
1351 ml->test_operator);
1352 return (0);
1353 }
1354 if (result == ml->test_not)
1355 return (0);
1356 if (ml->mimetype != NULL((void *)0))
1357 ms->mimetype = ml->mimetype;
1358
1359 magic_warn(ml, "test %s/%c matched at offset %lld (now %zu): "
1360 "'%s'", ml->type_string, ml->test_operator, offset,
1361 ms->offset, ml->result == NULL((void *)0) ? "" : ml->result);
1362
1363 if (ml->type == MAGIC_TYPE_USE) {
1364 if (*ml->name == '^')
1365 named = magic_get_named(m, ml->name + 1);
1366 else
1367 named = magic_get_named(m, ml->name);
1368 if (named == NULL((void *)0)) {
1369 magic_warn(ml, "no name found for use %s", ml->name);
1370 return (0);
1371 }
1372 magic_warn(ml, "use %s at offset %lld", ml->name, offset);
1373 magic_test_children(named, ms, offset, *ml->name == '^');
1374 }
1375
1376 magic_test_children(ml, ms, ms->start, ms->reverse);
1377
1378 if (ml->type == MAGIC_TYPE_CLEAR)
1379 ms->matched = 0;
1380 else
1381 ms->matched = 1;
1382 return (ml->result != NULL((void *)0));
1383}
1384
1385const char *
1386magic_test(struct magic *m, const void *base, size_t size, int flags)
1387{
1388 struct magic_line *ml;
1389 static struct magic_state ms;
1390
1391 memset(&ms, 0, sizeof ms);
1392
1393 ms.base = base;
1394 ms.size = size;
1395
1396 ms.text = !!(flags & MAGIC_TEST_TEXT0x1);
1397
1398 RB_FOREACH(ml, magic_tree, &m->tree)for ((ml) = magic_tree_RB_MINMAX(&m->tree, -1); (ml) !=
((void *)0); (ml) = magic_tree_RB_NEXT(ml))
{
1399 ms.offset = 0;
1400 if (ml->text == ms.text && magic_test_line(ml, &ms))
1401 break;
1402 }
1403
1404 if (*ms.out != '\0') {
1405 if (flags & MAGIC_TEST_MIME0x2) {
1406 if (ms.mimetype != NULL((void *)0))
1407 return (ms.mimetype);
1408 return (NULL((void *)0));
1409 }
1410 return (ms.out);
1411 }
1412 return (NULL((void *)0));
1413}