1 /* $OpenBSD: magic-test.c,v 1.3 2015/04/25 16:35:47 brynet 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 <unistd.h> 31 #include <vis.h> 32 33 #include "magic.h" 34 #include "xmalloc.h" 35 36 static int 37 magic_one_eq(char a, char b, int cflag) 38 { 39 if (a == b) 40 return (1); 41 if (cflag && tolower((u_char)a) == tolower((u_char)b)) 42 return (1); 43 return (0); 44 } 45 46 static int 47 magic_test_eq(const char *ap, size_t asize, const char *bp, size_t bsize, 48 int cflag, int bflag, int Bflag) 49 { 50 size_t aoff, boff, aspaces, bspaces; 51 52 aoff = boff = 0; 53 while (aoff != asize && boff != bsize) { 54 if (Bflag && isspace((u_char)ap[aoff])) { 55 aspaces = 0; 56 while (aoff != asize && isspace((u_char)ap[aoff])) { 57 aspaces++; 58 aoff++; 59 } 60 bspaces = 0; 61 while (boff != bsize && isspace((u_char)bp[boff])) { 62 bspaces++; 63 boff++; 64 } 65 if (bspaces >= aspaces) 66 continue; 67 return (1); 68 } 69 if (magic_one_eq(ap[aoff], bp[boff], cflag)) { 70 aoff++; 71 boff++; 72 continue; 73 } 74 if (bflag && isspace((u_char)bp[boff])) { 75 boff++; 76 continue; 77 } 78 if (ap[aoff] < bp[boff]) 79 return (-1); 80 return (1); 81 } 82 return (0); 83 } 84 85 static int 86 magic_copy_from(struct magic_state *ms, ssize_t offset, void *dst, size_t size) 87 { 88 if (offset < 0) 89 offset = ms->offset; 90 if (offset + size > ms->size) 91 return (-1); 92 memcpy(dst, ms->base + offset, size); 93 return (0); 94 } 95 96 static void 97 magic_add_result(struct magic_state *ms, struct magic_line *ml, 98 const char *fmt, ...) 99 { 100 va_list ap; 101 int separate; 102 char *s, *tmp, *add; 103 104 va_start(ap, fmt); 105 if (ml->stringify) { 106 if (vasprintf(&s, fmt, ap) == -1) { 107 va_end(ap); 108 return; 109 } 110 va_end(ap); 111 if (asprintf(&tmp, ml->result, s) == -1) { 112 free(s); 113 return; 114 } 115 free(s); 116 } else { 117 if (vasprintf(&tmp, ml->result, ap) == -1) { 118 va_end(ap); 119 return; 120 } 121 va_end(ap); 122 } 123 124 separate = 1; 125 if (tmp[0] == '\\' && tmp[1] == 'b') { 126 separate = 0; 127 add = tmp + 2; 128 } else 129 add = tmp; 130 131 if (separate && *ms->out != '\0') 132 strlcat(ms->out, " ", sizeof ms->out); 133 strlcat(ms->out, add, sizeof ms->out); 134 135 free(tmp); 136 } 137 138 static void 139 magic_add_string(struct magic_state *ms, struct magic_line *ml, 140 const char *s, size_t slen) 141 { 142 char *out; 143 size_t outlen, offset; 144 145 outlen = MAGIC_STRING_SIZE; 146 if (outlen > slen) 147 outlen = slen; 148 for (offset = 0; offset < outlen; offset++) { 149 if (s[offset] == '\0' || !isprint((u_char)s[offset])) { 150 outlen = offset; 151 break; 152 } 153 } 154 out = xreallocarray(NULL, 4, outlen + 1); 155 strvisx(out, s, outlen, VIS_TAB|VIS_NL|VIS_CSTYLE|VIS_OCTAL); 156 magic_add_result(ms, ml, "%s", out); 157 free(out); 158 } 159 160 static int 161 magic_test_signed(struct magic_line *ml, int64_t value, int64_t wanted) 162 { 163 switch (ml->test_operator) { 164 case 'x': 165 return (1); 166 case '<': 167 return (value < wanted); 168 case '[': 169 return (value <= wanted); 170 case '>': 171 return (value > wanted); 172 case ']': 173 return (value >= wanted); 174 case '=': 175 return (value == wanted); 176 case '&': 177 return ((value & wanted) == wanted); 178 case '^': 179 return ((~value & wanted) == wanted); 180 } 181 return (-1); 182 } 183 184 static int 185 magic_test_unsigned(struct magic_line *ml, uint64_t value, uint64_t wanted) 186 { 187 switch (ml->test_operator) { 188 case 'x': 189 return (1); 190 case '<': 191 return (value < wanted); 192 case '[': 193 return (value <= wanted); 194 case '>': 195 return (value > wanted); 196 case ']': 197 return (value >= wanted); 198 case '=': 199 return (value == wanted); 200 case '&': 201 return ((value & wanted) == wanted); 202 case '^': 203 return ((~value & wanted) == wanted); 204 } 205 return (-1); 206 } 207 208 static int 209 magic_test_type_none(__unused struct magic_line *ml, 210 __unused struct magic_state *ms) 211 { 212 return (0); 213 } 214 215 static int 216 magic_test_type_byte(struct magic_line *ml, struct magic_state *ms) 217 { 218 int8_t value; 219 int result; 220 221 if (magic_copy_from(ms, -1, &value, sizeof value) != 0) 222 return (0); 223 224 if (ml->type_operator == '&') 225 value &= (int8_t)ml->type_operand; 226 else if (ml->type_operator != ' ') 227 return (-1); 228 229 result = magic_test_signed(ml, value, (int8_t)ml->test_signed); 230 if (result == !ml->test_not && ml->result != NULL) { 231 magic_add_result(ms, ml, "%c", (int)value); 232 ms->offset += sizeof value; 233 } 234 return (result); 235 } 236 237 static int 238 magic_test_type_short(struct magic_line *ml, struct magic_state *ms) 239 { 240 int16_t value; 241 int result; 242 243 if (magic_copy_from(ms, -1, &value, sizeof value) != 0) 244 return (0); 245 if (ml->type == MAGIC_TYPE_BESHORT) 246 value = be16toh(value); 247 if (ml->type == MAGIC_TYPE_LESHORT) 248 value = le16toh(value); 249 250 if (ml->type_operator == '&') 251 value &= (int16_t)ml->type_operand; 252 else if (ml->type_operator != ' ') 253 return (-1); 254 255 result = magic_test_signed(ml, value, (int16_t)ml->test_signed); 256 if (result == !ml->test_not && ml->result != NULL) { 257 magic_add_result(ms, ml, "%hd", (int)value); 258 ms->offset += sizeof value; 259 } 260 return (result); 261 } 262 263 static int 264 magic_test_type_long(struct magic_line *ml, struct magic_state *ms) 265 { 266 int32_t value; 267 int result; 268 269 if (magic_copy_from(ms, -1, &value, sizeof value) != 0) 270 return (0); 271 if (ml->type == MAGIC_TYPE_BELONG) 272 value = be32toh(value); 273 if (ml->type == MAGIC_TYPE_LELONG) 274 value = le32toh(value); 275 276 if (ml->type_operator == '&') 277 value &= (int32_t)ml->type_operand; 278 else if (ml->type_operator != ' ') 279 return (-1); 280 281 result = magic_test_signed(ml, value, (int32_t)ml->test_signed); 282 if (result == !ml->test_not && ml->result != NULL) { 283 magic_add_result(ms, ml, "%d", (int)value); 284 ms->offset += sizeof value; 285 } 286 return (result); 287 } 288 289 static int 290 magic_test_type_quad(struct magic_line *ml, struct magic_state *ms) 291 { 292 int64_t value; 293 int result; 294 295 if (magic_copy_from(ms, -1, &value, sizeof value) != 0) 296 return (0); 297 if (ml->type == MAGIC_TYPE_BEQUAD) 298 value = be64toh(value); 299 if (ml->type == MAGIC_TYPE_LEQUAD) 300 value = le64toh(value); 301 302 if (ml->type_operator == '&') 303 value &= (int64_t)ml->type_operand; 304 else if (ml->type_operator != ' ') 305 return (-1); 306 307 result = magic_test_signed(ml, value, (int64_t)ml->test_signed); 308 if (result == !ml->test_not && ml->result != NULL) { 309 magic_add_result(ms, ml, "%lld", (long long)value); 310 ms->offset += sizeof value; 311 } 312 return (result); 313 } 314 315 static int 316 magic_test_type_ubyte(struct magic_line *ml, struct magic_state *ms) 317 { 318 uint8_t value; 319 int result; 320 321 if (magic_copy_from(ms, -1, &value, sizeof value) != 0) 322 return (0); 323 324 if (ml->type_operator == '&') 325 value &= (uint8_t)ml->type_operand; 326 else if (ml->type_operator != ' ') 327 return (-1); 328 329 result = magic_test_unsigned(ml, value, (uint8_t)ml->test_unsigned); 330 if (result == !ml->test_not && ml->result != NULL) { 331 magic_add_result(ms, ml, "%c", (unsigned int)value); 332 ms->offset += sizeof value; 333 } 334 return (result); 335 } 336 337 static int 338 magic_test_type_ushort(struct magic_line *ml, struct magic_state *ms) 339 { 340 uint16_t value; 341 int result; 342 343 if (magic_copy_from(ms, -1, &value, sizeof value) != 0) 344 return (0); 345 if (ml->type == MAGIC_TYPE_UBESHORT) 346 value = be16toh(value); 347 if (ml->type == MAGIC_TYPE_ULESHORT) 348 value = le16toh(value); 349 350 if (ml->type_operator == '&') 351 value &= (uint16_t)ml->type_operand; 352 else if (ml->type_operator != ' ') 353 return (-1); 354 355 result = magic_test_unsigned(ml, value, (uint16_t)ml->test_unsigned); 356 if (result == !ml->test_not && ml->result != NULL) { 357 magic_add_result(ms, ml, "%hu", (unsigned int)value); 358 ms->offset += sizeof value; 359 } 360 return (result); 361 } 362 363 static int 364 magic_test_type_ulong(struct magic_line *ml, struct magic_state *ms) 365 { 366 uint32_t value; 367 int result; 368 369 if (magic_copy_from(ms, -1, &value, sizeof value) != 0) 370 return (0); 371 if (ml->type == MAGIC_TYPE_UBELONG) 372 value = be32toh(value); 373 if (ml->type == MAGIC_TYPE_ULELONG) 374 value = le32toh(value); 375 376 if (ml->type_operator == '&') 377 value &= (uint32_t)ml->type_operand; 378 else if (ml->type_operator != ' ') 379 return (-1); 380 381 result = magic_test_unsigned(ml, value, (uint32_t)ml->test_unsigned); 382 if (result == !ml->test_not && ml->result != NULL) { 383 magic_add_result(ms, ml, "%u", (unsigned int)value); 384 ms->offset += sizeof value; 385 } 386 return (result); 387 } 388 389 static int 390 magic_test_type_uquad(struct magic_line *ml, struct magic_state *ms) 391 { 392 uint64_t value; 393 int result; 394 395 if (magic_copy_from(ms, -1, &value, sizeof value) != 0) 396 return (0); 397 if (ml->type == MAGIC_TYPE_UBEQUAD) 398 value = be64toh(value); 399 if (ml->type == MAGIC_TYPE_ULEQUAD) 400 value = le64toh(value); 401 402 if (ml->type_operator == '&') 403 value &= (uint64_t)ml->type_operand; 404 else if (ml->type_operator != ' ') 405 return (-1); 406 407 result = magic_test_unsigned(ml, value, (uint64_t)ml->test_unsigned); 408 if (result == !ml->test_not && ml->result != NULL) { 409 magic_add_result(ms, ml, "%llu", (unsigned long long)value); 410 ms->offset += sizeof value; 411 } 412 return (result); 413 } 414 415 static int 416 magic_test_type_float(struct magic_line *ml, struct magic_state *ms) 417 { 418 uint32_t value0; 419 double value; 420 421 if (magic_copy_from(ms, -1, &value0, sizeof value0) != 0) 422 return (0); 423 if (ml->type == MAGIC_TYPE_BEFLOAT) 424 value0 = be32toh(value0); 425 if (ml->type == MAGIC_TYPE_LEFLOAT) 426 value0 = le32toh(value0); 427 memcpy(&value, &value0, sizeof value); 428 429 if (ml->type_operator != ' ') 430 return (-1); 431 432 if (ml->test_operator != 'x') 433 return (-1); 434 435 magic_add_result(ms, ml, "%g", value); 436 ms->offset += sizeof value0; 437 return (1); 438 } 439 440 static int 441 magic_test_type_double(struct magic_line *ml, struct magic_state *ms) 442 { 443 uint64_t value0; 444 double value; 445 446 if (magic_copy_from(ms, -1, &value0, sizeof value0) != 0) 447 return (0); 448 if (ml->type == MAGIC_TYPE_BEDOUBLE) 449 value0 = be64toh(value0); 450 if (ml->type == MAGIC_TYPE_LEDOUBLE) 451 value0 = le64toh(value0); 452 memcpy(&value, &value0, sizeof value); 453 454 if (ml->type_operator != ' ') 455 return (-1); 456 457 if (ml->test_operator != 'x') 458 return (-1); 459 460 magic_add_result(ms, ml, "%g", value); 461 ms->offset += sizeof value0; 462 return (1); 463 } 464 465 static int 466 magic_test_type_string(struct magic_line *ml, struct magic_state *ms) 467 { 468 const char *s, *cp; 469 size_t slen; 470 int result, cflag = 0, bflag = 0, Bflag = 0; 471 472 cp = &ml->type_string[(sizeof "string") - 1]; 473 if (*cp != '\0') { 474 if (*cp != '/') 475 return (-1); 476 cp++; 477 for (; *cp != '\0'; cp++) { 478 switch (*cp) { 479 case 'B': 480 Bflag = 1; 481 break; 482 case 'b': 483 bflag = 1; 484 break; 485 case 'c': 486 cflag = 1; 487 break; 488 default: 489 return (-1); 490 } 491 } 492 } 493 494 s = ms->base + ms->offset; 495 slen = ms->size - ms->offset; 496 if (slen < ml->test_string_size) 497 return (0); 498 499 result = magic_test_eq(s, slen, ml->test_string, ml->test_string_size, 500 cflag, bflag, Bflag); 501 switch (ml->test_operator) { 502 case 'x': 503 result = 1; 504 break; 505 case '<': 506 result = result < 0; 507 break; 508 case '>': 509 result = result > 0; 510 break; 511 case '=': 512 result = result == 0; 513 break; 514 default: 515 result = -1; 516 break; 517 } 518 if (result == !ml->test_not) { 519 if (ml->result != NULL) 520 magic_add_string(ms, ml, s, slen); 521 if (result && ml->test_operator == '=') 522 ms->offset = s - ms->base + ml->test_string_size; 523 } 524 return (result); 525 } 526 527 static int 528 magic_test_type_pstring(struct magic_line *ml, struct magic_state *ms) 529 { 530 const char *s; 531 size_t slen; 532 int result; 533 534 s = ms->base + ms->offset; 535 if (ms->size - ms->offset < 1) 536 return (-1); 537 slen = *(u_char *)s; 538 if (slen > ms->size - ms->offset) 539 return (-1); 540 s++; 541 542 if (slen < ml->test_string_size) 543 result = -1; 544 else if (slen > ml->test_string_size) 545 result = 1; 546 else 547 result = memcmp(s, ml->test_string, ml->test_string_size); 548 switch (ml->test_operator) { 549 case 'x': 550 result = 1; 551 break; 552 case '<': 553 result = result < 0; 554 break; 555 case '>': 556 result = result > 0; 557 break; 558 case '=': 559 result = result == 0; 560 break; 561 default: 562 result = -1; 563 break; 564 } 565 if (result == !ml->test_not) { 566 if (ml->result != NULL) 567 magic_add_string(ms, ml, s, slen); 568 if (result) 569 ms->offset += slen + 1; 570 } 571 return (result); 572 } 573 574 static int 575 magic_test_type_date(struct magic_line *ml, struct magic_state *ms) 576 { 577 int32_t value; 578 int result; 579 time_t t; 580 char s[64]; 581 582 if (magic_copy_from(ms, -1, &value, sizeof value) != 0) 583 return (0); 584 if (ml->type == MAGIC_TYPE_BEDATE || 585 ml->type == MAGIC_TYPE_BELDATE) 586 value = be32toh(value); 587 if (ml->type == MAGIC_TYPE_LEDATE || 588 ml->type == MAGIC_TYPE_LELDATE) 589 value = le32toh(value); 590 591 if (ml->type_operator == '&') 592 value &= (int32_t)ml->type_operand; 593 else if (ml->type_operator != ' ') 594 return (-1); 595 596 result = magic_test_signed(ml, value, (int32_t)ml->test_signed); 597 if (result == !ml->test_not && ml->result != NULL) { 598 t = value; 599 switch (ml->type) { 600 case MAGIC_TYPE_LDATE: 601 case MAGIC_TYPE_LELDATE: 602 case MAGIC_TYPE_BELDATE: 603 ctime_r(&t, s); 604 break; 605 default: 606 asctime_r(localtime(&t), s); 607 break; 608 } 609 s[strcspn(s, "\n")] = '\0'; 610 magic_add_result(ms, ml, "%s", s); 611 ms->offset += sizeof value; 612 } 613 return (result); 614 } 615 616 static int 617 magic_test_type_qdate(struct magic_line *ml, struct magic_state *ms) 618 { 619 int64_t value; 620 int result; 621 time_t t; 622 char s[64]; 623 624 if (magic_copy_from(ms, -1, &value, sizeof value) != 0) 625 return (0); 626 if (ml->type == MAGIC_TYPE_BEQDATE || 627 ml->type == MAGIC_TYPE_BEQLDATE) 628 value = be64toh(value); 629 if (ml->type == MAGIC_TYPE_LEQDATE || 630 ml->type == MAGIC_TYPE_LEQLDATE) 631 value = le64toh(value); 632 633 if (ml->type_operator == '&') 634 value &= (int64_t)ml->type_operand; 635 else if (ml->type_operator != ' ') 636 return (-1); 637 638 result = magic_test_signed(ml, value, (int64_t)ml->test_signed); 639 if (result == !ml->test_not && ml->result != NULL) { 640 t = value; 641 switch (ml->type) { 642 case MAGIC_TYPE_QLDATE: 643 case MAGIC_TYPE_LEQLDATE: 644 case MAGIC_TYPE_BEQLDATE: 645 ctime_r(&t, s); 646 break; 647 default: 648 asctime_r(localtime(&t), s); 649 break; 650 } 651 s[strcspn(s, "\n")] = '\0'; 652 magic_add_result(ms, ml, "%s", s); 653 ms->offset += sizeof value; 654 } 655 return (result); 656 } 657 658 static int 659 magic_test_type_udate(struct magic_line *ml, struct magic_state *ms) 660 { 661 uint32_t value; 662 int result; 663 time_t t; 664 char s[64]; 665 666 if (magic_copy_from(ms, -1, &value, sizeof value) != 0) 667 return (0); 668 if (ml->type == MAGIC_TYPE_BEDATE || 669 ml->type == MAGIC_TYPE_BELDATE) 670 value = be32toh(value); 671 if (ml->type == MAGIC_TYPE_LEDATE || 672 ml->type == MAGIC_TYPE_LELDATE) 673 value = le32toh(value); 674 675 if (ml->type_operator == '&') 676 value &= (uint32_t)ml->type_operand; 677 else if (ml->type_operator != ' ') 678 return (-1); 679 680 result = magic_test_unsigned(ml, value, (uint32_t)ml->test_unsigned); 681 if (result == !ml->test_not && ml->result != NULL) { 682 t = value; 683 switch (ml->type) { 684 case MAGIC_TYPE_LDATE: 685 case MAGIC_TYPE_LELDATE: 686 case MAGIC_TYPE_BELDATE: 687 ctime_r(&t, s); 688 break; 689 default: 690 asctime_r(gmtime(&t), s); 691 break; 692 } 693 s[strcspn(s, "\n")] = '\0'; 694 magic_add_result(ms, ml, "%s", s); 695 ms->offset += sizeof value; 696 } 697 return (result); 698 } 699 700 static int 701 magic_test_type_uqdate(struct magic_line *ml, struct magic_state *ms) 702 { 703 uint64_t value; 704 int result; 705 time_t t; 706 char s[64]; 707 708 if (magic_copy_from(ms, -1, &value, sizeof value) != 0) 709 return (0); 710 if (ml->type == MAGIC_TYPE_UBEQDATE || 711 ml->type == MAGIC_TYPE_UBEQLDATE) 712 value = be64toh(value); 713 if (ml->type == MAGIC_TYPE_ULEQDATE || 714 ml->type == MAGIC_TYPE_ULEQLDATE) 715 value = le64toh(value); 716 717 if (ml->type_operator == '&') 718 value &= (uint64_t)ml->type_operand; 719 else if (ml->type_operator != ' ') 720 return (-1); 721 722 result = magic_test_unsigned(ml, value, (uint64_t)ml->test_unsigned); 723 if (result == !ml->test_not && ml->result != NULL) { 724 t = value; 725 switch (ml->type) { 726 case MAGIC_TYPE_UQLDATE: 727 case MAGIC_TYPE_ULEQLDATE: 728 case MAGIC_TYPE_UBEQLDATE: 729 ctime_r(&t, s); 730 break; 731 default: 732 asctime_r(gmtime(&t), s); 733 break; 734 } 735 s[strcspn(s, "\n")] = '\0'; 736 magic_add_result(ms, ml, "%s", s); 737 ms->offset += sizeof value; 738 } 739 return (result); 740 } 741 742 static int 743 magic_test_type_bestring16(__unused struct magic_line *ml, 744 __unused struct magic_state *ms) 745 { 746 return (-2); 747 } 748 749 static int 750 magic_test_type_lestring16(__unused struct magic_line *ml, 751 __unused struct magic_state *ms) 752 { 753 return (-2); 754 } 755 756 static int 757 magic_test_type_melong(__unused struct magic_line *ml, 758 __unused struct magic_state *ms) 759 { 760 return (-2); 761 } 762 763 static int 764 magic_test_type_medate(__unused struct magic_line *ml, 765 __unused struct magic_state *ms) 766 { 767 return (-2); 768 } 769 770 static int 771 magic_test_type_meldate(__unused struct magic_line *ml, 772 __unused struct magic_state *ms) 773 { 774 return (-2); 775 } 776 777 static int 778 magic_test_type_regex(struct magic_line *ml, struct magic_state *ms) 779 { 780 const char *cp; 781 regex_t re; 782 regmatch_t m; 783 int result, flags = 0, sflag = 0; 784 785 cp = &ml->type_string[(sizeof "regex") - 1]; 786 if (*cp != '\0') { 787 if (*cp != '/') 788 return (-1); 789 cp++; 790 for (; *cp != '\0'; cp++) { 791 switch (*cp) { 792 case 's': 793 sflag = 1; 794 break; 795 case 'c': 796 flags |= REG_ICASE; 797 break; 798 default: 799 return (-1); 800 } 801 } 802 } 803 804 if (regcomp(&re, ml->test_string, REG_EXTENDED) != 0) 805 return (-1); 806 m.rm_so = ms->offset; 807 m.rm_eo = ms->size; 808 809 result = (regexec(&re, ms->base, 1, &m, REG_STARTEND) == 0); 810 if (result == !ml->test_not && ml->result != NULL) { 811 magic_add_result(ms, ml, "%s", ""); 812 if (result) { 813 if (sflag) 814 ms->offset = m.rm_so; 815 else 816 ms->offset = m.rm_eo; 817 } 818 } 819 regfree(&re); 820 return (result); 821 } 822 823 static int 824 magic_test_type_search(struct magic_line *ml, struct magic_state *ms) 825 { 826 const char *cp, *endptr, *start, *found; 827 size_t size, end, i; 828 uint64_t range; 829 int result, n, cflag = 0, bflag = 0, Bflag = 0; 830 831 cp = &ml->type_string[(sizeof "search") - 1]; 832 if (*cp != '\0') { 833 if (*cp != '/') 834 return (-1); 835 cp++; 836 837 endptr = magic_strtoull(cp, &range); 838 if (endptr == NULL || (*endptr != '/' && *endptr != '\0')) 839 return (-1); 840 841 if (*endptr == '/') { 842 for (cp = endptr + 1; *cp != '\0'; cp++) { 843 switch (*cp) { 844 case 'B': 845 Bflag = 1; 846 break; 847 case 'b': 848 bflag = 1; 849 break; 850 case 'c': 851 cflag = 1; 852 break; 853 default: 854 return (-1); 855 } 856 } 857 } 858 } else 859 range = UINT64_MAX; 860 if (range > (uint64_t)ms->size - ms->offset) 861 range = ms->size - ms->offset; 862 size = ml->test_string_size; 863 864 /* Want to search every starting position from up to range + size. */ 865 end = range + size; 866 if (end > ms->size - ms->offset) { 867 if (size > ms->size - ms->offset) 868 end = 0; 869 else 870 end = ms->size - ms->offset - size; 871 } 872 873 /* 874 * < and > and the flags are only in /etc/magic with search/1 so don't 875 * support them with anything else. 876 */ 877 start = ms->base + ms->offset; 878 if (end == 0) 879 found = NULL; 880 else if (ml->test_operator == 'x') 881 found = start; 882 else if (range == 1) { 883 n = magic_test_eq(start, ms->size - ms->offset, ml->test_string, 884 size, cflag, bflag, Bflag); 885 if (n == -1 && ml->test_operator == '<') 886 found = start; 887 else if (n == 1 && ml->test_operator == '>') 888 found = start; 889 else if (n == 0 && ml->test_operator == '=') 890 found = start; 891 else 892 found = NULL; 893 } else { 894 if (ml->test_operator != '=') 895 return (-2); 896 for (i = 0; i < end; i++) { 897 n = magic_test_eq(start + i, ms->size - ms->offset - i, 898 ml->test_string, size, cflag, bflag, Bflag); 899 if (n == 0) { 900 found = start + i; 901 break; 902 } 903 } 904 if (i == end) 905 found = NULL; 906 } 907 result = (found != NULL); 908 909 if (result == !ml->test_not && ml->result != NULL && found != NULL) { 910 magic_add_string(ms, ml, found, ms->size - ms->offset); 911 ms->offset = found - start + size; 912 } 913 return (result); 914 } 915 916 static int 917 magic_test_type_default(__unused struct magic_line *ml, 918 __unused struct magic_state *ms) 919 { 920 return (1); 921 } 922 923 static int (*magic_test_functions[])(struct magic_line *, 924 struct magic_state *) = { 925 magic_test_type_none, 926 magic_test_type_byte, 927 magic_test_type_short, 928 magic_test_type_long, 929 magic_test_type_quad, 930 magic_test_type_ubyte, 931 magic_test_type_ushort, 932 magic_test_type_ulong, 933 magic_test_type_uquad, 934 magic_test_type_float, 935 magic_test_type_double, 936 magic_test_type_string, 937 magic_test_type_pstring, 938 magic_test_type_date, 939 magic_test_type_qdate, 940 magic_test_type_date, 941 magic_test_type_qdate, 942 magic_test_type_udate, 943 magic_test_type_uqdate, 944 magic_test_type_udate, 945 magic_test_type_qdate, 946 magic_test_type_short, 947 magic_test_type_long, 948 magic_test_type_quad, 949 magic_test_type_ushort, 950 magic_test_type_ulong, 951 magic_test_type_uquad, 952 magic_test_type_float, 953 magic_test_type_double, 954 magic_test_type_date, 955 magic_test_type_qdate, 956 magic_test_type_date, 957 magic_test_type_qdate, 958 magic_test_type_udate, 959 magic_test_type_uqdate, 960 magic_test_type_udate, 961 magic_test_type_uqdate, 962 magic_test_type_bestring16, 963 magic_test_type_short, 964 magic_test_type_long, 965 magic_test_type_quad, 966 magic_test_type_ushort, 967 magic_test_type_ulong, 968 magic_test_type_uquad, 969 magic_test_type_float, 970 magic_test_type_double, 971 magic_test_type_date, 972 magic_test_type_qdate, 973 magic_test_type_date, 974 magic_test_type_qdate, 975 magic_test_type_udate, 976 magic_test_type_uqdate, 977 magic_test_type_udate, 978 magic_test_type_uqdate, 979 magic_test_type_lestring16, 980 magic_test_type_melong, 981 magic_test_type_medate, 982 magic_test_type_meldate, 983 magic_test_type_regex, 984 magic_test_type_search, 985 magic_test_type_default, 986 }; 987 988 static int 989 magic_test_line(struct magic_line *ml, struct magic_state *ms) 990 { 991 struct magic_line *child; 992 int64_t offset, wanted, next; 993 int result; 994 uint8_t b; 995 uint16_t s; 996 uint32_t l; 997 998 if (ml->indirect_type == ' ') 999 wanted = ml->offset; 1000 else { 1001 wanted = ml->indirect_offset; 1002 if (ml->indirect_relative) { 1003 if (wanted < 0 && -wanted > ms->offset) 1004 return (0); 1005 if (wanted > 0 && ms->offset + wanted > ms->size) 1006 return (0); 1007 next = ms->offset + ml->indirect_offset; 1008 } else 1009 next = wanted; 1010 1011 switch (ml->indirect_type) { 1012 case 'b': 1013 case 'B': 1014 if (magic_copy_from(ms, next, &b, sizeof b) != 0) 1015 return (0); 1016 wanted = b; 1017 break; 1018 case 's': 1019 if (magic_copy_from(ms, next, &s, sizeof s) != 0) 1020 return (0); 1021 wanted = le16toh(s); 1022 break; 1023 case 'S': 1024 if (magic_copy_from(ms, next, &s, sizeof s) != 0) 1025 return (0); 1026 wanted = be16toh(s); 1027 break; 1028 case 'l': 1029 if (magic_copy_from(ms, next, &l, sizeof l) != 0) 1030 return (0); 1031 wanted = le16toh(l); 1032 break; 1033 case 'L': 1034 if (magic_copy_from(ms, next, &l, sizeof l) != 0) 1035 return (0); 1036 wanted = be16toh(l); 1037 break; 1038 } 1039 1040 switch (ml->indirect_operator) { 1041 case '+': 1042 wanted += ml->indirect_operand; 1043 break; 1044 case '-': 1045 wanted -= ml->indirect_operand; 1046 break; 1047 case '*': 1048 wanted *= ml->indirect_operand; 1049 break; 1050 } 1051 } 1052 1053 if (ml->offset_relative) { 1054 if (wanted < 0 && -wanted > ms->offset) 1055 return (0); 1056 if (wanted > 0 && ms->offset + wanted > ms->size) 1057 return (0); 1058 offset = ms->offset + wanted; 1059 } else 1060 offset = wanted; 1061 if (offset < 0 || offset > ms->size) 1062 return (0); 1063 ms->offset = offset; 1064 1065 result = magic_test_functions[ml->type](ml, ms); 1066 if (result == -1) { 1067 magic_warn(ml, "test %s/%c failed", ml->type_string, 1068 ml->test_operator); 1069 return (0); 1070 } 1071 if (result == -2) { 1072 magic_warn(ml, "test %s/%c not implemented", ml->type_string, 1073 ml->test_operator); 1074 return (0); 1075 } 1076 if (result == ml->test_not) 1077 return (0); 1078 if (ml->mimetype != NULL) 1079 ms->mimetype = ml->mimetype; 1080 1081 magic_warn(ml, "test %s/%c matched at offset %llu: '%s'", 1082 ml->type_string, ml->test_operator, ms->offset, 1083 ml->result == NULL ? "" : ml->result); 1084 1085 offset = ms->offset; 1086 TAILQ_FOREACH(child, &ml->children, entry) { 1087 ms->offset = offset; 1088 magic_test_line(child, ms); 1089 } 1090 return (1); 1091 } 1092 1093 const char * 1094 magic_test(struct magic *m, const void *base, size_t size, int flags) 1095 { 1096 struct magic_line *ml; 1097 static struct magic_state ms; 1098 1099 memset(&ms, 0, sizeof ms); 1100 1101 ms.base = base; 1102 ms.size = size; 1103 1104 ms.text = !!(flags & MAGIC_TEST_TEXT); 1105 1106 RB_FOREACH(ml, magic_tree, &m->tree) { 1107 ms.offset = 0; 1108 if (ml->text == ms.text && magic_test_line(ml, &ms)) 1109 break; 1110 } 1111 1112 if (*ms.out != '\0') { 1113 if (flags & MAGIC_TEST_MIME) { 1114 if (ms.mimetype) 1115 return (xstrdup(ms.mimetype)); 1116 return (NULL); 1117 } 1118 return (xstrdup(ms.out)); 1119 } 1120 return (NULL); 1121 } 1122