mirror of
https://github.com/Cisco-Talos/clamav.git
synced 2025-10-19 18:33:16 +00:00
Fix fmap-duplicate performance issue
The fmap_duplicate function is used create a new fmap with a view into an existing fmap. When the new view is a different size than the old fmap, a new hash must be calculated for the duplicate fmap. However, when the duplicated fmap is the same size as the original fmap, the hash will be the same and there's no point recalculating. The issue is apparent when scanning large EXE files because the hash was being calculated at the beginning and end of the scan. Digging into this issue revealed that hash calculations for fmaps were also being performed at the wrong place. For scans of maps we use fmap_duplicate() early in the process to apply the name API argument to the duplicate fmap. Fixing the logic so we doing recalculate the hash revealed that we never calculated hashes for fmap's created from buffers in the first place, so that also had to be fixed be relocating where the hash is calculated. I also found that fmap_duplicate()'s offset argument used an off_t, though it and all caller offsets are not allowed to be negative. This was a bit of tangent to fix a bunch of off_t variables and paramters that should've been size_t. Added a couple unit tests to verify that making duplicate fmaps, and duplicate-duplicate fmaps works as expected after the change. Changed CLI_ISCONTAINED() and CLI_ISCONTAINED2() macros to cast to size_t, because pointers and buffer sizes may not be negative, and these two macros do not rely on substraction.
This commit is contained in:
parent
c40f03ade6
commit
e4e3149368
17 changed files with 423 additions and 125 deletions
|
@ -53,7 +53,7 @@ int cli_scanapm(cli_ctx *ctx)
|
||||||
struct apm_partition_info aptable, apentry;
|
struct apm_partition_info aptable, apentry;
|
||||||
int ret = CL_CLEAN, detection = CL_CLEAN, old_school = 0;
|
int ret = CL_CLEAN, detection = CL_CLEAN, old_school = 0;
|
||||||
size_t sectorsize, maplen, partsize;
|
size_t sectorsize, maplen, partsize;
|
||||||
off_t pos = 0, partoff = 0;
|
size_t pos = 0, partoff = 0;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
uint32_t max_prtns = 0;
|
uint32_t max_prtns = 0;
|
||||||
|
|
||||||
|
@ -219,8 +219,8 @@ int cli_scanapm(cli_ctx *ctx)
|
||||||
cli_dbgmsg("Type: %s\n", (char *)apentry.type);
|
cli_dbgmsg("Type: %s\n", (char *)apentry.type);
|
||||||
cli_dbgmsg("Signature: %x\n", apentry.signature);
|
cli_dbgmsg("Signature: %x\n", apentry.signature);
|
||||||
cli_dbgmsg("Partition Count: %u\n", apentry.numPartitions);
|
cli_dbgmsg("Partition Count: %u\n", apentry.numPartitions);
|
||||||
cli_dbgmsg("Blocks: [%u, +%u), ([%lu, +%lu))\n",
|
cli_dbgmsg("Blocks: [%u, +%u), ([%zu, +%zu))\n",
|
||||||
apentry.pBlockStart, apentry.pBlockCount, (long unsigned)partoff, (long unsigned)partsize);
|
apentry.pBlockStart, apentry.pBlockCount, partoff, partsize);
|
||||||
|
|
||||||
/* send the partition to cli_magic_scan_nested_fmap_type */
|
/* send the partition to cli_magic_scan_nested_fmap_type */
|
||||||
ret = cli_magic_scan_nested_fmap_type(*ctx->fmap, partoff, partsize, ctx, CL_TYPE_PART_ANY, (const char *)apentry.name);
|
ret = cli_magic_scan_nested_fmap_type(*ctx->fmap, partoff, partsize, ctx, CL_TYPE_PART_ANY, (const char *)apentry.name);
|
||||||
|
@ -245,7 +245,7 @@ static int apm_partition_intersection(cli_ctx *ctx, struct apm_partition_info *a
|
||||||
struct apm_partition_info apentry;
|
struct apm_partition_info apentry;
|
||||||
unsigned i, pitxn;
|
unsigned i, pitxn;
|
||||||
int ret = CL_CLEAN, tmp = CL_CLEAN;
|
int ret = CL_CLEAN, tmp = CL_CLEAN;
|
||||||
off_t pos;
|
size_t pos;
|
||||||
uint32_t max_prtns = 0;
|
uint32_t max_prtns = 0;
|
||||||
int virus_found = 0;
|
int virus_found = 0;
|
||||||
|
|
||||||
|
|
|
@ -103,7 +103,7 @@ int cli_scancpio_old(cli_ctx *ctx)
|
||||||
unsigned int file = 0, trailer = 0;
|
unsigned int file = 0, trailer = 0;
|
||||||
uint32_t filesize, namesize, hdr_namesize;
|
uint32_t filesize, namesize, hdr_namesize;
|
||||||
int ret = CL_CLEAN, conv;
|
int ret = CL_CLEAN, conv;
|
||||||
off_t pos = 0;
|
size_t pos = 0;
|
||||||
int virus_found = 0;
|
int virus_found = 0;
|
||||||
|
|
||||||
memset(name, 0, sizeof(name));
|
memset(name, 0, sizeof(name));
|
||||||
|
@ -195,7 +195,7 @@ int cli_scancpio_odc(cli_ctx *ctx)
|
||||||
unsigned int file = 0, trailer = 0;
|
unsigned int file = 0, trailer = 0;
|
||||||
uint32_t filesize, namesize, hdr_namesize;
|
uint32_t filesize, namesize, hdr_namesize;
|
||||||
int ret = CL_CLEAN;
|
int ret = CL_CLEAN;
|
||||||
off_t pos = 0;
|
size_t pos = 0;
|
||||||
int virus_found = 0;
|
int virus_found = 0;
|
||||||
|
|
||||||
while (fmap_readn(*ctx->fmap, &hdr_odc, pos, sizeof(hdr_odc)) == sizeof(hdr_odc)) {
|
while (fmap_readn(*ctx->fmap, &hdr_odc, pos, sizeof(hdr_odc)) == sizeof(hdr_odc)) {
|
||||||
|
@ -281,7 +281,7 @@ int cli_scancpio_newc(cli_ctx *ctx, int crc)
|
||||||
unsigned int file = 0, trailer = 0;
|
unsigned int file = 0, trailer = 0;
|
||||||
uint32_t filesize, namesize, hdr_namesize, pad;
|
uint32_t filesize, namesize, hdr_namesize, pad;
|
||||||
int ret = CL_CLEAN;
|
int ret = CL_CLEAN;
|
||||||
off_t pos = 0;
|
size_t pos = 0;
|
||||||
int virus_found = 0;
|
int virus_found = 0;
|
||||||
|
|
||||||
memset(name, 0, 513);
|
memset(name, 0, 513);
|
||||||
|
|
|
@ -97,7 +97,7 @@ int cli_scandmg(cli_ctx *ctx)
|
||||||
struct dmg_koly_block hdr;
|
struct dmg_koly_block hdr;
|
||||||
int ret;
|
int ret;
|
||||||
size_t maplen, nread;
|
size_t maplen, nread;
|
||||||
off_t pos = 0;
|
size_t pos = 0;
|
||||||
char *dirname;
|
char *dirname;
|
||||||
const char *outdata;
|
const char *outdata;
|
||||||
unsigned int file = 0;
|
unsigned int file = 0;
|
||||||
|
@ -114,11 +114,11 @@ int cli_scandmg(cli_ctx *ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
maplen = (*ctx->fmap)->real_len;
|
maplen = (*ctx->fmap)->real_len;
|
||||||
pos = maplen - 512;
|
if (maplen <= 512) {
|
||||||
if (pos <= 0) {
|
cli_dbgmsg("cli_scandmg: DMG smaller than DMG koly block!\n");
|
||||||
cli_dbgmsg("cli_scandmg: Sizing problem for DMG archive.\n");
|
|
||||||
return CL_CLEAN;
|
return CL_CLEAN;
|
||||||
}
|
}
|
||||||
|
pos = maplen - 512;
|
||||||
|
|
||||||
/* Grab koly block */
|
/* Grab koly block */
|
||||||
if (fmap_readn(*ctx->fmap, &hdr, pos, sizeof(hdr)) != sizeof(hdr)) {
|
if (fmap_readn(*ctx->fmap, &hdr, pos, sizeof(hdr)) != sizeof(hdr)) {
|
||||||
|
@ -129,7 +129,7 @@ int cli_scandmg(cli_ctx *ctx)
|
||||||
/* Check magic */
|
/* Check magic */
|
||||||
hdr.magic = be32_to_host(hdr.magic);
|
hdr.magic = be32_to_host(hdr.magic);
|
||||||
if (hdr.magic == 0x6b6f6c79) {
|
if (hdr.magic == 0x6b6f6c79) {
|
||||||
cli_dbgmsg("cli_scandmg: Found koly block @ %ld\n", (long)pos);
|
cli_dbgmsg("cli_scandmg: Found koly block @ %zu\n", pos);
|
||||||
} else {
|
} else {
|
||||||
cli_dbgmsg("cli_scandmg: No koly magic, %8x\n", hdr.magic);
|
cli_dbgmsg("cli_scandmg: No koly magic, %8x\n", hdr.magic);
|
||||||
return CL_EFORMAT;
|
return CL_EFORMAT;
|
||||||
|
@ -179,7 +179,7 @@ int cli_scandmg(cli_ctx *ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* scan XML with cli_magic_scan_nested_fmap_type */
|
/* scan XML with cli_magic_scan_nested_fmap_type */
|
||||||
ret = cli_magic_scan_nested_fmap_type(*ctx->fmap, (off_t)hdr.xmlOffset, (size_t)hdr.xmlLength, ctx, CL_TYPE_ANY, NULL);
|
ret = cli_magic_scan_nested_fmap_type(*ctx->fmap, (size_t)hdr.xmlOffset, (size_t)hdr.xmlLength, ctx, CL_TYPE_ANY, NULL);
|
||||||
if (ret != CL_CLEAN) {
|
if (ret != CL_CLEAN) {
|
||||||
cli_dbgmsg("cli_scandmg: retcode from scanning TOC xml: %s\n", cl_strerror(ret));
|
cli_dbgmsg("cli_scandmg: retcode from scanning TOC xml: %s\n", cl_strerror(ret));
|
||||||
if (!ctx->engine->keeptmp)
|
if (!ctx->engine->keeptmp)
|
||||||
|
@ -844,7 +844,7 @@ static int dmg_stripe_inflate(cli_ctx *ctx, int fd, uint32_t index, struct dmg_m
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strm.avail_out != sizeof(obuf)) {
|
if (strm.avail_out != sizeof(obuf)) {
|
||||||
if (cli_writen(fd, obuf, sizeof(obuf) - strm.avail_out) < 0) {
|
if (cli_writen(fd, obuf, sizeof(obuf) - strm.avail_out) == (size_t)-1) {
|
||||||
cli_errmsg("dmg_stripe_inflate: failed write to output file\n");
|
cli_errmsg("dmg_stripe_inflate: failed write to output file\n");
|
||||||
inflateEnd(&strm);
|
inflateEnd(&strm);
|
||||||
return CL_EWRITE;
|
return CL_EWRITE;
|
||||||
|
|
|
@ -112,7 +112,6 @@ fmap_t *fmap_check_empty(int fd, off_t offset, size_t len, int *empty, const cha
|
||||||
{
|
{
|
||||||
STATBUF st;
|
STATBUF st;
|
||||||
fmap_t *m = NULL;
|
fmap_t *m = NULL;
|
||||||
unsigned char hash[16] = {'\0'};
|
|
||||||
|
|
||||||
*empty = 0;
|
*empty = 0;
|
||||||
if (FSTAT(fd, &st)) {
|
if (FSTAT(fd, &st)) {
|
||||||
|
@ -134,14 +133,6 @@ fmap_t *fmap_check_empty(int fd, off_t offset, size_t len, int *empty, const cha
|
||||||
if (!m)
|
if (!m)
|
||||||
return NULL;
|
return NULL;
|
||||||
m->mtime = st.st_mtime;
|
m->mtime = st.st_mtime;
|
||||||
m->handle_is_fd = 1;
|
|
||||||
|
|
||||||
/* Calculate the fmap hash to be used by the FP check later */
|
|
||||||
if (CL_SUCCESS != fmap_get_MD5(hash, m)) {
|
|
||||||
funmap(m);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
memcpy(m->maphash, hash, 16);
|
|
||||||
|
|
||||||
if (NULL != name) {
|
if (NULL != name) {
|
||||||
m->name = cli_strdup(name);
|
m->name = cli_strdup(name);
|
||||||
|
@ -180,7 +171,6 @@ fmap_t *fmap_check_empty(int fd, off_t offset, size_t len, int *empty, const cha
|
||||||
const void *data;
|
const void *data;
|
||||||
HANDLE fh;
|
HANDLE fh;
|
||||||
HANDLE mh;
|
HANDLE mh;
|
||||||
unsigned char hash[16] = {'\0'};
|
|
||||||
|
|
||||||
*empty = 0;
|
*empty = 0;
|
||||||
if (FSTAT(fd, &st)) {
|
if (FSTAT(fd, &st)) {
|
||||||
|
@ -224,18 +214,11 @@ fmap_t *fmap_check_empty(int fd, off_t offset, size_t len, int *empty, const cha
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
m->handle = (void *)(size_t)fd;
|
m->handle = (void *)(size_t)fd;
|
||||||
m->handle_is_fd = 1;
|
m->handle_is_fd = 1; /* This is probably(?) needed so `fmap_fd()` can return the file descriptor. */
|
||||||
m->fh = fh;
|
m->fh = fh;
|
||||||
m->mh = mh;
|
m->mh = mh;
|
||||||
m->unmap = unmap_win32;
|
m->unmap = unmap_win32;
|
||||||
|
|
||||||
/* Calculate the fmap hash to be used by the FP check later */
|
|
||||||
if (CL_SUCCESS != fmap_get_MD5(hash, m)) {
|
|
||||||
funmap(m);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
memcpy(m->maphash, hash, 16);
|
|
||||||
|
|
||||||
if (NULL != name) {
|
if (NULL != name) {
|
||||||
m->name = cli_strdup(name);
|
m->name = cli_strdup(name);
|
||||||
if (NULL == m->name) {
|
if (NULL == m->name) {
|
||||||
|
@ -250,11 +233,15 @@ fmap_t *fmap_check_empty(int fd, off_t offset, size_t len, int *empty, const cha
|
||||||
|
|
||||||
/* vvvvv SHARED STUFF BELOW vvvvv */
|
/* vvvvv SHARED STUFF BELOW vvvvv */
|
||||||
|
|
||||||
fmap_t *fmap_duplicate(cl_fmap_t *map, off_t offset, size_t length, const char *name)
|
fmap_t *fmap_duplicate(cl_fmap_t *map, size_t offset, size_t length, const char *name)
|
||||||
{
|
{
|
||||||
cl_error_t status = CL_ERROR;
|
cl_error_t status = CL_ERROR;
|
||||||
cl_fmap_t *duplicate_map = NULL;
|
cl_fmap_t *duplicate_map = NULL;
|
||||||
unsigned char hash[16] = {'\0'};
|
|
||||||
|
if (NULL == map) {
|
||||||
|
cli_warnmsg("fmap_duplicate: map is NULL!\n");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
duplicate_map = cli_malloc(sizeof(cl_fmap_t));
|
duplicate_map = cli_malloc(sizeof(cl_fmap_t));
|
||||||
if (!duplicate_map) {
|
if (!duplicate_map) {
|
||||||
|
@ -265,23 +252,30 @@ fmap_t *fmap_duplicate(cl_fmap_t *map, off_t offset, size_t length, const char *
|
||||||
/* Duplicate the state of the original map */
|
/* Duplicate the state of the original map */
|
||||||
memcpy(duplicate_map, map, sizeof(cl_fmap_t));
|
memcpy(duplicate_map, map, sizeof(cl_fmap_t));
|
||||||
|
|
||||||
/* Set the new offset and length for the new map */
|
if (offset > map->len) {
|
||||||
/* can't change offset because then we'd have to discard/move cached
|
/* invalid offset, exceeds length of map */
|
||||||
* data, instead use another offset to reuse the already cached data */
|
cli_warnmsg("fmap_duplicate: requested offset exceeds end of map\n");
|
||||||
duplicate_map->nested_offset += offset;
|
goto done;
|
||||||
duplicate_map->len = length;
|
}
|
||||||
duplicate_map->real_len = duplicate_map->nested_offset + length;
|
|
||||||
|
|
||||||
if (!CLI_ISCONTAINED(map->nested_offset, map->len,
|
if (offset > 0 || length < map->len) {
|
||||||
|
/* Caller requested a window into the current map, not the whole map */
|
||||||
|
unsigned char hash[16] = {'\0'};
|
||||||
|
|
||||||
|
/* Set the new nested offset and (nested) length for the new map */
|
||||||
|
/* can't change offset because then we'd have to discard/move cached
|
||||||
|
* data, instead use nested_offset to reuse the already cached data */
|
||||||
|
duplicate_map->nested_offset += offset;
|
||||||
|
duplicate_map->len = MIN(length, map->len - offset);
|
||||||
|
|
||||||
|
if (!CLI_ISCONTAINED2(map->nested_offset, map->len,
|
||||||
duplicate_map->nested_offset, duplicate_map->len)) {
|
duplicate_map->nested_offset, duplicate_map->len)) {
|
||||||
uint64_t len1, len2;
|
size_t len1, len2;
|
||||||
len1 = map->nested_offset + map->len;
|
len1 = map->nested_offset + map->len;
|
||||||
len2 = duplicate_map->nested_offset + duplicate_map->len;
|
len2 = duplicate_map->nested_offset + duplicate_map->len;
|
||||||
cli_warnmsg("fmap_duplicate: internal map error: %zu, " STDu64 "; %zu, " STDu64 "\n",
|
cli_warnmsg("fmap_duplicate: internal map error: %zu, %zu; %zu, %zu\n",
|
||||||
(size_t)map->nested_offset,
|
map->nested_offset, len1,
|
||||||
(uint64_t)len1,
|
duplicate_map->offset, len2);
|
||||||
(size_t)duplicate_map->offset,
|
|
||||||
(uint64_t)len2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate the fmap hash to be used by the FP check later */
|
/* Calculate the fmap hash to be used by the FP check later */
|
||||||
|
@ -290,6 +284,7 @@ fmap_t *fmap_duplicate(cl_fmap_t *map, off_t offset, size_t length, const char *
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
memcpy(duplicate_map->maphash, hash, 16);
|
memcpy(duplicate_map->maphash, hash, 16);
|
||||||
|
}
|
||||||
|
|
||||||
if (NULL != name) {
|
if (NULL != name) {
|
||||||
duplicate_map->name = cli_strdup(name);
|
duplicate_map->name = cli_strdup(name);
|
||||||
|
@ -356,6 +351,8 @@ extern cl_fmap_t *cl_fmap_open_handle(void *handle, size_t offset, size_t len,
|
||||||
cl_fmap_t *m = NULL;
|
cl_fmap_t *m = NULL;
|
||||||
int pgsz = cli_getpagesize();
|
int pgsz = cli_getpagesize();
|
||||||
|
|
||||||
|
unsigned char hash[16] = {'\0'};
|
||||||
|
|
||||||
if ((off_t)offset < 0 || offset != fmap_align_to(offset, pgsz)) {
|
if ((off_t)offset < 0 || offset != fmap_align_to(offset, pgsz)) {
|
||||||
cli_warnmsg("fmap: attempted mapping with unaligned offset\n");
|
cli_warnmsg("fmap: attempted mapping with unaligned offset\n");
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -429,6 +426,14 @@ extern cl_fmap_t *cl_fmap_open_handle(void *handle, size_t offset, size_t len,
|
||||||
m->need_offstr = handle_need_offstr;
|
m->need_offstr = handle_need_offstr;
|
||||||
m->gets = handle_gets;
|
m->gets = handle_gets;
|
||||||
m->unneed_off = handle_unneed_off;
|
m->unneed_off = handle_unneed_off;
|
||||||
|
m->handle_is_fd = 1;
|
||||||
|
|
||||||
|
/* Calculate the fmap hash to be used by the FP check later */
|
||||||
|
if (CL_SUCCESS != fmap_get_MD5(hash, m)) {
|
||||||
|
cli_warnmsg("fmap: failed to get MD5\n");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
memcpy(m->maphash, hash, 16);
|
||||||
|
|
||||||
status = CL_SUCCESS;
|
status = CL_SUCCESS;
|
||||||
|
|
||||||
|
@ -828,6 +833,8 @@ static const void *mem_gets(fmap_t *m, char *dst, size_t *at, size_t max_len);
|
||||||
|
|
||||||
fmap_t *fmap_open_memory(const void *start, size_t len, const char *name)
|
fmap_t *fmap_open_memory(const void *start, size_t len, const char *name)
|
||||||
{
|
{
|
||||||
|
unsigned char hash[16] = {'\0'};
|
||||||
|
|
||||||
int pgsz = cli_getpagesize();
|
int pgsz = cli_getpagesize();
|
||||||
cl_fmap_t *m = cli_calloc(1, sizeof(*m));
|
cl_fmap_t *m = cli_calloc(1, sizeof(*m));
|
||||||
if (!m) {
|
if (!m) {
|
||||||
|
@ -853,6 +860,16 @@ fmap_t *fmap_open_memory(const void *start, size_t len, const char *name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Calculate the fmap hash to be used by the FP check later */
|
||||||
|
if (CL_SUCCESS != fmap_get_MD5(hash, m)) {
|
||||||
|
if (NULL != m->name) {
|
||||||
|
free(m->name);
|
||||||
|
}
|
||||||
|
free(m);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memcpy(m->maphash, hash, 16);
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -130,7 +130,7 @@ fmap_t *fmap_open_memory(const void *start, size_t len, const char *name);
|
||||||
* @param name (optional) Original name of the file (to set fmap name metadata)
|
* @param name (optional) Original name of the file (to set fmap name metadata)
|
||||||
* @return fmap_t* NULL if failure or a special fmap that the caller must free with free_duplicate_fmap()
|
* @return fmap_t* NULL if failure or a special fmap that the caller must free with free_duplicate_fmap()
|
||||||
*/
|
*/
|
||||||
fmap_t *fmap_duplicate(cl_fmap_t *map, off_t offset, size_t length, const char *name);
|
fmap_t *fmap_duplicate(cl_fmap_t *map, size_t offset, size_t length, const char *name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Deallocate a _duplicated_ fmap. Does not unmap the mapped region.
|
* @brief Deallocate a _duplicated_ fmap. Does not unmap the mapped region.
|
||||||
|
|
|
@ -222,7 +222,7 @@ cl_error_t cli_parsegif(cli_ctx *ctx)
|
||||||
|
|
||||||
if (screen_desc.flags & GIF_SCREEN_DESC_FLAGS_MASK_HAVE_GLOBAL_COLOR_TABLE) {
|
if (screen_desc.flags & GIF_SCREEN_DESC_FLAGS_MASK_HAVE_GLOBAL_COLOR_TABLE) {
|
||||||
global_color_table_size = 3 * (1 << ((screen_desc.flags & GIF_SCREEN_DESC_FLAGS_MASK_SIZE_OF_GLOBAL_COLOR_TABLE) + 1));
|
global_color_table_size = 3 * (1 << ((screen_desc.flags & GIF_SCREEN_DESC_FLAGS_MASK_SIZE_OF_GLOBAL_COLOR_TABLE) + 1));
|
||||||
cli_dbgmsg("GIF: Global Color Table size: %u\n", global_color_table_size);
|
cli_dbgmsg("GIF: Global Color Table size: %zu\n", global_color_table_size);
|
||||||
|
|
||||||
if (offset + (size_t)global_color_table_size > map->len) {
|
if (offset + (size_t)global_color_table_size > map->len) {
|
||||||
cli_errmsg("GIF: EOF in the middle of the global color table, file truncated?\n");
|
cli_errmsg("GIF: EOF in the middle of the global color table, file truncated?\n");
|
||||||
|
@ -349,7 +349,7 @@ cl_error_t cli_parsegif(cli_ctx *ctx)
|
||||||
|
|
||||||
if (image_desc.flags & GIF_IMAGE_DESC_FLAGS_MASK_HAVE_LOCAL_COLOR_TABLE) {
|
if (image_desc.flags & GIF_IMAGE_DESC_FLAGS_MASK_HAVE_LOCAL_COLOR_TABLE) {
|
||||||
local_color_table_size = 3 * (1 << ((image_desc.flags & GIF_IMAGE_DESC_FLAGS_MASK_SIZE_OF_LOCAL_COLOR_TABLE) + 1));
|
local_color_table_size = 3 * (1 << ((image_desc.flags & GIF_IMAGE_DESC_FLAGS_MASK_SIZE_OF_LOCAL_COLOR_TABLE) + 1));
|
||||||
cli_dbgmsg("GIF: Found a Local Color Table (size: %u)\n", local_color_table_size);
|
cli_dbgmsg("GIF: Found a Local Color Table (size: %zu)\n", local_color_table_size);
|
||||||
offset += local_color_table_size;
|
offset += local_color_table_size;
|
||||||
} else {
|
} else {
|
||||||
cli_dbgmsg("GIF: No Local Color Table.\n");
|
cli_dbgmsg("GIF: No Local Color Table.\n");
|
||||||
|
|
|
@ -262,7 +262,7 @@ static int gpt_scan_partitions(cli_ctx *ctx, struct gpt_header hdr, size_t secto
|
||||||
struct gpt_partition_entry gpe;
|
struct gpt_partition_entry gpe;
|
||||||
int ret = CL_CLEAN, detection = CL_CLEAN;
|
int ret = CL_CLEAN, detection = CL_CLEAN;
|
||||||
size_t maplen, part_size = 0;
|
size_t maplen, part_size = 0;
|
||||||
off_t pos = 0, part_off = 0;
|
size_t pos = 0, part_off = 0;
|
||||||
unsigned i = 0, j = 0;
|
unsigned i = 0, j = 0;
|
||||||
uint32_t max_prtns = 0;
|
uint32_t max_prtns = 0;
|
||||||
|
|
||||||
|
@ -482,7 +482,7 @@ static int gpt_validate_header(cli_ctx *ctx, struct gpt_header hdr, size_t secto
|
||||||
static int gpt_check_mbr(cli_ctx *ctx, size_t sectorsize)
|
static int gpt_check_mbr(cli_ctx *ctx, size_t sectorsize)
|
||||||
{
|
{
|
||||||
struct mbr_boot_record pmbr;
|
struct mbr_boot_record pmbr;
|
||||||
off_t pos = 0, mbr_base = 0;
|
size_t pos = 0, mbr_base = 0;
|
||||||
int ret = CL_CLEAN;
|
int ret = CL_CLEAN;
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
|
|
||||||
|
@ -533,7 +533,7 @@ static void gpt_printSectors(cli_ctx *ctx, size_t sectorsize)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_GPT_PARSE
|
#ifdef DEBUG_GPT_PARSE
|
||||||
struct gpt_header phdr, shdr;
|
struct gpt_header phdr, shdr;
|
||||||
off_t ppos = 0, spos = 0;
|
size_t ppos = 0, spos = 0;
|
||||||
size_t pptable_len, sptable_len, maplen;
|
size_t pptable_len, sptable_len, maplen;
|
||||||
uint64_t ptableLastLBA, stableLastLBA;
|
uint64_t ptableLastLBA, stableLastLBA;
|
||||||
|
|
||||||
|
@ -586,7 +586,7 @@ static int gpt_partition_intersection(cli_ctx *ctx, struct gpt_header hdr, size_
|
||||||
struct gpt_partition_entry gpe;
|
struct gpt_partition_entry gpe;
|
||||||
unsigned i, pitxn;
|
unsigned i, pitxn;
|
||||||
int ret = CL_CLEAN, tmp = CL_CLEAN;
|
int ret = CL_CLEAN, tmp = CL_CLEAN;
|
||||||
off_t pos;
|
size_t pos;
|
||||||
size_t maplen;
|
size_t maplen;
|
||||||
uint32_t max_prtns = 0;
|
uint32_t max_prtns = 0;
|
||||||
int virus_found = 0;
|
int virus_found = 0;
|
||||||
|
|
|
@ -773,7 +773,7 @@ static int is_extract_cab(cli_ctx *ctx, uint64_t off, uint64_t size, uint64_t cs
|
||||||
zret = inflate(&z, 0);
|
zret = inflate(&z, 0);
|
||||||
if (zret == Z_OK || zret == Z_STREAM_END || zret == Z_BUF_ERROR) {
|
if (zret == Z_OK || zret == Z_STREAM_END || zret == Z_BUF_ERROR) {
|
||||||
unsigned int umpd = IS_CABBUFSZ - z.avail_out;
|
unsigned int umpd = IS_CABBUFSZ - z.avail_out;
|
||||||
if (cli_writen(ofd, outbuf, umpd) < umpd)
|
if (cli_writen(ofd, outbuf, umpd) != umpd)
|
||||||
break;
|
break;
|
||||||
outsz += umpd;
|
outsz += umpd;
|
||||||
if (zret == Z_STREAM_END || z.avail_out == IS_CABBUFSZ /* FIXMEISHIELD: is the latter ok? */) {
|
if (zret == Z_STREAM_END || z.avail_out == IS_CABBUFSZ /* FIXMEISHIELD: is the latter ok? */) {
|
||||||
|
|
|
@ -252,14 +252,14 @@ typedef enum {
|
||||||
|
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
static cl_error_t jpeg_check_photoshop_8bim(cli_ctx *ctx, off_t *off)
|
static cl_error_t jpeg_check_photoshop_8bim(cli_ctx *ctx, size_t *off)
|
||||||
{
|
{
|
||||||
cl_error_t retval;
|
cl_error_t retval;
|
||||||
const unsigned char *buf;
|
const unsigned char *buf;
|
||||||
uint16_t ntmp;
|
uint16_t ntmp;
|
||||||
uint8_t nlength, id[2];
|
uint8_t nlength, id[2];
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
off_t offset = *off;
|
size_t offset = *off;
|
||||||
fmap_t *map = *ctx->fmap;
|
fmap_t *map = *ctx->fmap;
|
||||||
|
|
||||||
if (!(buf = fmap_need_off_once(map, offset, 4 + 2 + 1))) {
|
if (!(buf = fmap_need_off_once(map, offset, 4 + 2 + 1))) {
|
||||||
|
@ -577,8 +577,8 @@ cl_error_t cli_parsejpeg(cli_ctx *ctx)
|
||||||
if ((fmap_readn(map, buff, offset - len + sizeof(len_u16), strlen("Photoshop 3.0") + 1) == strlen("Photoshop 3.0") + 1) &&
|
if ((fmap_readn(map, buff, offset - len + sizeof(len_u16), strlen("Photoshop 3.0") + 1) == strlen("Photoshop 3.0") + 1) &&
|
||||||
(0 == memcmp(buff, "Photoshop 3.0\0", strlen("Photoshop 3.0") + 1))) {
|
(0 == memcmp(buff, "Photoshop 3.0\0", strlen("Photoshop 3.0") + 1))) {
|
||||||
/* Found a Photoshop file */
|
/* Found a Photoshop file */
|
||||||
off_t photoshop_data_offset = offset - len + sizeof(len_u16) + strlen("Photoshop 3.0") + 1;
|
size_t photoshop_data_offset = offset - len + sizeof(len_u16) + strlen("Photoshop 3.0") + 1;
|
||||||
off_t old_offset;
|
size_t old_offset;
|
||||||
|
|
||||||
cli_dbgmsg("Found Photoshop segment\n");
|
cli_dbgmsg("Found Photoshop segment\n");
|
||||||
do {
|
do {
|
||||||
|
|
|
@ -263,6 +263,8 @@ CLAMAV_PRIVATE {
|
||||||
cli_realpath;
|
cli_realpath;
|
||||||
cli_codepage_to_utf8;
|
cli_codepage_to_utf8;
|
||||||
cli_get_filepath_from_filedesc;
|
cli_get_filepath_from_filedesc;
|
||||||
|
fmap_duplicate;
|
||||||
|
free_duplicate_fmap;
|
||||||
|
|
||||||
__cli_strcasestr;
|
__cli_strcasestr;
|
||||||
__cli_strndup;
|
__cli_strndup;
|
||||||
|
|
|
@ -64,17 +64,17 @@ enum MBR_STATE {
|
||||||
SEEN_EMPTY
|
SEEN_EMPTY
|
||||||
};
|
};
|
||||||
|
|
||||||
static int mbr_scanextprtn(cli_ctx *ctx, unsigned *prtncount, off_t extlba,
|
static int mbr_scanextprtn(cli_ctx *ctx, unsigned *prtncount, size_t extlba,
|
||||||
size_t extlbasize, size_t sectorsize);
|
size_t extlbasize, size_t sectorsize);
|
||||||
static int mbr_check_mbr(struct mbr_boot_record *record, size_t maplen, size_t sectorsize);
|
static int mbr_check_mbr(struct mbr_boot_record *record, size_t maplen, size_t sectorsize);
|
||||||
static int mbr_check_ebr(struct mbr_boot_record *record);
|
static int mbr_check_ebr(struct mbr_boot_record *record);
|
||||||
static int mbr_primary_partition_intersection(cli_ctx *ctx, struct mbr_boot_record mbr, size_t sectorsize);
|
static int mbr_primary_partition_intersection(cli_ctx *ctx, struct mbr_boot_record mbr, size_t sectorsize);
|
||||||
static int mbr_extended_partition_intersection(cli_ctx *ctx, unsigned *prtncount, off_t extlba, size_t sectorsize);
|
static int mbr_extended_partition_intersection(cli_ctx *ctx, unsigned *prtncount, size_t extlba, size_t sectorsize);
|
||||||
|
|
||||||
int cli_mbr_check(const unsigned char *buff, size_t len, size_t maplen)
|
int cli_mbr_check(const unsigned char *buff, size_t len, size_t maplen)
|
||||||
{
|
{
|
||||||
struct mbr_boot_record mbr;
|
struct mbr_boot_record mbr;
|
||||||
off_t mbr_base = 0;
|
size_t mbr_base = 0;
|
||||||
size_t sectorsize = 512;
|
size_t sectorsize = 512;
|
||||||
|
|
||||||
if (len < sectorsize) {
|
if (len < sectorsize) {
|
||||||
|
@ -94,7 +94,7 @@ int cli_mbr_check(const unsigned char *buff, size_t len, size_t maplen)
|
||||||
int cli_mbr_check2(cli_ctx *ctx, size_t sectorsize)
|
int cli_mbr_check2(cli_ctx *ctx, size_t sectorsize)
|
||||||
{
|
{
|
||||||
struct mbr_boot_record mbr;
|
struct mbr_boot_record mbr;
|
||||||
off_t pos = 0, mbr_base = 0;
|
size_t pos = 0, mbr_base = 0;
|
||||||
size_t maplen;
|
size_t maplen;
|
||||||
|
|
||||||
if (!ctx || !ctx->fmap) {
|
if (!ctx || !ctx->fmap) {
|
||||||
|
@ -140,7 +140,7 @@ int cli_scanmbr(cli_ctx *ctx, size_t sectorsize)
|
||||||
struct mbr_boot_record mbr;
|
struct mbr_boot_record mbr;
|
||||||
enum MBR_STATE state = SEEN_NOTHING;
|
enum MBR_STATE state = SEEN_NOTHING;
|
||||||
int ret = CL_CLEAN, detection = CL_CLEAN;
|
int ret = CL_CLEAN, detection = CL_CLEAN;
|
||||||
off_t pos = 0, mbr_base = 0, partoff = 0;
|
size_t pos = 0, mbr_base = 0, partoff = 0;
|
||||||
unsigned i = 0, prtncount = 0;
|
unsigned i = 0, prtncount = 0;
|
||||||
size_t maplen, partsize;
|
size_t maplen, partsize;
|
||||||
|
|
||||||
|
@ -210,10 +210,10 @@ int cli_scanmbr(cli_ctx *ctx, size_t sectorsize)
|
||||||
cli_dbgmsg("MBR Partition Entry %u:\n", i);
|
cli_dbgmsg("MBR Partition Entry %u:\n", i);
|
||||||
cli_dbgmsg("Status: %u\n", mbr.entries[i].status);
|
cli_dbgmsg("Status: %u\n", mbr.entries[i].status);
|
||||||
cli_dbgmsg("Type: %x\n", mbr.entries[i].type);
|
cli_dbgmsg("Type: %x\n", mbr.entries[i].type);
|
||||||
cli_dbgmsg("Blocks: [%u, +%u), ([%lu, +%lu))\n",
|
cli_dbgmsg("Blocks: [%u, +%u), ([%zu, +%zu))\n",
|
||||||
mbr.entries[i].firstLBA, mbr.entries[i].numLBA,
|
mbr.entries[i].firstLBA, mbr.entries[i].numLBA,
|
||||||
(unsigned long)(mbr.entries[i].firstLBA * sectorsize),
|
mbr.entries[i].firstLBA * sectorsize,
|
||||||
(unsigned long)(mbr.entries[i].numLBA * sectorsize));
|
mbr.entries[i].numLBA * sectorsize);
|
||||||
|
|
||||||
/* Handle MBR entry based on type */
|
/* Handle MBR entry based on type */
|
||||||
if (mbr.entries[i].type == MBR_EMPTY) {
|
if (mbr.entries[i].type == MBR_EMPTY) {
|
||||||
|
@ -257,12 +257,12 @@ int cli_scanmbr(cli_ctx *ctx, size_t sectorsize)
|
||||||
return detection;
|
return detection;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mbr_scanextprtn(cli_ctx *ctx, unsigned *prtncount, off_t extlba, size_t extlbasize, size_t sectorsize)
|
static int mbr_scanextprtn(cli_ctx *ctx, unsigned *prtncount, size_t extlba, size_t extlbasize, size_t sectorsize)
|
||||||
{
|
{
|
||||||
struct mbr_boot_record ebr;
|
struct mbr_boot_record ebr;
|
||||||
enum MBR_STATE state = SEEN_NOTHING;
|
enum MBR_STATE state = SEEN_NOTHING;
|
||||||
int ret = CL_CLEAN, detection = CL_CLEAN;
|
int ret = CL_CLEAN, detection = CL_CLEAN;
|
||||||
off_t pos = 0, mbr_base = 0, logiclba = 0, extoff = 0, partoff = 0;
|
size_t pos = 0, mbr_base = 0, logiclba = 0, extoff = 0, partoff = 0;
|
||||||
size_t partsize, extsize;
|
size_t partsize, extsize;
|
||||||
unsigned i = 0, j = 0;
|
unsigned i = 0, j = 0;
|
||||||
|
|
||||||
|
@ -424,7 +424,7 @@ void mbr_convert_to_host(struct mbr_boot_record *record)
|
||||||
static int mbr_check_mbr(struct mbr_boot_record *record, size_t maplen, size_t sectorsize)
|
static int mbr_check_mbr(struct mbr_boot_record *record, size_t maplen, size_t sectorsize)
|
||||||
{
|
{
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
off_t partoff = 0;
|
size_t partoff = 0;
|
||||||
size_t partsize = 0;
|
size_t partsize = 0;
|
||||||
|
|
||||||
for (i = 0; i < MBR_MAX_PARTITION_ENTRIES; ++i) {
|
for (i = 0; i < MBR_MAX_PARTITION_ENTRIES; ++i) {
|
||||||
|
@ -540,13 +540,13 @@ leave:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* checks internal logical partitions */
|
/* checks internal logical partitions */
|
||||||
static int mbr_extended_partition_intersection(cli_ctx *ctx, unsigned *prtncount, off_t extlba, size_t sectorsize)
|
static int mbr_extended_partition_intersection(cli_ctx *ctx, unsigned *prtncount, size_t extlba, size_t sectorsize)
|
||||||
{
|
{
|
||||||
struct mbr_boot_record ebr;
|
struct mbr_boot_record ebr;
|
||||||
partition_intersection_list_t prtncheck;
|
partition_intersection_list_t prtncheck;
|
||||||
unsigned i, pitxn;
|
unsigned i, pitxn;
|
||||||
int ret = CL_CLEAN, tmp = CL_CLEAN, mbr_base = 0;
|
int ret = CL_CLEAN, tmp = CL_CLEAN, mbr_base = 0;
|
||||||
off_t pos = 0, logiclba = 0;
|
size_t pos = 0, logiclba = 0;
|
||||||
int virus_found = 0;
|
int virus_found = 0;
|
||||||
|
|
||||||
mbr_base = sectorsize - sizeof(struct mbr_boot_record);
|
mbr_base = sectorsize - sizeof(struct mbr_boot_record);
|
||||||
|
|
|
@ -80,8 +80,8 @@ extern uint8_t cli_debug_flag;
|
||||||
extern uint8_t cli_always_gen_section_hash;
|
extern uint8_t cli_always_gen_section_hash;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CLI_ISCONTAINED(bb, bb_size, sb, sb_size) checks if sb (sub buffer) is contained
|
* CLI_ISCONTAINED(bb, bb_size, sb, sb_size) checks if sb (small buffer) is
|
||||||
* within bb (buffer).
|
* within bb (big buffer).
|
||||||
*
|
*
|
||||||
* bb and sb are pointers (or offsets) for the main buffer and the
|
* bb and sb are pointers (or offsets) for the main buffer and the
|
||||||
* sub-buffer respectively, and bb_size and sb_size are their sizes
|
* sub-buffer respectively, and bb_size and sb_size are their sizes
|
||||||
|
@ -89,29 +89,27 @@ extern uint8_t cli_always_gen_section_hash;
|
||||||
* The macro can be used to protect against wraps.
|
* The macro can be used to protect against wraps.
|
||||||
*/
|
*/
|
||||||
#define CLI_ISCONTAINED(bb, bb_size, sb, sb_size) \
|
#define CLI_ISCONTAINED(bb, bb_size, sb, sb_size) \
|
||||||
( \
|
((size_t)(bb_size) > 0 && (size_t)(sb_size) > 0 && \
|
||||||
(size_t)(bb_size) > 0 && (size_t)(sb_size) > 0 && \
|
|
||||||
(size_t)(sb_size) <= (size_t)(bb_size) && \
|
(size_t)(sb_size) <= (size_t)(bb_size) && \
|
||||||
(ptrdiff_t)(sb) >= (ptrdiff_t)(bb) && \
|
(size_t)(sb) >= (size_t)(bb) && \
|
||||||
(ptrdiff_t)(sb) + (ptrdiff_t)(sb_size) <= (ptrdiff_t)(bb) + (ptrdiff_t)(bb_size) && \
|
(size_t)(sb) + (size_t)(sb_size) <= (size_t)(bb) + (size_t)(bb_size) && \
|
||||||
(ptrdiff_t)(sb) + (ptrdiff_t)(sb_size) > (ptrdiff_t)(bb) && \
|
(size_t)(sb) + (size_t)(sb_size) > (size_t)(bb) && \
|
||||||
(ptrdiff_t)(sb) < (ptrdiff_t)(bb) + (ptrdiff_t)(bb_size))
|
(size_t)(sb) < (size_t)(bb) + (size_t)(bb_size))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CLI_ISCONTAINED2(bb, bb_size, sb, sb_size) checks if sb (sub buffer) is contained
|
* CLI_ISCONTAINED2(bb, bb_size, sb, sb_size) checks if sb (small buffer) is
|
||||||
* within bb (buffer).
|
* within bb (big buffer).
|
||||||
*
|
*
|
||||||
* CLI_ISCONTAINED2 is the same as CLI_ISCONTAINED except that it allows for sub-
|
* CLI_ISCONTAINED2 is the same as CLI_ISCONTAINED except that it allows for
|
||||||
* buffers with sb_size == 0.
|
* small-buffers with sb_size == 0.
|
||||||
*/
|
*/
|
||||||
#define CLI_ISCONTAINED2(bb, bb_size, sb, sb_size) \
|
#define CLI_ISCONTAINED2(bb, bb_size, sb, sb_size) \
|
||||||
( \
|
((size_t)(bb_size) > 0 && \
|
||||||
(size_t)(bb_size) > 0 && (size_t)(sb_size) >= 0 && \
|
|
||||||
(size_t)(sb_size) <= (size_t)(bb_size) && \
|
(size_t)(sb_size) <= (size_t)(bb_size) && \
|
||||||
(ptrdiff_t)(sb) >= (ptrdiff_t)(bb) && \
|
(size_t)(sb) >= (size_t)(bb) && \
|
||||||
(ptrdiff_t)(sb) + (ptrdiff_t)(sb_size) <= (ptrdiff_t)(bb) + (ptrdiff_t)(bb_size) && \
|
(size_t)(sb) + (size_t)(sb_size) <= (size_t)(bb) + (size_t)(bb_size) && \
|
||||||
(ptrdiff_t)(sb) + (ptrdiff_t)(sb_size) >= (ptrdiff_t)(bb) && \
|
(size_t)(sb) + (size_t)(sb_size) >= (size_t)(bb) && \
|
||||||
(ptrdiff_t)(sb) < (ptrdiff_t)(bb) + (ptrdiff_t)(bb_size))
|
(size_t)(sb) <= (size_t)(bb) + (size_t)(bb_size))
|
||||||
|
|
||||||
#define CLI_MAX_ALLOCATION (182 * 1024 * 1024)
|
#define CLI_MAX_ALLOCATION (182 * 1024 * 1024)
|
||||||
|
|
||||||
|
|
|
@ -426,7 +426,7 @@ scan_overlay:
|
||||||
/* Check if there's an overlay, and scan it if one exists. */
|
/* Check if there's an overlay, and scan it if one exists. */
|
||||||
if (map->len - offset > 0) {
|
if (map->len - offset > 0) {
|
||||||
cli_dbgmsg("PNG: Found " STDu64 " additional data after end of PNG! Scanning as a nested file.\n", map->len - offset);
|
cli_dbgmsg("PNG: Found " STDu64 " additional data after end of PNG! Scanning as a nested file.\n", map->len - offset);
|
||||||
status = cli_magic_scan_nested_fmap_type(map, offset, map->len - offset, ctx, CL_TYPE_ANY, NULL);
|
status = cli_magic_scan_nested_fmap_type(map, (size_t)offset, map->len - offset, ctx, CL_TYPE_ANY, NULL);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4583,15 +4583,15 @@ cl_error_t cl_scandesc(int desc, const char *filename, const char **virname, uns
|
||||||
* @param name (optional) Original name of the file (to set fmap name metadata)
|
* @param name (optional) Original name of the file (to set fmap name metadata)
|
||||||
* @return int CL_SUCCESS, or an error code.
|
* @return int CL_SUCCESS, or an error code.
|
||||||
*/
|
*/
|
||||||
static cl_error_t magic_scan_nested_fmap_type(cl_fmap_t *map, off_t offset, size_t length, cli_ctx *ctx, cli_file_t type, const char *name)
|
static cl_error_t magic_scan_nested_fmap_type(cl_fmap_t *map, size_t offset, size_t length, cli_ctx *ctx, cli_file_t type, const char *name)
|
||||||
{
|
{
|
||||||
cl_error_t ret = CL_CLEAN;
|
cl_error_t ret = CL_CLEAN;
|
||||||
|
|
||||||
cli_dbgmsg("magic_scan_nested_fmap_type: [%zu, +%zu), [" STDi64 ", +%zu)\n",
|
cli_dbgmsg("magic_scan_nested_fmap_type: [%zu, +%zu), [" STDi64 ", +%zu)\n",
|
||||||
map->nested_offset, map->len,
|
map->nested_offset, map->len,
|
||||||
(int64_t)offset, length);
|
(int64_t)offset, length);
|
||||||
if (offset < 0 || (size_t)offset >= map->len) {
|
if (offset >= map->len) {
|
||||||
cli_dbgmsg("Invalid offset: %ld\n", (long)offset);
|
cli_dbgmsg("Invalid offset: %zu\n", offset);
|
||||||
return CL_CLEAN;
|
return CL_CLEAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4599,8 +4599,8 @@ static cl_error_t magic_scan_nested_fmap_type(cl_fmap_t *map, off_t offset, size
|
||||||
length = map->len - offset;
|
length = map->len - offset;
|
||||||
if (length > map->len - offset) {
|
if (length > map->len - offset) {
|
||||||
cli_dbgmsg("Data truncated: %zu -> %zu\n",
|
cli_dbgmsg("Data truncated: %zu -> %zu\n",
|
||||||
length, map->len - (size_t)offset);
|
length, map->len - offset);
|
||||||
length = map->len - (size_t)offset;
|
length = map->len - offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (length <= 5) {
|
if (length <= 5) {
|
||||||
|
@ -4625,16 +4625,15 @@ static cl_error_t magic_scan_nested_fmap_type(cl_fmap_t *map, off_t offset, size
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For map scans that may be forced to disk */
|
/* For map scans that may be forced to disk */
|
||||||
cl_error_t cli_magic_scan_nested_fmap_type(cl_fmap_t *map, off_t offset, size_t length, cli_ctx *ctx, cli_file_t type, const char *name)
|
cl_error_t cli_magic_scan_nested_fmap_type(cl_fmap_t *map, size_t offset, size_t length, cli_ctx *ctx, cli_file_t type, const char *name)
|
||||||
{
|
{
|
||||||
off_t old_off = map->nested_offset;
|
size_t old_off = map->nested_offset;
|
||||||
size_t old_len = map->len;
|
size_t old_len = map->len;
|
||||||
cl_error_t ret = CL_CLEAN;
|
cl_error_t ret = CL_CLEAN;
|
||||||
|
|
||||||
cli_dbgmsg("cli_magic_scan_nested_fmap_type: [%ld, +%lu)\n",
|
cli_dbgmsg("cli_magic_scan_nested_fmap_type: [%zu, +%zu)\n", offset, length);
|
||||||
(long)offset, (unsigned long)length);
|
if (offset >= old_len) {
|
||||||
if (offset < 0 || (size_t)offset >= old_len) {
|
cli_dbgmsg("Invalid offset: %zu\n", offset);
|
||||||
cli_dbgmsg("Invalid offset: %ld\n", (long)offset);
|
|
||||||
return CL_CLEAN;
|
return CL_CLEAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4649,8 +4648,7 @@ cl_error_t cli_magic_scan_nested_fmap_type(cl_fmap_t *map, off_t offset, size_t
|
||||||
if (!length)
|
if (!length)
|
||||||
length = old_len - offset;
|
length = old_len - offset;
|
||||||
if (length > old_len - offset) {
|
if (length > old_len - offset) {
|
||||||
cli_dbgmsg("cli_magic_scan_nested_fmap_type: Data truncated: %lu -> %lu\n",
|
cli_dbgmsg("cli_magic_scan_nested_fmap_type: Data truncated: %zu -> %zu\n", length, old_len - offset);
|
||||||
(unsigned long)length, (unsigned long)(old_len - offset));
|
|
||||||
length = old_len - offset;
|
length = old_len - offset;
|
||||||
}
|
}
|
||||||
if (length <= 5) {
|
if (length <= 5) {
|
||||||
|
@ -4658,8 +4656,7 @@ cl_error_t cli_magic_scan_nested_fmap_type(cl_fmap_t *map, off_t offset, size_t
|
||||||
return CL_CLEAN;
|
return CL_CLEAN;
|
||||||
}
|
}
|
||||||
if (!CLI_ISCONTAINED(old_off, old_len, old_off + offset, length)) {
|
if (!CLI_ISCONTAINED(old_off, old_len, old_off + offset, length)) {
|
||||||
cli_dbgmsg("cli_magic_scan_nested_fmap_type: map error occurred [%ld, %zu]\n",
|
cli_dbgmsg("cli_magic_scan_nested_fmap_type: map error occurred [%zu, %zu]\n", old_off, old_len);
|
||||||
(long)old_off, old_len);
|
|
||||||
return CL_CLEAN;
|
return CL_CLEAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@ cl_error_t cli_magic_scan(cli_ctx *ctx, cli_file_t type);
|
||||||
* @param name (optional) Original name of the file (to set fmap name metadata)
|
* @param name (optional) Original name of the file (to set fmap name metadata)
|
||||||
* @return int CL_SUCCESS, or an error code.
|
* @return int CL_SUCCESS, or an error code.
|
||||||
*/
|
*/
|
||||||
cl_error_t cli_magic_scan_nested_fmap_type(cl_fmap_t *map, off_t offset, size_t length, cli_ctx *ctx, cli_file_t type, const char *name);
|
cl_error_t cli_magic_scan_nested_fmap_type(cl_fmap_t *map, size_t offset, size_t length, cli_ctx *ctx, cli_file_t type, const char *name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Convenience wrapper for cli_magic_scan_nested_fmap_type().
|
* @brief Convenience wrapper for cli_magic_scan_nested_fmap_type().
|
||||||
|
|
|
@ -266,7 +266,7 @@ tnef_message(fmap_t *map, off_t *pos, uint16_t type, uint16_t tag, int32_t lengt
|
||||||
|
|
||||||
/*cli_dbgmsg("%lu %lu\n", (long)(offset + length), ftell(fp));*/
|
/*cli_dbgmsg("%lu %lu\n", (long)(offset + length), ftell(fp));*/
|
||||||
|
|
||||||
if (!CLI_ISCONTAINED2(0, fsize, offset, (off_t)length)) {
|
if (!CLI_ISCONTAINED2(0, fsize, offset, length)) {
|
||||||
cli_dbgmsg("TNEF: Incorrect length field in tnef_message\n");
|
cli_dbgmsg("TNEF: Incorrect length field in tnef_message\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -561,6 +561,288 @@ START_TEST(test_cl_scanmap_callback_handle)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_fmap_duplicate)
|
||||||
|
{
|
||||||
|
cl_fmap_t *map;
|
||||||
|
cl_fmap_t *dup_map = NULL;
|
||||||
|
cl_fmap_t *dup_dup_map = NULL;
|
||||||
|
char map_data[6] = {'a', 'b', 'c', 'd', 'e', 'f'};
|
||||||
|
char tmp[6];
|
||||||
|
size_t bread = 0;
|
||||||
|
|
||||||
|
map = cl_fmap_open_memory(map_data, sizeof(map_data));
|
||||||
|
ck_assert_msg(!!map, "cl_fmap_open_handle failed");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test duplicate of entire map
|
||||||
|
*/
|
||||||
|
cli_dbgmsg("duplicating complete map\n");
|
||||||
|
dup_map = fmap_duplicate(map, 0, map->len, "complete duplicate");
|
||||||
|
ck_assert_msg(!!dup_map, "fmap_duplicate failed");
|
||||||
|
ck_assert_msg(dup_map->nested_offset == 0, "dup_map nested_offset is incorrect: %zu", dup_map->nested_offset);
|
||||||
|
ck_assert_msg(dup_map->len == map->len, "dup_map len is incorrect: %zu", dup_map->len);
|
||||||
|
ck_assert_msg(dup_map->real_len == map->len, "dup_map real len is incorrect: %zu", dup_map->real_len);
|
||||||
|
|
||||||
|
bread = fmap_readn(dup_map, tmp, 0, 6);
|
||||||
|
ck_assert(bread == 6);
|
||||||
|
ck_assert(0 == memcmp(map_data, tmp, 6));
|
||||||
|
|
||||||
|
cli_dbgmsg("freeing dup_map\n");
|
||||||
|
free_duplicate_fmap(dup_map);
|
||||||
|
dup_map = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test duplicate of map at offset 2
|
||||||
|
*/
|
||||||
|
cli_dbgmsg("duplicating 2 bytes into map\n");
|
||||||
|
dup_map = fmap_duplicate(map, 2, map->len, "offset duplicate");
|
||||||
|
ck_assert_msg(!!dup_map, "fmap_duplicate failed");
|
||||||
|
ck_assert_msg(dup_map->nested_offset == 2, "dup_map nested_offset is incorrect: %zu", dup_map->nested_offset);
|
||||||
|
ck_assert_msg(dup_map->len == 4, "dup_map len is incorrect: %zu", dup_map->len);
|
||||||
|
ck_assert_msg(dup_map->real_len == 6, "dup_map real len is incorrect: %zu", dup_map->real_len);
|
||||||
|
|
||||||
|
bread = fmap_readn(dup_map, tmp, 0, 6);
|
||||||
|
ck_assert(bread == 4);
|
||||||
|
ck_assert(0 == memcmp(map_data + 2, tmp, 4));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test duplicate of duplicate map, also at offset 2 (total 4 bytes in)
|
||||||
|
*/
|
||||||
|
cli_dbgmsg("duplicating 2 bytes into dup_map\n");
|
||||||
|
dup_dup_map = fmap_duplicate(dup_map, 2, dup_map->len, "double offset duplicate");
|
||||||
|
ck_assert_msg(!!dup_dup_map, "fmap_duplicate failed");
|
||||||
|
ck_assert_msg(dup_dup_map->nested_offset == 4, "dup_dup_map nested_offset is incorrect: %zu", dup_dup_map->nested_offset);
|
||||||
|
ck_assert_msg(dup_dup_map->len == 2, "dup_dup_map len is incorrect: %zu", dup_dup_map->len);
|
||||||
|
ck_assert_msg(dup_dup_map->real_len == 6, "dup_dup_map real len is incorrect: %zu", dup_dup_map->real_len);
|
||||||
|
|
||||||
|
bread = fmap_readn(dup_dup_map, tmp, 0, 6);
|
||||||
|
ck_assert(bread == 2);
|
||||||
|
ck_assert(0 == memcmp(map_data + 4, tmp, 2));
|
||||||
|
|
||||||
|
cli_dbgmsg("freeing dup_dup_map\n");
|
||||||
|
free_duplicate_fmap(dup_dup_map);
|
||||||
|
dup_dup_map = NULL;
|
||||||
|
cli_dbgmsg("freeing dup_map\n");
|
||||||
|
free_duplicate_fmap(dup_map);
|
||||||
|
dup_map = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test duplicate of map omiting the last 2 bytes
|
||||||
|
*/
|
||||||
|
cli_dbgmsg("duplicating map with shorter len\n");
|
||||||
|
dup_map = fmap_duplicate(map, 0, map->len - 2, "short duplicate");
|
||||||
|
ck_assert_msg(!!dup_map, "fmap_duplicate failed");
|
||||||
|
ck_assert_msg(dup_map->nested_offset == 0, "dup_map nested_offset is incorrect: %zu", dup_map->nested_offset);
|
||||||
|
ck_assert_msg(dup_map->len == 4, "dup_map len is incorrect: %zu", dup_map->len);
|
||||||
|
ck_assert_msg(dup_map->real_len == 6, "dup_map real len is incorrect: %zu", dup_map->real_len);
|
||||||
|
|
||||||
|
bread = fmap_readn(dup_map, tmp, 0, 6);
|
||||||
|
ck_assert(bread == 4);
|
||||||
|
ck_assert(0 == memcmp(map_data, tmp, 4));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test duplicate of the duplicate omiting the last 2 bytes again (so just the first 2 bytes)
|
||||||
|
*/
|
||||||
|
cli_dbgmsg("duplicating dup_map with shorter len\n");
|
||||||
|
dup_dup_map = fmap_duplicate(dup_map, 0, dup_map->len - 2, "double short duplicate");
|
||||||
|
ck_assert_msg(!!dup_dup_map, "fmap_duplicate failed");
|
||||||
|
ck_assert_msg(dup_dup_map->nested_offset == 0, "dup_dup_map nested_offset is incorrect: %zu", dup_dup_map->nested_offset);
|
||||||
|
ck_assert_msg(dup_dup_map->len == 2, "dup_dup_map len is incorrect: %zu", dup_dup_map->len);
|
||||||
|
ck_assert_msg(dup_dup_map->real_len == 6, "dup_dup_map real len is incorrect: %zu", dup_dup_map->real_len);
|
||||||
|
|
||||||
|
bread = fmap_readn(dup_dup_map, tmp, 0, 6);
|
||||||
|
ck_assert(bread == 2);
|
||||||
|
ck_assert(0 == memcmp(map_data, tmp, 2));
|
||||||
|
|
||||||
|
cli_dbgmsg("freeing dup_dup_map\n");
|
||||||
|
free_duplicate_fmap(dup_dup_map);
|
||||||
|
dup_dup_map = NULL;
|
||||||
|
cli_dbgmsg("freeing dup_map\n");
|
||||||
|
free_duplicate_fmap(dup_map);
|
||||||
|
dup_map = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test duplicate of map at offset 2
|
||||||
|
*/
|
||||||
|
cli_dbgmsg("duplicating 2 bytes into map\n");
|
||||||
|
dup_map = fmap_duplicate(map, 2, map->len, "offset duplicate");
|
||||||
|
ck_assert_msg(!!dup_map, "fmap_duplicate failed");
|
||||||
|
ck_assert_msg(dup_map->nested_offset == 2, "dup_map nested_offset is incorrect: %zu", dup_map->nested_offset);
|
||||||
|
ck_assert_msg(dup_map->len == 4, "dup_map len is incorrect: %zu", dup_map->len);
|
||||||
|
ck_assert_msg(dup_map->real_len == 6, "dup_map real len is incorrect: %zu", dup_map->real_len);
|
||||||
|
|
||||||
|
bread = fmap_readn(dup_map, tmp, 0, 6);
|
||||||
|
ck_assert(bread == 4);
|
||||||
|
ck_assert(0 == memcmp(map_data + 2, tmp, 4));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test duplicate of the duplicate omiting the last 2 bytes again (so just the middle 2 bytes)
|
||||||
|
*/
|
||||||
|
cli_dbgmsg("duplicating dup_map with shorter len\n");
|
||||||
|
dup_dup_map = fmap_duplicate(dup_map, 0, dup_map->len - 2, "offset short duplicate");
|
||||||
|
ck_assert_msg(!!dup_dup_map, "fmap_duplicate failed");
|
||||||
|
ck_assert_msg(dup_dup_map->nested_offset == 2, "dup_dup_map nested_offset is incorrect: %zu", dup_map->nested_offset);
|
||||||
|
ck_assert_msg(dup_dup_map->len == 2, "dup_dup_map len is incorrect: %zu", dup_map->len);
|
||||||
|
ck_assert_msg(dup_dup_map->real_len == 6, "dup_dup_map real len is incorrect: %zu", dup_map->real_len);
|
||||||
|
|
||||||
|
bread = fmap_readn(dup_dup_map, tmp, 0, 6);
|
||||||
|
ck_assert(bread == 2);
|
||||||
|
ck_assert(0 == memcmp(map_data + 2, tmp, 2));
|
||||||
|
|
||||||
|
cli_dbgmsg("freeing dup_dup_map\n");
|
||||||
|
free_duplicate_fmap(dup_dup_map);
|
||||||
|
dup_dup_map = NULL;
|
||||||
|
cli_dbgmsg("freeing dup_map\n");
|
||||||
|
free_duplicate_fmap(dup_map);
|
||||||
|
dup_map = NULL;
|
||||||
|
|
||||||
|
cli_dbgmsg("freeing map\n");
|
||||||
|
cl_fmap_close(map);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_fmap_duplicate_out_of_bounds)
|
||||||
|
{
|
||||||
|
cl_fmap_t *map;
|
||||||
|
cl_fmap_t *dup_map = NULL;
|
||||||
|
cl_fmap_t *dup_dup_map = NULL;
|
||||||
|
char map_data[6] = {'a', 'b', 'c', 'd', 'e', 'f'};
|
||||||
|
char tmp[6];
|
||||||
|
size_t bread = 0;
|
||||||
|
|
||||||
|
map = cl_fmap_open_memory(map_data, sizeof(map_data));
|
||||||
|
ck_assert_msg(!!map, "cl_fmap_open_handle failed");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test 0-byte duplicate
|
||||||
|
*/
|
||||||
|
cli_dbgmsg("duplicating 0 bytes of map\n");
|
||||||
|
dup_map = fmap_duplicate(map, 0, 0, "zero-byte dup");
|
||||||
|
ck_assert_msg(!!dup_map, "fmap_duplicate failed");
|
||||||
|
ck_assert_msg(dup_map->nested_offset == 0, "dup_map nested_offset is incorrect: %zu", dup_map->nested_offset);
|
||||||
|
ck_assert_msg(dup_map->len == 0, "dup_map len is incorrect: %zu", dup_map->len);
|
||||||
|
ck_assert_msg(dup_map->real_len == map->len, "dup_map real len is incorrect: %zu", dup_map->real_len);
|
||||||
|
|
||||||
|
bread = fmap_readn(dup_map, tmp, 0, 6);
|
||||||
|
ck_assert(bread == 0);
|
||||||
|
|
||||||
|
cli_dbgmsg("freeing dup_map\n");
|
||||||
|
free_duplicate_fmap(dup_map);
|
||||||
|
dup_map = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test duplicate of entire map + 1
|
||||||
|
*/
|
||||||
|
cli_dbgmsg("duplicating complete map + 1 byte\n");
|
||||||
|
dup_map = fmap_duplicate(map, 0, map->len + 1, "duplicate + 1");
|
||||||
|
ck_assert_msg(!!dup_map, "fmap_duplicate failed");
|
||||||
|
ck_assert_msg(dup_map->nested_offset == 0, "dup_map nested_offset is incorrect: %zu", dup_map->nested_offset);
|
||||||
|
ck_assert_msg(dup_map->len == map->len, "dup_map len is incorrect: %zu", dup_map->len);
|
||||||
|
ck_assert_msg(dup_map->real_len == map->len, "dup_map real len is incorrect: %zu", dup_map->real_len);
|
||||||
|
|
||||||
|
bread = fmap_readn(dup_map, tmp, 0, 6);
|
||||||
|
ck_assert(bread == 6);
|
||||||
|
ck_assert(0 == memcmp(map_data, tmp, 6));
|
||||||
|
|
||||||
|
cli_dbgmsg("freeing dup_map\n");
|
||||||
|
free_duplicate_fmap(dup_map);
|
||||||
|
dup_map = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test duplicate of map at offset 4
|
||||||
|
*/
|
||||||
|
cli_dbgmsg("duplicating 4 bytes into map\n");
|
||||||
|
dup_map = fmap_duplicate(map, 4, map->len, "offset duplicate");
|
||||||
|
ck_assert_msg(!!dup_map, "fmap_duplicate failed");
|
||||||
|
ck_assert_msg(dup_map->nested_offset == 4, "dup_map nested_offset is incorrect: %zu", dup_map->nested_offset);
|
||||||
|
ck_assert_msg(dup_map->len == 2, "dup_map len is incorrect: %zu", dup_map->len);
|
||||||
|
ck_assert_msg(dup_map->real_len == 6, "dup_map real len is incorrect: %zu", dup_map->real_len);
|
||||||
|
|
||||||
|
bread = fmap_readn(dup_map, tmp, 0, 6);
|
||||||
|
ck_assert(bread == 2);
|
||||||
|
ck_assert(0 == memcmp(map_data + 4, tmp, 2));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test duplicate of duplicate map, also at offset 4 (total 8 bytes in, which is 2 bytes too far)
|
||||||
|
*/
|
||||||
|
cli_dbgmsg("duplicating 4 bytes into dup_map\n");
|
||||||
|
dup_dup_map = fmap_duplicate(dup_map, 4, dup_map->len, "out of bounds offset duplicate");
|
||||||
|
ck_assert_msg(NULL == dup_dup_map, "fmap_duplicate should have failed!");
|
||||||
|
|
||||||
|
cli_dbgmsg("freeing dup_map\n");
|
||||||
|
free_duplicate_fmap(dup_map);
|
||||||
|
dup_map = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test duplicate just 2 bytes of the original
|
||||||
|
*/
|
||||||
|
cli_dbgmsg("duplicating map with shorter len\n");
|
||||||
|
dup_map = fmap_duplicate(map, 0, 2, "short duplicate");
|
||||||
|
ck_assert_msg(!!dup_map, "fmap_duplicate failed");
|
||||||
|
ck_assert_msg(dup_map->nested_offset == 0, "dup_map nested_offset is incorrect: %zu", dup_map->nested_offset);
|
||||||
|
ck_assert_msg(dup_map->len == 2, "dup_map len is incorrect: %zu", dup_map->len);
|
||||||
|
ck_assert_msg(dup_map->real_len == 6, "dup_map real len is incorrect: %zu", dup_map->real_len);
|
||||||
|
|
||||||
|
bread = fmap_readn(dup_map, tmp, 0, 6);
|
||||||
|
ck_assert(bread == 2);
|
||||||
|
ck_assert(0 == memcmp(map_data, tmp, 2));
|
||||||
|
|
||||||
|
/* Note: Keeping the previous dup_map around for a sequence of double-dup tests. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test duplicate 1 bytes into the 2-byte duplicate, requesting 2 bytes
|
||||||
|
* This should result in a 1-byte double-dup
|
||||||
|
*/
|
||||||
|
cli_dbgmsg("duplicating 1 byte in, 1 too many\n");
|
||||||
|
dup_dup_map = fmap_duplicate(dup_map, 1, 2, "1 byte in, 1 too many");
|
||||||
|
ck_assert_msg(!!dup_dup_map, "fmap_duplicate failed");
|
||||||
|
ck_assert_msg(dup_dup_map->nested_offset == 1, "dup_dup_map nested_offset is incorrect: %zu", dup_dup_map->nested_offset);
|
||||||
|
ck_assert_msg(dup_dup_map->len == 1, "dup_dup_map len is incorrect: %zu", dup_dup_map->len);
|
||||||
|
ck_assert_msg(dup_dup_map->real_len == 6, "dup_dup_map real len is incorrect: %zu", dup_dup_map->real_len);
|
||||||
|
|
||||||
|
bread = fmap_readn(dup_dup_map, tmp, 0, 6);
|
||||||
|
ck_assert(bread == 1);
|
||||||
|
ck_assert(0 == memcmp(map_data + 1, tmp, 1));
|
||||||
|
|
||||||
|
cli_dbgmsg("freeing dup_dup_map\n");
|
||||||
|
free_duplicate_fmap(dup_dup_map);
|
||||||
|
dup_dup_map = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test duplicate 2 bytes into the 2-byte duplicate, requesting 2 bytes
|
||||||
|
* This should result in a 0-byte double-dup
|
||||||
|
*/
|
||||||
|
cli_dbgmsg("duplicating 2 bytes in, 2 bytes too many\n");
|
||||||
|
dup_dup_map = fmap_duplicate(dup_map, 2, 2, "2 bytes in, 2 bytes too many");
|
||||||
|
ck_assert_msg(!!dup_dup_map, "fmap_duplicate failed");
|
||||||
|
ck_assert_msg(dup_dup_map->nested_offset == 2, "dup_dup_map nested_offset is incorrect: %zu", dup_dup_map->nested_offset);
|
||||||
|
ck_assert_msg(dup_dup_map->len == 0, "dup_dup_map len is incorrect: %zu", dup_dup_map->len);
|
||||||
|
ck_assert_msg(dup_dup_map->real_len == 6, "dup_dup_map real len is incorrect: %zu", dup_dup_map->real_len);
|
||||||
|
|
||||||
|
bread = fmap_readn(dup_dup_map, tmp, 0, 6);
|
||||||
|
ck_assert(bread == 0);
|
||||||
|
|
||||||
|
cli_dbgmsg("freeing dup_dup_map\n");
|
||||||
|
free_duplicate_fmap(dup_dup_map);
|
||||||
|
dup_dup_map = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test duplicate 3 bytes into the 2-byte duplicate, requesting 2 bytes
|
||||||
|
*/
|
||||||
|
cli_dbgmsg("duplicating 0-byte of duplicate\n");
|
||||||
|
dup_dup_map = fmap_duplicate(dup_map, 3, 2, "2 bytes in, 3 bytes too many");
|
||||||
|
ck_assert_msg(NULL == dup_dup_map, "fmap_duplicate should have failed!");
|
||||||
|
|
||||||
|
/* Ok, we're done with this dup_map */
|
||||||
|
cli_dbgmsg("freeing dup_map\n");
|
||||||
|
free_duplicate_fmap(dup_map);
|
||||||
|
dup_map = NULL;
|
||||||
|
|
||||||
|
cli_dbgmsg("freeing map\n");
|
||||||
|
cl_fmap_close(map);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_cl_scanmap_callback_handle_allscan)
|
START_TEST(test_cl_scanmap_callback_handle_allscan)
|
||||||
{
|
{
|
||||||
const char *virname = NULL;
|
const char *virname = NULL;
|
||||||
|
@ -710,6 +992,8 @@ static Suite *test_cl_suite(void)
|
||||||
tcase_add_loop_test(tc_cl_scan, test_cl_scanmap_callback_handle_allscan, 0, expect);
|
tcase_add_loop_test(tc_cl_scan, test_cl_scanmap_callback_handle_allscan, 0, expect);
|
||||||
tcase_add_loop_test(tc_cl_scan, test_cl_scanmap_callback_mem, 0, expect);
|
tcase_add_loop_test(tc_cl_scan, test_cl_scanmap_callback_mem, 0, expect);
|
||||||
tcase_add_loop_test(tc_cl_scan, test_cl_scanmap_callback_mem_allscan, 0, expect);
|
tcase_add_loop_test(tc_cl_scan, test_cl_scanmap_callback_mem_allscan, 0, expect);
|
||||||
|
tcase_add_loop_test(tc_cl_scan, test_fmap_duplicate, 0, expect);
|
||||||
|
tcase_add_loop_test(tc_cl_scan, test_fmap_duplicate_out_of_bounds, 0, expect);
|
||||||
|
|
||||||
user_timeout = getenv("T");
|
user_timeout = getenv("T");
|
||||||
if (user_timeout) {
|
if (user_timeout) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue