| File: | src/usr.bin/file/magic-test.c |
| Warning: | line 236, column 7 Array access (from variable 's') results in a null pointer dereference |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 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 | ||||
| 37 | static int magic_test_line(struct magic_line *, struct magic_state *); | |||
| 38 | ||||
| 39 | static struct magic_line * | |||
| 40 | magic_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 | ||||
| 48 | static enum magic_type | |||
| 49 | magic_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 | ||||
| 123 | static int | |||
| 124 | magic_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 | ||||
| 133 | static int | |||
| 134 | magic_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 | ||||
| 172 | static int | |||
| 173 | magic_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 | ||||
| 183 | static void | |||
| 184 | magic_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 | ||||
| 225 | static void | |||
| 226 | magic_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) | |||
| 234 | outlen = slen; | |||
| 235 | for (offset = 0; offset < outlen; offset++) { | |||
| 236 | if (s[offset] == '\0' || !isprint((u_char)s[offset])) { | |||
| ||||
| 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 | ||||
| 247 | static int | |||
| 248 | magic_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 | ||||
| 271 | static int | |||
| 272 | magic_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 | ||||
| 295 | static int | |||
| 296 | magic_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 | ||||
| 307 | static int | |||
| 308 | magic_test_type_none(__unused__attribute__((__unused__)) struct magic_line *ml, | |||
| 309 | __unused__attribute__((__unused__)) struct magic_state *ms) | |||
| 310 | { | |||
| 311 | return (0); | |||
| 312 | } | |||
| 313 | ||||
| 314 | static int | |||
| 315 | magic_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 | ||||
| 346 | static int | |||
| 347 | magic_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 | ||||
| 382 | static int | |||
| 383 | magic_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 | ||||
| 418 | static int | |||
| 419 | magic_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 | ||||
| 454 | static int | |||
| 455 | magic_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 | ||||
| 486 | static int | |||
| 487 | magic_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 | ||||
| 522 | static int | |||
| 523 | magic_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 | ||||
| 558 | static int | |||
| 559 | magic_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 | ||||
| 594 | static int | |||
| 595 | magic_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 | ||||
| 620 | static int | |||
| 621 | magic_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 | ||||
| 646 | static int | |||
| 647 | magic_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 | ||||
| 713 | static int | |||
| 714 | magic_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 | ||||
| 773 | static int | |||
| 774 | magic_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 | ||||
| 819 | static int | |||
| 820 | magic_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 | ||||
| 865 | static int | |||
| 866 | magic_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 | ||||
| 911 | static int | |||
| 912 | magic_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 | ||||
| 957 | static int | |||
| 958 | magic_test_type_bestring16(__unused__attribute__((__unused__)) struct magic_line *ml, | |||
| 959 | __unused__attribute__((__unused__)) struct magic_state *ms) | |||
| 960 | { | |||
| 961 | return (-2); | |||
| 962 | } | |||
| 963 | ||||
| 964 | static int | |||
| 965 | magic_test_type_lestring16(__unused__attribute__((__unused__)) struct magic_line *ml, | |||
| 966 | __unused__attribute__((__unused__)) struct magic_state *ms) | |||
| 967 | { | |||
| 968 | return (-2); | |||
| 969 | } | |||
| 970 | ||||
| 971 | static int | |||
| 972 | magic_test_type_melong(__unused__attribute__((__unused__)) struct magic_line *ml, | |||
| 973 | __unused__attribute__((__unused__)) struct magic_state *ms) | |||
| 974 | { | |||
| 975 | return (-2); | |||
| 976 | } | |||
| 977 | ||||
| 978 | static int | |||
| 979 | magic_test_type_medate(__unused__attribute__((__unused__)) struct magic_line *ml, | |||
| 980 | __unused__attribute__((__unused__)) struct magic_state *ms) | |||
| 981 | { | |||
| 982 | return (-2); | |||
| 983 | } | |||
| 984 | ||||
| 985 | static int | |||
| 986 | magic_test_type_meldate(__unused__attribute__((__unused__)) struct magic_line *ml, | |||
| 987 | __unused__attribute__((__unused__)) struct magic_state *ms) | |||
| 988 | { | |||
| 989 | return (-2); | |||
| 990 | } | |||
| 991 | ||||
| 992 | static int | |||
| 993 | magic_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 | ||||
| 1041 | static int | |||
| 1042 | magic_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') { | |||
| ||||
| 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) | |||
| 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) { | |||
| 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) | |||
| 1101 | found = NULL((void *)0); | |||
| 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) { | |||
| 1132 | if (ml->result != NULL((void *)0)) | |||
| 1133 | magic_add_string(ms, ml, found, ms->size - ms->offset); | |||
| 1134 | if (result && found != NULL((void *)0) && ml->test_operator == '=') | |||
| 1135 | ms->offset = (found + size) - ms->base; | |||
| 1136 | } | |||
| 1137 | return (result); | |||
| 1138 | } | |||
| 1139 | ||||
| 1140 | static int | |||
| 1141 | magic_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 | ||||
| 1148 | static int | |||
| 1149 | magic_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 | ||||
| 1156 | static int | |||
| 1157 | magic_test_type_name(__unused__attribute__((__unused__)) struct magic_line *ml, | |||
| 1158 | __unused__attribute__((__unused__)) struct magic_state *ms) | |||
| 1159 | { | |||
| 1160 | return (-1); | |||
| 1161 | } | |||
| 1162 | ||||
| 1163 | static int | |||
| 1164 | magic_test_type_use(__unused__attribute__((__unused__)) struct magic_line *ml, | |||
| 1165 | __unused__attribute__((__unused__)) struct magic_state *ms) | |||
| 1166 | { | |||
| 1167 | return (1); | |||
| 1168 | } | |||
| 1169 | ||||
| 1170 | static 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 | ||||
| 1238 | static void | |||
| 1239 | magic_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 | ||||
| 1265 | static int | |||
| 1266 | magic_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 | ||||
| 1385 | const char * | |||
| 1386 | magic_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 | } |