Add LZMA decompression for xar archives

remotes/push_mirror/0.98.1
Steve Morgan 12 years ago
parent 94b28c5989
commit 9b20264df9
  1. 134
      libclamav/xar.c

@ -29,7 +29,7 @@
#include <libxml/xmlreader.h>
#include "scanners.h"
#include "inflate64.h"
#include "7z_iface.h"
#include "lzma_iface.h"
/*
xar_cleanup_temp_file - cleanup after cli_gentempfd
@ -147,15 +147,15 @@ static int xar_get_toc_data_values(xmlTextReaderPtr reader, long *length, long *
} else {
if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) {
if (xmlStrEqual(name, (const xmlChar *)"data")) {
cli_dbgmsg("cli_scanxar: xmlTextReaderRead read %s\n", name);
cli_dbgmsg("cli_scanxar: xmlTextReaderRead read <data>\n");
indata = 1;
} else if (xmlStrEqual(name, (const xmlChar *)"ea")) {
cli_dbgmsg("cli_scanxar: xmlTextReaderRead read %s\n", name);
cli_dbgmsg("cli_scanxar: xmlTextReaderRead read <ea>\n");
inea = 1;
}
} else if ((xmlTextReaderNodeType(reader) == XML_READER_TYPE_END_ELEMENT) &&
xmlStrEqual(name, (const xmlChar *)"xar")) {
cli_dbgmsg("cli_scanxar: finished parsing xml TOC.\n");
cli_dbgmsg("cli_scanxar: finished parsing xar TOC.\n");
}
}
rc = xmlTextReaderRead(reader);
@ -254,10 +254,10 @@ int cli_scanxar(cli_ctx *ctx)
goto exit_toc;
}
/* cli_dbgmsg("cli_scanxar: TOC xml:\n%s\n", toc); */
/* printf("cli_scanxar: TOC xml:\n%s\n", toc); */
/* cli_dbgmsg("cli_scanxar: TOC end:\n"); */
/* printf("cli_scanxar: TOC end:\n"); */
/* cli_dbgmsg("cli_scanxar: TOC xml:\n%s\n", toc); */
/* printf("cli_scanxar: TOC xml:\n%s\n", toc); */
/* cli_dbgmsg("cli_scanxar: TOC end:\n"); */
/* printf("cli_scanxar: TOC end:\n"); */
/* scan the xml */
cli_dbgmsg("cli_scanxar: scanning xar TOC xml.\n");
@ -312,8 +312,9 @@ int cli_scanxar(cli_ctx *ctx)
goto exit_reader;
}
cli_dbgmsg("cli_scanxar: decompress and scanning heap offset %li len %li size %li\n",
offset, length, size);
cli_dbgmsg("cli_scanxar: decompress into temp file:\n%s, size %li,\n"
"from xar heap offset %li length %li\n",
tmpname, size, offset, length);
switch (encoding) {
case CL_TYPE_GZ:
@ -369,12 +370,113 @@ int cli_scanxar(cli_ctx *ctx)
inflateEnd(&strm);
break;
case CL_TYPE_7Z:
/*LZMA: TODO*/
/* this is broken, gives SZ_ERROR_NO_ARCHIVE: */
/* rc = cli_7unz(ctx, at); */
/* if (rc) { */
/* cli_errmsg("cli_scanrar: cli_7unz() fails: %i\n", rc); */
/* } */
{
#define CLI_LZMA_OBUF_SIZE 1024*1024
#define CLI_LZMA_HDR_SIZE LZMA_PROPS_SIZE+8
#define CLI_LZMA_CRATIO_SHIFT 2 /* estimated compression ratio 25% */
struct CLI_LZMA lz = {0};
unsigned long in_remaining = length;
unsigned long out_size = 0;
char * buff = __lzma_wrap_alloc(NULL, CLI_LZMA_OBUF_SIZE);
if (buff == NULL) {
cli_errmsg("cli_scanxar: memory request for lzma decompression buffer fails.\n");
rc = CL_EMEM;
goto exit_tmpfile;
}
blockp = (void*)fmap_need_off_once(map, at, CLI_LZMA_HDR_SIZE);
if (blockp == NULL) {
cli_errmsg("cli_scanxar: Can't read %li bytes @ %li, errno:%s.\n",
length, at, strerror(errno));
rc = CL_EREAD;
__lzma_wrap_free(NULL, buff);
goto exit_tmpfile;
}
lz.next_in = blockp;
lz.avail_in = CLI_LZMA_HDR_SIZE;
rc = cli_LzmaInit(&lz, 0);
if (rc != LZMA_RESULT_OK) {
cli_errmsg("cli_scanxar: cli_LzmaInit() fails: %i.\n", rc);
rc = CL_EFORMAT;
__lzma_wrap_free(NULL, buff);
goto exit_tmpfile;
}
at += CLI_LZMA_HDR_SIZE;
in_remaining -= CLI_LZMA_HDR_SIZE;
while (at < map->len && at < offset+hdr.toc_length_compressed+hdr.size+length) {
SizeT avail_in;
SizeT avail_out;
unsigned long in_consumed;
lz.next_out = buff;
lz.avail_out = CLI_LZMA_OBUF_SIZE;
lz.avail_in = avail_in = MIN(CLI_LZMA_OBUF_SIZE>>CLI_LZMA_CRATIO_SHIFT, in_remaining);
lz.next_in = (void*)fmap_need_off_once(map, at, lz.avail_in);
if (lz.next_in == NULL) {
cli_errmsg("cli_scanxar: Can't read %li bytes @ %li, errno: %s.\n",
length, at, strerror(errno));
rc = CL_EREAD;
__lzma_wrap_free(NULL, buff);
cli_LzmaShutdown(&lz);
goto exit_tmpfile;
}
rc = cli_LzmaDecode(&lz);
if (rc != LZMA_RESULT_OK && rc != LZMA_STREAM_END) {
cli_errmsg("cli_scanxar: cli_LzmaDecode() fails: %i.\n", rc);
rc = CL_EFORMAT;
__lzma_wrap_free(NULL, buff);
cli_LzmaShutdown(&lz);
goto exit_tmpfile;
}
in_consumed = avail_in - lz.avail_in;
in_remaining -= in_consumed;
at += in_consumed;
avail_out = CLI_LZMA_OBUF_SIZE - lz.avail_out;
if (avail_out == 0) {
cli_errmsg("cli_scanxar: cli_LzmaDecode() produces no output for "
"avail_in %lu, avail_out %lu.\n", avail_in, avail_out);
rc = CL_EFORMAT;
__lzma_wrap_free(NULL, buff);
cli_LzmaShutdown(&lz);
goto exit_tmpfile;
}
/* Write a decompressed block. */
cli_dbgmsg("Writing %li bytes to LZMA decompress temp file, "
"consumed %li of %li available bytes.\n",
avail_out, in_consumed, avail_in);
if (cli_writen(fd, buff, avail_out) < 0) {
cli_dbgmsg("cli_scanxar: cli_writen error writing lzma temp file for %li bytes.\n",
avail_out);
__lzma_wrap_free(NULL, buff);
cli_LzmaShutdown(&lz);
rc = CL_EWRITE;
goto exit_tmpfile;
}
/* Check file size limitation. */
out_size += avail_out;
if (cli_checklimits("cli_scanxar", ctx, out_size, 0, 0) != CL_CLEAN) {
break;
}
if (rc == LZMA_STREAM_END)
break;
}
cli_LzmaShutdown(&lz);
__lzma_wrap_free(NULL, buff);
}
break;
default:
case CL_TYPE_BZ:
case CL_TYPE_ANY:

Loading…
Cancel
Save