Add built-in zstd decompression support from Martin Rodriguez Reboredo.

While here, GC snprintf() and use makeerror() instead.
This commit is contained in:
Christos Zoulas 2022-09-14 14:37:07 +00:00
parent 011778a287
commit a8e7d84e16
2 changed files with 94 additions and 10 deletions

View File

@ -49,6 +49,11 @@ AC_ARG_ENABLE([xzlib],
[AS_HELP_STRING([--disable-xzlib], [disable liblzma/xz compression support @<:@default=auto@:>@])])
AC_MSG_RESULT($enable_xzlib)
AC_MSG_CHECKING(for zstdlib support)
AC_ARG_ENABLE([zstdlib],
[AS_HELP_STRING([--disable-zstdlib], [disable zstdlib compression support @<:@default=auto@:>@])])
AC_MSG_RESULT($enable_zstdlib)
AC_MSG_CHECKING(for libseccomp support)
AC_ARG_ENABLE([libseccomp],
[AS_HELP_STRING([--disable-libseccomp], [disable libseccomp sandboxing @<:@default=auto@:>@])])
@ -112,6 +117,9 @@ fi
if test "$enable_xzlib" != "no"; then
AC_CHECK_HEADERS(lzma.h)
fi
if test "$enable_zstdlib" != "no"; then
AC_CHECK_HEADERS(zstd.h zstd_errors.h)
fi
AC_CHECK_TYPE([sig_t],[AC_DEFINE([HAVE_SIG_T],1,[Have sig_t type])],,[#include <signal.h>])
dnl Checks for typedefs, structures, and compiler characteristics.
@ -180,6 +188,9 @@ fi
if test "$enable_xzlib" != "no"; then
AC_CHECK_LIB(lzma, lzma_stream_decoder)
fi
if test "$enable_zstdlib" != "no"; then
AC_CHECK_LIB(zstd, ZSTD_createDStream)
fi
if test "$enable_libseccomp" != "no"; then
AC_CHECK_LIB(seccomp, seccomp_init)
fi
@ -215,6 +226,14 @@ fi
if test "$ac_cv_header_lzma_h$ac_cv_lib_lzma_lzma_stream_decoder" = "yesyes"; then
AC_DEFINE([XZLIBSUPPORT], 1, [Enable xzlib compression support])
fi
if test "$enable_zstdlib" = "yes"; then
if test "$ac_cv_header_zstd_h$ac_cv_lib_zstd_ZSTD_createDStream" != "yesyes"; then
AC_MSG_ERROR([zstdlib support requested but not found])
fi
fi
if test "$ac_cv_header_zstd_h$ac_cv_lib_zstd_ZSTD_createDStream" = "yesyes"; then
AC_DEFINE([ZSTDLIBSUPPORT], 1, [Enable zstdlib compression support])
fi
AC_CONFIG_FILES([Makefile src/Makefile magic/Makefile tests/Makefile doc/Makefile python/Makefile libmagic.pc])
AC_OUTPUT

View File

@ -35,7 +35,7 @@
#include "file.h"
#ifndef lint
FILE_RCSID("@(#)$File: compress.c,v 1.136 2022/09/13 16:08:34 christos Exp $")
FILE_RCSID("@(#)$File: compress.c,v 1.137 2022/09/14 14:37:07 christos Exp $")
#endif
#include "magic.h"
@ -79,6 +79,12 @@ typedef void (*sig_t)(int);
#include <lzma.h>
#endif
#if defined(HAVE_ZSTD_H) && defined(ZSTDLIBSUPPORT)
#define BUILTIN_ZSTDLIB
#include <zstd.h>
#include <zstd_errors.h>
#endif
#ifdef DEBUG
int tty = -1;
#define DPRINTF(...) do { \
@ -175,6 +181,7 @@ private const struct {
#define METH_FROZEN 2
#define METH_BZIP 7
#define METH_XZ 9
#define METH_ZSTD 12
#define METH_LZMA 13
#define METH_ZLIB 14
{ { .magic = "\037\235" }, 2, gzip_args, NULL }, /* 0, compressed */
@ -223,6 +230,10 @@ private int uncompressbzlib(const unsigned char *, unsigned char **, size_t,
private int uncompressxzlib(const unsigned char *, unsigned char **, size_t,
size_t *);
#endif
#ifdef BUILTIN_ZSTDLIB
private int uncompresszstd(const unsigned char *, unsigned char **, size_t,
size_t *);
#endif
static int makeerror(unsigned char **, size_t *, const char *, ...)
__attribute__((__format__(__printf__, 3, 4)));
@ -608,9 +619,8 @@ uncompresszlib(const unsigned char *old, unsigned char **newch,
return OKDATA;
err:
strlcpy(RCAST(char *, *newch), z.msg ? z.msg : zError(rc), bytes_max);
*n = strlen(RCAST(char *, *newch));
return ERRDATA;
free(*newch);
return makeerror(newch, n, "%s", z.msg ? z.msg : zError(rc));
}
#endif
@ -651,9 +661,8 @@ uncompressbzlib(const unsigned char *old, unsigned char **newch,
return OKDATA;
err:
snprintf(RCAST(char *, *newch), bytes_max, "bunzip error %d", rc);
*n = strlen(RCAST(char *, *newch));
return ERRDATA;
free(*newch);
return makeerror(newch, n, "bunzip error %d", rc);
}
#endif
@ -691,9 +700,57 @@ uncompressxzlib(const unsigned char *old, unsigned char **newch,
return OKDATA;
err:
snprintf(RCAST(char *, *newch), bytes_max, "unxz error %d", rc);
*n = strlen(RCAST(char *, *newch));
return ERRDATA;
free(*newch);
return makeerror(newch, n, "unxz error %d", rc);
}
#endif
#ifdef BUILTIN_ZSTDLIB
private int
uncompresszstd(const unsigned char *old, unsigned char **newch,
size_t bytes_max, size_t *n)
{
size_t rc;
ZSTD_DStream *zstd;
ZSTD_inBuffer in;
ZSTD_outBuffer out;
if ((zstd = ZSTD_createDStream()) == NULL)
return makeerror(newch, n, "No ZSTD decompression stream, %s",
strerror(errno));
rc = ZSTD_DCtx_reset(zstd, ZSTD_reset_session_only);
if (ZSTD_isError(rc))
goto err;
if ((*newch = CAST(unsigned char *, malloc(bytes_max + 1))) == NULL) {
ZSTD_freeDStream(zstd);
return makeerror(newch, n, "No buffer, %s", strerror(errno));
}
in.src = CCAST(const void *, old);
in.size = *n;
in.pos = 0;
out.dst = RCAST(void *, *newch);
out.size = bytes_max;
out.pos = 0;
rc = ZSTD_decompressStream(zstd, &out, &in);
if (ZSTD_isError(rc))
goto err;
*n = out.pos;
ZSTD_freeDStream(zstd);
/* let's keep the nul-terminate tradition */
(*newch)[*n] = '\0';
return OKDATA;
err:
ZSTD_freeDStream(zstd);
free(*newch);
return makeerror(newch, n, "zstd error %d", ZSTD_getErrorCode(rc));
}
#endif
@ -863,6 +920,10 @@ methodname(size_t method)
case METH_XZ:
case METH_LZMA:
return "xzlib";
#endif
#ifdef BUILTIN_ZSTDLIB
case METH_ZSTD:
return "zstd";
#endif
default:
return compr[method].argv[0];
@ -899,6 +960,10 @@ uncompressbuf(int fd, size_t bytes_max, size_t method, const unsigned char *old,
case METH_XZ:
case METH_LZMA:
return uncompressxzlib(old, newch, bytes_max, n);
#endif
#ifdef BUILTIN_ZSTDLIB
case METH_ZSTD:
return uncompresszstd(old, newch, bytes_max, n);
#endif
default:
break;