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.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)); 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); 192 if (ml->stringify) { 193 if (vasprintf(&s, fmt, ap) == -1) { 194 va_end(ap); 195 return; 196 } 197 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); 206 return; 207 } 208 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_SIZE; 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, 4, outlen + 1); 242 strvisx(out, s, outlen, VIS_TAB|VIS_NL|VIS_CSTYLE|VIS_OCTAL); 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 struct magic_line *ml, 309 __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) { 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); 356 if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LESHORT)) 357 value = le16toh(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) { 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); 392 if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LELONG)) 393 value = le32toh(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) { 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); 428 if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LEQUAD)) 429 value = le64toh(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) { 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) { 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); 496 if (ml->type == MAGIC_TYPE_ULESHORT) 497 value = le16toh(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) { 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); 532 if (ml->type == MAGIC_TYPE_ULELONG) 533 value = le32toh(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) { 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); 568 if (ml->type == MAGIC_TYPE_ULEQUAD) 569 value = le64toh(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) { 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); 605 if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LEFLOAT)) 606 value0 = le32toh(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) { 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); 631 if (ml->type == magic_reverse_type(ms, MAGIC_TYPE_LEDOUBLE)) 632 value0 = le64toh(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) { 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) 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) 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); 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); 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) { 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); 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); 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) { 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); 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); 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) { 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); 924 if (ml->type == MAGIC_TYPE_ULEQDATE || 925 ml->type == MAGIC_TYPE_ULEQLDATE) 926 value = le64toh(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) { 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 struct magic_line *ml, 959 __unused struct magic_state *ms) 960 { 961 return (-2); 962 } 963 964 static int 965 magic_test_type_lestring16(__unused struct magic_line *ml, 966 __unused struct magic_state *ms) 967 { 968 return (-2); 969 } 970 971 static int 972 magic_test_type_melong(__unused struct magic_line *ml, 973 __unused struct magic_state *ms) 974 { 975 return (-2); 976 } 977 978 static int 979 magic_test_type_medate(__unused struct magic_line *ml, 980 __unused struct magic_state *ms) 981 { 982 return (-2); 983 } 984 985 static int 986 magic_test_type_meldate(__unused struct magic_line *ml, 987 __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_ICASE; 1012 break; 1013 default: 1014 return (-1); 1015 } 1016 } 1017 } 1018 1019 if (regcomp(&re, ml->test_string, REG_EXTENDED|REG_NEWLINE|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_STARTEND) == 0); 1025 if (result == !ml->test_not) { 1026 if (ml->result != NULL) { 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 || (*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_MAX; 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; 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; 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; 1128 } 1129 result = (found != NULL); 1130 1131 if (result == !ml->test_not) { 1132 if (ml->result != NULL) 1133 magic_add_string(ms, ml, found, ms->size - ms->offset); 1134 if (result && found != NULL && 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) 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) 1152 magic_add_result(ms, ml, "%s", ""); 1153 return (1); 1154 } 1155 1156 static int 1157 magic_test_type_name(__unused struct magic_line *ml, 1158 __unused struct magic_state *ms) 1159 { 1160 return (-1); 1161 } 1162 1163 static int 1164 magic_test_type_use(__unused struct magic_line *ml, 1165 __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) { 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); 1300 break; 1301 case 'S': 1302 if (magic_copy_from(ms, next, &s, sizeof s) != 0) 1303 return (0); 1304 wanted = be16toh(s); 1305 break; 1306 case 'l': 1307 if (magic_copy_from(ms, next, &l, sizeof l) != 0) 1308 return (0); 1309 wanted = le16toh(l); 1310 break; 1311 case 'L': 1312 if (magic_copy_from(ms, next, &l, sizeof l) != 0) 1313 return (0); 1314 wanted = be16toh(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) 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 ? "" : 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) { 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); 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_TEXT); 1397 1398 RB_FOREACH(ml, magic_tree, &m->tree) { 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_MIME) { 1406 if (ms.mimetype != NULL) 1407 return (ms.mimetype); 1408 return (NULL); 1409 } 1410 return (ms.out); 1411 } 1412 return (NULL); 1413 } 1414