1 /* 2 * Copyright (c) Ian F. Darwin 1986-1995. 3 * Software written by Ian F. Darwin and others; 4 * maintained 1995-present by Christos Zoulas and others. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice immediately at the beginning of the file, without modification, 11 * this list of conditions, and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 /* 29 * apprentice - make one pass through /etc/magic, learning its secrets. 30 */ 31 32 #include "file.h" 33 34 #ifndef lint 35 FILE_RCSID("@(#)$File: apprentice.c,v 1.369 2025/10/08 16:40:52 christos Exp $") 36 #endif /* lint */ 37 38 #include "magic.h" 39 #include <stdlib.h> 40 #ifdef HAVE_UNISTD_H 41 #include <unistd.h> 42 #endif 43 #include <stddef.h> 44 #include <string.h> 45 #include <assert.h> 46 #include <ctype.h> 47 #include <fcntl.h> 48 #ifdef QUICK 49 #include <sys/mman.h> 50 #endif 51 #include <dirent.h> 52 #include <limits.h> 53 #ifdef HAVE_BYTESWAP_H 54 #include <byteswap.h> 55 #endif 56 #ifdef HAVE_SYS_BSWAP_H 57 #include <sys/bswap.h> 58 #endif 59 60 61 #define EATAB {while (*l && isascii(CAST(unsigned char, *l)) && \ 62 isspace(CAST(unsigned char, *l))) ++l;} 63 #define LOWCASE(l) (isupper(CAST(unsigned char, l)) ? \ 64 tolower(CAST(unsigned char, l)) : (l)) 65 /* 66 * Work around a bug in headers on Digital Unix. 67 * At least confirmed for: OSF1 V4.0 878 68 */ 69 #if defined(__osf__) && defined(__DECC) 70 #ifdef MAP_FAILED 71 #undef MAP_FAILED 72 #endif 73 #endif 74 75 #ifndef MAP_FAILED 76 #define MAP_FAILED (void *) -1 77 #endif 78 79 #ifndef MAP_FILE 80 #define MAP_FILE 0 81 #endif 82 83 #define ALLOC_CHUNK CAST(size_t, 10) 84 #define ALLOC_INCR CAST(size_t, 200) 85 86 #define MAP_TYPE_USER 0 87 #define MAP_TYPE_MALLOC 1 88 #define MAP_TYPE_MMAP 2 89 90 struct magic_entry { 91 struct magic *mp; 92 uint32_t cont_count; 93 uint32_t max_count; 94 }; 95 96 struct magic_entry_set { 97 struct magic_entry *me; 98 uint32_t count; 99 uint32_t max; 100 }; 101 102 struct magic_map { 103 void *p; 104 size_t len; 105 int type; 106 struct magic *magic[MAGIC_SETS]; 107 uint32_t nmagic[MAGIC_SETS]; 108 }; 109 110 file_private int file_formats[FILE_NAMES_SIZE]; 111 file_private const size_t file_nformats = FILE_NAMES_SIZE; 112 file_protected const char *file_names[FILE_NAMES_SIZE]; 113 file_protected const size_t file_nnames = FILE_NAMES_SIZE; 114 115 file_private int getvalue(struct magic_set *ms, struct magic *, const char **, int); 116 file_private int hextoint(int); 117 file_private const char *getstr(struct magic_set *, struct magic *, const char *, 118 int); 119 file_private int parse(struct magic_set *, struct magic_entry *, const char *, 120 const char *, size_t, int); 121 file_private void eatsize(const char **); 122 file_private int apprentice_1(struct magic_set *, const char *, int); 123 file_private ssize_t apprentice_magic_strength_1(const struct magic *); 124 file_private int apprentice_sort(const void *, const void *); 125 file_private void apprentice_list(struct mlist *, int ); 126 file_private struct magic_map *apprentice_load(struct magic_set *, 127 const char *, int); 128 file_private struct mlist *mlist_alloc(void); 129 file_private void mlist_free_all(struct magic_set *); 130 file_private void mlist_free(struct mlist *); 131 file_private void byteswap(struct magic *, uint32_t); 132 file_private void bs1(struct magic *); 133 134 #if defined(HAVE_BYTESWAP_H) 135 #define swap2(x) bswap_16(x) 136 #define swap4(x) bswap_32(x) 137 #define swap8(x) bswap_64(x) 138 #elif defined(HAVE_SYS_BSWAP_H) 139 #define swap2(x) bswap16(x) 140 #define swap4(x) bswap32(x) 141 #define swap8(x) bswap64(x) 142 #else 143 file_private uint16_t swap2(uint16_t); 144 file_private uint32_t swap4(uint32_t); 145 file_private uint64_t swap8(uint64_t); 146 #endif 147 148 file_private char *mkdbname(struct magic_set *, const char *, int); 149 file_private struct magic_map *apprentice_buf(struct magic_set *, struct magic *, 150 size_t); 151 file_private struct magic_map *apprentice_map(struct magic_set *, const char *); 152 file_private int check_buffer(struct magic_set *, struct magic_map *, const char *); 153 file_private void apprentice_unmap(struct magic_map *); 154 file_private int apprentice_compile(struct magic_set *, struct magic_map *, 155 const char *); 156 file_private int check_format_type(const char *, int, const char **); 157 file_private int check_format(struct magic_set *, struct magic *); 158 file_private int get_op(char); 159 file_private int parse_mime(struct magic_set *, struct magic_entry *, const char *, 160 size_t); 161 file_private int parse_strength(struct magic_set *, struct magic_entry *, 162 const char *, size_t); 163 file_private int parse_apple(struct magic_set *, struct magic_entry *, const char *, 164 size_t); 165 file_private int parse_ext(struct magic_set *, struct magic_entry *, const char *, 166 size_t); 167 168 169 file_private size_t magicsize = sizeof(struct magic); 170 171 file_private const char usg_hdr[] = "cont\toffset\ttype\topcode\tmask\tvalue\tdesc"; 172 173 file_private struct { 174 const char *name; 175 size_t len; 176 int (*fun)(struct magic_set *, struct magic_entry *, const char *, 177 size_t); 178 } bang[] = { 179 #define DECLARE_FIELD(name) { # name, sizeof(# name) - 1, parse_ ## name } 180 DECLARE_FIELD(mime), 181 DECLARE_FIELD(apple), 182 DECLARE_FIELD(ext), 183 DECLARE_FIELD(strength), 184 #undef DECLARE_FIELD 185 { NULL, 0, NULL } 186 }; 187 188 #ifdef COMPILE_ONLY 189 190 int main(int, char *[]); 191 192 int 193 main(int argc, char *argv[]) 194 { 195 int ret; 196 struct magic_set *ms; 197 char *progname; 198 199 if ((progname = strrchr(argv[0], '/')) != NULL) 200 progname++; 201 else 202 progname = argv[0]; 203 204 if (argc != 2) { 205 (void)fprintf(stderr, "Usage: %s file\n", progname); 206 return 1; 207 } 208 209 if ((ms = magic_open(MAGIC_CHECK)) == NULL) { 210 (void)fprintf(stderr, "%s: %s\n", progname, strerror(errno)); 211 return 1; 212 } 213 ret = magic_compile(ms, argv[1]) == -1 ? 1 : 0; 214 if (ret == 1) 215 (void)fprintf(stderr, "%s: %s\n", progname, magic_error(ms)); 216 magic_close(ms); 217 return ret; 218 } 219 #endif /* COMPILE_ONLY */ 220 221 struct type_tbl_s { 222 const char name[16]; 223 const size_t len; 224 const int type; 225 const int format; 226 }; 227 228 /* 229 * XXX - the actual Single UNIX Specification says that "long" means "long", 230 * as in the C data type, but we treat it as meaning "4-byte integer". 231 * Given that the OS X version of file 5.04 did the same, I guess that passes 232 * the actual test; having "long" be dependent on how big a "long" is on 233 * the machine running "file" is silly. 234 */ 235 static const struct type_tbl_s type_tbl[] = { 236 # define XX(s) s, (sizeof(s) - 1) 237 # define XX_NULL "", 0 238 { XX("invalid"), FILE_INVALID, FILE_FMT_NONE }, 239 { XX("byte"), FILE_BYTE, FILE_FMT_NUM }, 240 { XX("short"), FILE_SHORT, FILE_FMT_NUM }, 241 { XX("default"), FILE_DEFAULT, FILE_FMT_NONE }, 242 { XX("long"), FILE_LONG, FILE_FMT_NUM }, 243 { XX("string"), FILE_STRING, FILE_FMT_STR }, 244 { XX("date"), FILE_DATE, FILE_FMT_STR }, 245 { XX("beshort"), FILE_BESHORT, FILE_FMT_NUM }, 246 { XX("belong"), FILE_BELONG, FILE_FMT_NUM }, 247 { XX("bedate"), FILE_BEDATE, FILE_FMT_STR }, 248 { XX("leshort"), FILE_LESHORT, FILE_FMT_NUM }, 249 { XX("lelong"), FILE_LELONG, FILE_FMT_NUM }, 250 { XX("ledate"), FILE_LEDATE, FILE_FMT_STR }, 251 { XX("pstring"), FILE_PSTRING, FILE_FMT_STR }, 252 { XX("ldate"), FILE_LDATE, FILE_FMT_STR }, 253 { XX("beldate"), FILE_BELDATE, FILE_FMT_STR }, 254 { XX("leldate"), FILE_LELDATE, FILE_FMT_STR }, 255 { XX("regex"), FILE_REGEX, FILE_FMT_STR }, 256 { XX("bestring16"), FILE_BESTRING16, FILE_FMT_STR }, 257 { XX("lestring16"), FILE_LESTRING16, FILE_FMT_STR }, 258 { XX("search"), FILE_SEARCH, FILE_FMT_STR }, 259 { XX("medate"), FILE_MEDATE, FILE_FMT_STR }, 260 { XX("meldate"), FILE_MELDATE, FILE_FMT_STR }, 261 { XX("melong"), FILE_MELONG, FILE_FMT_NUM }, 262 { XX("quad"), FILE_QUAD, FILE_FMT_QUAD }, 263 { XX("lequad"), FILE_LEQUAD, FILE_FMT_QUAD }, 264 { XX("bequad"), FILE_BEQUAD, FILE_FMT_QUAD }, 265 { XX("qdate"), FILE_QDATE, FILE_FMT_STR }, 266 { XX("leqdate"), FILE_LEQDATE, FILE_FMT_STR }, 267 { XX("beqdate"), FILE_BEQDATE, FILE_FMT_STR }, 268 { XX("qldate"), FILE_QLDATE, FILE_FMT_STR }, 269 { XX("leqldate"), FILE_LEQLDATE, FILE_FMT_STR }, 270 { XX("beqldate"), FILE_BEQLDATE, FILE_FMT_STR }, 271 { XX("float"), FILE_FLOAT, FILE_FMT_FLOAT }, 272 { XX("befloat"), FILE_BEFLOAT, FILE_FMT_FLOAT }, 273 { XX("lefloat"), FILE_LEFLOAT, FILE_FMT_FLOAT }, 274 { XX("double"), FILE_DOUBLE, FILE_FMT_DOUBLE }, 275 { XX("bedouble"), FILE_BEDOUBLE, FILE_FMT_DOUBLE }, 276 { XX("ledouble"), FILE_LEDOUBLE, FILE_FMT_DOUBLE }, 277 { XX("leid3"), FILE_LEID3, FILE_FMT_NUM }, 278 { XX("beid3"), FILE_BEID3, FILE_FMT_NUM }, 279 { XX("indirect"), FILE_INDIRECT, FILE_FMT_NUM }, 280 { XX("qwdate"), FILE_QWDATE, FILE_FMT_STR }, 281 { XX("leqwdate"), FILE_LEQWDATE, FILE_FMT_STR }, 282 { XX("beqwdate"), FILE_BEQWDATE, FILE_FMT_STR }, 283 { XX("name"), FILE_NAME, FILE_FMT_NONE }, 284 { XX("use"), FILE_USE, FILE_FMT_NONE }, 285 { XX("clear"), FILE_CLEAR, FILE_FMT_NONE }, 286 { XX("der"), FILE_DER, FILE_FMT_STR }, 287 { XX("guid"), FILE_GUID, FILE_FMT_STR }, 288 { XX("offset"), FILE_OFFSET, FILE_FMT_QUAD }, 289 { XX("bevarint"), FILE_BEVARINT, FILE_FMT_STR }, 290 { XX("levarint"), FILE_LEVARINT, FILE_FMT_STR }, 291 { XX("msdosdate"), FILE_MSDOSDATE, FILE_FMT_STR }, 292 { XX("lemsdosdate"), FILE_LEMSDOSDATE, FILE_FMT_STR }, 293 { XX("bemsdosdate"), FILE_BEMSDOSDATE, FILE_FMT_STR }, 294 { XX("msdostime"), FILE_MSDOSTIME, FILE_FMT_STR }, 295 { XX("lemsdostime"), FILE_LEMSDOSTIME, FILE_FMT_STR }, 296 { XX("bemsdostime"), FILE_BEMSDOSTIME, FILE_FMT_STR }, 297 { XX("octal"), FILE_OCTAL, FILE_FMT_STR }, 298 { XX_NULL, FILE_INVALID, FILE_FMT_NONE }, 299 }; 300 301 /* 302 * These are not types, and cannot be preceded by "u" to make them 303 * unsigned. 304 */ 305 static const struct type_tbl_s special_tbl[] = { 306 { XX("der"), FILE_DER, FILE_FMT_STR }, 307 { XX("name"), FILE_NAME, FILE_FMT_STR }, 308 { XX("use"), FILE_USE, FILE_FMT_STR }, 309 { XX("octal"), FILE_OCTAL, FILE_FMT_STR }, 310 { XX_NULL, FILE_INVALID, FILE_FMT_NONE }, 311 }; 312 # undef XX 313 # undef XX_NULL 314 315 file_private int 316 get_type(const struct type_tbl_s *tbl, const char *l, const char **t) 317 { 318 const struct type_tbl_s *p; 319 320 for (p = tbl; p->len; p++) { 321 if (strncmp(l, p->name, p->len) == 0) { 322 if (t) 323 *t = l + p->len; 324 break; 325 } 326 } 327 return p->type; 328 } 329 330 file_private off_t 331 maxoff_t(void) { 332 if (/*CONSTCOND*/sizeof(off_t) == sizeof(int)) 333 return CAST(off_t, INT_MAX); 334 if (/*CONSTCOND*/sizeof(off_t) == sizeof(long)) 335 return CAST(off_t, LONG_MAX); 336 return 0x7fffffff; 337 } 338 339 file_private int 340 get_standard_integer_type(const char *l, const char **t) 341 { 342 int type; 343 344 if (l[0] == '\0') 345 return FILE_INVALID; 346 if (l[1] == '\0') 347 return FILE_INVALID; 348 else if (isalpha(CAST(unsigned char, l[1]))) { 349 switch (l[1]) { 350 case 'C': 351 /* "dC" and "uC" */ 352 type = FILE_BYTE; 353 break; 354 case 'S': 355 /* "dS" and "uS" */ 356 type = FILE_SHORT; 357 break; 358 case 'I': 359 case 'L': 360 /* 361 * "dI", "dL", "uI", and "uL". 362 * 363 * XXX - the actual Single UNIX Specification says 364 * that "L" means "long", as in the C data type, 365 * but we treat it as meaning "4-byte integer". 366 * Given that the OS X version of file 5.04 did 367 * the same, I guess that passes the actual SUS 368 * validation suite; having "dL" be dependent on 369 * how big a "long" is on the machine running 370 * "file" is silly. 371 */ 372 type = FILE_LONG; 373 break; 374 case 'Q': 375 /* "dQ" and "uQ" */ 376 type = FILE_QUAD; 377 break; 378 default: 379 /* "d{anything else}", "u{anything else}" */ 380 return FILE_INVALID; 381 } 382 l += 2; 383 } else if (isdigit(CAST(unsigned char, l[1]))) { 384 /* 385 * "d{num}" and "u{num}"; we only support {num} values 386 * of 1, 2, 4, and 8 - the Single UNIX Specification 387 * doesn't say anything about whether arbitrary 388 * values should be supported, but both the Solaris 10 389 * and OS X Mountain Lion versions of file passed the 390 * Single UNIX Specification validation suite, and 391 * neither of them support values bigger than 8 or 392 * non-power-of-2 values. 393 */ 394 if (isdigit(CAST(unsigned char, l[2]))) { 395 /* Multi-digit, so > 9 */ 396 return FILE_INVALID; 397 } 398 switch (l[1]) { 399 case '1': 400 type = FILE_BYTE; 401 break; 402 case '2': 403 type = FILE_SHORT; 404 break; 405 case '4': 406 type = FILE_LONG; 407 break; 408 case '8': 409 type = FILE_QUAD; 410 break; 411 default: 412 /* XXX - what about 3, 5, 6, or 7? */ 413 return FILE_INVALID; 414 } 415 l += 2; 416 } else { 417 /* 418 * "d" or "u" by itself. 419 */ 420 type = FILE_LONG; 421 ++l; 422 } 423 if (t) 424 *t = l; 425 return type; 426 } 427 428 file_private void 429 init_file_tables(void) 430 { 431 static int done = 0; 432 const struct type_tbl_s *p; 433 434 if (done) 435 return; 436 done++; 437 438 for (p = type_tbl; p->len; p++) { 439 assert(p->type < FILE_NAMES_SIZE); 440 file_names[p->type] = p->name; 441 file_formats[p->type] = p->format; 442 } 443 assert(p - type_tbl == FILE_NAMES_SIZE); 444 } 445 446 file_private int 447 add_mlist(struct mlist *mlp, struct magic_map *map, size_t idx) 448 { 449 struct mlist *ml; 450 451 mlp->map = NULL; 452 if ((ml = CAST(struct mlist *, malloc(sizeof(*ml)))) == NULL) 453 return -1; 454 455 ml->map = idx == 0 ? map : NULL; 456 ml->magic = map->magic[idx]; 457 ml->nmagic = map->nmagic[idx]; 458 if (ml->nmagic) { 459 ml->magic_rxcomp = CAST(file_regex_t **, 460 calloc(ml->nmagic, sizeof(*ml->magic_rxcomp))); 461 if (ml->magic_rxcomp == NULL) { 462 free(ml); 463 return -1; 464 } 465 } else 466 ml->magic_rxcomp = NULL; 467 mlp->prev->next = ml; 468 ml->prev = mlp->prev; 469 ml->next = mlp; 470 mlp->prev = ml; 471 return 0; 472 } 473 474 /* 475 * Handle one file or directory. 476 */ 477 file_private int 478 apprentice_1(struct magic_set *ms, const char *fn, int action) 479 { 480 struct magic_map *map; 481 #ifndef COMPILE_ONLY 482 size_t i; 483 #endif 484 485 if (magicsize != FILE_MAGICSIZE) { 486 file_error(ms, 0, "magic element size %lu != %lu", 487 CAST(unsigned long, sizeof(*map->magic[0])), 488 CAST(unsigned long, FILE_MAGICSIZE)); 489 return -1; 490 } 491 492 if (action == FILE_COMPILE) { 493 map = apprentice_load(ms, fn, action); 494 if (map == NULL) 495 return -1; 496 return apprentice_compile(ms, map, fn); 497 } 498 499 #ifndef COMPILE_ONLY 500 map = apprentice_map(ms, fn); 501 if (map == NULL) { 502 if (ms->flags & MAGIC_CHECK) 503 file_magwarn(ms, "using regular magic file `%s'", fn); 504 map = apprentice_load(ms, fn, action); 505 if (map == NULL) 506 return -1; 507 } 508 509 for (i = 0; i < MAGIC_SETS; i++) { 510 if (add_mlist(ms->mlist[i], map, i) == -1) { 511 /* failed to add to any list, free explicitly */ 512 if (i == 0) 513 apprentice_unmap(map); 514 else 515 mlist_free_all(ms); 516 file_oomem(ms, sizeof(*ms->mlist[0])); 517 return -1; 518 } 519 } 520 521 if (action == FILE_LIST) { 522 for (i = 0; i < MAGIC_SETS; i++) { 523 printf("Set %" SIZE_T_FORMAT "u:\nBinary patterns:\n", 524 i); 525 apprentice_list(ms->mlist[i], BINTEST); 526 printf("Text patterns:\n"); 527 apprentice_list(ms->mlist[i], TEXTTEST); 528 } 529 } 530 return 0; 531 #else 532 return 0; 533 #endif /* COMPILE_ONLY */ 534 } 535 536 file_protected void 537 file_ms_free(struct magic_set *ms) 538 { 539 size_t i; 540 if (ms == NULL) 541 return; 542 for (i = 0; i < MAGIC_SETS; i++) 543 mlist_free(ms->mlist[i]); 544 free(ms->o.pbuf); 545 free(ms->o.buf); 546 free(ms->c.li); 547 free(ms->fnamebuf); 548 #ifdef USE_C_LOCALE 549 freelocale(ms->c_lc_ctype); 550 #endif 551 free(ms); 552 } 553 554 file_protected struct magic_set * 555 file_ms_alloc(int flags) 556 { 557 struct magic_set *ms; 558 size_t i, len; 559 560 if ((ms = CAST(struct magic_set *, calloc(CAST(size_t, 1u), 561 sizeof(*ms)))) == NULL) 562 return NULL; 563 564 if (magic_setflags(ms, flags) == -1) { 565 errno = EINVAL; 566 goto free; 567 } 568 569 ms->o.buf = ms->o.pbuf = NULL; 570 ms->o.blen = 0; 571 len = (ms->c.len = 10) * sizeof(*ms->c.li); 572 573 if ((ms->c.li = CAST(struct level_info *, malloc(len))) == NULL) 574 goto free; 575 576 ms->event_flags = 0; 577 ms->error = -1; 578 for (i = 0; i < MAGIC_SETS; i++) 579 ms->mlist[i] = NULL; 580 ms->fnamebuf = NULL; 581 ms->file = "unknown"; 582 ms->line = 0; 583 ms->magwarn = 0; 584 ms->indir_max = FILE_INDIR_MAX; 585 ms->name_max = FILE_NAME_MAX; 586 ms->elf_shnum_max = FILE_ELF_SHNUM_MAX; 587 ms->elf_shsize_max = FILE_ELF_SHSIZE_MAX; 588 ms->elf_phnum_max = FILE_ELF_PHNUM_MAX; 589 ms->elf_notes_max = FILE_ELF_NOTES_MAX; 590 ms->regex_max = FILE_REGEX_MAX; 591 ms->bytes_max = FILE_BYTES_MAX; 592 ms->encoding_max = FILE_ENCODING_MAX; 593 ms->magwarn_max = FILE_MAGWARN_MAX; 594 #ifdef USE_C_LOCALE 595 ms->c_lc_ctype = newlocale(LC_CTYPE_MASK, "C", 0); 596 assert(ms->c_lc_ctype != NULL); 597 #endif 598 return ms; 599 free: 600 free(ms); 601 return NULL; 602 } 603 604 file_private void 605 apprentice_unmap(struct magic_map *map) 606 { 607 size_t i; 608 char *p; 609 if (map == NULL) 610 return; 611 612 switch (map->type) { 613 case MAP_TYPE_USER: 614 break; 615 case MAP_TYPE_MALLOC: 616 p = CAST(char *, map->p); 617 for (i = 0; i < MAGIC_SETS; i++) { 618 char *b = RCAST(char *, map->magic[i]); 619 if (p != NULL && b >= p && b <= p + map->len) 620 continue; 621 free(b); 622 } 623 free(p); 624 break; 625 #ifdef QUICK 626 case MAP_TYPE_MMAP: 627 if (map->p && map->p != MAP_FAILED) 628 (void)munmap(map->p, map->len); 629 break; 630 #endif 631 default: 632 fprintf(stderr, "Bad map type %d", map->type); 633 abort(); 634 } 635 free(map); 636 } 637 638 file_private struct mlist * 639 mlist_alloc(void) 640 { 641 struct mlist *mlist; 642 if ((mlist = CAST(struct mlist *, calloc(1, sizeof(*mlist)))) == NULL) { 643 return NULL; 644 } 645 mlist->next = mlist->prev = mlist; 646 return mlist; 647 } 648 649 file_private void 650 mlist_free_all(struct magic_set *ms) 651 { 652 size_t i; 653 654 for (i = 0; i < MAGIC_SETS; i++) { 655 mlist_free(ms->mlist[i]); 656 ms->mlist[i] = NULL; 657 } 658 } 659 660 file_private void 661 mlist_free_one(struct mlist *ml) 662 { 663 size_t i; 664 665 if (ml->map) 666 apprentice_unmap(CAST(struct magic_map *, ml->map)); 667 668 for (i = 0; i < ml->nmagic; ++i) { 669 if (ml->magic_rxcomp[i]) { 670 file_regfree(ml->magic_rxcomp[i]); 671 free(ml->magic_rxcomp[i]); 672 ml->magic_rxcomp[i] = NULL; 673 } 674 } 675 free(ml->magic_rxcomp); 676 ml->magic_rxcomp = NULL; 677 free(ml); 678 } 679 680 file_private void 681 mlist_free(struct mlist *mlist) 682 { 683 struct mlist *ml, *next; 684 685 if (mlist == NULL) 686 return; 687 688 for (ml = mlist->next; ml != mlist;) { 689 next = ml->next; 690 mlist_free_one(ml); 691 ml = next; 692 } 693 mlist_free_one(mlist); 694 } 695 696 #ifndef COMPILE_ONLY 697 /* void **bufs: an array of compiled magic files */ 698 file_protected int 699 buffer_apprentice(struct magic_set *ms, struct magic **bufs, 700 size_t *sizes, size_t nbufs) 701 { 702 size_t i, j; 703 struct magic_map *map; 704 705 if (nbufs == 0) 706 return -1; 707 708 (void)file_reset(ms, 0); 709 710 init_file_tables(); 711 712 for (i = 0; i < MAGIC_SETS; i++) { 713 mlist_free(ms->mlist[i]); 714 if ((ms->mlist[i] = mlist_alloc()) == NULL) { 715 file_oomem(ms, sizeof(*ms->mlist[0])); 716 goto fail; 717 } 718 } 719 720 for (i = 0; i < nbufs; i++) { 721 map = apprentice_buf(ms, bufs[i], sizes[i]); 722 if (map == NULL) 723 goto fail; 724 725 for (j = 0; j < MAGIC_SETS; j++) { 726 if (add_mlist(ms->mlist[j], map, j) == -1) { 727 file_oomem(ms, sizeof(*ms->mlist[0])); 728 goto fail; 729 } 730 } 731 } 732 733 return 0; 734 fail: 735 mlist_free_all(ms); 736 return -1; 737 } 738 #endif 739 740 /* const char *fn: list of magic files and directories */ 741 file_protected int 742 file_apprentice(struct magic_set *ms, const char *fn, int action) 743 { 744 char *p; 745 int fileerr, errs = -1; 746 size_t i, j; 747 748 (void)file_reset(ms, 0); 749 750 if ((fn = magic_getpath(fn, action)) == NULL) 751 return -1; 752 753 init_file_tables(); 754 755 free(ms->fnamebuf); 756 ms->file = NULL; 757 if ((ms->fnamebuf = strdup(fn)) == NULL) { 758 file_oomem(ms, strlen(fn)); 759 return -1; 760 } 761 762 for (i = 0; i < MAGIC_SETS; i++) { 763 mlist_free(ms->mlist[i]); 764 if ((ms->mlist[i] = mlist_alloc()) == NULL) { 765 file_oomem(ms, sizeof(*ms->mlist[0])); 766 for (j = 0; j < i; j++) { 767 mlist_free(ms->mlist[j]); 768 ms->mlist[j] = NULL; 769 } 770 return -1; 771 } 772 } 773 fn = ms->fnamebuf; 774 775 while (fn) { 776 p = CCAST(char *, strchr(fn, PATHSEP)); 777 if (p) 778 *p++ = '\0'; 779 if (*fn == '\0') 780 break; 781 fileerr = apprentice_1(ms, fn, action); 782 errs = MAX(errs, fileerr); 783 fn = p; 784 } 785 786 if (errs == -1) { 787 for (i = 0; i < MAGIC_SETS; i++) { 788 mlist_free(ms->mlist[i]); 789 ms->mlist[i] = NULL; 790 } 791 file_error(ms, 0, "could not find any valid magic files!"); 792 return -1; 793 } 794 795 #if 0 796 /* 797 * Always leave the database loaded 798 */ 799 if (action == FILE_LOAD) 800 return 0; 801 802 for (i = 0; i < MAGIC_SETS; i++) { 803 mlist_free(ms->mlist[i]); 804 ms->mlist[i] = NULL; 805 } 806 #endif 807 808 switch (action) { 809 case FILE_LOAD: 810 case FILE_COMPILE: 811 case FILE_CHECK: 812 case FILE_LIST: 813 return 0; 814 default: 815 file_error(ms, 0, "Invalid action %d", action); 816 return -1; 817 } 818 } 819 820 /* 821 * Compute the real length of a magic expression, for the purposes 822 * of determining how "strong" a magic expression is (approximating 823 * how specific its matches are): 824 * - magic characters count 0 unless escaped. 825 * - [] expressions count 1 826 * - {} expressions count 0 827 * - regular characters or escaped magic characters count 1 828 * - 0 length expressions count as one 829 */ 830 file_private size_t 831 nonmagic(const char *str) 832 { 833 const char *p; 834 size_t rv = 0; 835 836 for (p = str; *p; p++) 837 switch (*p) { 838 case '\\': /* Escaped anything counts 1 */ 839 if (!*++p) 840 p--; 841 rv++; 842 continue; 843 case '?': /* Magic characters count 0 */ 844 case '*': 845 case '.': 846 case '+': 847 case '^': 848 case '$': 849 continue; 850 case '[': /* Bracketed expressions count 1 the ']' */ 851 while (*p && *p != ']') 852 p++; 853 p--; 854 continue; 855 case '{': /* Braced expressions count 0 */ 856 while (*p && *p != '}') 857 p++; 858 if (!*p) 859 p--; 860 continue; 861 default: /* Anything else counts 1 */ 862 rv++; 863 continue; 864 } 865 866 return rv == 0 ? 1 : rv; /* Return at least 1 */ 867 } 868 869 870 file_private size_t 871 typesize(int type) 872 { 873 switch (type) { 874 case FILE_BYTE: 875 return 1; 876 877 case FILE_SHORT: 878 case FILE_LESHORT: 879 case FILE_BESHORT: 880 case FILE_MSDOSDATE: 881 case FILE_BEMSDOSDATE: 882 case FILE_LEMSDOSDATE: 883 case FILE_MSDOSTIME: 884 case FILE_BEMSDOSTIME: 885 case FILE_LEMSDOSTIME: 886 return 2; 887 888 case FILE_LONG: 889 case FILE_LELONG: 890 case FILE_BELONG: 891 case FILE_MELONG: 892 return 4; 893 894 case FILE_DATE: 895 case FILE_LEDATE: 896 case FILE_BEDATE: 897 case FILE_MEDATE: 898 case FILE_LDATE: 899 case FILE_LELDATE: 900 case FILE_BELDATE: 901 case FILE_MELDATE: 902 case FILE_FLOAT: 903 case FILE_BEFLOAT: 904 case FILE_LEFLOAT: 905 case FILE_BEID3: 906 case FILE_LEID3: 907 return 4; 908 909 case FILE_QUAD: 910 case FILE_BEQUAD: 911 case FILE_LEQUAD: 912 case FILE_QDATE: 913 case FILE_LEQDATE: 914 case FILE_BEQDATE: 915 case FILE_QLDATE: 916 case FILE_LEQLDATE: 917 case FILE_BEQLDATE: 918 case FILE_QWDATE: 919 case FILE_LEQWDATE: 920 case FILE_BEQWDATE: 921 case FILE_DOUBLE: 922 case FILE_BEDOUBLE: 923 case FILE_LEDOUBLE: 924 case FILE_OFFSET: 925 case FILE_BEVARINT: 926 case FILE_LEVARINT: 927 return 8; 928 929 case FILE_GUID: 930 return 16; 931 932 default: 933 return FILE_BADSIZE; 934 } 935 } 936 937 /* 938 * Get weight of this magic entry, for sorting purposes. 939 */ 940 file_private ssize_t 941 apprentice_magic_strength_1(const struct magic *m) 942 { 943 #define MULT 10U 944 size_t ts, v; 945 ssize_t val = 2 * MULT; /* baseline strength */ 946 947 switch (m->type) { 948 case FILE_DEFAULT: /* make sure this sorts last */ 949 if (m->factor_op != FILE_FACTOR_OP_NONE) { 950 file_magwarn1("Unsupported factor_op in default %d", 951 m->factor_op); 952 } 953 return 0; 954 955 case FILE_BYTE: 956 case FILE_SHORT: 957 case FILE_LESHORT: 958 case FILE_BESHORT: 959 case FILE_LONG: 960 case FILE_LELONG: 961 case FILE_BELONG: 962 case FILE_MELONG: 963 case FILE_DATE: 964 case FILE_LEDATE: 965 case FILE_BEDATE: 966 case FILE_MEDATE: 967 case FILE_LDATE: 968 case FILE_LELDATE: 969 case FILE_BELDATE: 970 case FILE_MELDATE: 971 case FILE_FLOAT: 972 case FILE_BEFLOAT: 973 case FILE_LEFLOAT: 974 case FILE_QUAD: 975 case FILE_BEQUAD: 976 case FILE_LEQUAD: 977 case FILE_QDATE: 978 case FILE_LEQDATE: 979 case FILE_BEQDATE: 980 case FILE_QLDATE: 981 case FILE_LEQLDATE: 982 case FILE_BEQLDATE: 983 case FILE_QWDATE: 984 case FILE_LEQWDATE: 985 case FILE_BEQWDATE: 986 case FILE_DOUBLE: 987 case FILE_BEDOUBLE: 988 case FILE_LEDOUBLE: 989 case FILE_BEVARINT: 990 case FILE_LEVARINT: 991 case FILE_GUID: 992 case FILE_BEID3: 993 case FILE_LEID3: 994 case FILE_OFFSET: 995 case FILE_MSDOSDATE: 996 case FILE_BEMSDOSDATE: 997 case FILE_LEMSDOSDATE: 998 case FILE_MSDOSTIME: 999 case FILE_BEMSDOSTIME: 1000 case FILE_LEMSDOSTIME: 1001 ts = typesize(m->type); 1002 if (ts == FILE_BADSIZE) { 1003 (void)fprintf(stderr, "Bad size for type %d\n", 1004 m->type); 1005 abort(); 1006 } 1007 val += ts * MULT; 1008 break; 1009 1010 case FILE_PSTRING: 1011 case FILE_STRING: 1012 case FILE_OCTAL: 1013 val += m->vallen * MULT; 1014 break; 1015 1016 case FILE_BESTRING16: 1017 case FILE_LESTRING16: 1018 val += m->vallen * MULT / 2; 1019 break; 1020 1021 case FILE_SEARCH: 1022 if (m->vallen == 0) 1023 break; 1024 val += m->vallen * MAX(MULT / m->vallen, 1); 1025 break; 1026 1027 case FILE_REGEX: 1028 v = nonmagic(m->value.s); 1029 val += v * MAX(MULT / v, 1); 1030 break; 1031 1032 case FILE_INDIRECT: 1033 case FILE_NAME: 1034 case FILE_USE: 1035 case FILE_CLEAR: 1036 break; 1037 1038 case FILE_DER: 1039 val += MULT; 1040 break; 1041 1042 default: 1043 (void)fprintf(stderr, "Bad type %d\n", m->type); 1044 abort(); 1045 } 1046 1047 switch (m->reln) { 1048 case 'x': /* matches anything penalize */ 1049 case '!': /* matches almost anything penalize */ 1050 val = 0; 1051 break; 1052 1053 case '=': /* Exact match, prefer */ 1054 val += MULT; 1055 break; 1056 1057 case '>': 1058 case '<': /* comparison match reduce strength */ 1059 val -= 2 * MULT; 1060 break; 1061 1062 case '^': 1063 case '&': /* masking bits, we could count them too */ 1064 val -= MULT; 1065 break; 1066 1067 default: 1068 (void)fprintf(stderr, "Bad relation %c\n", m->reln); 1069 abort(); 1070 } 1071 1072 return val; 1073 } 1074 1075 1076 /*ARGSUSED*/ 1077 file_protected size_t 1078 file_magic_strength(const struct magic *m, 1079 size_t nmagic __attribute__((__unused__))) 1080 { 1081 ssize_t val = apprentice_magic_strength_1(m); 1082 1083 #ifdef notyet 1084 if (m->desc[0] == '\0') { 1085 size_t i; 1086 /* 1087 * Magic entries with no description get their continuations 1088 * added 1089 */ 1090 for (i = 1; m[i].cont_level != 0 && i < MIN(nmagic, 3); i++) { 1091 ssize_t v = apprentice_magic_strength_1(&m[i]) >> 1092 (i + 1); 1093 val += v; 1094 if (m[i].desc[0] != '\0') 1095 break; 1096 } 1097 } 1098 #endif 1099 1100 switch (m->factor_op) { 1101 case FILE_FACTOR_OP_NONE: 1102 break; 1103 case FILE_FACTOR_OP_PLUS: 1104 val += m->factor; 1105 break; 1106 case FILE_FACTOR_OP_MINUS: 1107 val -= m->factor; 1108 break; 1109 case FILE_FACTOR_OP_TIMES: 1110 val *= m->factor; 1111 break; 1112 case FILE_FACTOR_OP_DIV: 1113 val /= m->factor; 1114 break; 1115 default: 1116 (void)fprintf(stderr, "Bad factor_op %u\n", m->factor_op); 1117 abort(); 1118 } 1119 1120 if (val <= 0) /* ensure we only return 0 for FILE_DEFAULT */ 1121 val = 1; 1122 1123 #ifndef notyet 1124 /* 1125 * Magic entries with no description get a bonus because they depend 1126 * on subsequent magic entries to print something. 1127 */ 1128 if (m->desc[0] == '\0') 1129 val++; 1130 #endif 1131 1132 return val; 1133 } 1134 1135 /* 1136 * Sort callback for sorting entries by "strength" (basically length) 1137 */ 1138 file_private int 1139 apprentice_sort(const void *a, const void *b) 1140 { 1141 const struct magic_entry *ma = CAST(const struct magic_entry *, a); 1142 const struct magic_entry *mb = CAST(const struct magic_entry *, b); 1143 size_t sa = file_magic_strength(ma->mp, ma->cont_count); 1144 size_t sb = file_magic_strength(mb->mp, mb->cont_count); 1145 if (sa == sb) { 1146 struct magic mpa = *ma->mp; 1147 struct magic mpb = *mb->mp; 1148 mpa.lineno = mpb.lineno = 0; 1149 int x = memcmp(&mpa, &mpb, sizeof(mpa)); 1150 if (x == 0) { 1151 // Don't warn for DER 1152 if (mpa.type == FILE_DER) 1153 return 0; 1154 file_magwarn1("Duplicate magic entry `%s'", 1155 ma->mp->desc); 1156 #ifndef COMPILE_ONLY 1157 file_mdump(ma->mp); 1158 file_mdump(mb->mp); 1159 #endif 1160 return 0; 1161 } 1162 return x > 0 ? -1 : 1; 1163 } 1164 return sa > sb ? -1 : 1; 1165 } 1166 1167 /* 1168 * Shows sorted patterns list in the order which is used for the matching 1169 */ 1170 file_private void 1171 apprentice_list(struct mlist *mlist, int mode) 1172 { 1173 uint32_t magindex, descindex, mimeindex, lineindex; 1174 struct mlist *ml; 1175 for (ml = mlist->next; ml != mlist; ml = ml->next) { 1176 for (magindex = 0; magindex < ml->nmagic; magindex++) { 1177 struct magic *m = &ml->magic[magindex]; 1178 if ((m->flag & mode) != mode) { 1179 /* Skip sub-tests */ 1180 while (magindex + 1 < ml->nmagic && 1181 ml->magic[magindex + 1].cont_level != 0) 1182 ++magindex; 1183 continue; /* Skip to next top-level test*/ 1184 } 1185 1186 /* 1187 * Try to iterate over the tree until we find item with 1188 * description/mimetype. 1189 */ 1190 lineindex = descindex = mimeindex = magindex; 1191 for (; magindex + 1 < ml->nmagic && 1192 ml->magic[magindex + 1].cont_level != 0; 1193 magindex++) { 1194 uint32_t mi = magindex + 1; 1195 if (*ml->magic[descindex].desc == '\0' 1196 && *ml->magic[mi].desc) 1197 descindex = mi; 1198 if (*ml->magic[mimeindex].mimetype == '\0' 1199 && *ml->magic[mi].mimetype) 1200 mimeindex = mi; 1201 } 1202 1203 printf("Strength = %3" SIZE_T_FORMAT "u@%u: %s [%s]\n", 1204 file_magic_strength(m, ml->nmagic - magindex), 1205 ml->magic[lineindex].lineno, 1206 ml->magic[descindex].desc, 1207 ml->magic[mimeindex].mimetype); 1208 } 1209 } 1210 } 1211 1212 file_private void 1213 set_test_type(struct magic *mstart, struct magic *m) 1214 { 1215 switch (m->type) { 1216 case FILE_BYTE: 1217 case FILE_SHORT: 1218 case FILE_LONG: 1219 case FILE_DATE: 1220 case FILE_BESHORT: 1221 case FILE_BELONG: 1222 case FILE_BEDATE: 1223 case FILE_LESHORT: 1224 case FILE_LELONG: 1225 case FILE_LEDATE: 1226 case FILE_LDATE: 1227 case FILE_BELDATE: 1228 case FILE_LELDATE: 1229 case FILE_MEDATE: 1230 case FILE_MELDATE: 1231 case FILE_MELONG: 1232 case FILE_QUAD: 1233 case FILE_LEQUAD: 1234 case FILE_BEQUAD: 1235 case FILE_QDATE: 1236 case FILE_LEQDATE: 1237 case FILE_BEQDATE: 1238 case FILE_QLDATE: 1239 case FILE_LEQLDATE: 1240 case FILE_BEQLDATE: 1241 case FILE_QWDATE: 1242 case FILE_LEQWDATE: 1243 case FILE_BEQWDATE: 1244 case FILE_FLOAT: 1245 case FILE_BEFLOAT: 1246 case FILE_LEFLOAT: 1247 case FILE_DOUBLE: 1248 case FILE_BEDOUBLE: 1249 case FILE_LEDOUBLE: 1250 case FILE_BEVARINT: 1251 case FILE_LEVARINT: 1252 case FILE_DER: 1253 case FILE_GUID: 1254 case FILE_OFFSET: 1255 case FILE_MSDOSDATE: 1256 case FILE_BEMSDOSDATE: 1257 case FILE_LEMSDOSDATE: 1258 case FILE_MSDOSTIME: 1259 case FILE_BEMSDOSTIME: 1260 case FILE_LEMSDOSTIME: 1261 case FILE_OCTAL: 1262 mstart->flag |= BINTEST; 1263 break; 1264 case FILE_STRING: 1265 case FILE_PSTRING: 1266 case FILE_BESTRING16: 1267 case FILE_LESTRING16: 1268 case FILE_REGEX: 1269 case FILE_SEARCH: 1270 /* Check for override */ 1271 if (mstart->str_flags & STRING_BINTEST) 1272 mstart->flag |= BINTEST; 1273 if (mstart->str_flags & STRING_TEXTTEST) 1274 mstart->flag |= TEXTTEST; 1275 1276 if (mstart->flag & (TEXTTEST|BINTEST)) 1277 break; 1278 1279 /* 1280 * XXX: Compatibility: For string types assume binary match 1281 * in reality it is better in the long term to change all 1282 * the magic to be string/b where appropriate 1283 */ 1284 if (m->type != FILE_REGEX && m->type != FILE_SEARCH) { 1285 mstart->flag |= BINTEST; 1286 break; 1287 } 1288 1289 /* binary test if pattern is not text */ 1290 if (file_looks_utf8(m->value.us, CAST(size_t, m->vallen), NULL, 1291 NULL) <= 0) 1292 mstart->flag |= BINTEST; 1293 else 1294 mstart->flag |= TEXTTEST; 1295 break; 1296 case FILE_DEFAULT: 1297 /* can't deduce anything; we shouldn't see this at the 1298 top level anyway */ 1299 break; 1300 case FILE_INVALID: 1301 default: 1302 /* invalid search type, but no need to complain here */ 1303 break; 1304 } 1305 } 1306 1307 file_private int 1308 addentry(struct magic_set *ms, struct magic_entry *me, 1309 struct magic_entry_set *mset) 1310 { 1311 size_t i = me->mp->type == FILE_NAME ? 1 : 0; 1312 if (mset[i].me == NULL || mset[i].count == mset[i].max) { 1313 struct magic_entry *mp; 1314 1315 size_t incr = mset[i].max + ALLOC_INCR; 1316 if ((mp = CAST(struct magic_entry *, 1317 realloc(mset[i].me, sizeof(*mp) * incr))) == 1318 NULL) { 1319 file_oomem(ms, sizeof(*mp) * incr); 1320 return -1; 1321 } 1322 (void)memset(&mp[mset[i].count], 0, sizeof(*mp) * 1323 ALLOC_INCR); 1324 mset[i].me = mp; 1325 mset[i].max = CAST(uint32_t, incr); 1326 assert(mset[i].max == incr); 1327 } 1328 mset[i].me[mset[i].count++] = *me; 1329 memset(me, 0, sizeof(*me)); 1330 return 0; 1331 } 1332 1333 /* 1334 * Load and parse one file. 1335 */ 1336 file_private void 1337 load_1(struct magic_set *ms, int action, const char *fn, int *errs, 1338 struct magic_entry_set *mset) 1339 { 1340 size_t lineno = 0, llen = 0; 1341 char *line = NULL; 1342 ssize_t len; 1343 struct magic_entry me; 1344 1345 FILE *f = fopen(ms->file = fn, "r"); 1346 if (f == NULL) { 1347 if (errno != ENOENT) 1348 file_error(ms, errno, "cannot read magic file `%s'", 1349 fn); 1350 (*errs)++; 1351 return; 1352 } 1353 1354 memset(&me, 0, sizeof(me)); 1355 /* read and parse this file */ 1356 for (ms->line = 1; (len = getline(&line, &llen, f)) != -1; 1357 ms->line++) { 1358 if (ms->magwarn >= ms->magwarn_max) 1359 break; 1360 if (len == 0) /* null line, garbage, etc */ 1361 continue; 1362 if (line[len - 1] == '\n') { 1363 lineno++; 1364 line[len - 1] = '\0'; /* delete newline */ 1365 } 1366 switch (line[0]) { 1367 case '\0': /* empty, do not parse */ 1368 case '#': /* comment, do not parse */ 1369 continue; 1370 case '!': 1371 if (line[1] == ':') { 1372 size_t i; 1373 1374 for (i = 0; bang[i].name != NULL; i++) { 1375 if (CAST(size_t, len - 2) > bang[i].len && 1376 memcmp(bang[i].name, line + 2, 1377 bang[i].len) == 0) 1378 break; 1379 } 1380 if (bang[i].name == NULL) { 1381 file_error(ms, 0, 1382 "Unknown !: entry `%s'", line); 1383 (*errs)++; 1384 continue; 1385 } 1386 if (me.mp == NULL) { 1387 file_error(ms, 0, 1388 "No current entry for :!%s type", 1389 bang[i].name); 1390 (*errs)++; 1391 continue; 1392 } 1393 if ((*bang[i].fun)(ms, &me, 1394 line + bang[i].len + 2, 1395 len - bang[i].len - 2) != 0) { 1396 (*errs)++; 1397 continue; 1398 } 1399 continue; 1400 } 1401 /*FALLTHROUGH*/ 1402 default: 1403 again: 1404 switch (parse(ms, &me, fn, line, lineno, action)) { 1405 case 0: 1406 continue; 1407 case 1: 1408 (void)addentry(ms, &me, mset); 1409 goto again; 1410 default: 1411 (*errs)++; 1412 break; 1413 } 1414 } 1415 } 1416 if (me.mp) 1417 (void)addentry(ms, &me, mset); 1418 free(line); 1419 (void)fclose(f); 1420 } 1421 1422 /* 1423 * parse a file or directory of files 1424 * const char *fn: name of magic file or directory 1425 */ 1426 file_private int 1427 cmpstrp(const void *p1, const void *p2) 1428 { 1429 return strcmp(*RCAST(char *const *, p1), *RCAST(char *const *, p2)); 1430 } 1431 1432 1433 file_private uint32_t 1434 set_text_binary(struct magic_set *ms, struct magic_entry *me, uint32_t nme, 1435 uint32_t starttest) 1436 { 1437 static const char text[] = "text"; 1438 static const char binary[] = "binary"; 1439 static const size_t len = sizeof(text); 1440 1441 uint32_t i = starttest; 1442 1443 do { 1444 set_test_type(me[starttest].mp, me[i].mp); 1445 if ((ms->flags & MAGIC_DEBUG) == 0) 1446 continue; 1447 (void)fprintf(stderr, "%s%s%s: %s\n", 1448 me[i].mp->mimetype, 1449 me[i].mp->mimetype[0] == '\0' ? "" : "; ", 1450 me[i].mp->desc[0] ? me[i].mp->desc : "(no description)", 1451 me[i].mp->flag & BINTEST ? binary : text); 1452 if (me[i].mp->flag & BINTEST) { 1453 char *p = strstr(me[i].mp->desc, text); 1454 if (p && (p == me[i].mp->desc || 1455 isspace(CAST(unsigned char, p[-1]))) && 1456 (p + len - me[i].mp->desc == MAXstring 1457 || (p[len] == '\0' || 1458 isspace(CAST(unsigned char, p[len]))))) 1459 (void)fprintf(stderr, "*** Possible " 1460 "binary test for text type\n"); 1461 } 1462 } while (++i < nme && me[i].mp->cont_level != 0); 1463 return i; 1464 } 1465 1466 file_private void 1467 set_last_default(struct magic_set *ms, struct magic_entry *me, uint32_t nme) 1468 { 1469 uint32_t i; 1470 for (i = 0; i < nme; i++) { 1471 if (me[i].mp->cont_level == 0 && 1472 me[i].mp->type == FILE_DEFAULT) { 1473 while (++i < nme) 1474 if (me[i].mp->cont_level == 0) 1475 break; 1476 if (i != nme) { 1477 /* XXX - Ugh! */ 1478 ms->line = me[i].mp->lineno; 1479 file_magwarn(ms, 1480 "level 0 \"default\" did not sort last"); 1481 } 1482 return; 1483 } 1484 } 1485 } 1486 1487 file_private int 1488 coalesce_entries(struct magic_set *ms, struct magic_entry *me, uint32_t nme, 1489 struct magic **ma, uint32_t *nma) 1490 { 1491 uint32_t i, mentrycount = 0; 1492 size_t slen; 1493 1494 for (i = 0; i < nme; i++) 1495 mentrycount += me[i].cont_count; 1496 1497 if (mentrycount == 0) { 1498 *ma = NULL; 1499 *nma = 0; 1500 return 0; 1501 } 1502 1503 slen = sizeof(**ma) * mentrycount; 1504 if ((*ma = CAST(struct magic *, malloc(slen))) == NULL) { 1505 file_oomem(ms, slen); 1506 return -1; 1507 } 1508 1509 mentrycount = 0; 1510 for (i = 0; i < nme; i++) { 1511 (void)memcpy(*ma + mentrycount, me[i].mp, 1512 me[i].cont_count * sizeof(**ma)); 1513 mentrycount += me[i].cont_count; 1514 } 1515 *nma = mentrycount; 1516 return 0; 1517 } 1518 1519 file_private void 1520 magic_entry_free(struct magic_entry *me, uint32_t nme) 1521 { 1522 uint32_t i; 1523 if (me == NULL) 1524 return; 1525 for (i = 0; i < nme; i++) 1526 free(me[i].mp); 1527 free(me); 1528 } 1529 1530 file_private struct magic_map * 1531 apprentice_load(struct magic_set *ms, const char *fn, int action) 1532 { 1533 int errs = 0; 1534 uint32_t i, j; 1535 size_t files = 0, maxfiles = 0; 1536 char **filearr = NULL, *mfn; 1537 struct stat st; 1538 struct magic_map *map; 1539 struct magic_entry_set mset[MAGIC_SETS]; 1540 DIR *dir; 1541 struct dirent *d; 1542 1543 memset(mset, 0, sizeof(mset)); 1544 ms->flags |= MAGIC_CHECK; /* Enable checks for parsed files */ 1545 1546 1547 if ((map = CAST(struct magic_map *, calloc(1, sizeof(*map)))) == NULL) 1548 { 1549 file_oomem(ms, sizeof(*map)); 1550 return NULL; 1551 } 1552 map->type = MAP_TYPE_MALLOC; 1553 1554 /* print silly verbose header for USG compat. */ 1555 if (action == FILE_CHECK) 1556 (void)fprintf(stderr, "%s\n", usg_hdr); 1557 1558 /* load directory or file */ 1559 if (stat(fn, &st) == 0 && S_ISDIR(st.st_mode)) { 1560 dir = opendir(fn); 1561 if (!dir) { 1562 errs++; 1563 goto out; 1564 } 1565 while ((d = readdir(dir)) != NULL) { 1566 if (d->d_name[0] == '.') 1567 continue; 1568 if (asprintf(&mfn, "%s/%s", fn, d->d_name) < 0) { 1569 file_oomem(ms, 1570 strlen(fn) + strlen(d->d_name) + 2); 1571 errs++; 1572 closedir(dir); 1573 goto out; 1574 } 1575 if (stat(mfn, &st) == -1 || !S_ISREG(st.st_mode)) { 1576 free(mfn); 1577 continue; 1578 } 1579 if (files >= maxfiles) { 1580 size_t mlen; 1581 char **nfilearr; 1582 maxfiles = (maxfiles + 1) * 2; 1583 mlen = maxfiles * sizeof(*filearr); 1584 if ((nfilearr = CAST(char **, 1585 realloc(filearr, mlen))) == NULL) { 1586 file_oomem(ms, mlen); 1587 free(mfn); 1588 closedir(dir); 1589 errs++; 1590 goto out; 1591 } 1592 filearr = nfilearr; 1593 } 1594 filearr[files++] = mfn; 1595 } 1596 closedir(dir); 1597 if (filearr) { 1598 qsort(filearr, files, sizeof(*filearr), cmpstrp); 1599 for (i = 0; i < files; i++) { 1600 load_1(ms, action, filearr[i], &errs, mset); 1601 free(filearr[i]); 1602 } 1603 free(filearr); 1604 filearr = NULL; 1605 } 1606 } else 1607 load_1(ms, action, fn, &errs, mset); 1608 if (errs) 1609 goto out; 1610 1611 for (j = 0; j < MAGIC_SETS; j++) { 1612 /* Set types of tests */ 1613 for (i = 0; i < mset[j].count; ) { 1614 if (mset[j].me[i].mp->cont_level != 0) { 1615 i++; 1616 continue; 1617 } 1618 i = set_text_binary(ms, mset[j].me, mset[j].count, i); 1619 } 1620 if (mset[j].me) 1621 qsort(mset[j].me, mset[j].count, sizeof(*mset[0].me), 1622 apprentice_sort); 1623 1624 /* 1625 * Make sure that any level 0 "default" line is last 1626 * (if one exists). 1627 */ 1628 set_last_default(ms, mset[j].me, mset[j].count); 1629 1630 /* coalesce per file arrays into a single one, if needed */ 1631 if (mset[j].count == 0) 1632 continue; 1633 1634 if (coalesce_entries(ms, mset[j].me, mset[j].count, 1635 &map->magic[j], &map->nmagic[j]) == -1) { 1636 errs++; 1637 goto out; 1638 } 1639 } 1640 1641 out: 1642 free(filearr); 1643 for (j = 0; j < MAGIC_SETS; j++) 1644 magic_entry_free(mset[j].me, mset[j].count); 1645 1646 if (errs) { 1647 apprentice_unmap(map); 1648 return NULL; 1649 } 1650 return map; 1651 } 1652 1653 /* 1654 * extend the sign bit if the comparison is to be signed 1655 */ 1656 file_protected uint64_t 1657 file_signextend(struct magic_set *ms, struct magic *m, uint64_t v) 1658 { 1659 if (!(m->flag & UNSIGNED)) { 1660 switch(m->type) { 1661 /* 1662 * Do not remove the casts below. They are 1663 * vital. When later compared with the data, 1664 * the sign extension must have happened. 1665 */ 1666 case FILE_BYTE: 1667 v = CAST(signed char, v); 1668 break; 1669 case FILE_SHORT: 1670 case FILE_BESHORT: 1671 case FILE_LESHORT: 1672 v = CAST(short, v); 1673 break; 1674 case FILE_DATE: 1675 case FILE_BEDATE: 1676 case FILE_LEDATE: 1677 case FILE_MEDATE: 1678 case FILE_LDATE: 1679 case FILE_BELDATE: 1680 case FILE_LELDATE: 1681 case FILE_MELDATE: 1682 case FILE_LONG: 1683 case FILE_BELONG: 1684 case FILE_LELONG: 1685 case FILE_MELONG: 1686 case FILE_FLOAT: 1687 case FILE_BEFLOAT: 1688 case FILE_LEFLOAT: 1689 case FILE_MSDOSDATE: 1690 case FILE_BEMSDOSDATE: 1691 case FILE_LEMSDOSDATE: 1692 case FILE_MSDOSTIME: 1693 case FILE_BEMSDOSTIME: 1694 case FILE_LEMSDOSTIME: 1695 v = CAST(int32_t, v); 1696 break; 1697 case FILE_QUAD: 1698 case FILE_BEQUAD: 1699 case FILE_LEQUAD: 1700 case FILE_QDATE: 1701 case FILE_QLDATE: 1702 case FILE_QWDATE: 1703 case FILE_BEQDATE: 1704 case FILE_BEQLDATE: 1705 case FILE_BEQWDATE: 1706 case FILE_LEQDATE: 1707 case FILE_LEQLDATE: 1708 case FILE_LEQWDATE: 1709 case FILE_DOUBLE: 1710 case FILE_BEDOUBLE: 1711 case FILE_LEDOUBLE: 1712 case FILE_OFFSET: 1713 case FILE_BEVARINT: 1714 case FILE_LEVARINT: 1715 v = CAST(int64_t, v); 1716 break; 1717 case FILE_STRING: 1718 case FILE_PSTRING: 1719 case FILE_BESTRING16: 1720 case FILE_LESTRING16: 1721 case FILE_REGEX: 1722 case FILE_SEARCH: 1723 case FILE_DEFAULT: 1724 case FILE_INDIRECT: 1725 case FILE_NAME: 1726 case FILE_USE: 1727 case FILE_CLEAR: 1728 case FILE_DER: 1729 case FILE_GUID: 1730 case FILE_OCTAL: 1731 break; 1732 default: 1733 if (ms->flags & MAGIC_CHECK) 1734 file_magwarn(ms, "cannot happen: m->type=%d\n", 1735 m->type); 1736 return FILE_BADSIZE; 1737 } 1738 } 1739 return v; 1740 } 1741 1742 file_private int 1743 string_modifier_check(struct magic_set *ms, struct magic *m) 1744 { 1745 if ((ms->flags & MAGIC_CHECK) == 0) 1746 return 0; 1747 1748 if ((m->type != FILE_REGEX || (m->str_flags & REGEX_LINE_COUNT) == 0) && 1749 (m->type != FILE_PSTRING && (m->str_flags & PSTRING_LEN) != 0)) { 1750 file_magwarn(ms, 1751 "'/BHhLl' modifiers are only allowed for pascal strings\n"); 1752 return -1; 1753 } 1754 switch (m->type) { 1755 case FILE_BESTRING16: 1756 case FILE_LESTRING16: 1757 if (m->str_flags != 0) { 1758 file_magwarn(ms, 1759 "no modifiers allowed for 16-bit strings\n"); 1760 return -1; 1761 } 1762 break; 1763 case FILE_STRING: 1764 case FILE_PSTRING: 1765 if ((m->str_flags & REGEX_OFFSET_START) != 0) { 1766 file_magwarn(ms, 1767 "'/%c' only allowed on regex and search\n", 1768 CHAR_REGEX_OFFSET_START); 1769 return -1; 1770 } 1771 break; 1772 case FILE_SEARCH: 1773 if (m->str_range == 0) { 1774 file_magwarn(ms, 1775 "missing range; defaulting to %d\n", 1776 STRING_DEFAULT_RANGE); 1777 m->str_range = STRING_DEFAULT_RANGE; 1778 return -1; 1779 } 1780 break; 1781 case FILE_REGEX: 1782 if ((m->str_flags & STRING_COMPACT_WHITESPACE) != 0) { 1783 file_magwarn(ms, "'/%c' not allowed on regex\n", 1784 CHAR_COMPACT_WHITESPACE); 1785 return -1; 1786 } 1787 if ((m->str_flags & STRING_COMPACT_OPTIONAL_WHITESPACE) != 0) { 1788 file_magwarn(ms, "'/%c' not allowed on regex\n", 1789 CHAR_COMPACT_OPTIONAL_WHITESPACE); 1790 return -1; 1791 } 1792 if ((m->str_flags & STRING_IGNORE_LOWERCASE) != 0) { 1793 file_magwarn(ms, "'/%c' not allowed on regex\n", 1794 CHAR_IGNORE_LOWERCASE); 1795 return -1; 1796 } 1797 if ((m->str_flags & STRING_IGNORE_UPPERCASE) != 0) { 1798 file_magwarn(ms, "'/%c' not allowed on regex\n", 1799 CHAR_IGNORE_UPPERCASE); 1800 return -1; 1801 } 1802 break; 1803 default: 1804 file_magwarn(ms, "coding error: m->type=%d\n", 1805 m->type); 1806 return -1; 1807 } 1808 return 0; 1809 } 1810 1811 file_private int 1812 get_op(char c) 1813 { 1814 switch (c) { 1815 case '&': 1816 return FILE_OPAND; 1817 case '|': 1818 return FILE_OPOR; 1819 case '^': 1820 return FILE_OPXOR; 1821 case '+': 1822 return FILE_OPADD; 1823 case '-': 1824 return FILE_OPMINUS; 1825 case '*': 1826 return FILE_OPMULTIPLY; 1827 case '/': 1828 return FILE_OPDIVIDE; 1829 case '%': 1830 return FILE_OPMODULO; 1831 default: 1832 return -1; 1833 } 1834 } 1835 1836 #ifdef ENABLE_CONDITIONALS 1837 file_private int 1838 get_cond(const char *l, const char **t) 1839 { 1840 static const struct cond_tbl_s { 1841 char name[8]; 1842 size_t len; 1843 int cond; 1844 } cond_tbl[] = { 1845 { "if", 2, COND_IF }, 1846 { "elif", 4, COND_ELIF }, 1847 { "else", 4, COND_ELSE }, 1848 { "", 0, COND_NONE }, 1849 }; 1850 const struct cond_tbl_s *p; 1851 1852 for (p = cond_tbl; p->len; p++) { 1853 if (strncmp(l, p->name, p->len) == 0 && 1854 isspace(CAST(unsigned char, l[p->len]))) { 1855 if (t) 1856 *t = l + p->len; 1857 break; 1858 } 1859 } 1860 return p->cond; 1861 } 1862 1863 file_private int 1864 check_cond(struct magic_set *ms, int cond, uint32_t cont_level) 1865 { 1866 int last_cond; 1867 last_cond = ms->c.li[cont_level].last_cond; 1868 1869 switch (cond) { 1870 case COND_IF: 1871 if (last_cond != COND_NONE && last_cond != COND_ELIF) { 1872 if (ms->flags & MAGIC_CHECK) 1873 file_magwarn(ms, "syntax error: `if'"); 1874 return -1; 1875 } 1876 last_cond = COND_IF; 1877 break; 1878 1879 case COND_ELIF: 1880 if (last_cond != COND_IF && last_cond != COND_ELIF) { 1881 if (ms->flags & MAGIC_CHECK) 1882 file_magwarn(ms, "syntax error: `elif'"); 1883 return -1; 1884 } 1885 last_cond = COND_ELIF; 1886 break; 1887 1888 case COND_ELSE: 1889 if (last_cond != COND_IF && last_cond != COND_ELIF) { 1890 if (ms->flags & MAGIC_CHECK) 1891 file_magwarn(ms, "syntax error: `else'"); 1892 return -1; 1893 } 1894 last_cond = COND_NONE; 1895 break; 1896 1897 case COND_NONE: 1898 last_cond = COND_NONE; 1899 break; 1900 } 1901 1902 ms->c.li[cont_level].last_cond = last_cond; 1903 return 0; 1904 } 1905 #endif /* ENABLE_CONDITIONALS */ 1906 1907 file_private int 1908 parse_indirect_modifier(struct magic_set *ms, struct magic *m, const char **lp) 1909 { 1910 const char *l = *lp; 1911 1912 while (!isspace(CAST(unsigned char, *++l))) 1913 switch (*l) { 1914 case CHAR_INDIRECT_RELATIVE: 1915 m->str_flags |= INDIRECT_RELATIVE; 1916 break; 1917 default: 1918 if (ms->flags & MAGIC_CHECK) 1919 file_magwarn(ms, "indirect modifier `%c' " 1920 "invalid", *l); 1921 *lp = l; 1922 return -1; 1923 } 1924 *lp = l; 1925 return 0; 1926 } 1927 1928 file_private void 1929 parse_op_modifier(struct magic_set *ms, struct magic *m, const char **lp, 1930 int op) 1931 { 1932 const char *l = *lp; 1933 char *t; 1934 uint64_t val; 1935 1936 ++l; 1937 m->mask_op |= op; 1938 val = CAST(uint64_t, strtoull(l, &t, 0)); 1939 l = t; 1940 m->num_mask = file_signextend(ms, m, val); 1941 eatsize(&l); 1942 *lp = l; 1943 } 1944 1945 file_private int 1946 parse_string_modifier(struct magic_set *ms, struct magic *m, const char **lp) 1947 { 1948 const char *l = *lp; 1949 char *t; 1950 int have_range = 0; 1951 1952 while (!isspace(CAST(unsigned char, *++l))) { 1953 switch (*l) { 1954 case '0': case '1': case '2': 1955 case '3': case '4': case '5': 1956 case '6': case '7': case '8': 1957 case '9': 1958 if (have_range && (ms->flags & MAGIC_CHECK)) 1959 file_magwarn(ms, "multiple ranges"); 1960 have_range = 1; 1961 m->str_range = CAST(uint32_t, strtoul(l, &t, 0)); 1962 if (m->str_range == 0) 1963 file_magwarn(ms, "zero range"); 1964 l = t - 1; 1965 break; 1966 case CHAR_COMPACT_WHITESPACE: 1967 m->str_flags |= STRING_COMPACT_WHITESPACE; 1968 break; 1969 case CHAR_COMPACT_OPTIONAL_WHITESPACE: 1970 m->str_flags |= STRING_COMPACT_OPTIONAL_WHITESPACE; 1971 break; 1972 case CHAR_IGNORE_LOWERCASE: 1973 m->str_flags |= STRING_IGNORE_LOWERCASE; 1974 break; 1975 case CHAR_IGNORE_UPPERCASE: 1976 m->str_flags |= STRING_IGNORE_UPPERCASE; 1977 break; 1978 case CHAR_REGEX_OFFSET_START: 1979 m->str_flags |= REGEX_OFFSET_START; 1980 break; 1981 case CHAR_BINTEST: 1982 m->str_flags |= STRING_BINTEST; 1983 break; 1984 case CHAR_TEXTTEST: 1985 m->str_flags |= STRING_TEXTTEST; 1986 break; 1987 case CHAR_TRIM: 1988 m->str_flags |= STRING_TRIM; 1989 break; 1990 case CHAR_FULL_WORD: 1991 m->str_flags |= STRING_FULL_WORD; 1992 break; 1993 case CHAR_PSTRING_1_LE: 1994 #define SET_LENGTH(a) m->str_flags = (m->str_flags & ~PSTRING_LEN) | (a) 1995 if (m->type != FILE_PSTRING) 1996 goto bad; 1997 SET_LENGTH(PSTRING_1_LE); 1998 break; 1999 case CHAR_PSTRING_2_BE: 2000 if (m->type != FILE_PSTRING) 2001 goto bad; 2002 SET_LENGTH(PSTRING_2_BE); 2003 break; 2004 case CHAR_PSTRING_2_LE: 2005 if (m->type != FILE_PSTRING) 2006 goto bad; 2007 SET_LENGTH(PSTRING_2_LE); 2008 break; 2009 case CHAR_PSTRING_4_BE: 2010 if (m->type != FILE_PSTRING) 2011 goto bad; 2012 SET_LENGTH(PSTRING_4_BE); 2013 break; 2014 case CHAR_PSTRING_4_LE: 2015 switch (m->type) { 2016 case FILE_PSTRING: 2017 case FILE_REGEX: 2018 break; 2019 default: 2020 goto bad; 2021 } 2022 SET_LENGTH(PSTRING_4_LE); 2023 break; 2024 case CHAR_PSTRING_LENGTH_INCLUDES_ITSELF: 2025 if (m->type != FILE_PSTRING) 2026 goto bad; 2027 m->str_flags |= PSTRING_LENGTH_INCLUDES_ITSELF; 2028 break; 2029 default: 2030 bad: 2031 if (ms->flags & MAGIC_CHECK) 2032 file_magwarn(ms, "string modifier `%c' " 2033 "invalid", *l); 2034 goto out; 2035 } 2036 /* allow multiple '/' for readability */ 2037 if (l[1] == '/' && !isspace(CAST(unsigned char, l[2]))) 2038 l++; 2039 } 2040 if (string_modifier_check(ms, m) == -1) 2041 goto out; 2042 *lp = l; 2043 return 0; 2044 out: 2045 *lp = l; 2046 return -1; 2047 } 2048 2049 /* 2050 * parse one line from magic file, put into magic[index++] if valid 2051 */ 2052 file_private int 2053 parse(struct magic_set *ms, struct magic_entry *me, const char *file, 2054 const char *line, size_t lineno, int action) 2055 { 2056 #ifdef ENABLE_CONDITIONALS 2057 static uint32_t last_cont_level = 0; 2058 #endif 2059 size_t i; 2060 struct magic *m; 2061 const char *l = line; 2062 char *t; 2063 int op; 2064 uint32_t cont_level; 2065 int32_t diff; 2066 2067 cont_level = 0; 2068 2069 /* 2070 * Parse the offset. 2071 */ 2072 while (*l == '>') { 2073 ++l; /* step over */ 2074 cont_level++; 2075 } 2076 #ifdef ENABLE_CONDITIONALS 2077 if (cont_level == 0 || cont_level > last_cont_level) 2078 if (file_check_mem(ms, cont_level) == -1) 2079 return -1; 2080 last_cont_level = cont_level; 2081 #endif 2082 if (cont_level != 0) { 2083 if (me->mp == NULL) { 2084 file_magerror(ms, "No current entry for continuation"); 2085 return -1; 2086 } 2087 if (me->cont_count == 0) { 2088 file_magerror(ms, "Continuations present with 0 count"); 2089 return -1; 2090 } 2091 m = &me->mp[me->cont_count - 1]; 2092 diff = CAST(int32_t, cont_level) - CAST(int32_t, m->cont_level); 2093 if (diff > 1) 2094 file_magwarn(ms, "New continuation level %u is more " 2095 "than one larger than current level %u", cont_level, 2096 m->cont_level); 2097 if (me->cont_count == me->max_count) { 2098 struct magic *nm; 2099 size_t cnt = me->max_count + ALLOC_CHUNK; 2100 if ((nm = CAST(struct magic *, realloc(me->mp, 2101 sizeof(*nm) * cnt))) == NULL) { 2102 file_oomem(ms, sizeof(*nm) * cnt); 2103 return -1; 2104 } 2105 me->mp = nm; 2106 me->max_count = CAST(uint32_t, cnt); 2107 } 2108 m = &me->mp[me->cont_count++]; 2109 (void)memset(m, 0, sizeof(*m)); 2110 m->cont_level = cont_level; 2111 } else { 2112 static const size_t len = sizeof(*m) * ALLOC_CHUNK; 2113 if (me->mp != NULL) 2114 return 1; 2115 if ((m = CAST(struct magic *, malloc(len))) == NULL) { 2116 file_oomem(ms, len); 2117 return -1; 2118 } 2119 me->mp = m; 2120 me->max_count = ALLOC_CHUNK; 2121 (void)memset(m, 0, sizeof(*m)); 2122 m->factor_op = FILE_FACTOR_OP_NONE; 2123 m->cont_level = 0; 2124 me->cont_count = 1; 2125 } 2126 m->lineno = CAST(uint32_t, lineno); 2127 2128 if (*l == '&') { /* m->cont_level == 0 checked below. */ 2129 ++l; /* step over */ 2130 m->flag |= OFFADD; 2131 } 2132 if (*l == '(') { 2133 ++l; /* step over */ 2134 m->flag |= INDIR; 2135 if (m->flag & OFFADD) 2136 m->flag = (m->flag & ~OFFADD) | INDIROFFADD; 2137 2138 if (*l == '&') { /* m->cont_level == 0 checked below */ 2139 ++l; /* step over */ 2140 m->flag |= OFFADD; 2141 } 2142 } 2143 /* Indirect offsets are not valid at level 0. */ 2144 if (m->cont_level == 0 && (m->flag & (OFFADD | INDIROFFADD))) { 2145 if (ms->flags & MAGIC_CHECK) 2146 file_magwarn(ms, "relative offset at level 0"); 2147 return -1; 2148 } 2149 2150 /* get offset, then skip over it */ 2151 if (*l == '-' || *l == '+') { 2152 ++l; /* step over */ 2153 m->flag |= l[-1] == '-' ? OFFNEGATIVE : OFFPOSITIVE; 2154 } 2155 m->offset = CAST(int32_t, strtol(l, &t, 0)); 2156 if (l == t) { 2157 if (ms->flags & MAGIC_CHECK) 2158 file_magwarn(ms, "offset `%s' invalid", l); 2159 return -1; 2160 } 2161 2162 l = t; 2163 2164 if (m->flag & INDIR) { 2165 m->in_type = FILE_LONG; 2166 m->in_offset = 0; 2167 m->in_op = 0; 2168 /* 2169 * read [.,lbs][+-]nnnnn) 2170 */ 2171 if (*l == '.' || *l == ',') { 2172 if (*l == ',') 2173 m->in_op |= FILE_OPSIGNED; 2174 l++; 2175 switch (*l) { 2176 case 'l': 2177 m->in_type = FILE_LELONG; 2178 break; 2179 case 'L': 2180 m->in_type = FILE_BELONG; 2181 break; 2182 case 'm': 2183 m->in_type = FILE_MELONG; 2184 break; 2185 case 'h': 2186 case 's': 2187 m->in_type = FILE_LESHORT; 2188 break; 2189 case 'H': 2190 case 'S': 2191 m->in_type = FILE_BESHORT; 2192 break; 2193 case 'c': 2194 case 'b': 2195 case 'C': 2196 case 'B': 2197 m->in_type = FILE_BYTE; 2198 break; 2199 case 'e': 2200 case 'f': 2201 case 'g': 2202 m->in_type = FILE_LEDOUBLE; 2203 break; 2204 case 'E': 2205 case 'F': 2206 case 'G': 2207 m->in_type = FILE_BEDOUBLE; 2208 break; 2209 case 'i': 2210 m->in_type = FILE_LEID3; 2211 break; 2212 case 'I': 2213 m->in_type = FILE_BEID3; 2214 break; 2215 case 'o': 2216 m->in_type = FILE_OCTAL; 2217 break; 2218 case 'q': 2219 m->in_type = FILE_LEQUAD; 2220 break; 2221 case 'Q': 2222 m->in_type = FILE_BEQUAD; 2223 break; 2224 default: 2225 if (ms->flags & MAGIC_CHECK) 2226 file_magwarn(ms, 2227 "indirect offset type `%c' invalid", 2228 *l); 2229 return -1; 2230 } 2231 l++; 2232 } 2233 2234 if (*l == '~') { 2235 m->in_op |= FILE_OPINVERSE; 2236 l++; 2237 } 2238 if ((op = get_op(*l)) != -1) { 2239 m->in_op |= op; 2240 l++; 2241 } 2242 if (*l == '(') { 2243 m->in_op |= FILE_OPINDIRECT; 2244 l++; 2245 } 2246 if (isdigit(CAST(unsigned char, *l)) || *l == '-') { 2247 m->in_offset = CAST(int32_t, strtol(l, &t, 0)); 2248 if (l == t) { 2249 if (ms->flags & MAGIC_CHECK) 2250 file_magwarn(ms, 2251 "in_offset `%s' invalid", l); 2252 return -1; 2253 } 2254 l = t; 2255 } 2256 if (*l++ != ')' || 2257 ((m->in_op & FILE_OPINDIRECT) && *l++ != ')')) { 2258 if (ms->flags & MAGIC_CHECK) 2259 file_magwarn(ms, 2260 "missing ')' in indirect offset"); 2261 return -1; 2262 } 2263 } 2264 EATAB; 2265 2266 #ifdef ENABLE_CONDITIONALS 2267 m->cond = get_cond(l, &l); 2268 if (check_cond(ms, m->cond, cont_level) == -1) 2269 return -1; 2270 2271 EATAB; 2272 #endif 2273 2274 /* 2275 * Parse the type. 2276 */ 2277 if (*l == 'u') { 2278 /* 2279 * Try it as a keyword type prefixed by "u"; match what 2280 * follows the "u". If that fails, try it as an SUS 2281 * integer type. 2282 */ 2283 m->type = get_type(type_tbl, l + 1, &l); 2284 if (m->type == FILE_INVALID) { 2285 /* 2286 * Not a keyword type; parse it as an SUS type, 2287 * 'u' possibly followed by a number or C/S/L. 2288 */ 2289 m->type = get_standard_integer_type(l, &l); 2290 } 2291 /* It's unsigned. */ 2292 if (m->type != FILE_INVALID) 2293 m->flag |= UNSIGNED; 2294 } else { 2295 /* 2296 * Try it as a keyword type. If that fails, try it as 2297 * an SUS integer type if it begins with "d" or as an 2298 * SUS string type if it begins with "s". In any case, 2299 * it's not unsigned. 2300 */ 2301 m->type = get_type(type_tbl, l, &l); 2302 if (m->type == FILE_INVALID) { 2303 /* 2304 * Not a keyword type; parse it as an SUS type, 2305 * either 'd' possibly followed by a number or 2306 * C/S/L, or just 's'. 2307 */ 2308 if (*l == 'd') 2309 m->type = get_standard_integer_type(l, &l); 2310 else if (*l == 's' 2311 && !isalpha(CAST(unsigned char, l[1]))) { 2312 m->type = FILE_STRING; 2313 ++l; 2314 } 2315 } 2316 } 2317 2318 if (m->type == FILE_INVALID) { 2319 /* Not found - try it as a special keyword. */ 2320 m->type = get_type(special_tbl, l, &l); 2321 } 2322 2323 if (m->type == FILE_INVALID) { 2324 if (ms->flags & MAGIC_CHECK) 2325 file_magwarn(ms, "type `%s' invalid", l); 2326 return -1; 2327 } 2328 2329 if (m->type == FILE_NAME && cont_level != 0) { 2330 if (ms->flags & MAGIC_CHECK) 2331 file_magwarn(ms, "`name%s' entries can only be " 2332 "declared at top level", l); 2333 return -1; 2334 } 2335 2336 /* New-style anding: "0 byte&0x80 =0x80 dynamically linked" */ 2337 /* New and improved: ~ & | ^ + - * / % -- exciting, isn't it? */ 2338 2339 m->mask_op = 0; 2340 if (*l == '~') { 2341 if (!IS_STRING(m->type)) 2342 m->mask_op |= FILE_OPINVERSE; 2343 else if (ms->flags & MAGIC_CHECK) 2344 file_magwarn(ms, "'~' invalid for string types"); 2345 ++l; 2346 } 2347 m->str_range = 0; 2348 m->str_flags = m->type == FILE_PSTRING ? PSTRING_1_LE : 0; 2349 if ((op = get_op(*l)) != -1) { 2350 if (IS_STRING(m->type)) { 2351 int r; 2352 2353 if (op != FILE_OPDIVIDE) { 2354 if (ms->flags & MAGIC_CHECK) 2355 file_magwarn(ms, 2356 "invalid string/indirect op: " 2357 "`%c'", *t); 2358 return -1; 2359 } 2360 2361 if (m->type == FILE_INDIRECT) 2362 r = parse_indirect_modifier(ms, m, &l); 2363 else 2364 r = parse_string_modifier(ms, m, &l); 2365 if (r == -1) 2366 return -1; 2367 } else 2368 parse_op_modifier(ms, m, &l, op); 2369 } 2370 2371 /* 2372 * We used to set mask to all 1's here, instead let's just not do 2373 * anything if mask = 0 (unless you have a better idea) 2374 */ 2375 EATAB; 2376 2377 switch (*l) { 2378 case '>': 2379 case '<': 2380 m->reln = *l; 2381 ++l; 2382 if (*l == '=') { 2383 if (ms->flags & MAGIC_CHECK) { 2384 file_magwarn(ms, "%c= not supported", 2385 m->reln); 2386 return -1; 2387 } 2388 ++l; 2389 } 2390 break; 2391 /* Old-style anding: "0 byte &0x80 dynamically linked" */ 2392 case '&': 2393 case '^': 2394 case '=': 2395 m->reln = *l; 2396 ++l; 2397 if (*l == '=') { 2398 /* HP compat: ignore &= etc. */ 2399 ++l; 2400 } 2401 break; 2402 case '!': 2403 m->reln = *l; 2404 ++l; 2405 break; 2406 default: 2407 m->reln = '='; /* the default relation */ 2408 if (*l == 'x' && ((isascii(CAST(unsigned char, l[1])) && 2409 isspace(CAST(unsigned char, l[1]))) || !l[1])) { 2410 m->reln = *l; 2411 ++l; 2412 } 2413 break; 2414 } 2415 2416 2417 /* 2418 * Grab the value part, except for an 'x' reln. 2419 */ 2420 if (m->reln != 'x') { 2421 if (*l == '\0') { 2422 file_magwarn(ms, "incomplete magic `%s'", line); 2423 return -1; 2424 } 2425 if (getvalue(ms, m, &l, action)) 2426 return -1; 2427 } 2428 2429 /* 2430 * TODO finish this macro and start using it! 2431 * #define offsetcheck {if (offset > ms->bytes_max -1) 2432 * magwarn("offset too big"); } 2433 */ 2434 2435 /* 2436 * Now get last part - the description 2437 */ 2438 EATAB; 2439 if (l[0] == '\b') { 2440 ++l; 2441 m->flag |= NOSPACE; 2442 } else if ((l[0] == '\\') && (l[1] == 'b')) { 2443 ++l; 2444 ++l; 2445 m->flag |= NOSPACE; 2446 } 2447 for (i = 0; i < sizeof(m->desc) && (m->desc[i++] = *l++) != '\0';) 2448 continue; 2449 if (m->desc[0] == '\0') { 2450 // Tuck in the filename for debugging. 2451 strlcpy(m->desc + 1, file, sizeof(m->desc) - 1); 2452 } 2453 if (i == sizeof(m->desc)) { 2454 m->desc[sizeof(m->desc) - 1] = '\0'; 2455 if (ms->flags & MAGIC_CHECK) 2456 file_magwarn(ms, "description `%s' truncated", m->desc); 2457 } 2458 2459 /* 2460 * We only do this check while compiling, or if any of the magic 2461 * files were not compiled. 2462 */ 2463 if (ms->flags & MAGIC_CHECK) { 2464 if (check_format(ms, m) == -1) 2465 return -1; 2466 } 2467 #ifndef COMPILE_ONLY 2468 if (action == FILE_CHECK) { 2469 file_mdump(m); 2470 } 2471 #endif 2472 m->mimetype[0] = '\0'; /* initialise MIME type to none */ 2473 return 0; 2474 } 2475 2476 /* 2477 * parse a STRENGTH annotation line from magic file, put into magic[index - 1] 2478 * if valid 2479 */ 2480 /*ARGSUSED*/ 2481 file_private int 2482 parse_strength(struct magic_set *ms, struct magic_entry *me, const char *line, 2483 size_t len __attribute__((__unused__))) 2484 { 2485 const char *l = line; 2486 char *el; 2487 unsigned long factor; 2488 char sbuf[512]; 2489 struct magic *m = &me->mp[0]; 2490 2491 if (m->factor_op != FILE_FACTOR_OP_NONE) { 2492 file_magwarn(ms, 2493 "Current entry already has a strength type: %c %d", 2494 m->factor_op, m->factor); 2495 return -1; 2496 } 2497 if (m->type == FILE_NAME) { 2498 file_magwarn(ms, "%s: Strength setting is not supported in " 2499 "\"name\" magic entries", 2500 file_printable(ms, sbuf, sizeof(sbuf), m->value.s, 2501 sizeof(m->value.s))); 2502 return -1; 2503 } 2504 EATAB; 2505 switch (*l) { 2506 case FILE_FACTOR_OP_NONE: 2507 break; 2508 case FILE_FACTOR_OP_PLUS: 2509 case FILE_FACTOR_OP_MINUS: 2510 case FILE_FACTOR_OP_TIMES: 2511 case FILE_FACTOR_OP_DIV: 2512 m->factor_op = *l++; 2513 break; 2514 default: 2515 file_magwarn(ms, "Unknown factor op `%c'", *l); 2516 return -1; 2517 } 2518 EATAB; 2519 factor = strtoul(l, &el, 0); 2520 if (factor > 255) { 2521 file_magwarn(ms, "Too large factor `%lu'", factor); 2522 goto out; 2523 } 2524 if (*el && !isspace(CAST(unsigned char, *el))) { 2525 file_magwarn(ms, "Bad factor `%s'", l); 2526 goto out; 2527 } 2528 m->factor = CAST(uint8_t, factor); 2529 if (m->factor == 0 && m->factor_op == FILE_FACTOR_OP_DIV) { 2530 file_magwarn(ms, "Cannot have factor op `%c' and factor %u", 2531 m->factor_op, m->factor); 2532 goto out; 2533 } 2534 return 0; 2535 out: 2536 m->factor_op = FILE_FACTOR_OP_NONE; 2537 m->factor = 0; 2538 return -1; 2539 } 2540 2541 file_private int 2542 goodchar(unsigned char x, const char *extra) 2543 { 2544 return (isascii(x) && isalnum(x)) || strchr(extra, x); 2545 } 2546 2547 file_private int 2548 parse_extra(struct magic_set *ms, struct magic_entry *me, const char *line, 2549 size_t llen, off_t off, size_t len, const char *name, const char *extra, 2550 int nt) 2551 { 2552 size_t i; 2553 const char *l = line; 2554 struct magic *m = &me->mp[me->cont_count == 0 ? 0 : me->cont_count - 1]; 2555 char *buf = CAST(char *, CAST(void *, m)) + off; 2556 2557 if (buf[0] != '\0') { 2558 len = nt ? strlen(buf) : len; 2559 file_magwarn(ms, "Current entry already has a %s type " 2560 "`%.*s', new type `%s'", name, CAST(int, len), buf, l); 2561 return -1; 2562 } 2563 2564 if (*m->desc == '\0') { 2565 file_magwarn(ms, "Current entry does not yet have a " 2566 "description for adding a %s type", name); 2567 return -1; 2568 } 2569 2570 EATAB; 2571 for (i = 0; *l && i < llen && i < len && goodchar(*l, extra); 2572 buf[i++] = *l++) 2573 continue; 2574 2575 if (i == len && *l) { 2576 if (nt) 2577 buf[len - 1] = '\0'; 2578 if (ms->flags & MAGIC_CHECK) 2579 file_magwarn(ms, "%s type `%s' truncated %" 2580 SIZE_T_FORMAT "u", name, line, i); 2581 } else { 2582 if (!isspace(CAST(unsigned char, *l)) && !goodchar(*l, extra)) 2583 file_magwarn(ms, "%s type `%s' has bad char '%c'", 2584 name, line, *l); 2585 if (nt) 2586 buf[i] = '\0'; 2587 } 2588 2589 if (i > 0) 2590 return 0; 2591 2592 file_magerror(ms, "Bad magic entry '%s'", line); 2593 return -1; 2594 } 2595 2596 /* 2597 * Parse an Apple CREATOR/TYPE annotation from magic file and put it into 2598 * magic[index - 1] 2599 */ 2600 file_private int 2601 parse_apple(struct magic_set *ms, struct magic_entry *me, const char *line, 2602 size_t len) 2603 { 2604 return parse_extra(ms, me, line, len, 2605 CAST(off_t, offsetof(struct magic, apple)), 2606 sizeof(me->mp[me->cont_count - 1].apple), "APPLE", "!+-./?", 0); 2607 } 2608 2609 /* 2610 * Parse a comma-separated list of extensions 2611 */ 2612 file_private int 2613 parse_ext(struct magic_set *ms, struct magic_entry *me, const char *line, 2614 size_t len) 2615 { 2616 return parse_extra(ms, me, line, len, 2617 CAST(off_t, offsetof(struct magic, ext)), 2618 sizeof(me->mp[me->cont_count - 1].ext), "EXTENSION", ",!+-/@?_$&~", 2619 0); 2620 /* & for b&w */ 2621 /* ~ for journal~ */ 2622 } 2623 2624 /* 2625 * parse a MIME annotation line from magic file, put into magic[index - 1] 2626 * if valid 2627 */ 2628 file_private int 2629 parse_mime(struct magic_set *ms, struct magic_entry *me, const char *line, 2630 size_t len) 2631 { 2632 return parse_extra(ms, me, line, len, 2633 CAST(off_t, offsetof(struct magic, mimetype)), 2634 sizeof(me->mp[me->cont_count - 1].mimetype), "MIME", "+-/.$?:{};=", 2635 1); 2636 } 2637 2638 file_private int 2639 check_format_type(const char *ptr, int type, const char **estr) 2640 { 2641 int quad = 0, h; 2642 size_t len, cnt; 2643 if (*ptr == '\0') { 2644 /* Missing format string; bad */ 2645 *estr = "missing format spec"; 2646 return -1; 2647 } 2648 2649 switch (file_formats[type]) { 2650 case FILE_FMT_QUAD: 2651 quad = 1; 2652 /*FALLTHROUGH*/ 2653 case FILE_FMT_NUM: 2654 if (quad == 0) { 2655 switch (type) { 2656 case FILE_BYTE: 2657 h = 2; 2658 break; 2659 case FILE_SHORT: 2660 case FILE_BESHORT: 2661 case FILE_LESHORT: 2662 h = 1; 2663 break; 2664 case FILE_LONG: 2665 case FILE_BELONG: 2666 case FILE_LELONG: 2667 case FILE_MELONG: 2668 case FILE_LEID3: 2669 case FILE_BEID3: 2670 case FILE_INDIRECT: 2671 h = 0; 2672 break; 2673 default: 2674 fprintf(stderr, "Bad number format %d", type); 2675 abort(); 2676 } 2677 } else 2678 h = 0; 2679 while (*ptr && strchr("+-.#", *ptr) != NULL) 2680 ptr++; 2681 #define CHECKLEN() do { \ 2682 for (len = cnt = 0; isdigit(CAST(unsigned char, *ptr)); ptr++, cnt++) \ 2683 len = len * 10 + (*ptr - '0'); \ 2684 if (cnt > 5 || len > 1024) \ 2685 goto toolong; \ 2686 } while (/*CONSTCOND*/0) 2687 2688 CHECKLEN(); 2689 if (*ptr == '.') 2690 ptr++; 2691 CHECKLEN(); 2692 if (quad) { 2693 if (*ptr++ != 'l') 2694 goto invalid; 2695 if (*ptr++ != 'l') 2696 goto invalid; 2697 } 2698 2699 switch (*ptr++) { 2700 #ifdef STRICT_FORMAT /* "long" formats are int formats for us */ 2701 /* so don't accept the 'l' modifier */ 2702 case 'l': 2703 switch (*ptr++) { 2704 case 'i': 2705 case 'd': 2706 case 'u': 2707 case 'o': 2708 case 'x': 2709 case 'X': 2710 if (h == 0) 2711 return 0; 2712 /*FALLTHROUGH*/ 2713 default: 2714 goto invalid; 2715 } 2716 2717 /* 2718 * Don't accept h and hh modifiers. They make writing 2719 * magic entries more complicated, for very little benefit 2720 */ 2721 case 'h': 2722 if (h-- <= 0) 2723 goto invalid; 2724 switch (*ptr++) { 2725 case 'h': 2726 if (h-- <= 0) 2727 goto invalid; 2728 switch (*ptr++) { 2729 case 'i': 2730 case 'd': 2731 case 'u': 2732 case 'o': 2733 case 'x': 2734 case 'X': 2735 return 0; 2736 default: 2737 goto invalid; 2738 } 2739 case 'i': 2740 case 'd': 2741 case 'u': 2742 case 'o': 2743 case 'x': 2744 case 'X': 2745 if (h == 0) 2746 return 0; 2747 /*FALLTHROUGH*/ 2748 default: 2749 goto invalid; 2750 } 2751 #endif 2752 case 'c': 2753 if (h == 2) 2754 return 0; 2755 goto invalid; 2756 case 'i': 2757 case 'd': 2758 case 'u': 2759 case 'o': 2760 case 'x': 2761 case 'X': 2762 #ifdef STRICT_FORMAT 2763 if (h == 0) 2764 return 0; 2765 /*FALLTHROUGH*/ 2766 #else 2767 return 0; 2768 #endif 2769 default: 2770 goto invalid; 2771 } 2772 2773 case FILE_FMT_FLOAT: 2774 case FILE_FMT_DOUBLE: 2775 if (*ptr == '-') 2776 ptr++; 2777 if (*ptr == '.') 2778 ptr++; 2779 CHECKLEN(); 2780 if (*ptr == '.') 2781 ptr++; 2782 CHECKLEN(); 2783 switch (*ptr++) { 2784 case 'e': 2785 case 'E': 2786 case 'f': 2787 case 'F': 2788 case 'g': 2789 case 'G': 2790 return 0; 2791 2792 default: 2793 goto invalid; 2794 } 2795 2796 2797 case FILE_FMT_STR: 2798 if (*ptr == '-') 2799 ptr++; 2800 while (isdigit(CAST(unsigned char, *ptr))) 2801 ptr++; 2802 if (*ptr == '.') { 2803 ptr++; 2804 while (isdigit(CAST(unsigned char , *ptr))) 2805 ptr++; 2806 } 2807 2808 switch (*ptr++) { 2809 case 's': 2810 return 0; 2811 default: 2812 goto invalid; 2813 } 2814 2815 default: 2816 /* internal error */ 2817 fprintf(stderr, "Bad file format %d", type); 2818 abort(); 2819 } 2820 invalid: 2821 *estr = "not valid"; 2822 return -1; 2823 toolong: 2824 *estr = "too long"; 2825 return -1; 2826 } 2827 2828 /* 2829 * Check that the optional printf format in description matches 2830 * the type of the magic. 2831 */ 2832 file_private int 2833 check_format(struct magic_set *ms, struct magic *m) 2834 { 2835 char *ptr; 2836 const char *estr; 2837 2838 for (ptr = m->desc; *ptr; ptr++) 2839 if (*ptr == '%') 2840 break; 2841 if (*ptr == '\0') { 2842 /* No format string; ok */ 2843 return 1; 2844 } 2845 2846 assert(file_nformats == file_nnames); 2847 2848 if (m->type >= file_nformats) { 2849 file_magwarn(ms, "Internal error inconsistency between " 2850 "m->type and format strings"); 2851 return -1; 2852 } 2853 if (file_formats[m->type] == FILE_FMT_NONE) { 2854 file_magwarn(ms, "No format string for `%s' with description " 2855 "`%s'", m->desc, file_names[m->type]); 2856 return -1; 2857 } 2858 2859 ptr++; 2860 if (check_format_type(ptr, m->type, &estr) == -1) { 2861 /* 2862 * TODO: this error message is unhelpful if the format 2863 * string is not one character long 2864 */ 2865 file_magwarn(ms, "Printf format is %s for type " 2866 "`%s' in description `%s'", estr, 2867 file_names[m->type], m->desc); 2868 return -1; 2869 } 2870 2871 for (; *ptr; ptr++) { 2872 if (*ptr == '%') { 2873 file_magwarn(ms, 2874 "Too many format strings (should have at most one) " 2875 "for `%s' with description `%s'", 2876 file_names[m->type], m->desc); 2877 return -1; 2878 } 2879 } 2880 return 0; 2881 } 2882 2883 /* 2884 * Read a numeric value from a pointer, into the value union of a magic 2885 * pointer, according to the magic type. Update the string pointer to point 2886 * just after the number read. Return 0 for success, non-zero for failure. 2887 */ 2888 file_no_overflow file_private int 2889 getvalue(struct magic_set *ms, struct magic *m, const char **p, int action) 2890 { 2891 char *ep; 2892 uint64_t ull; 2893 int y; 2894 2895 switch (m->type) { 2896 case FILE_BESTRING16: 2897 case FILE_LESTRING16: 2898 case FILE_STRING: 2899 case FILE_PSTRING: 2900 case FILE_REGEX: 2901 case FILE_SEARCH: 2902 case FILE_NAME: 2903 case FILE_USE: 2904 case FILE_DER: 2905 case FILE_OCTAL: 2906 *p = getstr(ms, m, *p, action == FILE_COMPILE); 2907 if (*p == NULL) { 2908 if (ms->flags & MAGIC_CHECK) 2909 file_magwarn(ms, "cannot get string from `%s'", 2910 m->value.s); 2911 return -1; 2912 } 2913 if (m->type == FILE_REGEX) { 2914 file_regex_t rx; 2915 int rc = 2916 file_regcomp(ms, &rx, m->value.s, REG_EXTENDED); 2917 if (rc == 0) { 2918 file_regfree(&rx); 2919 } 2920 return rc ? -1 : 0; 2921 } 2922 return 0; 2923 default: 2924 if (m->reln == 'x') 2925 return 0; 2926 break; 2927 } 2928 2929 switch (m->type) { 2930 case FILE_FLOAT: 2931 case FILE_BEFLOAT: 2932 case FILE_LEFLOAT: 2933 errno = 0; 2934 #ifdef HAVE_STRTOF 2935 m->value.f = strtof(*p, &ep); 2936 #else 2937 m->value.f = (float)strtod(*p, &ep); 2938 #endif 2939 if (errno == 0) 2940 *p = ep; 2941 return 0; 2942 case FILE_DOUBLE: 2943 case FILE_BEDOUBLE: 2944 case FILE_LEDOUBLE: 2945 errno = 0; 2946 m->value.d = strtod(*p, &ep); 2947 if (errno == 0) 2948 *p = ep; 2949 return 0; 2950 case FILE_GUID: 2951 if (file_parse_guid(*p, m->value.guid) == -1) { 2952 file_magwarn(ms, "Error parsing guid `%s'", *p); 2953 return -1; 2954 } 2955 *p += FILE_GUID_SIZE - 1; 2956 return 0; 2957 default: 2958 errno = 0; 2959 ull = CAST(uint64_t, strtoull(*p, &ep, 0)); 2960 m->value.q = file_signextend(ms, m, ull); 2961 if (*p == ep) { 2962 file_magwarn(ms, "Unparsable number `%s'", *p); 2963 return -1; 2964 } else { 2965 size_t ts = typesize(m->type); 2966 uint64_t x; 2967 const char *q; 2968 2969 if (ts == FILE_BADSIZE) { 2970 file_magwarn(ms, 2971 "Expected numeric type got `%s'", 2972 type_tbl[m->type].name); 2973 return -1; 2974 } 2975 for (q = *p; isspace(CAST(unsigned char, *q)); q++) 2976 continue; 2977 if (*q == '-' && ull != UINT64_MAX) 2978 ull = -CAST(int64_t, ull); 2979 switch (ts) { 2980 case 1: 2981 x = CAST(uint64_t, ull & ~0xffULL); 2982 y = (x & ~0xffULL) != ~0xffULL; 2983 break; 2984 case 2: 2985 x = CAST(uint64_t, ull & ~0xffffULL); 2986 y = (x & ~0xffffULL) != ~0xffffULL; 2987 break; 2988 case 4: 2989 x = CAST(uint64_t, ull & ~0xffffffffULL); 2990 y = (x & ~0xffffffffULL) != ~0xffffffffULL; 2991 break; 2992 case 8: 2993 x = 0; 2994 y = 0; 2995 break; 2996 default: 2997 fprintf(stderr, "Bad width %zu", ts); 2998 abort(); 2999 } 3000 if (x && y) { 3001 file_magwarn(ms, "Overflow for numeric" 3002 " type `%s' value %#" PRIx64, 3003 type_tbl[m->type].name, ull); 3004 return -1; 3005 } 3006 } 3007 if (errno == 0) { 3008 *p = ep; 3009 eatsize(p); 3010 } 3011 return 0; 3012 } 3013 } 3014 3015 /* 3016 * Convert a string containing C character escapes. Stop at an unescaped 3017 * space or tab. 3018 * Copy the converted version to "m->value.s", and the length in m->vallen. 3019 * Return updated scan pointer as function result. Warn if set. 3020 */ 3021 file_private const char * 3022 getstr(struct magic_set *ms, struct magic *m, const char *s, int warn) 3023 { 3024 const char *origs = s; 3025 char *p = m->value.s; 3026 size_t plen = sizeof(m->value.s); 3027 char *origp = p; 3028 char *pmax = p + plen - 1; 3029 int c; 3030 int val; 3031 size_t bracket_nesting = 0; 3032 3033 while ((c = *s++) != '\0') { 3034 if (isspace(CAST(unsigned char, c))) 3035 break; 3036 if (p >= pmax) { 3037 file_error(ms, 0, "string too long: `%s'", origs); 3038 return NULL; 3039 } 3040 if (c != '\\') { 3041 if (c == '[') { 3042 bracket_nesting++; 3043 } 3044 if (c == ']' && bracket_nesting > 0) { 3045 bracket_nesting--; 3046 } 3047 *p++ = CAST(char, c); 3048 continue; 3049 } 3050 switch(c = *s++) { 3051 3052 case '\0': 3053 if (warn) 3054 file_magwarn(ms, "incomplete escape"); 3055 s--; 3056 goto out; 3057 case '.': 3058 if (m->type == FILE_REGEX && 3059 bracket_nesting == 0 && warn) { 3060 file_magwarn(ms, "escaped dot ('.') found, " 3061 "use \\\\. instead"); 3062 } 3063 warn = 0; /* already did */ 3064 /*FALLTHROUGH*/ 3065 case '\t': 3066 if (warn) { 3067 file_magwarn(ms, 3068 "escaped tab found, use \\\\t instead"); 3069 warn = 0; /* already did */ 3070 } 3071 /*FALLTHROUGH*/ 3072 default: 3073 if (warn) { 3074 if (isprint(CAST(unsigned char, c))) { 3075 /* Allow escaping of 3076 * ``relations'' */ 3077 if (strchr("<>&^=!", c) == NULL 3078 && (m->type != FILE_REGEX || 3079 strchr("[]().*?^$|{}", c) 3080 == NULL)) { 3081 file_magwarn(ms, "no " 3082 "need to escape " 3083 "`%c'", c); 3084 } 3085 } else { 3086 file_magwarn(ms, 3087 "unknown escape sequence: " 3088 "\\%03o", c); 3089 } 3090 } 3091 /*FALLTHROUGH*/ 3092 /* space, perhaps force people to use \040? */ 3093 case ' ': 3094 #if 0 3095 /* 3096 * Other things people escape, but shouldn't need to, 3097 * so we disallow them 3098 */ 3099 case '\'': 3100 case '"': 3101 case '?': 3102 #endif 3103 /* Relations */ 3104 case '>': 3105 case '<': 3106 case '&': 3107 case '^': 3108 case '=': 3109 case '!': 3110 /* and backslash itself */ 3111 case '\\': 3112 *p++ = CAST(char, c); 3113 break; 3114 3115 case 'a': 3116 *p++ = '\a'; 3117 break; 3118 3119 case 'b': 3120 *p++ = '\b'; 3121 break; 3122 3123 case 'f': 3124 *p++ = '\f'; 3125 break; 3126 3127 case 'n': 3128 *p++ = '\n'; 3129 break; 3130 3131 case 'r': 3132 *p++ = '\r'; 3133 break; 3134 3135 case 't': 3136 *p++ = '\t'; 3137 break; 3138 3139 case 'v': 3140 *p++ = '\v'; 3141 break; 3142 3143 /* \ and up to 3 octal digits */ 3144 case '0': 3145 case '1': 3146 case '2': 3147 case '3': 3148 case '4': 3149 case '5': 3150 case '6': 3151 case '7': 3152 val = c - '0'; 3153 c = *s++; /* try for 2 */ 3154 if (c >= '0' && c <= '7') { 3155 val = (val << 3) | (c - '0'); 3156 c = *s++; /* try for 3 */ 3157 if (c >= '0' && c <= '7') 3158 val = (val << 3) | (c-'0'); 3159 else 3160 --s; 3161 } 3162 else 3163 --s; 3164 *p++ = CAST(char, val); 3165 break; 3166 3167 /* \x and up to 2 hex digits */ 3168 case 'x': 3169 val = 'x'; /* Default if no digits */ 3170 c = hextoint(*s++); /* Get next char */ 3171 if (c >= 0) { 3172 val = c; 3173 c = hextoint(*s++); 3174 if (c >= 0) 3175 val = (val << 4) + c; 3176 else 3177 --s; 3178 } else 3179 --s; 3180 *p++ = CAST(char, val); 3181 break; 3182 } 3183 } 3184 --s; 3185 out: 3186 *p = '\0'; 3187 m->vallen = CAST(unsigned char, (p - origp)); 3188 if (m->type == FILE_PSTRING) { 3189 size_t l = file_pstring_length_size(ms, m); 3190 if (l == FILE_BADSIZE) 3191 return NULL; 3192 m->vallen += CAST(unsigned char, l); 3193 } 3194 return s; 3195 } 3196 3197 3198 /* Single hex char to int; -1 if not a hex char. */ 3199 file_private int 3200 hextoint(int c) 3201 { 3202 if (!isascii(CAST(unsigned char, c))) 3203 return -1; 3204 if (isdigit(CAST(unsigned char, c))) 3205 return c - '0'; 3206 if ((c >= 'a') && (c <= 'f')) 3207 return c + 10 - 'a'; 3208 if (( c>= 'A') && (c <= 'F')) 3209 return c + 10 - 'A'; 3210 return -1; 3211 } 3212 3213 3214 /* 3215 * Print a string containing C character escapes. 3216 */ 3217 file_protected void 3218 file_showstr(FILE *fp, const char *s, size_t len) 3219 { 3220 char c; 3221 3222 for (;;) { 3223 if (len == FILE_BADSIZE) { 3224 c = *s++; 3225 if (c == '\0') 3226 break; 3227 } 3228 else { 3229 if (len-- == 0) 3230 break; 3231 c = *s++; 3232 } 3233 if (c >= 040 && c <= 0176) /* TODO isprint && !iscntrl */ 3234 (void) fputc(c, fp); 3235 else { 3236 (void) fputc('\\', fp); 3237 switch (c) { 3238 case '\a': 3239 (void) fputc('a', fp); 3240 break; 3241 3242 case '\b': 3243 (void) fputc('b', fp); 3244 break; 3245 3246 case '\f': 3247 (void) fputc('f', fp); 3248 break; 3249 3250 case '\n': 3251 (void) fputc('n', fp); 3252 break; 3253 3254 case '\r': 3255 (void) fputc('r', fp); 3256 break; 3257 3258 case '\t': 3259 (void) fputc('t', fp); 3260 break; 3261 3262 case '\v': 3263 (void) fputc('v', fp); 3264 break; 3265 3266 default: 3267 (void) fprintf(fp, "%.3o", c & 0377); 3268 break; 3269 } 3270 } 3271 } 3272 } 3273 3274 /* 3275 * eatsize(): Eat the size spec from a number [eg. 10UL] 3276 */ 3277 file_private void 3278 eatsize(const char **p) 3279 { 3280 const char *l = *p; 3281 3282 if (LOWCASE(*l) == 'u') 3283 l++; 3284 3285 switch (LOWCASE(*l)) { 3286 case 'l': /* long */ 3287 case 's': /* short */ 3288 case 'h': /* short */ 3289 case 'b': /* char/byte */ 3290 case 'c': /* char/byte */ 3291 l++; 3292 /*FALLTHROUGH*/ 3293 default: 3294 break; 3295 } 3296 3297 *p = l; 3298 } 3299 3300 /* 3301 * handle a buffer containing a compiled file. 3302 */ 3303 file_private struct magic_map * 3304 apprentice_buf(struct magic_set *ms, struct magic *buf, size_t len) 3305 { 3306 struct magic_map *map; 3307 3308 if ((map = CAST(struct magic_map *, calloc(1, sizeof(*map)))) == NULL) { 3309 file_oomem(ms, sizeof(*map)); 3310 return NULL; 3311 } 3312 map->len = len; 3313 map->p = buf; 3314 map->type = MAP_TYPE_USER; 3315 if (check_buffer(ms, map, "buffer") != 0) { 3316 apprentice_unmap(map); 3317 return NULL; 3318 } 3319 return map; 3320 } 3321 3322 /* 3323 * handle a compiled file. 3324 */ 3325 3326 file_private struct magic_map * 3327 apprentice_map(struct magic_set *ms, const char *fn) 3328 { 3329 int fd; 3330 struct stat st; 3331 char *dbname = NULL; 3332 struct magic_map *map; 3333 struct magic_map *rv = NULL; 3334 3335 fd = -1; 3336 if ((map = CAST(struct magic_map *, calloc(1, sizeof(*map)))) == NULL) { 3337 file_oomem(ms, sizeof(*map)); 3338 goto error; 3339 } 3340 map->type = MAP_TYPE_USER; /* unspecified */ 3341 3342 dbname = mkdbname(ms, fn, 0); 3343 if (dbname == NULL) 3344 goto error; 3345 3346 if ((fd = open(dbname, O_RDONLY|O_BINARY)) == -1) 3347 goto error; 3348 3349 if (fstat(fd, &st) == -1) { 3350 file_error(ms, errno, "cannot stat `%s'", dbname); 3351 goto error; 3352 } 3353 if (st.st_size < 8 || st.st_size > maxoff_t()) { 3354 file_error(ms, 0, "file `%s' is too %s", dbname, 3355 st.st_size < 8 ? "small" : "large"); 3356 goto error; 3357 } 3358 3359 map->len = CAST(size_t, st.st_size); 3360 #ifdef QUICK 3361 map->type = MAP_TYPE_MMAP; 3362 if ((map->p = mmap(0, CAST(size_t, st.st_size), PROT_READ|PROT_WRITE, 3363 MAP_PRIVATE|MAP_FILE, fd, CAST(off_t, 0))) == MAP_FAILED) { 3364 file_error(ms, errno, "cannot map `%s'", dbname); 3365 goto error; 3366 } 3367 #else 3368 map->type = MAP_TYPE_MALLOC; 3369 if ((map->p = CAST(void *, malloc(map->len))) == NULL) { 3370 file_oomem(ms, map->len); 3371 goto error; 3372 } 3373 if (read(fd, map->p, map->len) != (ssize_t)map->len) { 3374 file_badread(ms); 3375 goto error; 3376 } 3377 #endif 3378 (void)close(fd); 3379 fd = -1; 3380 3381 if (check_buffer(ms, map, dbname) != 0) { 3382 goto error; 3383 } 3384 #ifdef QUICK 3385 if (mprotect(map->p, CAST(size_t, st.st_size), PROT_READ) == -1) { 3386 file_error(ms, errno, "cannot mprotect `%s'", dbname); 3387 goto error; 3388 } 3389 #endif 3390 3391 free(dbname); 3392 return map; 3393 3394 error: 3395 if (fd != -1) 3396 (void)close(fd); 3397 apprentice_unmap(map); 3398 free(dbname); 3399 return rv; 3400 } 3401 3402 file_private int 3403 check_buffer(struct magic_set *ms, struct magic_map *map, const char *dbname) 3404 { 3405 uint32_t *ptr; 3406 uint32_t entries, nentries; 3407 uint32_t version; 3408 int i, needsbyteswap; 3409 3410 entries = CAST(uint32_t, map->len / sizeof(struct magic)); 3411 if (entries < MAGIC_SETS) { 3412 file_error(ms, 0, "Too few magic entries %u in `%s'", 3413 entries, dbname); 3414 return -1; 3415 } 3416 if ((entries * sizeof(struct magic)) != map->len) { 3417 file_error(ms, 0, "Size of `%s' %" SIZE_T_FORMAT "u is not " 3418 "a multiple of %" SIZE_T_FORMAT "u", 3419 dbname, map->len, sizeof(struct magic)); 3420 return -1; 3421 } 3422 3423 ptr = CAST(uint32_t *, map->p); 3424 if (*ptr != MAGICNO) { 3425 if (swap4(*ptr) != MAGICNO) { 3426 file_error(ms, 0, "bad magic in `%s'", dbname); 3427 return -1; 3428 } 3429 needsbyteswap = 1; 3430 } else 3431 needsbyteswap = 0; 3432 if (needsbyteswap) 3433 version = swap4(ptr[1]); 3434 else 3435 version = ptr[1]; 3436 if (version != VERSIONNO) { 3437 file_error(ms, 0, "File %s supports only version %d magic " 3438 "files. `%s' is version %d", VERSION, 3439 VERSIONNO, dbname, version); 3440 return -1; 3441 } 3442 map->magic[0] = CAST(struct magic *, map->p) + 1; 3443 nentries = 0; 3444 for (i = 0; i < MAGIC_SETS; i++) { 3445 if (needsbyteswap) 3446 map->nmagic[i] = swap4(ptr[i + 2]); 3447 else 3448 map->nmagic[i] = ptr[i + 2]; 3449 if (i != MAGIC_SETS - 1) 3450 map->magic[i + 1] = map->magic[i] + map->nmagic[i]; 3451 nentries += map->nmagic[i]; 3452 } 3453 if (entries != nentries + 1) { 3454 file_error(ms, 0, "Inconsistent entries in `%s' %u != %u", 3455 dbname, entries, nentries + 1); 3456 return -1; 3457 } 3458 if (needsbyteswap) 3459 for (i = 0; i < MAGIC_SETS; i++) 3460 byteswap(map->magic[i], map->nmagic[i]); 3461 return 0; 3462 } 3463 3464 /* 3465 * handle an mmaped file. 3466 */ 3467 file_private int 3468 apprentice_compile(struct magic_set *ms, struct magic_map *map, const char *fn) 3469 { 3470 static const size_t nm = sizeof(*map->nmagic) * MAGIC_SETS; 3471 static const size_t m = sizeof(**map->magic); 3472 int fd = -1; 3473 size_t len; 3474 char *dbname; 3475 int rv = -1; 3476 uint32_t i; 3477 union { 3478 struct magic m; 3479 uint32_t h[2 + MAGIC_SETS]; 3480 } hdr; 3481 3482 dbname = mkdbname(ms, fn, 1); 3483 3484 if (dbname == NULL) 3485 goto out; 3486 3487 if ((fd = open(dbname, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0644)) == -1) 3488 { 3489 file_error(ms, errno, "cannot open `%s'", dbname); 3490 goto out; 3491 } 3492 memset(&hdr, 0, sizeof(hdr)); 3493 hdr.h[0] = MAGICNO; 3494 hdr.h[1] = VERSIONNO; 3495 memcpy(hdr.h + 2, map->nmagic, nm); 3496 3497 if (write(fd, &hdr, sizeof(hdr)) != CAST(ssize_t, sizeof(hdr))) { 3498 file_error(ms, errno, "error writing `%s'", dbname); 3499 goto out2; 3500 } 3501 3502 for (i = 0; i < MAGIC_SETS; i++) { 3503 len = m * map->nmagic[i]; 3504 if (write(fd, map->magic[i], len) != CAST(ssize_t, len)) { 3505 file_error(ms, errno, "error writing `%s'", dbname); 3506 goto out2; 3507 } 3508 } 3509 3510 rv = 0; 3511 out2: 3512 if (fd != -1) 3513 (void)close(fd); 3514 out: 3515 apprentice_unmap(map); 3516 free(dbname); 3517 return rv; 3518 } 3519 3520 file_private const char ext[] = ".mgc"; 3521 /* 3522 * make a dbname 3523 */ 3524 file_private char * 3525 mkdbname(struct magic_set *ms, const char *fn, int strip) 3526 { 3527 const char *p, *q; 3528 char *buf; 3529 3530 if (strip) { 3531 if ((p = strrchr(fn, '/')) != NULL) 3532 fn = ++p; 3533 } 3534 3535 for (q = fn; *q; q++) 3536 continue; 3537 /* Look for .mgc */ 3538 for (p = ext + sizeof(ext) - 1; p >= ext && q >= fn; p--, q--) 3539 if (*p != *q) 3540 break; 3541 3542 /* Did not find .mgc, restore q */ 3543 if (p >= ext) 3544 for (q = fn; *q; q++) 3545 continue; 3546 3547 q++; 3548 /* Compatibility with old code that looked in .mime */ 3549 if (ms->flags & MAGIC_MIME) { 3550 if (asprintf(&buf, "%.*s.mime%s", CAST(int, q - fn), fn, ext) 3551 < 0) 3552 return NULL; 3553 if (access(buf, R_OK) != -1) { 3554 ms->flags &= MAGIC_MIME_TYPE; 3555 return buf; 3556 } 3557 free(buf); 3558 } 3559 if (asprintf(&buf, "%.*s%s", CAST(int, q - fn), fn, ext) < 0) 3560 return NULL; 3561 3562 /* Compatibility with old code that looked in .mime */ 3563 if (strstr(fn, ".mime") != NULL) 3564 ms->flags &= MAGIC_MIME_TYPE; 3565 return buf; 3566 } 3567 3568 /* 3569 * Byteswap an mmap'ed file if needed 3570 */ 3571 file_private void 3572 byteswap(struct magic *magic, uint32_t nmagic) 3573 { 3574 uint32_t i; 3575 for (i = 0; i < nmagic; i++) 3576 bs1(&magic[i]); 3577 } 3578 3579 #if !defined(HAVE_BYTESWAP_H) && !defined(HAVE_SYS_BSWAP_H) 3580 /* 3581 * swap a short 3582 */ 3583 file_private uint16_t 3584 swap2(uint16_t sv) 3585 { 3586 uint16_t rv; 3587 uint8_t *s = RCAST(uint8_t *, RCAST(void *, &sv)); 3588 uint8_t *d = RCAST(uint8_t *, RCAST(void *, &rv)); 3589 d[0] = s[1]; 3590 d[1] = s[0]; 3591 return rv; 3592 } 3593 3594 /* 3595 * swap an int 3596 */ 3597 file_private uint32_t 3598 swap4(uint32_t sv) 3599 { 3600 uint32_t rv; 3601 uint8_t *s = RCAST(uint8_t *, RCAST(void *, &sv)); 3602 uint8_t *d = RCAST(uint8_t *, RCAST(void *, &rv)); 3603 d[0] = s[3]; 3604 d[1] = s[2]; 3605 d[2] = s[1]; 3606 d[3] = s[0]; 3607 return rv; 3608 } 3609 3610 /* 3611 * swap a quad 3612 */ 3613 file_private uint64_t 3614 swap8(uint64_t sv) 3615 { 3616 uint64_t rv; 3617 uint8_t *s = RCAST(uint8_t *, RCAST(void *, &sv)); 3618 uint8_t *d = RCAST(uint8_t *, RCAST(void *, &rv)); 3619 # if 0 3620 d[0] = s[3]; 3621 d[1] = s[2]; 3622 d[2] = s[1]; 3623 d[3] = s[0]; 3624 d[4] = s[7]; 3625 d[5] = s[6]; 3626 d[6] = s[5]; 3627 d[7] = s[4]; 3628 # else 3629 d[0] = s[7]; 3630 d[1] = s[6]; 3631 d[2] = s[5]; 3632 d[3] = s[4]; 3633 d[4] = s[3]; 3634 d[5] = s[2]; 3635 d[6] = s[1]; 3636 d[7] = s[0]; 3637 # endif 3638 return rv; 3639 } 3640 #endif 3641 3642 file_protected uintmax_t 3643 file_varint2uintmax_t(const unsigned char *us, int t, size_t *l) 3644 { 3645 uintmax_t x = 0; 3646 const unsigned char *c; 3647 if (t == FILE_LEVARINT) { 3648 for (c = us; *c; c++) { 3649 if ((*c & 0x80) == 0) 3650 break; 3651 } 3652 if (l) 3653 *l = c - us + 1; 3654 for (; c >= us; c--) { 3655 x |= *c & 0x7f; 3656 x <<= 7; 3657 } 3658 } else { 3659 for (c = us; *c; c++) { 3660 x |= *c & 0x7f; 3661 if ((*c & 0x80) == 0) 3662 break; 3663 x <<= 7; 3664 } 3665 if (l) 3666 *l = c - us + 1; 3667 } 3668 return x; 3669 } 3670 3671 3672 /* 3673 * byteswap a single magic entry 3674 */ 3675 file_private void 3676 bs1(struct magic *m) 3677 { 3678 m->flag = swap2(m->flag); 3679 m->offset = swap4(CAST(uint32_t, m->offset)); 3680 m->in_offset = swap4(CAST(uint32_t, m->in_offset)); 3681 m->lineno = swap4(CAST(uint32_t, m->lineno)); 3682 if (IS_STRING(m->type)) { 3683 m->str_range = swap4(m->str_range); 3684 m->str_flags = swap4(m->str_flags); 3685 } else { 3686 m->value.q = swap8(m->value.q); 3687 m->num_mask = swap8(m->num_mask); 3688 } 3689 } 3690 3691 file_protected size_t 3692 file_pstring_length_size(struct magic_set *ms, const struct magic *m) 3693 { 3694 switch (m->str_flags & PSTRING_LEN) { 3695 case PSTRING_1_LE: 3696 return 1; 3697 case PSTRING_2_LE: 3698 case PSTRING_2_BE: 3699 return 2; 3700 case PSTRING_4_LE: 3701 case PSTRING_4_BE: 3702 return 4; 3703 default: 3704 file_error(ms, 0, "corrupt magic file " 3705 "(bad pascal string length %d)", 3706 m->str_flags & PSTRING_LEN); 3707 return FILE_BADSIZE; 3708 } 3709 } 3710 file_protected size_t 3711 file_pstring_get_length(struct magic_set *ms, const struct magic *m, 3712 const char *ss) 3713 { 3714 size_t len = 0; 3715 const unsigned char *s = RCAST(const unsigned char *, ss); 3716 unsigned int s3, s2, s1, s0; 3717 3718 switch (m->str_flags & PSTRING_LEN) { 3719 case PSTRING_1_LE: 3720 len = *s; 3721 break; 3722 case PSTRING_2_LE: 3723 s0 = s[0]; 3724 s1 = s[1]; 3725 len = (s1 << 8) | s0; 3726 break; 3727 case PSTRING_2_BE: 3728 s0 = s[0]; 3729 s1 = s[1]; 3730 len = (s0 << 8) | s1; 3731 break; 3732 case PSTRING_4_LE: 3733 s0 = s[0]; 3734 s1 = s[1]; 3735 s2 = s[2]; 3736 s3 = s[3]; 3737 len = (s3 << 24) | (s2 << 16) | (s1 << 8) | s0; 3738 break; 3739 case PSTRING_4_BE: 3740 s0 = s[0]; 3741 s1 = s[1]; 3742 s2 = s[2]; 3743 s3 = s[3]; 3744 len = (s0 << 24) | (s1 << 16) | (s2 << 8) | s3; 3745 break; 3746 default: 3747 file_error(ms, 0, "corrupt magic file " 3748 "(bad pascal string length %d)", 3749 m->str_flags & PSTRING_LEN); 3750 return FILE_BADSIZE; 3751 } 3752 3753 if (m->str_flags & PSTRING_LENGTH_INCLUDES_ITSELF) { 3754 size_t l = file_pstring_length_size(ms, m); 3755 if (l == FILE_BADSIZE) 3756 return l; 3757 len -= l; 3758 } 3759 3760 return len; 3761 } 3762 3763 file_protected int 3764 file_magicfind(struct magic_set *ms, const char *name, struct mlist *v) 3765 { 3766 uint32_t i, j; 3767 struct mlist *mlist, *ml; 3768 3769 mlist = ms->mlist[1]; 3770 3771 for (ml = mlist->next; ml != mlist; ml = ml->next) { 3772 struct magic *ma = ml->magic; 3773 for (i = 0; i < ml->nmagic; i++) { 3774 if (ma[i].type != FILE_NAME) 3775 continue; 3776 if (strcmp(ma[i].value.s, name) == 0) { 3777 v->magic = &ma[i]; 3778 v->magic_rxcomp = &(ml->magic_rxcomp[i]); 3779 for (j = i + 1; j < ml->nmagic; j++) 3780 if (ma[j].cont_level == 0) 3781 break; 3782 v->nmagic = j - i; 3783 return 0; 3784 } 3785 } 3786 } 3787 return -1; 3788 } 3789