|
|
|
@ -32,7 +32,15 @@ |
|
|
|
|
#ifdef HAVE_UNISTD_H |
|
|
|
|
#include <unistd.h> |
|
|
|
|
#endif |
|
|
|
|
#if HAVE_MMAP |
|
|
|
|
#ifdef HAVE_SYS_MMAN_H |
|
|
|
|
#include <sys/mman.h> |
|
|
|
|
#endif |
|
|
|
|
#endif /* HAVE_MMAP */ |
|
|
|
|
#if HAVE_STRING_H |
|
|
|
|
#include <string.h> |
|
|
|
|
#endif |
|
|
|
|
#include <limits.h> |
|
|
|
|
#include <strings.h> |
|
|
|
|
#include <zlib.h> |
|
|
|
|
|
|
|
|
@ -45,6 +53,10 @@ |
|
|
|
|
#define O_BINARY 0 |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#ifndef LONG_MAX |
|
|
|
|
#define LONG_MAX ((-1UL)>>1) |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#ifndef HAVE_ATTRIB_PACKED |
|
|
|
|
#define __attribute__(x) |
|
|
|
|
#endif |
|
|
|
@ -463,12 +475,20 @@ struct IS_HDR { |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define IS_FREE_HDR if(map) munmap(map, mp_hdrsz); else free(hdr); |
|
|
|
|
#if HAVE_MMAP |
|
|
|
|
#define IS_MAX_NOMAP_SZ 0x100000 |
|
|
|
|
#else |
|
|
|
|
#define IS_MAX_NOMAP_SZ CLI_MAX_ALLOCATION |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
/* Process data1.hdr and extracts all the available files from dataX.cab */ |
|
|
|
|
static int is_parse_hdr(int desc, cli_ctx *ctx, struct IS_CABSTUFF *c) {
|
|
|
|
|
uint32_t h1_data_off, objs_files_cnt, objs_dirs_off; |
|
|
|
|
unsigned int off, i, scanned = 0; |
|
|
|
|
int ret = CL_BREAK; |
|
|
|
|
char hash[33], *hdr; |
|
|
|
|
char hash[33], *hdr, *map = NULL; |
|
|
|
|
size_t mp_hdrsz; |
|
|
|
|
|
|
|
|
|
struct IS_HDR *h1; |
|
|
|
|
struct IS_OBJECTS *objs; |
|
|
|
@ -479,26 +499,41 @@ static int is_parse_hdr(int desc, cli_ctx *ctx, struct IS_CABSTUFF *c) { |
|
|
|
|
return CL_CLEAN; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if(!(hdr = (char *)cli_malloc(c->hdrsz))) /* FIXMEISHIELD: mmap if large */ |
|
|
|
|
return CL_EMEM; |
|
|
|
|
|
|
|
|
|
if(pread(desc, hdr, c->hdrsz, c->hdr) < (ssize_t)c->hdrsz) { |
|
|
|
|
cli_errmsg("is_parse_hdr: short read for header\n"); |
|
|
|
|
free(hdr); |
|
|
|
|
return CL_EREAD; /* hdr must be within bounds, it's k to hard fail here */ |
|
|
|
|
if(c->hdrsz < IS_MAX_NOMAP_SZ) { |
|
|
|
|
if(!(hdr = (char *)cli_malloc(c->hdrsz))) |
|
|
|
|
return CL_EMEM; |
|
|
|
|
if(pread(desc, hdr, c->hdrsz, c->hdr) < (ssize_t)c->hdrsz) { |
|
|
|
|
cli_errmsg("is_parse_hdr: short read for header\n"); |
|
|
|
|
free(hdr); |
|
|
|
|
return CL_EREAD; /* hdr must be within bounds, it's k to hard fail here */ |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
#if HAVE_MMAP |
|
|
|
|
int psz = getpagesize(); |
|
|
|
|
off_t mp_hdr = (c->hdr / psz) * psz; |
|
|
|
|
mp_hdrsz = c->hdrsz + c->hdr - mp_hdr; |
|
|
|
|
if((map = mmap(NULL, mp_hdrsz, PROT_READ, MAP_PRIVATE, desc, mp_hdr))==MAP_FAILED) { |
|
|
|
|
cli_errmsg("is_parse_hdr: mmap failed\n"); |
|
|
|
|
return CL_EMEM; |
|
|
|
|
} |
|
|
|
|
hdr = map + c->hdr - mp_hdr; |
|
|
|
|
#else |
|
|
|
|
cli_warnmsg("is_parse_hdr: hdr too big and mmap unavailable\n"); |
|
|
|
|
return CL_CLEAN |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
h1 = (struct IS_HDR *)hdr; |
|
|
|
|
if(!CLI_ISCONTAINED(hdr, c->hdrsz, ((char *)h1), sizeof(*h1))) { |
|
|
|
|
cli_dbgmsg("is_parse_hdr: not enough room for H1\n"); |
|
|
|
|
free(hdr); |
|
|
|
|
IS_FREE_HDR; |
|
|
|
|
return CL_CLEAN; |
|
|
|
|
} |
|
|
|
|
h1_data_off = le32_to_host(h1->data_off); |
|
|
|
|
objs = (struct IS_OBJECTS *)(hdr + h1_data_off); |
|
|
|
|
if(!CLI_ISCONTAINED(hdr, c->hdrsz, ((char *)objs), sizeof(*objs))) { |
|
|
|
|
cli_dbgmsg("is_parse_hdr: not enough room for OBJECTS\n"); |
|
|
|
|
free(hdr); |
|
|
|
|
IS_FREE_HDR; |
|
|
|
|
return CL_CLEAN; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -506,6 +541,7 @@ static int is_parse_hdr(int desc, cli_ctx *ctx, struct IS_CABSTUFF *c) { |
|
|
|
|
h1->magic, h1->unk1, h1->unk2, h1_data_off, h1->data_sz); |
|
|
|
|
if(le32_to_host(h1->magic) != 0x28635349) { |
|
|
|
|
cli_dbgmsg("is_parse_hdr: bad magic. wrong version?\n"); |
|
|
|
|
IS_FREE_HDR; |
|
|
|
|
return CL_CLEAN; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -602,6 +638,7 @@ static int is_parse_hdr(int desc, cli_ctx *ctx, struct IS_CABSTUFF *c) { |
|
|
|
|
scanned++; |
|
|
|
|
if (ctx->engine->maxfiles && scanned >= ctx->engine->maxfiles) { |
|
|
|
|
cli_dbgmsg("is_parse_hdr: File limit reached (max: %u)\n", ctx->engine->maxfiles); |
|
|
|
|
IS_FREE_HDR; |
|
|
|
|
return CL_EMAXFILES; |
|
|
|
|
} |
|
|
|
|
cabret = is_extract_cab(desc, ctx, file_stream_off + c->cabs[j].off, file_size, file_csize); |
|
|
|
@ -635,7 +672,7 @@ static int is_parse_hdr(int desc, cli_ctx *ctx, struct IS_CABSTUFF *c) { |
|
|
|
|
} |
|
|
|
|
off += sizeof(*file); |
|
|
|
|
} |
|
|
|
|
free(hdr); |
|
|
|
|
IS_FREE_HDR; |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -687,10 +724,17 @@ static int is_extract_cab(int desc, cli_ctx *ctx, uint64_t off, uint64_t size, u |
|
|
|
|
fclose(in); |
|
|
|
|
return CL_EMEM; |
|
|
|
|
} |
|
|
|
|
if(!(tempfile = cli_gentemp(ctx->engine->tmpdir))) return CL_EMEM; |
|
|
|
|
if(!(tempfile = cli_gentemp(ctx->engine->tmpdir))) { |
|
|
|
|
free(inbuf); |
|
|
|
|
free(outbuf); |
|
|
|
|
fclose(in); |
|
|
|
|
return CL_EMEM; |
|
|
|
|
} |
|
|
|
|
if((ofd = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRUSR|S_IWUSR)) < 0) { |
|
|
|
|
cli_errmsg("is_extract_cab: failed to create file %s\n", tempfile); |
|
|
|
|
free(tempfile); |
|
|
|
|
free(inbuf); |
|
|
|
|
free(outbuf); |
|
|
|
|
fclose(in); |
|
|
|
|
return CL_ECREAT; |
|
|
|
|
} |
|
|
|
@ -754,6 +798,8 @@ static int is_extract_cab(int desc, cli_ctx *ctx, uint64_t off, uint64_t size, u |
|
|
|
|
if(!success) break; |
|
|
|
|
} |
|
|
|
|
fclose(in); |
|
|
|
|
free(inbuf); |
|
|
|
|
free(outbuf); |
|
|
|
|
if(success) { |
|
|
|
|
if (outsz != size) |
|
|
|
|
cli_dbgmsg("is_extract_cab: extracted %llu bytes to %s, expected %llu, scanning anyway.\n", outsz, tempfile, size); |
|
|
|
|