mirror of
https://github.com/Cisco-Talos/clamav.git
synced 2025-10-19 10:23:17 +00:00
Fix ZIP parser issue recording empty file entries
If csize (and usize) are 0, like with a directory or other empty file entry, then the functionionality to record file record information when indexing the central directory and each associated file record will neglect to store the `local_header_offset` or `local_header_size`. That causes problems later after sorting the file records and then checking for overlapping files. CLAM-2884
This commit is contained in:
parent
87e389d1b2
commit
e98b0075e6
1 changed files with 33 additions and 30 deletions
|
@ -717,17 +717,35 @@ static cl_error_t parse_local_file_header(
|
||||||
zip += LOCAL_HEADER_elen;
|
zip += LOCAL_HEADER_elen;
|
||||||
bytes_remaining -= LOCAL_HEADER_elen;
|
bytes_remaining -= LOCAL_HEADER_elen;
|
||||||
|
|
||||||
if (!csize) { /* FIXME: what's used for method0 files? csize or usize? Nothing in the specs, needs testing */
|
|
||||||
cli_dbgmsg("cli_unzip: local header - skipping empty file\n");
|
|
||||||
} else {
|
|
||||||
if (bytes_remaining < csize) {
|
if (bytes_remaining < csize) {
|
||||||
cli_dbgmsg("cli_unzip: local header - stream out of file\n");
|
cli_dbgmsg("cli_unzip: local header - stream out of file\n");
|
||||||
status = CL_EPARSE;
|
status = CL_EPARSE;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (NULL != record) {
|
||||||
/* Don't actually unzip if we're just collecting the file record information (offset, sizes) */
|
/* Don't actually unzip if we're just collecting the file record information (offset, sizes) */
|
||||||
if (NULL == record) {
|
if (NULL == original_filename) {
|
||||||
|
record->original_filename = NULL;
|
||||||
|
} else {
|
||||||
|
record->original_filename = CLI_STRNDUP(original_filename, strlen(original_filename));
|
||||||
|
}
|
||||||
|
record->local_header_offset = loff;
|
||||||
|
record->local_header_size = zip - local_header;
|
||||||
|
record->compressed_size = csize;
|
||||||
|
record->uncompressed_size = usize;
|
||||||
|
record->method = LOCAL_HEADER_method;
|
||||||
|
record->flags = LOCAL_HEADER_flags;
|
||||||
|
record->encrypted = (LOCAL_HEADER_flags & F_ENCR) ? 1 : 0;
|
||||||
|
|
||||||
|
status = CL_SUCCESS;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Unzip or decompress & then unzip.
|
||||||
|
*/
|
||||||
|
if (!csize) { /* FIXME: what's used for method0 files? csize or usize? Nothing in the specs, needs testing */
|
||||||
|
cli_dbgmsg("cli_unzip: local header - skipping empty file\n");
|
||||||
|
} else {
|
||||||
zip = fmap_need_ptr_once(ctx->fmap, zip, csize);
|
zip = fmap_need_ptr_once(ctx->fmap, zip, csize);
|
||||||
if (NULL == zip) {
|
if (NULL == zip) {
|
||||||
cli_dbgmsg("cli_unzip: local header - data out of file\n");
|
cli_dbgmsg("cli_unzip: local header - data out of file\n");
|
||||||
|
@ -751,26 +769,11 @@ static cl_error_t parse_local_file_header(
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if (NULL == original_filename) {
|
|
||||||
record->original_filename = NULL;
|
|
||||||
} else {
|
|
||||||
record->original_filename = CLI_STRNDUP(original_filename, strlen(original_filename));
|
|
||||||
}
|
}
|
||||||
record->local_header_offset = loff;
|
|
||||||
record->local_header_size = zip - local_header;
|
|
||||||
record->compressed_size = csize;
|
|
||||||
record->uncompressed_size = usize;
|
|
||||||
record->method = LOCAL_HEADER_method;
|
|
||||||
record->flags = LOCAL_HEADER_flags;
|
|
||||||
record->encrypted = (LOCAL_HEADER_flags & F_ENCR) ? 1 : 0;
|
|
||||||
|
|
||||||
status = CL_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
zip += csize;
|
zip += csize;
|
||||||
bytes_remaining -= csize;
|
bytes_remaining -= csize;
|
||||||
}
|
|
||||||
|
|
||||||
if (LOCAL_HEADER_flags & F_USEDD) {
|
if (LOCAL_HEADER_flags & F_USEDD) {
|
||||||
if (bytes_remaining < 12) {
|
if (bytes_remaining < 12) {
|
||||||
|
@ -910,8 +913,8 @@ static cl_error_t parse_central_directory_file_header(
|
||||||
|
|
||||||
central_header = fmap_need_off(ctx->fmap, central_file_header_offset, SIZEOF_CENTRAL_HEADER);
|
central_header = fmap_need_off(ctx->fmap, central_file_header_offset, SIZEOF_CENTRAL_HEADER);
|
||||||
if (NULL == central_header) {
|
if (NULL == central_header) {
|
||||||
cli_dbgmsg("cli_unzip: central header - file header offset out of file\n");
|
cli_dbgmsg("cli_unzip: central header - reached end of central directory.\n");
|
||||||
status = CL_EPARSE;
|
status = CL_BREAK;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue