35FILE_RCSID(
"@(#)$File: softmagic.c,v 1.345 2023/07/02 12:48:39 christos Exp $")
49 const struct buffer *,
size_t,
int,
int,
int, uint16_t *,
50 uint16_t *,
int *,
int *,
int *,
int *,
int *);
52 const unsigned char *,
size_t,
53 size_t,
unsigned int,
int,
int,
int, uint16_t *,
54 uint16_t *,
int *,
int *,
int *,
int *,
int *);
56 const struct buffer *,
size_t,
unsigned int);
63 const unsigned char *, uint32_t,
size_t,
struct magic *);
72#define OFFSET_OOB(n, o, i) ((n) < CAST(uint32_t, (o)) || (i) > ((n) - (o)))
74 (CAST(uint64_t, (p)->hq[0])<<56)| \
75 (CAST(uint64_t, (p)->hq[1])<<48)| \
76 (CAST(uint64_t, (p)->hq[2])<<40)| \
77 (CAST(uint64_t, (p)->hq[3])<<32)| \
78 (CAST(uint64_t, (p)->hq[4])<<24)| \
79 (CAST(uint64_t, (p)->hq[5])<<16)| \
80 (CAST(uint64_t, (p)->hq[6])<<8)| \
81 (CAST(uint64_t, (p)->hq[7])))
83 (CAST(uint64_t, (p)->hq[7])<<56)| \
84 (CAST(uint64_t, (p)->hq[6])<<48)| \
85 (CAST(uint64_t, (p)->hq[5])<<40)| \
86 (CAST(uint64_t, (p)->hq[4])<<32)| \
87 (CAST(uint64_t, (p)->hq[3])<<24)| \
88 (CAST(uint64_t, (p)->hq[2])<<16)| \
89 (CAST(uint64_t, (p)->hq[1])<<8)| \
90 (CAST(uint64_t, (p)->hq[0])))
92 (CAST(uint32_t, (p)->hl[3])<<24)| \
93 (CAST(uint32_t, (p)->hl[2])<<16)| \
94 (CAST(uint32_t, (p)->hl[1])<<8)| \
95 (CAST(uint32_t, (p)->hl[0])))
97 (CAST(uint32_t, (p)->hl[0])<<24)| \
98 (CAST(uint32_t, (p)->hl[1])<<16)| \
99 (CAST(uint32_t, (p)->hl[2])<<8)| \
100 (CAST(uint32_t, (p)->hl[3])))
102 (CAST(uint32_t, (p)->hl[1])<<24)| \
103 (CAST(uint32_t, (p)->hl[0])<<16)| \
104 (CAST(uint32_t, (p)->hl[3])<<8)| \
105 (CAST(uint32_t, (p)->hl[2])))
107#define BE16(p) ((CAST(uint16_t, (p)->hs[0])<<8)|(CAST(uint16_t, (p)->hs[1])))
108#define LE16(p) ((CAST(uint16_t, (p)->hs[1])<<8)|(CAST(uint16_t, (p)->hs[0])))
109#define SEXT(s,v,p) ((s) ? \
110 CAST(intmax_t, CAST(int##v##_t, p)) : \
111 CAST(intmax_t, CAST(uint##v##_t, p)))
120 uint16_t *indir_count, uint16_t *name_count,
int mode,
int text)
123 int rv = 0, printed_something = 0, need_separator = 0, firstline = 1;
126 if (name_count ==
NULL) {
130 if (indir_count ==
NULL) {
137 0,
mode,
text, 0, indir_count, name_count,
138 &printed_something, &need_separator, &firstline,
157#if defined(FILE_FMTDEBUG) && defined(HAVE_FMTCHECK)
158#define F(a, b, c) file_fmtcheck((a), (b), (c), __FILE__, __LINE__)
161file_fmtcheck(struct
magic_set *ms, const
char *desc, const
char *def,
169 ptr = fmtcheck(desc, def);
173 " with `%s'",
file,
line, desc, def);
176#elif defined(HAVE_FMTCHECK)
177#define F(a, b, c) fmtcheck((b), (c))
179#define F(a, b, c) ((b))
214 int flip, uint16_t *indir_count, uint16_t *name_count,
215 int *printed_something,
int *need_separator,
int *firstline,
216 int *returnval,
int *found_match)
218 uint32_t magindex = 0;
219 unsigned int cont_level = 0;
220 int found_matchv = 0;
221 int returnvalv = 0, e;
229 if (returnval ==
NULL)
230 returnval = &returnvalv;
231 if (found_match ==
NULL)
232 found_match = &found_matchv;
237 for (magindex = 0; magindex < nmagic; magindex++) {
249 while (magindex < nmagic - 1 &&
261 switch (
mget(ms, m, b,
CAST(
const unsigned char *, bb.
fbuf),
263 mode,
text, flip, indir_count, name_count,
264 printed_something, need_separator, firstline, returnval,
302 *printed_something = 1;
317 *printed_something = 1;
337 while (magindex + 1 < nmagic &&
339 m = &
magic[++magindex];
365#ifdef ENABLE_CONDITIONALS
372 switch (
mget(ms, m, b,
CAST(
const unsigned char *,
375 name_count, printed_something, need_separator,
376 firstline, returnval, found_match)) {
397#ifdef ENABLE_CONDITIONALS
402#ifdef ENABLE_CONDITIONALS
417 *printed_something = 1;
437 if (!*printed_something) {
438 *printed_something = 1;
474 if (*printed_something) {
481 *printed_something = 0;
514#if !defined(HAVE_STRNDUP) || defined(__aiws__) || defined(_AIX)
515# if defined(__aiws__) || defined(_AIX)
516# define strndup aix_strndup
518char *
strndup(
const char *,
size_t);
539 const char *
ptr, *sptr, *e, *t, *ee, *et;
550 if (!*
ptr ||
ptr[1] !=
'?')
552 for (et = t =
ptr + 2; *et && *et !=
':'; et++)
556 for (ee = e = et + 1; *ee && *ee !=
'}'; ee++)
562 if (ms->
mode & 0111) {
597 char buf[128], tbuf[26], sbuf[512], ebuf[512];
601 if (varexpand(ms, ebuf,
sizeof(ebuf), m->
desc) == -1)
606#define PRINTER(value, format, stype, utype) \
607 v = file_signextend(ms, m, CAST(uint64_t, value)); \
608 switch (check_fmt(ms, desc)) { \
612 if (m->flag & UNSIGNED) { \
613 (void)snprintf(buf, sizeof(buf), "%" format "u", \
616 (void)snprintf(buf, sizeof(buf), "%" format "d", \
619 if (file_printf(ms, F(ms, desc, "%s"), buf) == -1) \
623 if (m->flag & UNSIGNED) { \
624 if (file_printf(ms, F(ms, desc, "%" format "u"), \
625 CAST(utype, v)) == -1) \
628 if (file_printf(ms, F(ms, desc, "%" format "d"), \
629 CAST(stype, v)) == -1) \
643 PRINTER(
p->h,
"", int16_t, uint16_t);
649 PRINTER(
p->l,
"", int32_t, uint32_t);
661 if (m->
reln ==
'=' || m->
reln ==
'!') {
664 sizeof(m->
value.
s))) == -1)
673 str[
strcspn(str,
"\r\n")] =
'\0';
680 sizeof(
p->s) - (str -
p->s))) == -1)
846 size_t nbytes =
b->flen;
851 o =
CAST(int32_t, (ms->
offset +
sizeof(
char)));
863 o =
CAST(int32_t, (ms->
offset +
sizeof(
short)));
870 o =
CAST(int32_t, (ms->
offset +
sizeof(int32_t)));
876 o =
CAST(int32_t, (ms->
offset +
sizeof(int64_t)));
884 if (m->
reln ==
'=' || m->
reln ==
'!') {
896 o +=
CAST(uint32_t,
l);
905 o =
CAST(int32_t, (ms->
offset +
sizeof(uint32_t)));
912 o =
CAST(int32_t, (ms->
offset +
sizeof(uint32_t)));
918 o =
CAST(int32_t, (ms->
offset +
sizeof(uint64_t)));
924 o =
CAST(int32_t, (ms->
offset +
sizeof(uint64_t)));
930 o =
CAST(int32_t, (ms->
offset +
sizeof(
float)));
936 o =
CAST(int32_t, (ms->
offset +
sizeof(
double)));
964 if (o == -1 ||
CAST(
size_t, o) > nbytes) {
967 "Bad DER offset %d nbytes=%"
976 o =
CAST(int32_t, (ms->
offset + 2 *
sizeof(uint64_t)));
984 if (
CAST(
size_t, o) > nbytes) {
998 v = ((((
v >> 0) & 0x7f) << 0) |
999 (((
v >> 8) & 0x7f) << 7) |
1000 (((
v >> 16) & 0x7f) << 14) |
1001 (((
v >> 24) & 0x7f) << 21));
1003 fprintf(stderr,
"id3 offs=%u\n",
v);
1057#define DO_CVT(fld, type) \
1059 switch (m->mask_op & FILE_OPS_MASK) { \
1061 p->fld &= CAST(type, m->num_mask); \
1064 p->fld |= CAST(type, m->num_mask); \
1067 p->fld ^= CAST(type, m->num_mask); \
1070 p->fld += CAST(type, m->num_mask); \
1072 case FILE_OPMINUS: \
1073 p->fld -= CAST(type, m->num_mask); \
1075 case FILE_OPMULTIPLY: \
1076 p->fld *= CAST(type, m->num_mask); \
1078 case FILE_OPDIVIDE: \
1079 if (CAST(type, m->num_mask) == 0) \
1081 p->fld /= CAST(type, m->num_mask); \
1083 case FILE_OPMODULO: \
1084 if (CAST(type, m->num_mask) == 0) \
1086 p->fld %= CAST(type, m->num_mask); \
1089 if (m->mask_op & FILE_OPINVERSE) \
1120#define DO_CVT2(fld, type) \
1122 switch (m->mask_op & FILE_OPS_MASK) { \
1124 p->fld += CAST(type, m->num_mask); \
1126 case FILE_OPMINUS: \
1127 p->fld -= CAST(type, m->num_mask); \
1129 case FILE_OPMULTIPLY: \
1130 p->fld *= CAST(type, m->num_mask); \
1132 case FILE_OPDIVIDE: \
1133 if (CAST(type, m->num_mask) == 0) \
1135 p->fld /= CAST(type, m->num_mask); \
1197 p->s[
sizeof(
p->s) - 1] =
'\0';
1210 sz =
sizeof(
p->s) - sz;
1326 (
void) fputc(
'\n', stderr);
1327 (
void) fputc(
'\n', stderr);
1332 const unsigned char *
s, uint32_t
offset,
size_t nbytes,
struct magic *m)
1334 size_t size =
sizeof(*p);
1356 size_t lines, linecnt, bytecnt;
1365 linecnt = m->str_range;
1366 bytecnt = linecnt * 80;
1369 bytecnt = m->str_range;
1372 if (bytecnt == 0 || bytecnt > nbytes -
offset)
1373 bytecnt = nbytes -
offset;
1381 ((
b =
CAST(
const char *,
1382 memchr(c =
b,
'\n',
CAST(
size_t, (
end -
b)))))
1383 || (
b =
CAST(
const char *,
1384 memchr(c,
'\r',
CAST(
size_t, (
end - c))))));
1386 if (
b <
end - 1 &&
b[0] ==
'\r' &&
b[1] ==
'\n')
1388 if (
b <
end - 1 &&
b[0] ==
'\n')
1403 const unsigned char *src =
s +
offset;
1404 const unsigned char *esrc =
s + nbytes;
1406 char *edst = &
p->s[
sizeof(
p->s) - 1];
1414 for (; src < esrc; src += 2, dst++) {
1421 *(src - 1) !=
'\0' :
1422 ((src + 1 < esrc) &&
1423 *(src + 1) !=
'\0'))
1432 if (m->str_range != 0 && m->str_range <
sizeof(*
p))
1433 size = m->str_range;
1451 nbytes = nbytes -
offset;
1461 if (nbytes <
sizeof(*
p))
1463 sizeof(*
p) - nbytes);
1473 if (lhs >= UINT_MAX || lhs <=
INT_MIN ||
1474 off >= UINT_MAX || off <=
INT_MIN) {
1476 fprintf(stderr,
"lhs/off overflow %jd %jd\n", lhs, off);
1511 if (
offset >= UINT_MAX) {
1522 const struct buffer *
b,
size_t o,
unsigned int cont_level)
1527 if (cont_level > 0) {
1531 file_error(ms, 0,
"negative offset %d at continuation"
1532 "level %u", m->
offset, cont_level);
1541 "u at level %u", o, cont_level);
1550 if (cont_level == 0) {
1565 b->flen,
b->elen,
offset, cont_level);
1594 const unsigned char *
s,
size_t nbytes,
size_t o,
unsigned int cont_level,
1595 int mode,
int text,
int flip, uint16_t *indir_count, uint16_t *name_count,
1596 int *printed_something,
int *need_separator,
int *firstline,
int *returnval,
1603 int rv, oneed_separator, in_type, nfound_match;
1606 struct mlist ml, *mlp;
1610 file_error(ms, 0,
"indirect count (%hu) exceeded",
1616 file_error(ms, 0,
"name use count (%hu) exceeded",
1628 fprintf(stderr,
"mget(type=%d, flag=%#x, offset=%u, o=%"
1630 "u, il=%hu, nc=%hu)\n",
1632 *indir_count, *name_count);
1651 off =
SEXT(sgn,8,
q->b);
1656 off =
SEXT(sgn,16,
q->h);
1671 off =
SEXT(sgn,32,
q->l);
1703 off =
SEXT(sgn,64,strtoull(
p->s,
NULL, 8));
1707 fprintf(stderr,
"bad op=%d\n", op);
1711 fprintf(stderr,
"indirect offs=%jd\n", off);
1786 SEXT(sgn,64,strtoull(
p->s,
NULL, 8)), off))
1791 fprintf(stderr,
"bad in_type=%d\n", in_type);
1796 if (cont_level == 0) {
1799 "indirect *zero* cont_level\n");
1806 "indirect *zero* offset\n");
1907 name_count, printed_something, need_separator,
1924 if (rbuf)
efree(rbuf);
1928 if (rbuf)
efree(rbuf);
1932 if (rbuf)
efree(rbuf);
1944 file_error(ms, 0,
"cannot find entry `%s'", rbuf);
1952 oneed_separator = *need_separator;
1954 *need_separator = 0;
1961 printed_something, need_separator, firstline, returnval,
1965 *found_match |= nfound_match;
1970 *need_separator = oneed_separator;
1973 return rv || *found_match;
2002 const unsigned char *
a =
RCAST(
const unsigned char *, s1);
2003 const unsigned char *
b =
RCAST(
const unsigned char *, s2);
2006 const unsigned char *eb =
b + (ws ?
maxlen :
len);
2017 if ((
v = *
b++ - *
a++) !=
'\0')
2028 if ((
v = tolower(*
b++) - *
a++) !=
'\0')
2033 if ((
v = toupper(*
b++) - *
a++) !=
'\0')
2042 if (isspace(*
b++)) {
2044 while (
EXPECTED(_i++ < 2048) &&
b < eb && isspace(*
b))
2055 while (
b < eb && isspace(*
b))
2059 if ((
v = *
b++ - *
a++) !=
'\0')
2064 if (*
b && !isspace(*
b))
2153 matched = isunordered(fl, fv) ? 1 : fv != fl;
2157 matched = isunordered(fl, fv) ? 0 : fv == fl;
2161 matched = isgreater(fv, fl);
2165 matched = isless(fv, fl);
2170 "invalid relation `%c'", m->
reln);
2186 matched = isunordered(dv,
dl) ? 1 : dv !=
dl;
2190 matched = isunordered(dv,
dl) ? 0 : dv ==
dl;
2194 matched = isgreater(dv,
dl);
2198 matched = isless(dv,
dl);
2203 "invalid relation `%c'", m->
reln);
2219 sizeof(
p->s), m->str_flags);
2226 sizeof(
p->s), m->str_flags);
2240 if (slen > 0 && m->str_flags == 0) {
2242 idx = m->str_range + slen;
2258 for (idx = 0; m->str_range == 0 || idx < m->str_range; idx++) {
2289 zend_string_release(pattern);
2306 zend_string_release(haystack);
2310 zend_string_release(pattern);
2337 zend_string_release(pattern);
2344 zend_string_release(pattern);
2355 if (matched == -1) {
2358 "EOF comparing DER entries\n");
2378 "u == *any* = 1",
CAST(
unsigned long long,
v));
2387 CAST(
unsigned long long,
v),
2388 CAST(
unsigned long long,
l), matched);
2396 CAST(
unsigned long long,
v),
2397 CAST(
unsigned long long,
l), matched);
2406 CAST(
unsigned long long,
v),
2407 CAST(
unsigned long long,
l), matched);
2410 matched =
CAST(int64_t,
v) >
CAST(int64_t,
l);
2415 CAST(
long long,
l), matched);
2425 CAST(
unsigned long long,
v),
2426 CAST(
unsigned long long,
l), matched);
2429 matched =
CAST(int64_t,
v) <
CAST(int64_t,
l);
2434 CAST(
long long,
l), matched);
2439 matched = (
v &
l) ==
l;
2443 "x) = %d",
CAST(
unsigned long long,
v),
2444 CAST(
unsigned long long,
l),
2445 CAST(
unsigned long long,
l),
2450 matched = (
v &
l) !=
l;
2454 "x) = %d",
CAST(
unsigned long long,
v),
2455 CAST(
unsigned long long,
l),
2456 CAST(
unsigned long long,
l), matched);
file_protected void file_showstr(FILE *fp, const char *s, size_t len)
file_protected size_t file_pstring_length_size(struct magic_set *ms, const struct magic *m)
file_protected uint64_t file_signextend(struct magic_set *ms, struct magic *m, uint64_t v)
file_protected int file_magicfind(struct magic_set *ms, const char *name, struct mlist *v)
file_protected size_t file_pstring_get_length(struct magic_set *ms, const struct magic *m, const char *ss)
file_protected size_t file_magic_strength(const struct magic *m, size_t nmagic __attribute__((__unused__)))
fprintf($stream, string $format, mixed ... $values)
file(string $filename, int $flags=0, $context=null)
copy(string $from, string $to, $context=null)
strstr(string $haystack, string $needle, bool $before_needle=false)
strcspn(string $string, string $characters, int $offset=0, ?int $length=null)
strchr(string $haystack, string $needle, bool $before_needle=false)
void buffer_fini(struct buffer *b)
int buffer_fill(const struct buffer *bb)
void buffer_init(struct buffer *b, int fd, const zend_stat_t *st, const void *data, size_t len)
int der_cmp(struct magic_set *ms, struct magic *m)
int32_t der_offs(struct magic_set *ms, struct magic *m, size_t nbytes)
dl(string $extension_filename)
memset(ptr, 0, type->size)
zend_ffi_ctype_name_buf buf
file_protected int file_printf(struct magic_set *, const char *,...) __attribute__((__format__(__printf__
#define INDIRECT_RELATIVE
#define STRING_IGNORE_CASE
file_protected char * file_strtrim(char *)
file_protected const char * file_fmttime(char *, size_t, uint16_t)
file_protected void file_protected void file_protected void file_protected void file_mdump(struct magic *)
#define STRING_COMPACT_WHITESPACE
#define IS_LIBMAGIC_STRING(t)
file_protected void file_protected void file_magerror(struct magic_set *, const char *,...) __attribute__((__format__(__printf__
#define STRING_COMPACT_OPTIONAL_WHITESPACE
file_protected const char * file_fmtnum(char *, size_t, const char *, int)
#define REGEX_OFFSET_START
file_protected const char * file_fmtdatetime(char *, size_t, uint64_t, int)
#define STRING_IGNORE_LOWERCASE
file_protected file_pushbuf_t * file_push_buffer(struct magic_set *)
file_protected void file_error(struct magic_set *, int, const char *,...) __attribute__((__format__(__printf__
file_protected int file_print_guid(char *, size_t, const uint64_t *)
file_protected char * file_printable(struct magic_set *, char *, size_t, const char *, size_t)
file_protected void file_oomem(struct magic_set *, size_t)
file_protected char * file_pop_buffer(struct magic_set *, file_pushbuf_t *)
file_protected int file_check_mem(struct magic_set *, unsigned int)
file_protected int file_protected int file_separator(struct magic_set *)
#define STRING_IGNORE_UPPERCASE
file_protected const char * file_fmtdate(char *, size_t, uint16_t)
unsigned const char * end
unsigned const char * text
PHP_JSON_API size_t int options
zend_string * convert_libmagic_pattern(const char *val, size_t len, uint32_t options)
#define PREG_OFFSET_CAPTURE
PHPAPI pcre2_match_context * php_pcre_mctx(void)
PHPAPI pcre2_code * php_pcre_pce_re(pcre_cache_entry *pce)
PHPAPI pcre2_match_data * php_pcre_create_match_data(uint32_t capture_count, pcre2_code *re)
PHPAPI pcre_cache_entry * pcre_get_compiled_regex_cache_ex(zend_string *regex, bool locale_aware)
PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, zend_string *subject_str, zval *return_value, zval *subpats, bool global, zend_long flags, zend_off_t start_offset)
PHPAPI pcre_cache_entry * pcre_get_compiled_regex_cache(zend_string *regex)
PHPAPI void php_pcre_free_match_data(pcre2_match_data *match_data)
struct _pcre_cache_entry pcre_cache_entry
file_private int print_sep(struct magic_set *, int)
file_private uint64_t file_strncmp(const char *s1, const char *s2, size_t len, size_t maxlen, uint32_t flags)
file_private int magiccheck(struct magic_set *, struct magic *)
file_private int handle_annotation(struct magic_set *, struct magic *, int)
file_private int do_ops(struct magic_set *ms, struct magic *m, uint32_t *rv, intmax_t lhs, intmax_t off)
file_private uint64_t file_strncmp16(const char *a, const char *b, size_t len, size_t maxlen, uint32_t flags)
file_private int msetoffset(struct magic_set *, struct magic *, struct buffer *, const struct buffer *, size_t, unsigned int)
#define PRINTER(value, format, stype, utype)
#define OFFSET_OOB(n, o, i)
file_private int cvt_16(union VALUETYPE *, const struct magic *)
file_private int cvt_32(union VALUETYPE *, const struct magic *)
file_private int save_cont(struct magic_set *ms, struct cont *c)
file_private int mcopy(struct magic_set *, union VALUETYPE *, int, int, const unsigned char *, uint32_t, size_t, struct magic *)
file_private int check_fmt(struct magic_set *ms, const char *fmt)
file_private int match(struct magic_set *, struct magic *, size_t, const struct buffer *, size_t, int, int, int, uint16_t *, uint16_t *, int *, int *, int *, int *, int *)
file_protected int file_softmagic(struct magic_set *ms, const struct buffer *b, uint16_t *indir_count, uint16_t *name_count, int mode, int text)
#define DO_CVT(fld, type)
#define DO_CVT2(fld, type)
file_private uint32_t cvt_id3(struct magic_set *ms, uint32_t v)
file_private int cvt_flip(int type, int flip)
file_private int cvt_float(union VALUETYPE *p, const struct magic *m)
file_private int mconvert(struct magic_set *, struct magic *, int)
file_private int cvt_double(union VALUETYPE *p, const struct magic *m)
file_private int cvt_64(union VALUETYPE *, const struct magic *)
file_private int moffset(struct magic_set *, struct magic *, const struct buffer *, int32_t *)
char * strndup(const char *, size_t)
file_private void mdebug(uint32_t, const char *, size_t)
file_private int cvt_8(union VALUETYPE *, const struct magic *)
file_private int mget(struct magic_set *, struct magic *, const struct buffer *, const unsigned char *, size_t, size_t, unsigned int, int, int, int, uint16_t *, uint16_t *, int *, int *, int *, int *, int *)
file_private void restore_cont(struct magic_set *ms, struct cont *c)
file_private int mprint(struct magic_set *, struct magic *)
struct magic_set::@064260247024367202255202336305226346003333017071 search
struct mlist * mlist[MAGIC_SETS]
#define estrndup(s, length)
define(string $constant_name, mixed $value, bool $case_insensitive=false)
zend_string_release_ex(func->internal_function.function_name, 0)
ZEND_API void(ZEND_FASTCALL *zend_touch_vm_stack_data)(void *vm_stack_data)
ZEND_API zval *ZEND_FASTCALL zend_hash_index_find(const HashTable *ht, zend_ulong h)
struct _zend_string zend_string
#define EXPECTED(condition)
#define ZSTR_INIT_LITERAL(s, persistent)
#define Z_ARRVAL_P(zval_p)
struct _zend_array HashTable
#define Z_STRLEN_P(zval_p)
ZEND_API void zval_ptr_dtor(zval *zval_ptr)