diff --git a/inc/crn_decomp.h b/inc/crn_decomp.h index c3269688..10db6000 100644 --- a/inc/crn_decomp.h +++ b/inc/crn_decomp.h @@ -2204,7 +2204,7 @@ const crn_header* crnd_get_header(const void* pData, uint32 data_size) { return &file_header; } -bool crnd_validate_file(const void* pData, uint32 data_size, crn_file_info* pFile_info) { +bool crnd_validate_header(const void* pData, uint32 data_size, crn_file_info* pFile_info) { if (pFile_info) { if (pFile_info->m_struct_size != sizeof(crn_file_info)) return false; @@ -2223,10 +2223,8 @@ bool crnd_validate_file(const void* pData, uint32 data_size, crn_file_info* pFil if (header_crc != pHeader->m_header_crc16) return false; - const uint32 data_crc = crc16((const uint8*)pData + pHeader->m_header_size, pHeader->m_data_size - pHeader->m_header_size); - if (data_crc != pHeader->m_data_crc16) - return false; - + if (pHeader->m_data_size < pHeader->m_header_size) + return false; if ((pHeader->m_faces != 1) && (pHeader->m_faces != 6)) return false; if ((pHeader->m_width < 1) || (pHeader->m_width > cCRNMaxLevelResolution)) @@ -2268,6 +2266,20 @@ bool crnd_validate_file(const void* pData, uint32 data_size, crn_file_info* pFil return true; } +bool crnd_validate_file(const void* pData, uint32 data_size, crn_file_info* pFile_info) { + if (!crnd_validate_header(pData, data_size, pFile_info)) + return false; + + // was already validated by crnd_get_header + const crn_header* pHeader = static_cast(pData); + + if (pHeader->m_data_size > data_size) + return false; + + const uint32 data_crc = crc16((const uint8*)pData + pHeader->m_header_size, pHeader->m_data_size - pHeader->m_header_size); + return data_crc == pHeader->m_data_crc16; +} + bool crnd_get_texture_info(const void* pData, uint32 data_size, crn_texture_info* pInfo) { if ((!pData) || (data_size < sizeof(crn_header)) || (!pInfo)) return false; diff --git a/inc/crn_defs.h b/inc/crn_defs.h index 1000cbbf..4b676d76 100644 --- a/inc/crn_defs.h +++ b/inc/crn_defs.h @@ -113,7 +113,14 @@ uint32 crnd_get_crn_format_bits_per_texel(crn_format fmt); // Returns the number of bytes per DXTn block (8 or 16). uint32 crnd_get_bytes_per_dxt_block(crn_format fmt); -// Validates the entire file by checking the header and data CRC's. +// Validates the file header, performing a CRC check on it and verifying that there is +// e.g. a sane number of levels. +// pData/data_size need only include the header, but may be the whole file. +// The crn_file_info.m_struct_size field must be set before calling this function. +bool crnd_validate_header(const void* pData, uint32 data_size, crn_file_info* pFile_info); + +// Validates the entire file by calling crnd_validate_header, then checking the data CRC +// for the whole file. // This is not something you want to be doing much! // The crn_file_info.m_struct_size field must be set before calling this function. bool crnd_validate_file(const void* pData, uint32 data_size, crn_file_info* pFile_info);