Coverage Report

Created: 2026-09-03 06:05

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