Browse Source

Upgraded the lib to use PHP memory allocation routines.

Fixed a crash caused by analysis of DEADJOE files
A little bit of CS inside libmagic
PECL
Ilia Alshanetsky 18 years ago
parent
commit
b805c7f8b7
  1. 181
      ext/fileinfo/libmagic/apprentice.c
  2. 21
      ext/fileinfo/libmagic/ascmagic.c
  3. 19
      ext/fileinfo/libmagic/compress.c
  4. 11
      ext/fileinfo/libmagic/config.h
  5. 481
      ext/fileinfo/libmagic/file.c
  6. 7
      ext/fileinfo/libmagic/file.h
  7. 48
      ext/fileinfo/libmagic/file_opts.h
  8. 48
      ext/fileinfo/libmagic/funcs.c
  9. 482
      ext/fileinfo/libmagic/getopt_long.c
  10. 39
      ext/fileinfo/libmagic/magic.c
  11. 14
      ext/fileinfo/libmagic/readelf.c
  12. 86
      ext/fileinfo/libmagic/softmagic.c

181
ext/fileinfo/libmagic/apprentice.c

@ -42,9 +42,6 @@
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/param.h>
#ifdef QUICK
#include <sys/mman.h>
#endif
#include <sys/types.h>
#include <dirent.h>
@ -124,42 +121,7 @@ private const char usg_hdr[] = "cont\toffset\ttype\topcode\tmask\tvalue\tdesc";
private const char mime_marker[] = "!:mime";
private const size_t mime_marker_len = sizeof(mime_marker) - 1;
#ifdef COMPILE_ONLY
int main(int, char *[]);
int
main(int argc, char *argv[])
{
int ret;
struct magic_set *ms;
char *progname;
if ((progname = strrchr(argv[0], '/')) != NULL)
progname++;
else
progname = argv[0];
if (argc != 2) {
(void)fprintf(stderr, "Usage: %s file\n", progname);
return 1;
}
if ((ms = magic_open(MAGIC_CHECK)) == NULL) {
(void)fprintf(stderr, "%s: %s\n", progname, strerror(errno));
return 1;
}
ret = magic_compile(ms, argv[1]) == -1 ? 1 : 0;
if (ret == 1)
(void)fprintf(stderr, "%s: %s\n", progname, magic_error(ms));
magic_close(ms);
return ret;
}
#endif /* COMPILE_ONLY */
#ifdef PHP_BUNDLE
#include "../data_file.c"
#endif
static const struct type_tbl_s {
const char name[16];
@ -269,7 +231,7 @@ apprentice_1(struct magic_set *ms, const char *fn, int action,
if (rv != 0)
return -1;
rv = apprentice_compile(ms, &magic, &nmagic, fn);
free(magic);
efree(magic);
return rv;
}
@ -289,11 +251,7 @@ apprentice_1(struct magic_set *ms, const char *fn, int action,
return -1;
}
if ((ml = malloc(sizeof(*ml))) == NULL) {
file_delmagic(magic, mapped, nmagic);
file_oomem(ms, sizeof(*ml));
return -1;
}
ml = emalloc(sizeof(*ml));
ml->magic = magic;
ml->nmagic = nmagic;
@ -314,23 +272,18 @@ file_delmagic(struct magic *p, int type, size_t entries)
if (p == NULL)
return;
switch (type) {
#ifdef PHP_BUNDLE
case 3:
/* Do nothing, it's part of the code segment */
break;
#endif
#ifdef QUICK
case 2:
p--;
(void)munmap((void *)p, sizeof(*p) * (entries + 1));
break;
#endif
case 1:
p--;
/*FALLTHROUGH*/
case 0:
free(p);
efree(p);
break;
default:
abort();
}
@ -349,30 +302,16 @@ file_apprentice(struct magic_set *ms, const char *fn, int action)
if (fn == NULL)
fn = getenv("MAGIC");
if (fn == NULL) {
#ifdef PHP_BUNDLE
if ((mlist = malloc(sizeof(*mlist))) == NULL) {
file_oomem(ms, sizeof(*mlist));
return NULL;
}
mlist = emalloc(sizeof(*mlist));
mlist->next = mlist->prev = mlist;
apprentice_1(ms, fn, action, mlist);
return mlist;
#else
fn = MAGIC;
#endif
}
if ((mfn = strdup(fn)) == NULL) {
file_oomem(ms, strlen(fn));
return NULL;
}
mfn = estrdup(fn);
fn = mfn;
if ((mlist = malloc(sizeof(*mlist))) == NULL) {
free(mfn);
file_oomem(ms, sizeof(*mlist));
return NULL;
}
mlist = emalloc(sizeof(*mlist));
mlist->next = mlist->prev = mlist;
while (fn) {
@ -386,13 +325,13 @@ file_apprentice(struct magic_set *ms, const char *fn, int action)
fn = p;
}
if (errs == -1) {
free(mfn);
free(mlist);
efree(mfn);
efree(mlist);
mlist = NULL;
file_error(ms, 0, "could not find any magic files!");
return NULL;
}
free(mfn);
efree(mfn);
return mlist;
}
@ -649,10 +588,7 @@ apprentice_load(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
ms->flags |= MAGIC_CHECK; /* Enable checks for parsed files */
maxmagic = MAXMAGIS;
if ((marray = calloc(maxmagic, sizeof(*marray))) == NULL) {
file_oomem(ms, maxmagic * sizeof(*marray));
return -1;
}
marray = ecalloc(maxmagic, sizeof(*marray));
marraycount = 0;
/* print silly verbose header for USG compat. */
@ -735,11 +671,7 @@ apprentice_load(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
for (i = 0; i < marraycount; i++)
mentrycount += marray[i].cont_count;
if ((*magicp = malloc(sizeof(**magicp) * mentrycount)) == NULL) {
file_oomem(ms, sizeof(**magicp) * mentrycount);
errs++;
goto out;
}
*magicp = emalloc(sizeof(**magicp) * mentrycount);
mentrycount = 0;
for (i = 0; i < marraycount; i++) {
@ -749,8 +681,8 @@ apprentice_load(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
}
out:
for (i = 0; i < marraycount; i++)
free(marray[i].mp);
free(marray);
efree(marray[i].mp);
efree(marray);
if (errs) {
*magicp = NULL;
*nmagicp = 0;
@ -823,9 +755,9 @@ file_signextend(struct magic_set *ms, struct magic *m, uint64_t v)
case FILE_DEFAULT:
break;
default:
if (ms->flags & MAGIC_CHECK)
file_magwarn(ms, "cannot happen: m->type=%d\n",
m->type);
if (ms->flags & MAGIC_CHECK) {
file_magwarn(ms, "cannot happen: m->type=%d\n", m->type);
}
return ~0U;
}
}
@ -1024,10 +956,7 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp,
if (me->cont_count == me->max_count) {
struct magic *nm;
size_t cnt = me->max_count + ALLOC_CHUNK;
if ((nm = realloc(me->mp, sizeof(*nm) * cnt)) == NULL) {
file_oomem(ms, sizeof(*nm) * cnt);
return -1;
}
nm = erealloc(me->mp, sizeof(*nm) * cnt);
me->mp = m = nm;
me->max_count = cnt;
}
@ -1039,21 +968,13 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp,
struct magic_entry *mp;
maxmagic += ALLOC_INCR;
if ((mp = realloc(*mentryp, sizeof(*mp) * maxmagic)) ==
NULL) {
file_oomem(ms, sizeof(*mp) * maxmagic);
return -1;
}
(void)memset(&mp[*nmentryp], 0, sizeof(*mp) *
ALLOC_INCR);
mp = erealloc(*mentryp, sizeof(*mp) * maxmagic);
(void)memset(&mp[*nmentryp], 0, sizeof(*mp) * ALLOC_INCR);
*mentryp = mp;
}
me = &(*mentryp)[*nmentryp];
if (me->mp == NULL) {
if ((m = malloc(sizeof(*m) * ALLOC_CHUNK)) == NULL) {
file_oomem(ms, sizeof(*m) * ALLOC_CHUNK);
return -1;
}
m = safe_emalloc(sizeof(*m), ALLOC_CHUNK, 0);
me->mp = m;
me->max_count = ALLOC_CHUNK;
} else
@ -1908,13 +1829,11 @@ apprentice_map(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
void *mm = NULL;
int ret = 0;
#ifdef PHP_BUNDLE
if (fn == NULL) {
mm = &php_magic_database;
ret = 3;
goto internal_loaded;
}
#endif
mkdbname(fn, &dbname, 0);
if (dbname == NULL)
@ -1932,29 +1851,18 @@ apprentice_map(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
goto error1;
}
#ifdef QUICK
if ((mm = mmap(0, (size_t)st.st_size, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_FILE, fd, (off_t)0)) == MAP_FAILED) {
file_error(ms, errno, "cannot map `%s'", dbname);
goto error1;
}
ret = 2;
#else
if ((mm = malloc((size_t)st.st_size)) == NULL) {
file_oomem(ms, (size_t)st.st_size);
goto error1;
}
mm = emalloc((size_t)st.st_size);
if (read(fd, mm, (size_t)st.st_size) != (size_t)st.st_size) {
file_badread(ms);
goto error1;
}
ret = 1;
#endif
(void)close(fd);
fd = -1;
#ifdef PHP_BUNDLE
internal_loaded:
#endif
*magicp = mm;
ptr = (uint32_t *)(void *)*magicp;
if (*ptr != MAGICNO) {
@ -1975,35 +1883,36 @@ internal_loaded:
VERSIONNO, dbname, version);
goto error1;
}
#ifdef PHP_BUNDLE
if (fn == NULL)
if (fn == NULL) {
*nmagicp = (sizeof(php_magic_database) / sizeof(struct magic));
else /* the statement after the #endif is used */
#endif
*nmagicp = (uint32_t)(st.st_size / sizeof(struct magic));
if (*nmagicp > 0)
} else {
*nmagicp = (uint32_t)(st.st_size / sizeof(struct magic));
}
if (*nmagicp > 0) {
(*nmagicp)--;
}
(*magicp)++;
if (needsbyteswap)
if (needsbyteswap) {
byteswap(*magicp, *nmagicp);
free(dbname);
}
if (dbname) {
efree(dbname);
}
return ret;
error1:
if (fd != -1)
(void)close(fd);
if (mm) {
#ifdef QUICK
(void)munmap((void *)mm, (size_t)st.st_size);
#else
free(mm);
#endif
efree(mm);
} else {
*magicp = NULL;
*nmagicp = 0;
}
error2:
free(dbname);
efree(dbname);
return -1;
}
@ -2051,7 +1960,7 @@ apprentice_compile(struct magic_set *ms, struct magic **magicp,
(void)close(fd);
rv = 0;
out:
free(dbname);
efree(dbname);
return rv;
}
@ -2068,9 +1977,9 @@ mkdbname(const char *fn, char **buf, int strip)
fn = ++p;
}
(void)asprintf(buf, "%s%s", fn, ext);
(void)spprintf(buf, 0, "%s%s", fn, ext);
if (*buf && strlen(*buf) > MAXPATHLEN) {
free(*buf);
efree(*buf);
*buf = NULL;
}
}

21
ext/fileinfo/libmagic/ascmagic.c

@ -101,13 +101,12 @@ file_ascmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes)
* Undo the NUL-termination kindly provided by process()
* but leave at least one byte to look at
*/
while (nbytes > 1 && buf[nbytes - 1] == '\0')
while (nbytes > 1 && buf[nbytes - 1] == '\0') {
nbytes--;
}
if ((nbuf = calloc(1, (nbytes + 1) * sizeof(nbuf[0]))) == NULL)
goto done;
if ((ubuf = calloc(1, (nbytes + 1) * sizeof(ubuf[0]))) == NULL)
goto done;
nbuf = ecalloc(1, (nbytes + 1) * sizeof(nbuf[0]));
ubuf = ecalloc(1, (nbytes + 1) * sizeof(ubuf[0]));
/*
* Then try to determine whether it's any character code we can
@ -172,10 +171,8 @@ file_ascmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes)
re-converting improved, or at least realloced after
re-converting conversion. */
mlen = ulen * 6;
if ((utf8_buf = malloc(mlen)) == NULL) {
file_oomem(ms, mlen);
goto done;
}
utf8_buf = emalloc(mlen);
if ((utf8_end = encode_utf8(utf8_buf, mlen, ubuf, ulen)) == NULL)
goto done;
if (file_softmagic(ms, utf8_buf, utf8_end - utf8_buf, TEXTTEST) != 0) {
@ -348,11 +345,11 @@ subtype_identified:
rv = 1;
done:
if (nbuf)
free(nbuf);
efree(nbuf);
if (ubuf)
free(ubuf);
efree(ubuf);
if (utf8_buf)
free(utf8_buf);
efree(utf8_buf);
return rv;
}

19
ext/fileinfo/libmagic/compress.c

@ -32,6 +32,7 @@
* uncompress(method, old, n, newch) - uncompress old into new,
* using method, return sizeof new
*/
#include "config.h"
#include "file.h"
#include "magic.h"
#include <stdio.h>
@ -133,7 +134,7 @@ file_zmagic(struct magic_set *ms, int fd, const char *name,
}
error:
if (newbuf)
free(newbuf);
efree(newbuf);
ms->flags |= MAGIC_COMPRESS;
return rv;
}
@ -330,9 +331,7 @@ uncompressgzipped(struct magic_set *ms, const unsigned char *old,
if (data_start >= n)
return 0;
if ((*newch = (unsigned char *)malloc(HOWMANY + 1)) == NULL) {
return 0;
}
*newch = (unsigned char *)emalloc(HOWMANY + 1));
/* XXX: const castaway, via strchr */
z.next_in = (Bytef *)strchr((const char *)old + data_start,
@ -455,20 +454,14 @@ uncompressbuf(struct magic_set *ms, int fd, size_t method,
fdin[1] = -1;
}
if ((*newch = (unsigned char *) malloc(HOWMANY + 1)) == NULL) {
#ifdef DEBUG
(void)fprintf(stderr, "Malloc failed (%s)\n",
strerror(errno));
#endif
n = 0;
goto err;
}
*newch = (unsigned char *) emalloc(HOWMANY + 1);
if ((r = sread(fdout[0], *newch, HOWMANY, 0)) <= 0) {
#ifdef DEBUG
(void)fprintf(stderr, "Read failed (%s)\n",
strerror(errno));
#endif
free(*newch);
efree(*newch);
n = 0;
newch[0] = '\0';
goto err;

11
ext/fileinfo/libmagic/config.h

@ -1,10 +1 @@
#ifdef PHP_WIN32
# include "config.w32.h"
#else
# include <php_config.h>
#endif
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#define PHP_BUNDLE
#include "php.h"

481
ext/fileinfo/libmagic/file.c

@ -1,481 +0,0 @@
/*
* Copyright (c) Ian F. Darwin 1986-1995.
* Software written by Ian F. Darwin and others;
* maintained 1995-present by Christos Zoulas and others.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice immediately at the beginning of the file, without modification,
* this list of conditions, and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* file - find type of a file or files - main program.
*/
#include "file.h"
#include "magic.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/param.h> /* for MAXPATHLEN */
#include <sys/stat.h>
#ifdef RESTORE_TIME
# if (__COHERENT__ >= 0x420)
# include <sys/utime.h>
# else
# ifdef USE_UTIMES
# include <sys/time.h>
# else
# include <utime.h>
# endif
# endif
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* for read() */
#endif
#ifdef HAVE_LOCALE_H
#include <locale.h>
#endif
#ifdef HAVE_WCHAR_H
#include <wchar.h>
#endif
#include <getopt.h>
#ifndef HAVE_GETOPT_LONG
int getopt_long(int argc, char * const *argv, const char *optstring, const struct option *longopts, int *longindex);
#endif
#include <netinet/in.h> /* for byte swapping */
#include "patchlevel.h"
#ifndef lint
FILE_RCSID("@(#)$File: file.c,v 1.119 2008/02/07 00:58:52 christos Exp $")
#endif /* lint */
#ifdef S_IFLNK
#define SYMLINKFLAG "Lh"
#else
#define SYMLINKFLAG ""
#endif
# define USAGE "Usage: %s [-bcik" SYMLINKFLAG "nNrsvz0] [-e test] [-f namefile] [-F separator] [-m magicfiles] file...\n %s -C -m magicfiles\n"
#ifndef MAXPATHLEN
#define MAXPATHLEN 512
#endif
private int /* Global command-line options */
bflag = 0, /* brief output format */
nopad = 0, /* Don't pad output */
nobuffer = 0, /* Do not buffer stdout */
nulsep = 0; /* Append '\0' to the separator */
private const char *magicfile = 0; /* where the magic is */
private const char *default_magicfile = MAGIC;
private const char *separator = ":"; /* Default field separator */
private char *progname; /* used throughout */
private struct magic_set *magic;
private void unwrap(char *);
private void usage(void);
private void help(void);
int main(int, char *[]);
private void process(const char *, int);
private void load(const char *, int);
/*
* main - parse arguments and handle options
*/
int
main(int argc, char *argv[])
{
int c;
size_t i;
int action = 0, didsomefiles = 0, errflg = 0;
int flags = 0;
char *home, *usermagic;
struct stat sb;
static const char hmagic[] = "/.magic";
#define OPTSTRING "bcCde:f:F:hikLm:nNprsvz0"
int longindex;
static const struct option long_options[] =
{
#define OPT(shortname, longname, opt, doc) \
{longname, opt, NULL, shortname},
#define OPT_LONGONLY(longname, opt, doc) \
{longname, opt, NULL, 0},
#include "file_opts.h"
#undef OPT
#undef OPT_LONGONLY
{0, 0, NULL, 0}
};
static const struct {
const char *name;
int value;
} nv[] = {
{ "apptype", MAGIC_NO_CHECK_APPTYPE },
{ "ascii", MAGIC_NO_CHECK_ASCII },
{ "compress", MAGIC_NO_CHECK_COMPRESS },
{ "elf", MAGIC_NO_CHECK_ELF },
{ "soft", MAGIC_NO_CHECK_SOFT },
{ "tar", MAGIC_NO_CHECK_TAR },
{ "tokens", MAGIC_NO_CHECK_TOKENS },
};
/* makes islower etc work for other langs */
(void)setlocale(LC_CTYPE, "");
#ifdef __EMX__
/* sh-like wildcard expansion! Shouldn't hurt at least ... */
_wildcard(&argc, &argv);
#endif
if ((progname = strrchr(argv[0], '/')) != NULL)
progname++;
else
progname = argv[0];
magicfile = default_magicfile;
if ((usermagic = getenv("MAGIC")) != NULL)
magicfile = usermagic;
else
if ((home = getenv("HOME")) != NULL) {
if ((usermagic = malloc(strlen(home)
+ sizeof(hmagic))) != NULL) {
(void)strcpy(usermagic, home);
(void)strcat(usermagic, hmagic);
if (stat(usermagic, &sb)<0)
free(usermagic);
else
magicfile = usermagic;
}
}
#ifdef S_IFLNK
flags |= getenv("POSIXLY_CORRECT") ? MAGIC_SYMLINK : 0;
#endif
while ((c = getopt_long(argc, argv, OPTSTRING, long_options,
&longindex)) != -1)
switch (c) {
case 0 :
switch (longindex) {
case 0:
help();
break;
case 10:
flags |= MAGIC_MIME_TYPE;
break;
case 11:
flags |= MAGIC_MIME_ENCODING;
break;
}
break;
case '0':
nulsep = 1;
break;
case 'b':
bflag++;
break;
case 'c':
action = FILE_CHECK;
break;
case 'C':
action = FILE_COMPILE;
break;
case 'd':
flags |= MAGIC_DEBUG|MAGIC_CHECK;
break;
case 'e':
for (i = 0; i < sizeof(nv) / sizeof(nv[0]); i++)
if (strcmp(nv[i].name, optarg) == 0)
break;
if (i == sizeof(nv) / sizeof(nv[0]))
errflg++;
else
flags |= nv[i].value;
break;
case 'f':
if(action)
usage();
load(magicfile, flags);
unwrap(optarg);
++didsomefiles;
break;
case 'F':
separator = optarg;
break;
case 'i':
flags |= MAGIC_MIME;
break;
case 'k':
flags |= MAGIC_CONTINUE;
break;
case 'm':
magicfile = optarg;
break;
case 'n':
++nobuffer;
break;
case 'N':
++nopad;
break;
#if defined(HAVE_UTIME) || defined(HAVE_UTIMES)
case 'p':
flags |= MAGIC_PRESERVE_ATIME;
break;
#endif
case 'r':
flags |= MAGIC_RAW;
break;
case 's':
flags |= MAGIC_DEVICES;
break;
case 'v':
(void)fprintf(stderr, "%s-%d.%.2d\n", progname,
FILE_VERSION_MAJOR, patchlevel);
(void)fprintf(stderr, "magic file from %s\n",
magicfile);
return 1;
case 'z':
flags |= MAGIC_COMPRESS;
break;
#ifdef S_IFLNK
case 'L':
flags |= MAGIC_SYMLINK;
break;
case 'h':
flags &= ~MAGIC_SYMLINK;
break;
#endif
case '?':
default:
errflg++;
break;
}
if (errflg) {
usage();
}
switch(action) {
case FILE_CHECK:
case FILE_COMPILE:
magic = magic_open(flags|MAGIC_CHECK);
if (magic == NULL) {
(void)fprintf(stderr, "%s: %s\n", progname,
strerror(errno));
return 1;
}
c = action == FILE_CHECK ? magic_check(magic, magicfile) :
magic_compile(magic, magicfile);
if (c == -1) {
(void)fprintf(stderr, "%s: %s\n", progname,
magic_error(magic));
return -1;
}
return 0;
default:
load(magicfile, flags);
break;
}
if (optind == argc) {
if (!didsomefiles) {
usage();
}
}
else {
size_t j, wid, nw;
for (wid = 0, j = (size_t)optind; j < (size_t)argc; j++) {
nw = file_mbswidth(argv[j]);
if (nw > wid)
wid = nw;
}
/*
* If bflag is only set twice, set it depending on
* number of files [this is undocumented, and subject to change]
*/
if (bflag == 2) {
bflag = optind >= argc - 1;
}
for (; optind < argc; optind++)
process(argv[optind], wid);
}
c = magic->haderr ? 1 : 0;
magic_close(magic);
return c;
}
private void
/*ARGSUSED*/
load(const char *m, int flags)
{
if (magic || m == NULL)
return;
magic = magic_open(flags);
if (magic == NULL) {
(void)fprintf(stderr, "%s: %s\n", progname, strerror(errno));
exit(1);
}
if (magic_load(magic, magicfile) == -1) {
(void)fprintf(stderr, "%s: %s\n",
progname, magic_error(magic));
exit(1);
}
}
/*
* unwrap -- read a file of filenames, do each one.
*/
private void
unwrap(char *fn)
{
char buf[MAXPATHLEN];
FILE *f;
int wid = 0, cwid;
if (strcmp("-", fn) == 0) {
f = stdin;
wid = 1;
} else {
if ((f = fopen(fn, "r")) == NULL) {
(void)fprintf(stderr, "%s: Cannot open `%s' (%s).\n",
progname, fn, strerror(errno));
exit(1);
}
while (fgets(buf, MAXPATHLEN, f) != NULL) {
buf[strcspn(buf, "\n")] = '\0';
cwid = file_mbswidth(buf);
if (cwid > wid)
wid = cwid;
}
rewind(f);
}
while (fgets(buf, sizeof(buf), f) != NULL) {
buf[strcspn(buf, "\n")] = '\0';
process(buf, wid);
if(nobuffer)
(void)fflush(stdout);
}
(void)fclose(f);
}
/*
* Called for each input file on the command line (or in a list of files)
*/
private void
process(const char *inname, int wid)
{
const char *type;
int std_in = strcmp(inname, "-") == 0;
if (wid > 0 && !bflag) {
(void)printf("%s", std_in ? "/dev/stdin" : inname);
if (nulsep)
(void)putc('\0', stdout);
else
(void)printf("%s", separator);
(void)printf("%*s ",
(int) (nopad ? 0 : (wid - file_mbswidth(inname))), "");
}
type = magic_file(magic, std_in ? NULL : inname);
if (type == NULL)
(void)printf("ERROR: %s\n", magic_error(magic));
else
(void)printf("%s\n", type);
}
size_t
file_mbswidth(const char *s)
{
#if defined(HAVE_WCHAR_H) && defined(HAVE_MBRTOWC) && defined(HAVE_WCWIDTH)
size_t bytesconsumed, old_n, n, width = 0;
mbstate_t state;
wchar_t nextchar;
(void)memset(&state, 0, sizeof(mbstate_t));
old_n = n = strlen(s);
while (n > 0) {
bytesconsumed = mbrtowc(&nextchar, s, n, &state);
if (bytesconsumed == (size_t)(-1) ||
bytesconsumed == (size_t)(-2)) {
/* Something went wrong, return something reasonable */
return old_n;
}
if (s[0] == '\n') {
/*
* do what strlen() would do, so that caller
* is always right
*/
width++;
} else
width += wcwidth(nextchar);
s += bytesconsumed, n -= bytesconsumed;
}
return width;
#else
return strlen(s);
#endif
}
private void
usage(void)
{
(void)fprintf(stderr, USAGE, progname, progname);
(void)fputs("Try `file --help' for more information.\n", stderr);
exit(1);
}
private void
help(void)
{
(void)fputs(
"Usage: file [OPTION...] [FILE...]\n"
"Determine type of FILEs.\n"
"\n", stderr);
#define OPT(shortname, longname, opt, doc) \
fprintf(stderr, " -%c, --" longname doc, shortname);
#define OPT_LONGONLY(longname, opt, doc) \
fprintf(stderr, " --" longname doc);
#include "file_opts.h"
#undef OPT
#undef OPT_LONGONLY
exit(0);
}

7
ext/fileinfo/libmagic/file.h

@ -366,13 +366,6 @@ extern char *sys_errlist[];
#define strtoul(a, b, c) strtol(a, b, c)
#endif
#ifndef HAVE_VASPRINTF
int vasprintf(char **ptr, const char *format_string, va_list vargs);
#endif
#ifndef HAVE_ASPRINTF
int asprintf(char **ptr, const char *format_string, ...);
#endif
#if defined(HAVE_MMAP) && defined(HAVE_SYS_MMAN_H) && !defined(QUICK)
#define QUICK
#endif

48
ext/fileinfo/libmagic/file_opts.h

@ -1,48 +0,0 @@
/*
* Table of command-line options
*
* The first column specifies the short name, if any, or 0 if none.
* The second column specifies the long name.
* The third column specifies whether it takes a parameter.
* The fourth column is the documentation.
*
* N.B. The long options' order must correspond to the code in file.c,
* and OPTSTRING must be kept up-to-date with the short options.
* Pay particular attention to the numbers of long-only options in the
* switch statement!
*/
OPT_LONGONLY("help", 0, " display this help and exit\n")
OPT('v', "version", 0, " output version information and exit\n")
OPT('m', "magic-file", 1, " LIST use LIST as a colon-separated list of magic\n"
" number files\n")
OPT('z', "uncompress", 0, " try to look inside compressed files\n")
OPT('b', "brief", 0, " do not prepend filenames to output lines\n")
OPT('c', "checking-printout", 0, " print the parsed form of the magic file, use in\n"
" conjunction with -m to debug a new magic file\n"
" before installing it\n")
OPT('e', "exclude", 1, " TEST exclude TEST from the list of test to be\n"
" performed for file. Valid tests are:\n"
" ascii, apptype, compress, elf, soft, tar, tokens, troff\n")
OPT('f', "files-from", 1, " FILE read the filenames to be examined from FILE\n")
OPT('F', "separator", 1, " STRING use string as separator instead of `:'\n")
OPT('i', "mime", 0, " output MIME type strings (--mime-type and\n"
" --mime-encoding)\n")
OPT_LONGONLY("mime-type", 0, " output the MIME type\n")
OPT_LONGONLY("mime-encoding", 0, " output the MIME encoding\n")
OPT('k', "keep-going", 0, " don't stop at the first match\n")
#ifdef S_IFLNK
OPT('L', "dereference", 0, " follow symlinks (default)\n")
OPT('h', "no-dereference", 0, " don't follow symlinks\n")
#endif
OPT('n', "no-buffer", 0, " do not buffer output\n")
OPT('N', "no-pad", 0, " do not pad output\n")
OPT('0', "print0", 0, " terminate filenames with ASCII NUL\n")
#if defined(HAVE_UTIME) || defined(HAVE_UTIMES)
OPT('p', "preserve-date", 0, " preserve access times on files\n")
#endif
OPT('r', "raw", 0, " don't translate unprintable chars to \\ooo\n")
OPT('s', "special-files", 0, " treat special (block/char devices) files as\n"
" ordinary ones\n")
OPT('C', "compile", 0, " compile file specified by -m\n")
OPT('d', "debug", 0, " print debugging messages\n")

48
ext/fileinfo/libmagic/funcs.c

@ -54,27 +54,23 @@ file_printf(struct magic_set *ms, const char *fmt, ...)
va_list ap;
size_t size;
int len;
char *buf, *newstr;
char *buf = NULL, *newstr;
va_start(ap, fmt);
len = vasprintf(&buf, fmt, ap);
if (len < 0)
goto out;
len = vspprintf(&buf, 0, fmt, ap);
va_end(ap);
if (ms->o.buf != NULL) {
len = asprintf(&newstr, "%s%s", ms->o.buf, buf);
free(buf);
if (len < 0)
goto out;
free(ms->o.buf);
buf = newstr;
len = spprintf(&newstr, 0, "%s%s", ms->o.buf, (buf ? buf : ""));
if (buf) {
efree(buf);
}
efree(ms->o.buf);
ms->o.buf = newstr;
} else {
ms->o.buf = buf;
}
ms->o.buf = buf;
return 0;
out:
file_error(ms, errno, "vasprintf failed");
return -1;
}
/*
@ -89,7 +85,7 @@ file_error_core(struct magic_set *ms, int error, const char *f, va_list va,
if (ms->haderr)
return;
if (lineno != 0) {
free(ms->o.buf);
efree(ms->o.buf);
ms->o.buf = NULL;
file_printf(ms, "line %u: ", lineno);
}
@ -123,12 +119,6 @@ file_magerror(struct magic_set *ms, const char *f, ...)
va_end(va);
}
protected void
file_oomem(struct magic_set *ms, size_t len)
{
file_error(ms, errno, "cannot allocate %zu bytes", len);
}
protected void
file_badseek(struct magic_set *ms)
{
@ -223,6 +213,9 @@ file_reset(struct magic_set *ms)
file_error(ms, 0, "no magic files loaded");
return -1;
}
if (ms->o.buf) {
efree(ms->o.buf);
}
ms->o.buf = NULL;
ms->haderr = 0;
ms->error = -1;
@ -252,14 +245,10 @@ file_getbuffer(struct magic_set *ms)
/* * 4 is for octal representation, + 1 is for NUL */
len = strlen(ms->o.buf);
if (len > (SIZE_MAX - 1) / 4) {
file_oomem(ms, len);
return NULL;
}
psize = len * 4 + 1;
if ((pbuf = realloc(ms->o.pbuf, psize)) == NULL) {
file_oomem(ms, psize);
return NULL;
}
pbuf = erealloc(ms->o.pbuf, psize);
ms->o.pbuf = pbuf;
#if defined(HAVE_WCHAR_H) && defined(HAVE_MBRTOWC) && defined(HAVE_WCWIDTH)
@ -319,12 +308,7 @@ file_check_mem(struct magic_set *ms, unsigned int level)
if (level >= ms->c.len) {
len = (ms->c.len += 20) * sizeof(*ms->c.li);
ms->c.li = (ms->c.li == NULL) ? malloc(len) :
realloc(ms->c.li, len);
if (ms->c.li == NULL) {
file_oomem(ms, len);
return -1;
}
ms->c.li = (ms->c.li == NULL) ? emalloc(len) : erealloc(ms->c.li, len);
}
ms->c.li[level].got_match = 0;
#ifdef ENABLE_CONDITIONALS

482
ext/fileinfo/libmagic/getopt_long.c

@ -1,482 +0,0 @@
/* $NetBSD: getopt_long.c,v 1.21.4.1 2008/01/09 01:34:14 matt Exp $ */
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Dieter Baron and Thomas Klausner.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
#include <err.h>
#include <errno.h>
#include <getopt.h>
#include <stdlib.h>
#include <string.h>
#define REPLACE_GETOPT
#define _DIAGASSERT assert
#ifdef REPLACE_GETOPT
#ifdef __weak_alias
__weak_alias(getopt,_getopt)
#endif
int opterr = 1; /* if error message should be printed */
int optind = 1; /* index into parent argv vector */
int optopt = '?'; /* character checked for validity */
int optreset; /* reset getopt */
char *optarg; /* argument associated with option */
#elif HAVE_NBTOOL_CONFIG_H && !HAVE_DECL_OPTRESET
static int optreset;
#endif
#ifdef __weak_alias
__weak_alias(getopt_long,_getopt_long)
#endif
#define IGNORE_FIRST (*options == '-' || *options == '+')
#define PRINT_ERROR ((opterr) && ((*options != ':') \
|| (IGNORE_FIRST && options[1] != ':')))
#define IS_POSIXLY_CORRECT (getenv("POSIXLY_CORRECT") != NULL)
#define PERMUTE (!IS_POSIXLY_CORRECT && !IGNORE_FIRST)
/* XXX: GNU ignores PC if *options == '-' */
#define IN_ORDER (!IS_POSIXLY_CORRECT && *options == '-')
/* return values */
#define BADCH (int)'?'
#define BADARG ((IGNORE_FIRST && options[1] == ':') \
|| (*options == ':') ? (int)':' : (int)'?')
#define INORDER (int)1
#define EMSG ""
static int getopt_internal __P((int, char **, const char *));
static int gcd __P((int, int));
static void permute_args __P((int, int, int, char **));
static const char *place = EMSG; /* option letter processing */
/* XXX: set optreset to 1 rather than these two */
static int nonopt_start = -1; /* first non option argument (for permute) */
static int nonopt_end = -1; /* first option after non options (for permute) */
/* Error messages */
static const char recargchar[] = "option requires an argument -- %c";
static const char recargstring[] = "option requires an argument -- %s";
static const char ambig[] = "ambiguous option -- %.*s";
static const char noarg[] = "option doesn't take an argument -- %.*s";
static const char illoptchar[] = "unknown option -- %c";
static const char illoptstring[] = "unknown option -- %s";
/*
* Compute the greatest common divisor of a and b.
*/
static int
gcd(a, b)
int a;
int b;
{
int c;
c = a % b;
while (c != 0) {
a = b;
b = c;
c = a % b;
}
return b;
}
/*
* Exchange the block from nonopt_start to nonopt_end with the block
* from nonopt_end to opt_end (keeping the same order of arguments
* in each block).
*/
static void
permute_args(panonopt_start, panonopt_end, opt_end, nargv)
int panonopt_start;
int panonopt_end;
int opt_end;
char **nargv;
{
int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
char *swap;
_DIAGASSERT(nargv != NULL);
/*
* compute lengths of blocks and number and size of cycles
*/
nnonopts = panonopt_end - panonopt_start;
nopts = opt_end - panonopt_end;
ncycle = gcd(nnonopts, nopts);
cyclelen = (opt_end - panonopt_start) / ncycle;
for (i = 0; i < ncycle; i++) {
cstart = panonopt_end+i;
pos = cstart;
for (j = 0; j < cyclelen; j++) {
if (pos >= panonopt_end)
pos -= nnonopts;
else
pos += nopts;
swap = nargv[pos];
nargv[pos] = nargv[cstart];
nargv[cstart] = swap;
}
}
}
/*
* getopt_internal --
* Parse argc/argv argument vector. Called by user level routines.
* Returns -2 if -- is found (can be long option or end of options marker).
*/
static int
getopt_internal(nargc, nargv, options)
int nargc;
char **nargv;
const char *options;
{
char *oli; /* option letter list index */
int optchar;
_DIAGASSERT(nargv != NULL);
_DIAGASSERT(options != NULL);
optarg = NULL;
/*
* XXX Some programs (like rsyncd) expect to be able to
* XXX re-initialize optind to 0 and have getopt_long(3)
* XXX properly function again. Work around this braindamage.
*/
if (optind == 0)
optind = 1;
if (optreset)
nonopt_start = nonopt_end = -1;
start:
if (optreset || !*place) { /* update scanning pointer */
optreset = 0;
if (optind >= nargc) { /* end of argument vector */
place = EMSG;
if (nonopt_end != -1) {
/* do permutation, if we have to */
permute_args(nonopt_start, nonopt_end,
optind, nargv);
optind -= nonopt_end - nonopt_start;
}
else if (nonopt_start != -1) {
/*
* If we skipped non-options, set optind
* to the first of them.
*/
optind = nonopt_start;
}
nonopt_start = nonopt_end = -1;
return -1;
}
if ((*(place = nargv[optind]) != '-')
|| (place[1] == '\0')) { /* found non-option */
place = EMSG;
if (IN_ORDER) {
/*
* GNU extension:
* return non-option as argument to option 1
*/
optarg = nargv[optind++];
return INORDER;
}
if (!PERMUTE) {
/*
* if no permutation wanted, stop parsing
* at first non-option
*/
return -1;
}
/* do permutation */
if (nonopt_start == -1)
nonopt_start = optind;
else if (nonopt_end != -1) {
permute_args(nonopt_start, nonopt_end,
optind, nargv);
nonopt_start = optind -
(nonopt_end - nonopt_start);
nonopt_end = -1;
}
optind++;
/* process next argument */
goto start;
}
if (nonopt_start != -1 && nonopt_end == -1)
nonopt_end = optind;
if (place[1] && *++place == '-') { /* found "--" */
place++;
return -2;
}
}
if ((optchar = (int)*place++) == (int)':' ||
(oli = strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) {
/* option letter unknown or ':' */
if (!*place)
++optind;
if (PRINT_ERROR)
warnx(illoptchar, optchar);
optopt = optchar;
return BADCH;
}
if (optchar == 'W' && oli[1] == ';') { /* -W long-option */
/* XXX: what if no long options provided (called by getopt)? */
if (*place)
return -2;
if (++optind >= nargc) { /* no arg */
place = EMSG;
if (PRINT_ERROR)
warnx(recargchar, optchar);
optopt = optchar;
return BADARG;
} else /* white space */
place = nargv[optind];
/*
* Handle -W arg the same as --arg (which causes getopt to
* stop parsing).
*/
return -2;
}
if (*++oli != ':') { /* doesn't take argument */
if (!*place)
++optind;
} else { /* takes (optional) argument */
optarg = NULL;
if (*place) /* no white space */
optarg = (char *)place;
/* XXX: disable test for :: if PC? (GNU doesn't) */
else if (oli[1] != ':') { /* arg not optional */
if (++optind >= nargc) { /* no arg */
place = EMSG;
if (PRINT_ERROR)
warnx(recargchar, optchar);
optopt = optchar;
return BADARG;
} else
optarg = nargv[optind];
}
place = EMSG;
++optind;
}
/* dump back option letter */
return optchar;
}
#ifdef REPLACE_GETOPT
/*
* getopt --
* Parse argc/argv argument vector.
*
* [eventually this will replace the real getopt]
*/
int
getopt(nargc, nargv, options)
int nargc;
char * const *nargv;
const char *options;
{
int retval;
_DIAGASSERT(nargv != NULL);
_DIAGASSERT(options != NULL);
retval = getopt_internal(nargc, (char **)nargv, options);
if (retval == -2) {
++optind;
/*
* We found an option (--), so if we skipped non-options,
* we have to permute.
*/
if (nonopt_end != -1) {
permute_args(nonopt_start, nonopt_end, optind,
(char **)nargv);
optind -= nonopt_end - nonopt_start;
}
nonopt_start = nonopt_end = -1;
retval = -1;
}
return retval;
}
#endif
/*
* getopt_long --
* Parse argc/argv argument vector.
*/
int
getopt_long(nargc, nargv, options, long_options, idx)
int nargc;
char * const *nargv;
const char *options;
const struct option *long_options;
int *idx;
{
int retval;
#define IDENTICAL_INTERPRETATION(_x, _y) \
(long_options[(_x)].has_arg == long_options[(_y)].has_arg && \
long_options[(_x)].flag == long_options[(_y)].flag && \
long_options[(_x)].val == long_options[(_y)].val)
_DIAGASSERT(nargv != NULL);
_DIAGASSERT(options != NULL);
_DIAGASSERT(long_options != NULL);
/* idx may be NULL */
retval = getopt_internal(nargc, (char **)nargv, options);
if (retval == -2) {
char *current_argv, *has_equal;
size_t current_argv_len;
int i, ambiguous, match;
current_argv = (char *)place;
match = -1;
ambiguous = 0;
optind++;
place = EMSG;
if (*current_argv == '\0') { /* found "--" */
/*
* We found an option (--), so if we skipped
* non-options, we have to permute.
*/
if (nonopt_end != -1) {
permute_args(nonopt_start, nonopt_end,
optind, (char **)nargv);
optind -= nonopt_end - nonopt_start;
}
nonopt_start = nonopt_end = -1;
return -1;
}
if ((has_equal = strchr(current_argv, '=')) != NULL) {
/* argument found (--option=arg) */
current_argv_len = has_equal - current_argv;
has_equal++;
} else
current_argv_len = strlen(current_argv);
for (i = 0; long_options[i].name; i++) {
/* find matching long option */
if (strncmp(current_argv, long_options[i].name,
current_argv_len))
continue;
if (strlen(long_options[i].name) ==
(unsigned)current_argv_len) {
/* exact match */
match = i;
ambiguous = 0;
break;
}
if (match == -1) /* partial match */
match = i;
else if (!IDENTICAL_INTERPRETATION(i, match))
ambiguous = 1;
}
if (ambiguous) {
/* ambiguous abbreviation */
if (PRINT_ERROR)
warnx(ambig, (int)current_argv_len,
current_argv);
optopt = 0;
return BADCH;
}
if (match != -1) { /* option found */
if (long_options[match].has_arg == no_argument
&& has_equal) {
if (PRINT_ERROR)
warnx(noarg, (int)current_argv_len,
current_argv);
/*
* XXX: GNU sets optopt to val regardless of
* flag
*/
if (long_options[match].flag == NULL)
optopt = long_options[match].val;
else
optopt = 0;
return BADARG;
}
if (long_options[match].has_arg == required_argument ||
long_options[match].has_arg == optional_argument) {
if (has_equal)
optarg = has_equal;
else if (long_options[match].has_arg ==
required_argument) {
/*
* optional argument doesn't use
* next nargv
*/
optarg = nargv[optind++];
}
}
if ((long_options[match].has_arg == required_argument)
&& (optarg == NULL)) {
/*
* Missing argument; leading ':'
* indicates no error should be generated
*/
if (PRINT_ERROR)
warnx(recargstring, current_argv);
/*
* XXX: GNU sets optopt to val regardless
* of flag
*/
if (long_options[match].flag == NULL)
optopt = long_options[match].val;
else
optopt = 0;
--optind;
return BADARG;
}
} else { /* unknown option */
if (PRINT_ERROR)
warnx(illoptstring, current_argv);
optopt = 0;
return BADCH;
}
if (long_options[match].flag) {
*long_options[match].flag = long_options[match].val;
retval = 0;
} else
retval = long_options[match].val;
if (idx)
*idx = match;
}
return retval;
#undef IDENTICAL_INTERPRETATION
}

39
ext/fileinfo/libmagic/magic.c

@ -35,9 +35,6 @@
#include <sys/types.h>
#include <sys/param.h> /* for MAXPATHLEN */
#include <sys/stat.h>
#ifdef QUICK
#include <sys/mman.h>
#endif
#include <limits.h> /* for PIPE_BUF */
#if defined(HAVE_UTIMES)
@ -98,8 +95,7 @@ magic_open(int flags)
{
struct magic_set *ms;
if ((ms = calloc((size_t)1, sizeof(struct magic_set))) == NULL)
return NULL;
ms = ecalloc((size_t)1, sizeof(struct magic_set));
if (magic_setflags(ms, flags) == -1) {
errno = EINVAL;
@ -108,9 +104,7 @@ magic_open(int flags)
ms->o.buf = ms->o.pbuf = NULL;
ms->c.li = malloc((ms->c.len = 10) * sizeof(*ms->c.li));
if (ms->c.li == NULL)
goto free;
ms->c.li = emalloc((ms->c.len = 10) * sizeof(*ms->c.li));
ms->haderr = 0;
ms->error = -1;
@ -119,7 +113,7 @@ magic_open(int flags)
ms->line = 0;
return ms;
free:
free(ms);
efree(ms);
return NULL;
}
@ -135,10 +129,10 @@ free_mlist(struct mlist *mlist)
struct mlist *next = ml->next;
struct magic *mg = ml->magic;
file_delmagic(mg, ml->mapped, ml->nmagic);
free(ml);
efree(ml);
ml = next;
}
free(ml);
efree(ml);
}
private int
@ -162,11 +156,19 @@ info_from_stat(struct magic_set *ms, mode_t md)
public void
magic_close(struct magic_set *ms)
{
free_mlist(ms->mlist);
free(ms->o.pbuf);
free(ms->o.buf);
free(ms->c.li);
free(ms);
if (ms->mlist) {
free_mlist(ms->mlist);
}
if (ms->o.pbuf) {
efree(ms->o.pbuf);
}
if (ms->o.buf) {
efree(ms->o.buf);
}
if (ms->c.li) {
efree(ms->c.li);
}
efree(ms);
}
/*
@ -267,8 +269,7 @@ file_or_fd(struct magic_set *ms, const char *inname, int fd)
* some overlapping space for matches near EOF
*/
#define SLOP (1 + sizeof(union VALUETYPE))
if ((buf = malloc(HOWMANY + SLOP)) == NULL)
return NULL;
buf = emalloc(HOWMANY + SLOP);
if (file_reset(ms) == -1)
goto done;
@ -351,7 +352,7 @@ file_or_fd(struct magic_set *ms, const char *inname, int fd)
goto done;
rv = 0;
done:
free(buf);
efree(buf);
close_and_restore(ms, inname, fd, &sb);
return rv == 0 ? file_getbuffer(ms) : NULL;
}

14
ext/fileinfo/libmagic/readelf.c

@ -789,20 +789,16 @@ doshn(struct magic_set *ms, int class, int swap, int fd, off_t off, int num,
file_badread(ms);
return -1;
}
if ((nbuf = malloc((size_t)xsh_size)) == NULL) {
file_error(ms, errno, "Cannot allocate memory"
" for note");
return -1;
}
nbuf = emalloc((size_t)xsh_size);
if ((noff = lseek(fd, (off_t)xsh_offset, SEEK_SET)) ==
(off_t)-1) {
file_badread(ms);
free(nbuf);
efree(nbuf);
return -1;
}
if (read(fd, nbuf, (size_t)xsh_size) !=
(ssize_t)xsh_size) {
free(nbuf);
efree(nbuf);
file_badread(ms);
return -1;
}
@ -818,11 +814,11 @@ doshn(struct magic_set *ms, int class, int swap, int fd, off_t off, int num,
break;
}
if ((lseek(fd, off, SEEK_SET)) == (off_t)-1) {
free(nbuf);
efree(nbuf);
file_badread(ms);
return -1;
}
free(nbuf);
efree(nbuf);
break;
}
}

86
ext/fileinfo/libmagic/softmagic.c

@ -127,9 +127,9 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
if ((m->flag & BINTEST) != mode) {
/* Skip sub-tests */
while (magic[magindex + 1].cont_level != 0 &&
++magindex < nmagic)
while (magic[magindex + 1].cont_level != 0 && ++magindex < nmagic) {
continue;
}
continue; /* Skip to next top-level test*/
}
@ -157,9 +157,9 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
* main entry didn't match,
* flush its continuations
*/
while (magindex < nmagic - 1 &&
magic[magindex + 1].cont_level != 0)
while (magindex < nmagic - 1 && magic[magindex + 1].cont_level != 0) {
magindex++;
}
continue;
}
@ -197,8 +197,7 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
}
ms->offset = m->offset;
if (m->flag & OFFADD) {
ms->offset +=
ms->c.li[cont_level - 1].off;
ms->offset += ms->c.li[cont_level - 1].off;
}
#ifdef ENABLE_CONDITIONALS
@ -282,11 +281,12 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
private int
check_fmt(struct magic_set *ms, struct magic *m)
{
regex_t rx;
regex_t rx = {0};
int rc;
if (strchr(MAGIC_DESC, '%') == NULL)
if (strchr(MAGIC_DESC, '%') == NULL) {
return 0;
}
rc = regcomp(&rx, "%[-0-9\\.]*s", REG_EXTENDED|REG_NOSUB);
if (rc) {
@ -295,32 +295,14 @@ check_fmt(struct magic_set *ms, struct magic *m)
file_magerror(ms, "regex error %d, (%s)", rc, errmsg);
return -1;
} else {
rc = regexec(&rx, MAGIC_DESC, 0, 0, 0);
regmatch_t *pmatch = (regmatch_t *)ecalloc(sizeof(regmatch_t), rx.re_nsub + 1);
rc = regexec(&rx, MAGIC_DESC, rx.re_nsub + 1, pmatch, 0);
efree(pmatch);
regfree(&rx);
return !rc;
}
}
#ifndef HAVE_STRNDUP
char * strndup(const char *, size_t);
char *
strndup(const char *str, size_t n)
{
size_t len;
char *copy;
len = strlen(str);
if (len > n)
len = n;
if (!(copy = malloc(len + 1)))
return (NULL);
(void) memcpy(copy, str, len + 1);
copy[len] = '\0';
return (copy);
}
#endif /* HAVE_STRNDUP */
private int32_t
mprint(struct magic_set *ms, struct magic *m)
{
@ -338,7 +320,7 @@ mprint(struct magic_set *ms, struct magic *m)
case -1:
return -1;
case 1:
if (asprintf(&buf, "%c", (unsigned char)v) < 0)
if (spprintf(&buf, 0, "%c", (unsigned char)v) < 0)
return -1;
if (file_printf(ms, MAGIC_DESC, buf) == -1)
return -1;
@ -359,7 +341,7 @@ mprint(struct magic_set *ms, struct magic *m)
case -1:
return -1;
case 1:
if (asprintf(&buf, "%hu", (unsigned short)v) < 0)
if (spprintf(&buf, 0, "%hu", (unsigned short)v) < 0)
return -1;
if (file_printf(ms, MAGIC_DESC, buf) == -1)
return -1;
@ -381,7 +363,7 @@ mprint(struct magic_set *ms, struct magic *m)
case -1:
return -1;
case 1:
if (asprintf(&buf, "%u", (uint32_t)v) < 0)
if (spprintf(&buf, 0, "%u", (uint32_t)v) < 0)
return -1;
if (file_printf(ms, MAGIC_DESC, buf) == -1)
return -1;
@ -467,7 +449,7 @@ mprint(struct magic_set *ms, struct magic *m)
case -1:
return -1;
case 1:
if (asprintf(&buf, "%g", vf) < 0)
if (spprintf(&buf, 0, "%g", vf) < 0)
return -1;
if (file_printf(ms, MAGIC_DESC, buf) == -1)
return -1;
@ -488,7 +470,7 @@ mprint(struct magic_set *ms, struct magic *m)
case -1:
return -1;
case 1:
if (asprintf(&buf, "%g", vd) < 0)
if (spprintf(&buf, 0, "%g", vd) < 0)
return -1;
if (file_printf(ms, MAGIC_DESC, buf) == -1)
return -1;
@ -505,13 +487,10 @@ mprint(struct magic_set *ms, struct magic *m)
char *cp;
int rval;
cp = strndup((const char *)ms->search.s, ms->search.rm_len);
if (cp == NULL) {
file_oomem(ms, ms->search.rm_len);
return -1;
}
cp = estrndup((const char *)ms->search.s, ms->search.rm_len);
rval = file_printf(ms, MAGIC_DESC, cp);
free(cp);
efree(cp);
if (rval == -1)
return -1;
@ -1665,24 +1644,20 @@ magiccheck(struct magic_set *ms, struct magic *m)
}
case FILE_REGEX: {
int rc;
regex_t rx;
regex_t rx = {0};
char errmsg[512];
if (ms->search.s == NULL)
return 0;
l = 0;
rc = regcomp(&rx, m->value.s,
REG_EXTENDED|REG_NEWLINE|
((m->str_flags & STRING_IGNORE_CASE) ? REG_ICASE : 0));
rc = regcomp(&rx, m->value.s, REG_EXTENDED|REG_NEWLINE|((m->str_flags & STRING_IGNORE_CASE) ? REG_ICASE : 0));
if (rc) {
(void)regerror(rc, &rx, errmsg, sizeof(errmsg));
file_magerror(ms, "regex error %d, (%s)",
rc, errmsg);
file_magerror(ms, "regex error %d, (%s)", rc, errmsg);
v = (uint64_t)-1;
}
else {
regmatch_t pmatch[1];
} else {
regmatch_t *pmatch = (regmatch_t *)ecalloc(sizeof(regmatch_t), rx.re_nsub + 1);
#ifndef REG_STARTEND
#define REG_STARTEND 0
size_t l = ms->search.s_len - 1;
@ -1692,8 +1667,7 @@ magiccheck(struct magic_set *ms, struct magic *m)
pmatch[0].rm_so = 0;
pmatch[0].rm_eo = ms->search.s_len;
#endif
rc = regexec(&rx, (const char *)ms->search.s,
1, pmatch, REG_STARTEND);
rc = regexec(&rx, (const char *)ms->search.s, 1, pmatch, REG_STARTEND);
#if REG_STARTEND == 0
((char *)(intptr_t)ms->search.s)[l] = c;
#endif
@ -1701,8 +1675,7 @@ magiccheck(struct magic_set *ms, struct magic *m)
case 0:
ms->search.s += (int)pmatch[0].rm_so;
ms->search.offset += (size_t)pmatch[0].rm_so;
ms->search.rm_len =
(size_t)(pmatch[0].rm_eo - pmatch[0].rm_so);
ms->search.rm_len = (size_t)(pmatch[0].rm_eo - pmatch[0].rm_so);
v = 0;
break;
@ -1712,15 +1685,16 @@ magiccheck(struct magic_set *ms, struct magic *m)
default:
(void)regerror(rc, &rx, errmsg, sizeof(errmsg));
file_magerror(ms, "regexec error %d, (%s)",
rc, errmsg);
file_magerror(ms, "regexec error %d, (%s)", rc, errmsg);
v = (uint64_t)-1;
break;
}
regfree(&rx);
efree(pmatch);
}
if (v == (uint64_t)-1)
if (v == (uint64_t)-1) {
return -1;
}
break;
}
default:

Loading…
Cancel
Save