Re-introduce checksum validation

This commit is contained in:
Ted John 2017-01-31 20:19:26 +00:00
parent fed4c248e3
commit bb62bbebb3
3 changed files with 44 additions and 20 deletions

View File

@ -97,4 +97,41 @@ namespace SawyerEncoding
}
return success;
}
bool ValidateChecksum(IStream * stream)
{
// Get data size
uint64 initialPosition = stream->GetPosition();
uint64 dataSize = stream->GetLength() - initialPosition;
if (dataSize < 8)
{
return false;
}
dataSize -= 4;
// Calculate checksum
uint32 checksum = 0;
do
{
uint8 buffer[4096];
uint64 bufferSize = Math::Min(dataSize, sizeof(buffer));
stream->Read(buffer, bufferSize);
for (uint64 i = 0; i < bufferSize; i++)
{
checksum += buffer[i];
}
dataSize -= bufferSize;
}
while (dataSize != 0);
// Read file checksum
uint32 fileChecksum = stream->ReadValue<uint32>();
// Rewind
stream->SetPosition(initialPosition);
return checksum == fileChecksum;
}
}

View File

@ -31,4 +31,6 @@ namespace SawyerEncoding
{
return TryReadChunk(dst, sizeof(T), stream);
}
bool ValidateChecksum(IStream * stream);
}

View File

@ -85,15 +85,6 @@ public:
void LoadSavedGame(const utf8 * path) override
{
// if (!sawyercoding_validate_checksum(rw))
// {
// gErrorType = ERROR_TYPE_FILE_LOAD;
// gGameCommandErrorTitle = STR_FILE_CONTAINS_INVALID_DATA;
//
// log_error("failed to load saved game, invalid checksum");
// throw IOException("Invalid SV6 checksum.");
// }
auto fs = FileStream(path, FILE_MODE_OPEN);
LoadFromStream(&fs, false);
_s6Path = path;
@ -101,17 +92,6 @@ public:
void LoadScenario(const utf8 * path) override
{
// if (!gConfigGeneral.allow_loading_with_incorrect_checksum && !sawyercoding_validate_checksum(rw))
// {
// SDL_RWclose(rw);
//
// gErrorType = ERROR_TYPE_FILE_LOAD;
// gErrorStringId = STR_FILE_CONTAINS_INVALID_DATA;
//
// log_error("failed to load scenario, invalid checksum");
// throw IOException("Invalid SC6 checksum.");
// }
auto fs = FileStream(path, FILE_MODE_OPEN);
LoadFromStream(&fs, true);
_s6Path = path;
@ -119,6 +99,11 @@ public:
void LoadFromStream(IStream * stream, bool isScenario)
{
if (!gConfigGeneral.allow_loading_with_incorrect_checksum && !SawyerEncoding::ValidateChecksum(stream))
{
throw IOException("Invalid checksum.");
}
SawyerEncoding::ReadChunkTolerant(&_s6.header, sizeof(_s6.header), stream);
log_verbose("saved game classic_flag = 0x%02x\n", _s6.header.classic_flag);