1 /* $OpenBSD: magic-test.c,v 1.13 2015/08/12 09:39:43 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 <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 && islower((u_char)b) && tolower((u_char)a) == (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_double(struct magic_line *ml, double value, double wanted) 210 { 211 switch (ml->test_operator) { 212 case 'x': 213 return (1); 214 case '=': 215 return (value == wanted); 216 } 217 return (-1); 218 } 219 220 static int 221 magic_test_type_none(__unused struct magic_line *ml, 222 __unused struct magic_state *ms) 223 { 224 return (0); 225 } 226 227 static int 228 magic_test_type_byte(struct magic_line *ml, struct magic_state *ms) 229 { 230 int8_t value; 231 int result; 232 233 if (magic_copy_from(ms, -1, &value, sizeof value) != 0) 234 return (0); 235 236 if (ml->type_operator == '&') 237 value &= (int8_t)ml->type_operand; 238 else if (ml->type_operator == '-') 239 value -= (int8_t)ml->type_operand; 240 else if (ml->type_operator == '+') 241 value += (int8_t)ml->type_operand; 242 else if (ml->type_operator == '/') 243 value /= (int8_t)ml->type_operand; 244 else if (ml->type_operator == '%') 245 value %= (int8_t)ml->type_operand; 246 else if (ml->type_operator == '*') 247 value *= (int8_t)ml->type_operand; 248 else if (ml->type_operator != ' ') 249 return (-1); 250 251 result = magic_test_signed(ml, value, (int8_t)ml->test_signed); 252 if (result == !ml->test_not && ml->result != NULL) { 253 magic_add_result(ms, ml, "%c", (int)value); 254 ms->offset += sizeof value; 255 } 256 return (result); 257 } 258 259 static int 260 magic_test_type_short(struct magic_line *ml, struct magic_state *ms) 261 { 262 int16_t value; 263 int result; 264 265 if (magic_copy_from(ms, -1, &value, sizeof value) != 0) 266 return (0); 267 if (ml->type == MAGIC_TYPE_BESHORT) 268 value = be16toh(value); 269 if (ml->type == MAGIC_TYPE_LESHORT) 270 value = le16toh(value); 271 272 if (ml->type_operator == '&') 273 value &= (int16_t)ml->type_operand; 274 else if (ml->type_operator == '-') 275 value -= (int16_t)ml->type_operand; 276 else if (ml->type_operator == '+') 277 value += (int16_t)ml->type_operand; 278 else if (ml->type_operator == '/') 279 value /= (int16_t)ml->type_operand; 280 else if (ml->type_operator == '%') 281 value %= (int16_t)ml->type_operand; 282 else if (ml->type_operator == '*') 283 value *= (int16_t)ml->type_operand; 284 else if (ml->type_operator != ' ') 285 return (-1); 286 287 result = magic_test_signed(ml, value, (int16_t)ml->test_signed); 288 if (result == !ml->test_not && ml->result != NULL) { 289 magic_add_result(ms, ml, "%hd", (int)value); 290 ms->offset += sizeof value; 291 } 292 return (result); 293 } 294 295 static int 296 magic_test_type_long(struct magic_line *ml, struct magic_state *ms) 297 { 298 int32_t value; 299 int result; 300 301 if (magic_copy_from(ms, -1, &value, sizeof value) != 0) 302 return (0); 303 if (ml->type == MAGIC_TYPE_BELONG) 304 value = be32toh(value); 305 if (ml->type == MAGIC_TYPE_LELONG) 306 value = le32toh(value); 307 308 if (ml->type_operator == '&') 309 value &= (int32_t)ml->type_operand; 310 else if (ml->type_operator == '-') 311 value -= (int32_t)ml->type_operand; 312 else if (ml->type_operator == '+') 313 value += (int32_t)ml->type_operand; 314 else if (ml->type_operator == '/') 315 value /= (int32_t)ml->type_operand; 316 else if (ml->type_operator == '%') 317 value %= (int32_t)ml->type_operand; 318 else if (ml->type_operator == '*') 319 value *= (int32_t)ml->type_operand; 320 else if (ml->type_operator != ' ') 321 return (-1); 322 323 result = magic_test_signed(ml, value, (int32_t)ml->test_signed); 324 if (result == !ml->test_not && ml->result != NULL) { 325 magic_add_result(ms, ml, "%d", (int)value); 326 ms->offset += sizeof value; 327 } 328 return (result); 329 } 330 331 static int 332 magic_test_type_quad(struct magic_line *ml, struct magic_state *ms) 333 { 334 int64_t value; 335 int result; 336 337 if (magic_copy_from(ms, -1, &value, sizeof value) != 0) 338 return (0); 339 if (ml->type == MAGIC_TYPE_BEQUAD) 340 value = be64toh(value); 341 if (ml->type == MAGIC_TYPE_LEQUAD) 342 value = le64toh(value); 343 344 if (ml->type_operator == '&') 345 value &= (int64_t)ml->type_operand; 346 else if (ml->type_operator == '-') 347 value -= (int64_t)ml->type_operand; 348 else if (ml->type_operator == '+') 349 value += (int64_t)ml->type_operand; 350 else if (ml->type_operator == '/') 351 value /= (int64_t)ml->type_operand; 352 else if (ml->type_operator == '%') 353 value %= (int64_t)ml->type_operand; 354 else if (ml->type_operator == '*') 355 value *= (int64_t)ml->type_operand; 356 else if (ml->type_operator != ' ') 357 return (-1); 358 359 result = magic_test_signed(ml, value, (int64_t)ml->test_signed); 360 if (result == !ml->test_not && ml->result != NULL) { 361 magic_add_result(ms, ml, "%lld", (long long)value); 362 ms->offset += sizeof value; 363 } 364 return (result); 365 } 366 367 static int 368 magic_test_type_ubyte(struct magic_line *ml, struct magic_state *ms) 369 { 370 uint8_t value; 371 int result; 372 373 if (magic_copy_from(ms, -1, &value, sizeof value) != 0) 374 return (0); 375 376 if (ml->type_operator == '&') 377 value &= (uint8_t)ml->type_operand; 378 else if (ml->type_operator == '-') 379 value -= (uint8_t)ml->type_operand; 380 else if (ml->type_operator == '+') 381 value += (uint8_t)ml->type_operand; 382 else if (ml->type_operator == '/') 383 value /= (uint8_t)ml->type_operand; 384 else if (ml->type_operator == '%') 385 value %= (uint8_t)ml->type_operand; 386 else if (ml->type_operator == '*') 387 value *= (uint8_t)ml->type_operand; 388 else if (ml->type_operator != ' ') 389 return (-1); 390 391 result = magic_test_unsigned(ml, value, (uint8_t)ml->test_unsigned); 392 if (result == !ml->test_not && ml->result != NULL) { 393 magic_add_result(ms, ml, "%c", (unsigned int)value); 394 ms->offset += sizeof value; 395 } 396 return (result); 397 } 398 399 static int 400 magic_test_type_ushort(struct magic_line *ml, struct magic_state *ms) 401 { 402 uint16_t value; 403 int result; 404 405 if (magic_copy_from(ms, -1, &value, sizeof value) != 0) 406 return (0); 407 if (ml->type == MAGIC_TYPE_UBESHORT) 408 value = be16toh(value); 409 if (ml->type == MAGIC_TYPE_ULESHORT) 410 value = le16toh(value); 411 412 if (ml->type_operator == '&') 413 value &= (uint16_t)ml->type_operand; 414 else if (ml->type_operator == '-') 415 value -= (uint16_t)ml->type_operand; 416 else if (ml->type_operator == '+') 417 value += (uint16_t)ml->type_operand; 418 else if (ml->type_operator == '/') 419 value /= (uint16_t)ml->type_operand; 420 else if (ml->type_operator == '%') 421 value %= (uint16_t)ml->type_operand; 422 else if (ml->type_operator == '*') 423 value *= (uint16_t)ml->type_operand; 424 else if (ml->type_operator != ' ') 425 return (-1); 426 427 result = magic_test_unsigned(ml, value, (uint16_t)ml->test_unsigned); 428 if (result == !ml->test_not && ml->result != NULL) { 429 magic_add_result(ms, ml, "%hu", (unsigned int)value); 430 ms->offset += sizeof value; 431 } 432 return (result); 433 } 434 435 static int 436 magic_test_type_ulong(struct magic_line *ml, struct magic_state *ms) 437 { 438 uint32_t value; 439 int result; 440 441 if (magic_copy_from(ms, -1, &value, sizeof value) != 0) 442 return (0); 443 if (ml->type == MAGIC_TYPE_UBELONG) 444 value = be32toh(value); 445 if (ml->type == MAGIC_TYPE_ULELONG) 446 value = le32toh(value); 447 448 if (ml->type_operator == '&') 449 value &= (uint32_t)ml->type_operand; 450 else if (ml->type_operator == '-') 451 value -= (uint32_t)ml->type_operand; 452 else if (ml->type_operator == '+') 453 value += (uint32_t)ml->type_operand; 454 else if (ml->type_operator == '/') 455 value /= (uint32_t)ml->type_operand; 456 else if (ml->type_operator == '%') 457 value %= (uint32_t)ml->type_operand; 458 else if (ml->type_operator == '*') 459 value *= (uint32_t)ml->type_operand; 460 else if (ml->type_operator != ' ') 461 return (-1); 462 463 result = magic_test_unsigned(ml, value, (uint32_t)ml->test_unsigned); 464 if (result == !ml->test_not && ml->result != NULL) { 465 magic_add_result(ms, ml, "%u", (unsigned int)value); 466 ms->offset += sizeof value; 467 } 468 return (result); 469 } 470 471 static int 472 magic_test_type_uquad(struct magic_line *ml, struct magic_state *ms) 473 { 474 uint64_t value; 475 int result; 476 477 if (magic_copy_from(ms, -1, &value, sizeof value) != 0) 478 return (0); 479 if (ml->type == MAGIC_TYPE_UBEQUAD) 480 value = be64toh(value); 481 if (ml->type == MAGIC_TYPE_ULEQUAD) 482 value = le64toh(value); 483 484 if (ml->type_operator == '&') 485 value &= (uint64_t)ml->type_operand; 486 else if (ml->type_operator == '-') 487 value -= (uint64_t)ml->type_operand; 488 else if (ml->type_operator == '+') 489 value += (uint64_t)ml->type_operand; 490 else if (ml->type_operator == '/') 491 value /= (uint64_t)ml->type_operand; 492 else if (ml->type_operator == '%') 493 value %= (uint64_t)ml->type_operand; 494 else if (ml->type_operator == '*') 495 value *= (uint64_t)ml->type_operand; 496 else if (ml->type_operator != ' ') 497 return (-1); 498 499 result = magic_test_unsigned(ml, value, (uint64_t)ml->test_unsigned); 500 if (result == !ml->test_not && ml->result != NULL) { 501 magic_add_result(ms, ml, "%llu", (unsigned long long)value); 502 ms->offset += sizeof value; 503 } 504 return (result); 505 } 506 507 static int 508 magic_test_type_float(struct magic_line *ml, struct magic_state *ms) 509 { 510 uint32_t value0; 511 double value; 512 int result; 513 514 if (magic_copy_from(ms, -1, &value0, sizeof value0) != 0) 515 return (0); 516 if (ml->type == MAGIC_TYPE_BEFLOAT) 517 value0 = be32toh(value0); 518 if (ml->type == MAGIC_TYPE_LEFLOAT) 519 value0 = le32toh(value0); 520 memcpy(&value, &value0, sizeof value); 521 522 if (ml->type_operator != ' ') 523 return (-1); 524 525 result = magic_test_double(ml, value, (float)ml->test_double); 526 if (result == !ml->test_not && ml->result != NULL) { 527 magic_add_result(ms, ml, "%g", value); 528 ms->offset += sizeof value0; 529 } 530 return (1); 531 } 532 533 static int 534 magic_test_type_double(struct magic_line *ml, struct magic_state *ms) 535 { 536 uint64_t value0; 537 double value; 538 int result; 539 540 if (magic_copy_from(ms, -1, &value0, sizeof value0) != 0) 541 return (0); 542 if (ml->type == MAGIC_TYPE_BEDOUBLE) 543 value0 = be64toh(value0); 544 if (ml->type == MAGIC_TYPE_LEDOUBLE) 545 value0 = le64toh(value0); 546 memcpy(&value, &value0, sizeof value); 547 548 if (ml->type_operator != ' ') 549 return (-1); 550 551 result = magic_test_double(ml, value, (double)ml->test_double); 552 if (result == !ml->test_not && ml->result != NULL) { 553 magic_add_result(ms, ml, "%g", value); 554 ms->offset += sizeof value0; 555 } 556 return (1); 557 } 558 559 static int 560 magic_test_type_string(struct magic_line *ml, struct magic_state *ms) 561 { 562 const char *s, *cp; 563 size_t slen; 564 int result, cflag = 0, bflag = 0, Bflag = 0; 565 566 cp = &ml->type_string[(sizeof "string") - 1]; 567 if (*cp != '\0') { 568 if (*cp != '/') 569 return (-1); 570 cp++; 571 for (; *cp != '\0'; cp++) { 572 switch (*cp) { 573 case 'B': 574 case 'W': 575 Bflag = 1; 576 break; 577 case 'b': 578 case 'w': 579 bflag = 1; 580 break; 581 case 'c': 582 cflag = 1; 583 break; 584 case 't': 585 break; 586 default: 587 return (-1); 588 } 589 } 590 } 591 592 s = ms->base + ms->offset; 593 slen = ms->size - ms->offset; 594 if (slen < ml->test_string_size) 595 return (0); 596 597 result = magic_test_eq(s, slen, ml->test_string, ml->test_string_size, 598 cflag, bflag, Bflag); 599 switch (ml->test_operator) { 600 case 'x': 601 result = 1; 602 break; 603 case '<': 604 result = result < 0; 605 break; 606 case '>': 607 result = result > 0; 608 break; 609 case '=': 610 slen = ml->test_string_size; /* only print what was found */ 611 result = result == 0; 612 break; 613 default: 614 result = -1; 615 break; 616 } 617 if (result == !ml->test_not) { 618 if (ml->result != NULL) 619 magic_add_string(ms, ml, s, slen); 620 if (result && ml->test_operator == '=') 621 ms->offset = s - ms->base + ml->test_string_size; 622 } 623 return (result); 624 } 625 626 static int 627 magic_test_type_pstring(struct magic_line *ml, struct magic_state *ms) 628 { 629 const char *s, *cp; 630 size_t slen; 631 int result; 632 633 cp = &ml->type_string[(sizeof "pstring") - 1]; 634 if (*cp != '\0') { 635 if (*cp != '/') 636 return (-1); 637 cp++; 638 for (; *cp != '\0'; cp++) { 639 switch (*cp) { 640 default: 641 return (-1); 642 } 643 } 644 } 645 646 s = ms->base + ms->offset; 647 if (ms->size - ms->offset < 1) 648 return (-1); 649 slen = *(u_char *)s; 650 if (slen > ms->size - ms->offset) 651 return (-1); 652 s++; 653 654 if (slen < ml->test_string_size) 655 result = -1; 656 else if (slen > ml->test_string_size) 657 result = 1; 658 else 659 result = memcmp(s, ml->test_string, ml->test_string_size); 660 switch (ml->test_operator) { 661 case 'x': 662 result = 1; 663 break; 664 case '<': 665 result = result < 0; 666 break; 667 case '>': 668 result = result > 0; 669 break; 670 case '=': 671 result = result == 0; 672 break; 673 default: 674 result = -1; 675 break; 676 } 677 if (result == !ml->test_not) { 678 if (ml->result != NULL) 679 magic_add_string(ms, ml, s, slen); 680 if (result && ml->test_operator == '=') 681 ms->offset += slen + 1; 682 } 683 return (result); 684 } 685 686 static int 687 magic_test_type_date(struct magic_line *ml, struct magic_state *ms) 688 { 689 int32_t value; 690 int result; 691 time_t t; 692 char s[64]; 693 694 if (magic_copy_from(ms, -1, &value, sizeof value) != 0) 695 return (0); 696 if (ml->type == MAGIC_TYPE_BEDATE || 697 ml->type == MAGIC_TYPE_BELDATE) 698 value = be32toh(value); 699 if (ml->type == MAGIC_TYPE_LEDATE || 700 ml->type == MAGIC_TYPE_LELDATE) 701 value = le32toh(value); 702 703 if (ml->type_operator == '&') 704 value &= (int32_t)ml->type_operand; 705 else if (ml->type_operator == '-') 706 value -= (int32_t)ml->type_operand; 707 else if (ml->type_operator == '+') 708 value += (int32_t)ml->type_operand; 709 else if (ml->type_operator != ' ') 710 return (-1); 711 712 result = magic_test_signed(ml, value, (int32_t)ml->test_signed); 713 if (result == !ml->test_not && ml->result != NULL) { 714 t = value; 715 switch (ml->type) { 716 case MAGIC_TYPE_LDATE: 717 case MAGIC_TYPE_LELDATE: 718 case MAGIC_TYPE_BELDATE: 719 ctime_r(&t, s); 720 break; 721 default: 722 asctime_r(gmtime(&t), s); 723 break; 724 } 725 s[strcspn(s, "\n")] = '\0'; 726 magic_add_result(ms, ml, "%s", s); 727 ms->offset += sizeof value; 728 } 729 return (result); 730 } 731 732 static int 733 magic_test_type_qdate(struct magic_line *ml, struct magic_state *ms) 734 { 735 int64_t value; 736 int result; 737 time_t t; 738 char s[64]; 739 740 if (magic_copy_from(ms, -1, &value, sizeof value) != 0) 741 return (0); 742 if (ml->type == MAGIC_TYPE_BEQDATE || 743 ml->type == MAGIC_TYPE_BEQLDATE) 744 value = be64toh(value); 745 if (ml->type == MAGIC_TYPE_LEQDATE || 746 ml->type == MAGIC_TYPE_LEQLDATE) 747 value = le64toh(value); 748 749 if (ml->type_operator == '&') 750 value &= (int64_t)ml->type_operand; 751 else if (ml->type_operator == '-') 752 value -= (int64_t)ml->type_operand; 753 else if (ml->type_operator == '+') 754 value += (int64_t)ml->type_operand; 755 else if (ml->type_operator != ' ') 756 return (-1); 757 758 result = magic_test_signed(ml, value, (int64_t)ml->test_signed); 759 if (result == !ml->test_not && ml->result != NULL) { 760 t = value; 761 switch (ml->type) { 762 case MAGIC_TYPE_QLDATE: 763 case MAGIC_TYPE_LEQLDATE: 764 case MAGIC_TYPE_BEQLDATE: 765 ctime_r(&t, s); 766 break; 767 default: 768 asctime_r(gmtime(&t), s); 769 break; 770 } 771 s[strcspn(s, "\n")] = '\0'; 772 magic_add_result(ms, ml, "%s", s); 773 ms->offset += sizeof value; 774 } 775 return (result); 776 } 777 778 static int 779 magic_test_type_udate(struct magic_line *ml, struct magic_state *ms) 780 { 781 uint32_t value; 782 int result; 783 time_t t; 784 char s[64]; 785 786 if (magic_copy_from(ms, -1, &value, sizeof value) != 0) 787 return (0); 788 if (ml->type == MAGIC_TYPE_BEDATE || 789 ml->type == MAGIC_TYPE_BELDATE) 790 value = be32toh(value); 791 if (ml->type == MAGIC_TYPE_LEDATE || 792 ml->type == MAGIC_TYPE_LELDATE) 793 value = le32toh(value); 794 795 if (ml->type_operator == '&') 796 value &= (uint32_t)ml->type_operand; 797 else if (ml->type_operator == '-') 798 value -= (uint32_t)ml->type_operand; 799 else if (ml->type_operator == '+') 800 value += (uint32_t)ml->type_operand; 801 else if (ml->type_operator != ' ') 802 return (-1); 803 804 result = magic_test_unsigned(ml, value, (uint32_t)ml->test_unsigned); 805 if (result == !ml->test_not && ml->result != NULL) { 806 t = value; 807 switch (ml->type) { 808 case MAGIC_TYPE_LDATE: 809 case MAGIC_TYPE_LELDATE: 810 case MAGIC_TYPE_BELDATE: 811 ctime_r(&t, s); 812 break; 813 default: 814 asctime_r(gmtime(&t), s); 815 break; 816 } 817 s[strcspn(s, "\n")] = '\0'; 818 magic_add_result(ms, ml, "%s", s); 819 ms->offset += sizeof value; 820 } 821 return (result); 822 } 823 824 static int 825 magic_test_type_uqdate(struct magic_line *ml, struct magic_state *ms) 826 { 827 uint64_t value; 828 int result; 829 time_t t; 830 char s[64]; 831 832 if (magic_copy_from(ms, -1, &value, sizeof value) != 0) 833 return (0); 834 if (ml->type == MAGIC_TYPE_UBEQDATE || 835 ml->type == MAGIC_TYPE_UBEQLDATE) 836 value = be64toh(value); 837 if (ml->type == MAGIC_TYPE_ULEQDATE || 838 ml->type == MAGIC_TYPE_ULEQLDATE) 839 value = le64toh(value); 840 841 if (ml->type_operator == '&') 842 value &= (uint64_t)ml->type_operand; 843 else if (ml->type_operator == '-') 844 value -= (uint64_t)ml->type_operand; 845 else if (ml->type_operator == '+') 846 value += (uint64_t)ml->type_operand; 847 else if (ml->type_operator != ' ') 848 return (-1); 849 850 result = magic_test_unsigned(ml, value, (uint64_t)ml->test_unsigned); 851 if (result == !ml->test_not && ml->result != NULL) { 852 t = value; 853 switch (ml->type) { 854 case MAGIC_TYPE_UQLDATE: 855 case MAGIC_TYPE_ULEQLDATE: 856 case MAGIC_TYPE_UBEQLDATE: 857 ctime_r(&t, s); 858 break; 859 default: 860 asctime_r(gmtime(&t), s); 861 break; 862 } 863 s[strcspn(s, "\n")] = '\0'; 864 magic_add_result(ms, ml, "%s", s); 865 ms->offset += sizeof value; 866 } 867 return (result); 868 } 869 870 static int 871 magic_test_type_bestring16(__unused struct magic_line *ml, 872 __unused struct magic_state *ms) 873 { 874 return (-2); 875 } 876 877 static int 878 magic_test_type_lestring16(__unused struct magic_line *ml, 879 __unused struct magic_state *ms) 880 { 881 return (-2); 882 } 883 884 static int 885 magic_test_type_melong(__unused struct magic_line *ml, 886 __unused struct magic_state *ms) 887 { 888 return (-2); 889 } 890 891 static int 892 magic_test_type_medate(__unused struct magic_line *ml, 893 __unused struct magic_state *ms) 894 { 895 return (-2); 896 } 897 898 static int 899 magic_test_type_meldate(__unused struct magic_line *ml, 900 __unused struct magic_state *ms) 901 { 902 return (-2); 903 } 904 905 static int 906 magic_test_type_regex(struct magic_line *ml, struct magic_state *ms) 907 { 908 const char *cp; 909 regex_t re; 910 regmatch_t m; 911 int result, flags = 0, sflag = 0; 912 913 cp = &ml->type_string[(sizeof "regex") - 1]; 914 if (*cp != '\0') { 915 if (*cp != '/') 916 return (-1); 917 cp++; 918 for (; *cp != '\0'; cp++) { 919 switch (*cp) { 920 case 's': 921 sflag = 1; 922 break; 923 case 'c': 924 flags |= REG_ICASE; 925 break; 926 default: 927 return (-1); 928 } 929 } 930 } 931 932 if (regcomp(&re, ml->test_string, REG_EXTENDED) != 0) 933 return (-1); 934 m.rm_so = ms->offset; 935 m.rm_eo = ms->size; 936 937 result = (regexec(&re, ms->base, 1, &m, REG_STARTEND) == 0); 938 if (result == !ml->test_not) { 939 if (ml->result != NULL) 940 magic_add_result(ms, ml, "%s", ""); 941 if (result) { 942 if (sflag) 943 ms->offset = m.rm_so; 944 else 945 ms->offset = m.rm_eo; 946 } 947 } 948 regfree(&re); 949 return (result); 950 } 951 952 static int 953 magic_test_type_search(struct magic_line *ml, struct magic_state *ms) 954 { 955 const char *cp, *endptr, *start, *found; 956 size_t size, end, i; 957 uint64_t range; 958 int result, n, cflag = 0, bflag = 0, Bflag = 0; 959 960 cp = &ml->type_string[(sizeof "search") - 1]; 961 if (*cp != '\0') { 962 if (*cp != '/') 963 return (-1); 964 cp++; 965 966 endptr = magic_strtoull(cp, &range); 967 if (endptr == NULL || (*endptr != '/' && *endptr != '\0')) 968 return (-1); 969 970 if (*endptr == '/') { 971 for (cp = endptr + 1; *cp != '\0'; cp++) { 972 switch (*cp) { 973 case 'B': 974 case 'W': 975 Bflag = 1; 976 break; 977 case 'b': 978 case 'w': 979 bflag = 1; 980 break; 981 case 'c': 982 cflag = 1; 983 break; 984 case 't': 985 break; 986 default: 987 return (-1); 988 } 989 } 990 } 991 } else 992 range = UINT64_MAX; 993 if (range > (uint64_t)ms->size - ms->offset) 994 range = ms->size - ms->offset; 995 size = ml->test_string_size; 996 997 /* Want to search every starting position from up to range + size. */ 998 end = range + size; 999 if (end > ms->size - ms->offset) { 1000 if (size > ms->size - ms->offset) 1001 end = 0; 1002 else 1003 end = ms->size - ms->offset - size; 1004 } 1005 1006 /* 1007 * < and > and the flags are only in /etc/magic with search/1 so don't 1008 * support them with anything else. 1009 */ 1010 start = ms->base + ms->offset; 1011 if (end == 0) 1012 found = NULL; 1013 else if (ml->test_operator == 'x') 1014 found = start; 1015 else if (range == 1) { 1016 n = magic_test_eq(start, ms->size - ms->offset, ml->test_string, 1017 size, cflag, bflag, Bflag); 1018 if (n == -1 && ml->test_operator == '<') 1019 found = start; 1020 else if (n == 1 && ml->test_operator == '>') 1021 found = start; 1022 else if (n == 0 && ml->test_operator == '=') 1023 found = start; 1024 else 1025 found = NULL; 1026 } else { 1027 if (ml->test_operator != '=') 1028 return (-2); 1029 for (i = 0; i < end; i++) { 1030 n = magic_test_eq(start + i, ms->size - ms->offset - i, 1031 ml->test_string, size, cflag, bflag, Bflag); 1032 if (n == 0) { 1033 found = start + i; 1034 break; 1035 } 1036 } 1037 if (i == end) 1038 found = NULL; 1039 } 1040 result = (found != NULL); 1041 1042 if (result == !ml->test_not) { 1043 if (ml->result != NULL) 1044 magic_add_string(ms, ml, found, ms->size - ms->offset); 1045 if (result && found != NULL && ml->test_operator == '=') 1046 ms->offset = (found + size) - ms->base; 1047 } 1048 return (result); 1049 } 1050 1051 static int 1052 magic_test_type_default(__unused struct magic_line *ml, 1053 __unused struct magic_state *ms) 1054 { 1055 return (1); 1056 } 1057 1058 static int (*magic_test_functions[])(struct magic_line *, 1059 struct magic_state *) = { 1060 magic_test_type_none, 1061 magic_test_type_byte, 1062 magic_test_type_short, 1063 magic_test_type_long, 1064 magic_test_type_quad, 1065 magic_test_type_ubyte, 1066 magic_test_type_ushort, 1067 magic_test_type_ulong, 1068 magic_test_type_uquad, 1069 magic_test_type_float, 1070 magic_test_type_double, 1071 magic_test_type_string, 1072 magic_test_type_pstring, 1073 magic_test_type_date, 1074 magic_test_type_qdate, 1075 magic_test_type_date, 1076 magic_test_type_qdate, 1077 magic_test_type_udate, 1078 magic_test_type_uqdate, 1079 magic_test_type_udate, 1080 magic_test_type_qdate, 1081 magic_test_type_short, 1082 magic_test_type_long, 1083 magic_test_type_quad, 1084 magic_test_type_ushort, 1085 magic_test_type_ulong, 1086 magic_test_type_uquad, 1087 magic_test_type_float, 1088 magic_test_type_double, 1089 magic_test_type_date, 1090 magic_test_type_qdate, 1091 magic_test_type_date, 1092 magic_test_type_qdate, 1093 magic_test_type_udate, 1094 magic_test_type_uqdate, 1095 magic_test_type_udate, 1096 magic_test_type_uqdate, 1097 magic_test_type_bestring16, 1098 magic_test_type_short, 1099 magic_test_type_long, 1100 magic_test_type_quad, 1101 magic_test_type_ushort, 1102 magic_test_type_ulong, 1103 magic_test_type_uquad, 1104 magic_test_type_float, 1105 magic_test_type_double, 1106 magic_test_type_date, 1107 magic_test_type_qdate, 1108 magic_test_type_date, 1109 magic_test_type_qdate, 1110 magic_test_type_udate, 1111 magic_test_type_uqdate, 1112 magic_test_type_udate, 1113 magic_test_type_uqdate, 1114 magic_test_type_lestring16, 1115 magic_test_type_melong, 1116 magic_test_type_medate, 1117 magic_test_type_meldate, 1118 magic_test_type_regex, 1119 magic_test_type_search, 1120 magic_test_type_default, 1121 }; 1122 1123 static int 1124 magic_test_line(struct magic_line *ml, struct magic_state *ms) 1125 { 1126 struct magic_line *child; 1127 int64_t offset, wanted, next; 1128 int result; 1129 uint8_t b; 1130 uint16_t s; 1131 uint32_t l; 1132 1133 if (ml->indirect_type == ' ') 1134 wanted = ml->offset; 1135 else { 1136 wanted = ml->indirect_offset; 1137 if (ml->indirect_relative) { 1138 if (wanted < 0 && -wanted > ms->offset) 1139 return (0); 1140 if (wanted > 0 && ms->offset + wanted > ms->size) 1141 return (0); 1142 next = ms->offset + ml->indirect_offset; 1143 } else 1144 next = wanted; 1145 1146 switch (ml->indirect_type) { 1147 case 'b': 1148 case 'B': 1149 if (magic_copy_from(ms, next, &b, sizeof b) != 0) 1150 return (0); 1151 wanted = b; 1152 break; 1153 case 's': 1154 if (magic_copy_from(ms, next, &s, sizeof s) != 0) 1155 return (0); 1156 wanted = le16toh(s); 1157 break; 1158 case 'S': 1159 if (magic_copy_from(ms, next, &s, sizeof s) != 0) 1160 return (0); 1161 wanted = be16toh(s); 1162 break; 1163 case 'l': 1164 if (magic_copy_from(ms, next, &l, sizeof l) != 0) 1165 return (0); 1166 wanted = le16toh(l); 1167 break; 1168 case 'L': 1169 if (magic_copy_from(ms, next, &l, sizeof l) != 0) 1170 return (0); 1171 wanted = be16toh(l); 1172 break; 1173 } 1174 1175 switch (ml->indirect_operator) { 1176 case '+': 1177 wanted += ml->indirect_operand; 1178 break; 1179 case '-': 1180 wanted -= ml->indirect_operand; 1181 break; 1182 case '*': 1183 wanted *= ml->indirect_operand; 1184 break; 1185 } 1186 } 1187 1188 if (ml->offset_relative) { 1189 if (wanted < 0 && -wanted > ms->offset) 1190 return (0); 1191 if (wanted > 0 && ms->offset + wanted > ms->size) 1192 return (0); 1193 offset = ms->offset + wanted; 1194 } else 1195 offset = wanted; 1196 if (offset < 0 || offset > ms->size) 1197 return (0); 1198 ms->offset = offset; 1199 1200 result = magic_test_functions[ml->type](ml, ms); 1201 if (result == -1) { 1202 magic_warn(ml, "test %s/%c failed", ml->type_string, 1203 ml->test_operator); 1204 return (0); 1205 } 1206 if (result == -2) { 1207 magic_warn(ml, "test %s/%c not implemented", ml->type_string, 1208 ml->test_operator); 1209 return (0); 1210 } 1211 if (result == ml->test_not) 1212 return (0); 1213 if (ml->mimetype != NULL) 1214 ms->mimetype = ml->mimetype; 1215 1216 magic_warn(ml, "test %s/%c matched at offset %llu: '%s'", 1217 ml->type_string, ml->test_operator, ms->offset, 1218 ml->result == NULL ? "" : ml->result); 1219 1220 offset = ms->offset; 1221 TAILQ_FOREACH(child, &ml->children, entry) { 1222 ms->offset = offset; 1223 magic_test_line(child, ms); 1224 } 1225 return (ml->result != NULL); 1226 } 1227 1228 const char * 1229 magic_test(struct magic *m, const void *base, size_t size, int flags) 1230 { 1231 struct magic_line *ml; 1232 static struct magic_state ms; 1233 1234 memset(&ms, 0, sizeof ms); 1235 1236 ms.base = base; 1237 ms.size = size; 1238 1239 ms.text = !!(flags & MAGIC_TEST_TEXT); 1240 1241 RB_FOREACH(ml, magic_tree, &m->tree) { 1242 ms.offset = 0; 1243 if (ml->text == ms.text && magic_test_line(ml, &ms)) 1244 break; 1245 } 1246 1247 if (*ms.out != '\0') { 1248 if (flags & MAGIC_TEST_MIME) { 1249 if (ms.mimetype) 1250 return (xstrdup(ms.mimetype)); 1251 return (NULL); 1252 } 1253 return (xstrdup(ms.out)); 1254 } 1255 return (NULL); 1256 } 1257