diff options
author | Charles Longeau <chl@cvs.openbsd.org> | 2008-05-08 01:40:58 +0000 |
---|---|---|
committer | Charles Longeau <chl@cvs.openbsd.org> | 2008-05-08 01:40:58 +0000 |
commit | 05744bdb96c275f787205ebc59751a053e00bb05 (patch) | |
tree | 9b49fbdec84cb9e5d1af212de09a450cfee68aa0 /usr.bin/file/funcs.c | |
parent | 6b48017a29bf2d49da78618c15452a73b5327e04 (diff) |
Update file to 4.21.
tested by ian@ sthen@
OK ian@, "move ahead with it" deraadt@
Diffstat (limited to 'usr.bin/file/funcs.c')
-rw-r--r-- | usr.bin/file/funcs.c | 238 |
1 files changed, 205 insertions, 33 deletions
diff --git a/usr.bin/file/funcs.c b/usr.bin/file/funcs.c index 0a37f4a97fc..7b8fdb182fa 100644 --- a/usr.bin/file/funcs.c +++ b/usr.bin/file/funcs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: funcs.c,v 1.4 2007/07/09 16:39:48 dim Exp $ */ +/* $OpenBSD: funcs.c,v 1.5 2008/05/08 01:40:56 chl Exp $ */ /* * Copyright (c) Christos Zoulas 2003. * All Rights Reserved. @@ -12,8 +12,6 @@ * 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. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -29,16 +27,35 @@ */ #include "file.h" #include "magic.h" -#include <limits.h> #include <stdarg.h> -#include <stddef.h> #include <stdlib.h> #include <string.h> #include <ctype.h> +#if defined(HAVE_WCHAR_H) +#include <wchar.h> +#endif +#if defined(HAVE_WCTYPE_H) +#include <wctype.h> +#endif +#if defined(HAVE_LIMITS_H) +#include <limits.h> +#endif +#ifndef SIZE_T_MAX +#ifdef __LP64__ +#define SIZE_T_MAX (size_t)0xfffffffffffffffffU +#else +#define SIZE_T_MAX (size_t)0xffffffffU +#endif +#endif #ifndef lint -FILE_RCSID("@(#)$Id: funcs.c,v 1.4 2007/07/09 16:39:48 dim Exp $") +FILE_RCSID("@(#)$Id: funcs.c,v 1.5 2008/05/08 01:40:56 chl Exp $") #endif /* lint */ + +#ifndef HAVE_VSNPRINTF +int vsnprintf(char *, size_t, const char *, va_list); +#endif + /* * Like printf, only we print to a buffer and advance it. */ @@ -46,10 +63,8 @@ protected int file_printf(struct magic_set *ms, const char *fmt, ...) { va_list ap; - int len; - size_t size; + size_t len, size; char *buf; - ptrdiff_t diff; va_start(ap, fmt); @@ -58,10 +73,12 @@ file_printf(struct magic_set *ms, const char *fmt, ...) file_error(ms, errno, "vsnprintf failed"); return -1; } else if (len >= ms->o.left) { + long diff; /* XXX: really ptrdiff_t */ + va_end(ap); size = (ms->o.size - ms->o.left) + len + 1024; if ((buf = realloc(ms->o.buf, size)) == NULL) { - file_oomem(ms); + file_oomem(ms, size); return -1; } diff = ms->o.ptr - ms->o.buf; @@ -77,9 +94,9 @@ file_printf(struct magic_set *ms, const char *fmt, ...) return -1; } } + va_end(ap); ms->o.ptr += len; ms->o.left -= len; - va_end(ap); return 0; } @@ -87,18 +104,22 @@ file_printf(struct magic_set *ms, const char *fmt, ...) * error - print best error message possible */ /*VARARGS*/ -protected void -file_error(struct magic_set *ms, int error, const char *f, ...) +private void +file_error_core(struct magic_set *ms, int error, const char *f, va_list va, + uint32_t lineno) { - va_list va; + size_t len; /* Only the first error is ok */ if (ms->haderr) return; - va_start(va, f); - (void)vsnprintf(ms->o.buf, ms->o.size, f, va); - va_end(va); + len = 0; + if (lineno != 0) { + (void)snprintf(ms->o.buf, ms->o.size, "line %u: ", lineno); + len = strlen(ms->o.buf); + } + (void)vsnprintf(ms->o.buf + len, ms->o.size - len, f, va); if (error > 0) { - size_t len = strlen(ms->o.buf); + len = strlen(ms->o.buf); (void)snprintf(ms->o.buf + len, ms->o.size - len, " (%s)", strerror(error)); } @@ -106,11 +127,33 @@ file_error(struct magic_set *ms, int error, const char *f, ...) ms->error = error; } +/*VARARGS*/ +protected void +file_error(struct magic_set *ms, int error, const char *f, ...) +{ + va_list va; + va_start(va, f); + file_error_core(ms, error, f, va, 0); + va_end(va); +} + +/* + * Print an error with magic line number. + */ +/*VARARGS*/ +protected void +file_magerror(struct magic_set *ms, const char *f, ...) +{ + va_list va; + va_start(va, f); + file_error_core(ms, 0, f, va, ms->line); + va_end(va); +} protected void -file_oomem(struct magic_set *ms) +file_oomem(struct magic_set *ms, size_t len) { - file_error(ms, errno, "cannot allocate memory"); + file_error(ms, errno, "cannot allocate %zu bytes", len); } protected void @@ -125,29 +168,66 @@ file_badread(struct magic_set *ms) file_error(ms, errno, "error reading"); } +#ifndef COMPILE_ONLY protected int -file_buffer(struct magic_set *ms, const void *buf, size_t nb) +file_buffer(struct magic_set *ms, int fd, const char *inname, const void *buf, + size_t nb) { int m; + +#ifdef __EMX__ + if ((ms->flags & MAGIC_NO_CHECK_APPTYPE) == 0 && inname) { + switch (file_os2_apptype(ms, inname, buf, nb)) { + case -1: + return -1; + case 0: + break; + default: + return 1; + } + } +#endif + /* try compression stuff */ - if ((m = file_zmagic(ms, buf, nb)) == 0) { + if ((ms->flags & MAGIC_NO_CHECK_COMPRESS) != 0 || + (m = file_zmagic(ms, fd, inname, buf, nb)) == 0) { /* Check if we have a tar file */ - if ((m = file_is_tar(ms, buf, nb)) == 0) { + if ((ms->flags & MAGIC_NO_CHECK_TAR) != 0 || + (m = file_is_tar(ms, buf, nb)) == 0) { /* try tests in /etc/magic (or surrogate magic file) */ - if ((m = file_softmagic(ms, buf, nb)) == 0) { + if ((ms->flags & MAGIC_NO_CHECK_SOFT) != 0 || + (m = file_softmagic(ms, buf, nb)) == 0) { /* try known keywords, check whether it is ASCII */ - if ((m = file_ascmagic(ms, buf, nb)) == 0) { + if ((ms->flags & MAGIC_NO_CHECK_ASCII) != 0 || + (m = file_ascmagic(ms, buf, nb)) == 0) { /* abandon hope, all ye who remain here */ if (file_printf(ms, ms->flags & MAGIC_MIME ? - "application/octet-stream" : "data") == -1) + (nb ? "application/octet-stream" : + "application/empty") : + (nb ? "data" : + "empty")) == -1) return -1; m = 1; } } } } +#ifdef BUILTIN_ELF + if ((ms->flags & MAGIC_NO_CHECK_ELF) == 0 && m == 1 && nb > 5 && fd != -1) { + /* + * We matched something in the file, so this *might* + * be an ELF file, and the file is at least 5 bytes + * long, so if it's an ELF file it has at least one + * byte past the ELF magic number - try extracting + * information from the ELF headers that cannot easily + * be extracted with rules in the magic file. + */ + (void)file_tryelf(ms, fd, buf, nb); + } +#endif return m; } +#endif protected int file_reset(struct magic_set *ms) @@ -157,11 +237,20 @@ file_reset(struct magic_set *ms) return -1; } ms->o.ptr = ms->o.buf; + ms->o.left = ms->o.size; ms->haderr = 0; ms->error = -1; return 0; } +#define OCTALIFY(n, o) \ + /*LINTED*/ \ + (void)(*(n)++ = '\\', \ + *(n)++ = (((uint32_t)*(o) >> 6) & 3) + '0', \ + *(n)++ = (((uint32_t)*(o) >> 3) & 7) + '0', \ + *(n)++ = (((uint32_t)*(o) >> 0) & 7) + '0', \ + (o)++) + protected const char * file_getbuffer(struct magic_set *ms) { @@ -175,31 +264,114 @@ file_getbuffer(struct magic_set *ms) return ms->o.buf; len = ms->o.size - ms->o.left; + /* * 4 is for octal representation, + 1 is for NUL */ if (len > (SIZE_T_MAX - 1) / 4) { - file_oomem(ms); + file_oomem(ms, len); return NULL; } - /* * 4 is for octal representation, + 1 is for NUL */ psize = len * 4 + 1; if (ms->o.psize < psize) { if ((pbuf = realloc(ms->o.pbuf, psize)) == NULL) { - file_oomem(ms); + file_oomem(ms, psize); return NULL; } ms->o.psize = psize; ms->o.pbuf = pbuf; } +#if defined(HAVE_WCHAR_H) && defined(HAVE_MBRTOWC) && defined(HAVE_WCWIDTH) + { + mbstate_t state; + wchar_t nextchar; + int mb_conv = 1; + size_t bytesconsumed; + char *eop; + (void)memset(&state, 0, sizeof(mbstate_t)); + + np = ms->o.pbuf; + op = ms->o.buf; + eop = op + strlen(ms->o.buf); + + while (op < eop) { + bytesconsumed = mbrtowc(&nextchar, op, + (size_t)(eop - op), &state); + if (bytesconsumed == (size_t)(-1) || + bytesconsumed == (size_t)(-2)) { + mb_conv = 0; + break; + } + + if (iswprint(nextchar)) { + (void)memcpy(np, op, bytesconsumed); + op += bytesconsumed; + np += bytesconsumed; + } else { + while (bytesconsumed-- > 0) + OCTALIFY(np, op); + } + } + *np = '\0'; + + /* Parsing succeeded as a multi-byte sequence */ + if (mb_conv != 0) + return ms->o.pbuf; + } +#endif + for (np = ms->o.pbuf, op = ms->o.buf; *op; op++) { if (isprint((unsigned char)*op)) { *np++ = *op; } else { - *np++ = '\\'; - *np++ = ((*op >> 6) & 3) + '0'; - *np++ = ((*op >> 3) & 7) + '0'; - *np++ = ((*op >> 0) & 7) + '0'; + OCTALIFY(np, op); } } *np = '\0'; return ms->o.pbuf; } + +protected int +file_check_mem(struct magic_set *ms, unsigned int level) +{ + size_t len; + + 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[level].got_match = 0; +#ifdef ENABLE_CONDITIONALS + ms->c.li[level].last_match = 0; + ms->c.li[level].last_cond = COND_NONE; +#endif /* ENABLE_CONDITIONALS */ + return 0; +} +/* + * Yes these wrappers suffer from buffer overflows, but if your OS does not + * have the real functions, maybe you should consider replacing your OS? + */ +#ifndef HAVE_VSNPRINTF +int +vsnprintf(char *buf, size_t len, const char *fmt, va_list ap) +{ + return vsprintf(buf, fmt, ap); +} +#endif + +#ifndef HAVE_SNPRINTF +/*ARGSUSED*/ +int +snprintf(char *buf, size_t len, const char *fmt, ...) +{ + int rv; + va_list ap; + va_start(ap, fmt); + rv = vsprintf(buf, fmt, ap); + va_end(ap); + return rv; +} +#endif |