Enhance DDT processing in ddt_v1.c and ddt_v2.c with improved error handling for LZMA compression

This commit is contained in:
2025-10-08 19:46:07 +01:00
parent 69c0b53e1b
commit 15885c76a2
2 changed files with 71 additions and 14 deletions

View File

@@ -20,6 +20,7 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "errors.h"
#ifdef __linux__
#include <sys/mman.h>
@@ -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)

View File

@@ -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;