diff --git a/src/ddt/ddt_v1.c b/src/ddt/ddt_v1.c index f648480..33bb58c 100644 --- a/src/ddt/ddt_v1.c +++ b/src/ddt/ddt_v1.c @@ -20,6 +20,7 @@ #include #include #include +#include "errors.h" #ifdef __linux__ #include @@ -141,6 +142,12 @@ int32_t process_ddt_v1(aaruformatContext *ctx, IndexEntry *entry, bool *found_us { // TODO: Check CRC case Lzma: + if(ddt_header.cmpLength <= LZMA_PROPERTIES_LENGTH) + { + FATAL("Compressed DDT payload too small (%" PRIu64 ") for LZMA properties.", ddt_header.cmpLength); + return AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK; + } + lzma_size = ddt_header.cmpLength - LZMA_PROPERTIES_LENGTH; cmp_data = (uint8_t *)malloc(lzma_size); @@ -201,6 +208,9 @@ int32_t process_ddt_v1(aaruformatContext *ctx, IndexEntry *entry, bool *found_us return AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK; } + free(cmp_data); + cmp_data = NULL; + ctx->inMemoryDdt = true; *found_user_data_ddt = true; @@ -239,6 +249,12 @@ int32_t process_ddt_v1(aaruformatContext *ctx, IndexEntry *entry, bool *found_us { // TODO: Check CRC case Lzma: + if(ddt_header.cmpLength <= LZMA_PROPERTIES_LENGTH) + { + FATAL("Compressed DDT payload too small (%" PRIu64 ") for LZMA properties.", ddt_header.cmpLength); + return AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK; + } + lzma_size = ddt_header.cmpLength - LZMA_PROPERTIES_LENGTH; cmp_data = (uint8_t *)malloc(lzma_size); @@ -295,6 +311,9 @@ int32_t process_ddt_v1(aaruformatContext *ctx, IndexEntry *entry, bool *found_us return AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK; } + free(cmp_data); + cmp_data = NULL; + if(entry->dataType == CdSectorPrefixCorrected) ctx->sectorPrefixDdt = cd_ddt; else if(entry->dataType == CdSectorSuffixCorrected) @@ -397,10 +416,24 @@ int32_t decode_ddt_entry_v1(aaruformatContext *ctx, const uint64_t sector_addres return AARUF_ERROR_NOT_AARUFORMAT; } - const uint64_t ddt_entry = ctx->userDataDdt[sector_address]; - const uint32_t offset_mask = (uint32_t)((1 << ctx->shift) - 1); - *offset = ddt_entry & offset_mask; - *block_offset = ddt_entry >> ctx->shift; + if(ctx->userDataDdt == NULL) + { + FATAL("User data DDT not loaded."); + TRACE("Exiting decode_ddt_entry_v1() = AARUF_ERROR_NOT_AARUFORMAT"); + return AARUF_ERROR_NOT_AARUFORMAT; + } + + if(ctx->shift >= 64) + { + FATAL("Invalid DDT shift value %u", ctx->shift); + TRACE("Exiting decode_ddt_entry_v1() = AARUF_ERROR_INCORRECT_DATA_SIZE"); + return AARUF_ERROR_INCORRECT_DATA_SIZE; + } + + const uint64_t ddt_entry = ctx->userDataDdt[sector_address]; + const uint64_t offset_mask64 = (UINT64_C(1) << ctx->shift) - UINT64_C(1); + *offset = ddt_entry & offset_mask64; + *block_offset = ddt_entry >> ctx->shift; // Partially written image... as we can't know the real sector size just assume it's common :/ if(ddt_entry == 0) diff --git a/src/ddt/ddt_v2.c b/src/ddt/ddt_v2.c index 8cb72f2..a1d06e5 100644 --- a/src/ddt/ddt_v2.c +++ b/src/ddt/ddt_v2.c @@ -158,7 +158,14 @@ int32_t process_ddt_v2(aaruformatContext *ctx, IndexEntry *entry, bool *found_us switch(ddt_header.compression) { case Lzma: - lzma_size = ddt_header.cmpLength - LZMA_PROPERTIES_LENGTH; + if(ddt_header.cmpLength <= LZMA_PROPERTIES_LENGTH) + { + FATAL("Compressed DDT payload too small (%" PRIu64 ") for LZMA properties.", ddt_header.cmpLength); + TRACE("Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK"); + return AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK; + } + + lzma_size = (size_t)(ddt_header.cmpLength - LZMA_PROPERTIES_LENGTH); cmp_data = (uint8_t *)malloc(lzma_size); if(cmp_data == NULL) @@ -309,7 +316,14 @@ int32_t process_ddt_v2(aaruformatContext *ctx, IndexEntry *entry, bool *found_us switch(ddt_header.compression) { case Lzma: - lzma_size = ddt_header.cmpLength - LZMA_PROPERTIES_LENGTH; + if(ddt_header.cmpLength <= LZMA_PROPERTIES_LENGTH) + { + FATAL("Compressed DDT payload too small (%" PRIu64 ") for LZMA properties.", ddt_header.cmpLength); + TRACE("Exiting process_ddt_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK"); + return AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK; + } + + lzma_size = (size_t)(ddt_header.cmpLength - LZMA_PROPERTIES_LENGTH); cmp_data = (uint8_t *)malloc(lzma_size); if(cmp_data == NULL) @@ -367,6 +381,9 @@ int32_t process_ddt_v2(aaruformatContext *ctx, IndexEntry *entry, bool *found_us return AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK; } + free(cmp_data); + cmp_data = NULL; + crc64_context = aaruf_crc64_init(); if(crc64_context == NULL) @@ -825,14 +842,14 @@ int32_t decode_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_addres if(read_bytes != sizeof(DdtHeader2)) { - FATAL("Could not read block header at %" PRIu64 "", secondaryDdtOffset); + FATAL("Could not read block header at %" PRIu64 "", secondary_ddt_offset); TRACE("Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_READ_BLOCK"); return AARUF_ERROR_CANNOT_READ_BLOCK; } if(ddt_header.identifier != DeDuplicationTable2 || ddt_header.type != UserData) { - FATAL("Invalid block header at %" PRIu64 "", secondaryDdtOffset); + FATAL("Invalid block header at %" PRIu64 "", secondary_ddt_offset); TRACE("Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_READ_BLOCK"); return AARUF_ERROR_CANNOT_READ_BLOCK; } @@ -841,7 +858,14 @@ int32_t decode_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_addres switch(ddt_header.compression) { case Lzma: - lzma_size = ddt_header.cmpLength - LZMA_PROPERTIES_LENGTH; + if(ddt_header.cmpLength <= LZMA_PROPERTIES_LENGTH) + { + FATAL("Compressed DDT payload too small (%" PRIu64 ") for LZMA properties.", ddt_header.cmpLength); + TRACE("Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK"); + return AARUF_ERROR_CANNOT_DECOMPRESS_BLOCK; + } + + lzma_size = (size_t)(ddt_header.cmpLength - LZMA_PROPERTIES_LENGTH); cmp_data = (uint8_t *)malloc(lzma_size); if(cmp_data == NULL) @@ -919,7 +943,7 @@ int32_t decode_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_addres if(crc64 != ddt_header.crc64) { - FATAL("Expected DDT CRC 0x%16lX but got 0x%16lX.", ddtHeader.crc64, crc64); + FATAL("Expected DDT CRC 0x%16lX but got 0x%16lX.", ddt_header.crc64, crc64); free(buffer); TRACE("Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_INVALID_BLOCK_CRC"); return AARUF_ERROR_INVALID_BLOCK_CRC; @@ -968,7 +992,7 @@ int32_t decode_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_addres if(crc64 != ddt_header.crc64) { - FATAL("Expected DDT CRC 0x%16lX but got 0x%16lX.", ddtHeader.crc64, crc64); + FATAL("Expected DDT CRC 0x%16lX but got 0x%16lX.", ddt_header.crc64, crc64); free(buffer); TRACE("Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_INVALID_BLOCK_CRC"); return AARUF_ERROR_INVALID_BLOCK_CRC; @@ -983,7 +1007,7 @@ int32_t decode_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_addres break; default: - FATAL("Found unknown compression type %d, stopping...", ddtHeader.compression); + FATAL("Found unknown compression type %d, stopping...", ddt_header.compression); TRACE("Exiting decode_ddt_multi_level_v2() = AARUF_ERROR_CANNOT_READ_BLOCK"); return AARUF_ERROR_CANNOT_READ_BLOCK; } @@ -1719,7 +1743,7 @@ bool set_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_address, boo if(read_bytes != sizeof(DdtHeader2) || ddt_header.identifier != DeDuplicationTable2 || ddt_header.type != UserData) { - FATAL("Invalid secondary DDT header at %" PRIu64, secondaryDdtOffset); + FATAL("Invalid secondary DDT header at %" PRIu64, secondary_ddt_offset); TRACE("Exiting set_ddt_multi_level_v2() = false"); return false; } @@ -1757,7 +1781,7 @@ bool set_ddt_multi_level_v2(aaruformatContext *ctx, uint64_t sector_address, boo if(crc64 != ddt_header.crc64) { - FATAL("Secondary DDT CRC mismatch. Expected 0x%16lX but got 0x%16lX.", ddtHeader.crc64, crc64); + FATAL("Secondary DDT CRC mismatch. Expected 0x%16lX but got 0x%16lX.", ddt_header.crc64, crc64); free(buffer); TRACE("Exiting set_ddt_multi_level_v2() = false"); return false;