void cab_free(struct cab_archive *cab) { struct cab_folder *folder; struct cab_file *file; if(cab->state) { if(cab->state->stream) { switch(cab->state->cmethod & 0x000f) { case 0x0001: mszip_free(cab->state->stream); break; case 0x0002: qtm_free(cab->state->stream); break; case 0x0003: lzx_free(cab->state->stream); } } free(cab->state); } while(cab->folders) { folder = cab->folders; cab->folders = cab->folders->next; free(folder); } while(cab->files) { file = cab->files; cab->files = cab->files->next; free(file->name); free(file); } }
static int chm_decompress_stream(int fd, chm_metadata_t *metadata, const char *dirname, cli_ctx *ctx) { lzx_content_t lzx_content; lzx_reset_table_t lzx_reset_table; lzx_control_t lzx_control; int window_bits, length, tmpfd, retval=-1; struct lzx_stream * stream; char filename[1024]; struct cab_file file; snprintf(filename, 1024, "%s"PATHSEP"clamav-unchm.bin", dirname); tmpfd = open(filename, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU); if (tmpfd<0) { cli_dbgmsg("open failed for %s\n", filename); return -1; } if (!metadata->sys_control.length || !metadata->sys_content.length ||!metadata->sys_reset.length) { cli_dbgmsg("Control file missing\n"); goto abort; } if (!read_sys_control(metadata, &lzx_control)) { goto abort; } if (!read_sys_content(metadata, &lzx_content)) { goto abort; } if (!read_sys_reset_table(metadata, &lzx_reset_table)) { goto abort; } switch (lzx_control.window_size) { case 0x008000: window_bits = 15; break; case 0x010000: window_bits = 16; break; case 0x020000: window_bits = 17; break; case 0x040000: window_bits = 18; break; case 0x080000: window_bits = 19; break; case 0x100000: window_bits = 20; break; case 0x200000: window_bits = 21; break; default: cli_dbgmsg("bad control window size: 0x%x\n", lzx_control.window_size); goto abort; } if (lzx_control.reset_interval % LZX_FRAME_SIZE) { cli_dbgmsg("bad reset_interval: 0x%x\n", lzx_control.window_size); goto abort; } length = lzx_reset_table.uncom_len; length += lzx_control.reset_interval; length &= -lzx_control.reset_interval; cli_dbgmsg("Compressed offset: %lu\n", (unsigned long int) lzx_content.offset); if ((uint64_t) lseek(fd, lzx_content.offset, SEEK_SET) != lzx_content.offset) { goto abort; } memset(&file, 0, sizeof(struct cab_file)); file.max_size = ctx->engine->maxfilesize; stream = lzx_init(fd, tmpfd, window_bits, lzx_control.reset_interval / LZX_FRAME_SIZE, 4096, length, &file, NULL); if (!stream) { cli_dbgmsg("lzx_init failed\n"); goto abort; } lzx_decompress(stream, length); lzx_free(stream); #ifndef _WIN32 /* Delete the file */ if(cli_unlink(filename)) retval = -1; else #endif retval = tmpfd; abort: if ((retval == -1) && (tmpfd >= 0)) { close(tmpfd); } return retval; }