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