Merge commit from fork

* Harden serializer deserialization bounds

* Finalize Unix serializer hardening

Validate object types before parsing and release owned objects on failure.
Enforce nesting limits through shared serialization entry points.

Mirror read/write size limits and reject embedded NULs while preserving
the wire format. Add regression tests for bounds, types, and cleanup.

Validated Linux self-tests, C++03 platform tests, and ASan/UBSan with leak
detection.

Co-authored-by: Damian Rickard <damian@rickard.us>

---------

Co-authored-by: Damian Rickard <damian@rickard.us>
Co-authored-by: Mounir IDRASSI <mounir.idrassi@amcrypto.jp>
This commit is contained in:
authored and GitHub committed 2026-09-30 20:12:20 +09:00
1 parent dea8fb0dc0
commit fb9d96c52d
25 files changed
+738 -171

No files matched your search

+8 -8
View File
@@ -136,18 +136,18 @@ namespace VeraCrypt
#ifdef TC_HEADER_Platform_Exception
void PCSCException::Deserialize(shared_ptr <Stream> stream)
void PCSCException::DeserializeData(shared_ptr <Stream> stream)
{
Exception::Deserialize(stream);
Exception::DeserializeData(stream);
Serializer sr(stream);
int64 v;
sr.Deserialize("ErrorCode", v);
ErrorCode = (LONG_PCSC)v;
}
void PCSCException::Serialize(shared_ptr <Stream> stream) const
void PCSCException::SerializeData(shared_ptr <Stream> stream) const
{
Exception::Serialize(stream);
Exception::SerializeData(stream);
Serializer sr(stream);
int64 v = (int64)ErrorCode;
sr.Serialize("ErrorCode", v);
@@ -176,17 +176,17 @@ namespace VeraCrypt
#ifdef TC_HEADER_Platform_Exception
void CommandAPDUNotValid::Deserialize(shared_ptr <Stream> stream)
void CommandAPDUNotValid::DeserializeData(shared_ptr <Stream> stream)
{
Exception::Deserialize(stream);
Exception::DeserializeData(stream);
Serializer sr(stream);
sr.Deserialize("SrcPos", SrcPos);
sr.Deserialize("ErrorStr", ErrorStr);
}
void CommandAPDUNotValid::Serialize(shared_ptr <Stream> stream) const
void CommandAPDUNotValid::SerializeData(shared_ptr <Stream> stream) const
{
Exception::Serialize(stream);
Exception::SerializeData(stream);
Serializer sr(stream);
sr.Serialize("SrcPos", SrcPos);
sr.Serialize("ErrorStr", ErrorStr);
+4 -4
View File
@@ -753,9 +753,9 @@ namespace VeraCrypt
#ifdef TC_HEADER_Platform_Exception
void Pkcs11Exception::Deserialize(shared_ptr <Stream> stream)
void Pkcs11Exception::DeserializeData(shared_ptr <Stream> stream)
{
Exception::Deserialize(stream);
Exception::DeserializeData(stream);
Serializer sr(stream);
uint64 code;
sr.Deserialize("ErrorCode", code);
@@ -764,9 +764,9 @@ namespace VeraCrypt
ErrorCode = (CK_RV)code;
}
void Pkcs11Exception::Serialize(shared_ptr <Stream> stream) const
void Pkcs11Exception::SerializeData(shared_ptr <Stream> stream) const
{
Exception::Serialize(stream);
Exception::SerializeData(stream);
Serializer sr(stream);
sr.Serialize("ErrorCode", (uint64)ErrorCode);
sr.Serialize("SubjectErrorCodeValid", SubjectErrorCodeValid);
+1
View File
@@ -13,6 +13,7 @@
OBJS :=
OBJS += CoreBase.o
OBJS += CoreException.o
OBJS += CoreTest.o
OBJS += FatFormatter.o
OBJS += HostDevice.o
OBJS += MountOptions.o
+8 -8
View File
@@ -15,24 +15,24 @@
namespace VeraCrypt
{
void ElevationFailed::Deserialize (shared_ptr <Stream> stream)
void ElevationFailed::DeserializeData (shared_ptr <Stream> stream)
{
ExecutedProcessFailed::Deserialize (stream);
ExecutedProcessFailed::DeserializeData (stream);
}
void ElevationFailed::Serialize (shared_ptr <Stream> stream) const
void ElevationFailed::SerializeData (shared_ptr <Stream> stream) const
{
ExecutedProcessFailed::Serialize (stream);
ExecutedProcessFailed::SerializeData (stream);
}
void FilesystemDismountFailed::Deserialize (shared_ptr <Stream> stream)
void FilesystemDismountFailed::DeserializeData (shared_ptr <Stream> stream)
{
ExecutedProcessFailed::Deserialize (stream);
ExecutedProcessFailed::DeserializeData (stream);
}
void FilesystemDismountFailed::Serialize (shared_ptr <Stream> stream) const
void FilesystemDismountFailed::SerializeData (shared_ptr <Stream> stream) const
{
ExecutedProcessFailed::Serialize (stream);
ExecutedProcessFailed::SerializeData (stream);
}
#define TC_EXCEPTION(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE)
+126
View File
@@ -0,0 +1,126 @@
/*
Copyright (c) 2026 AM Crypto. All rights reserved.
Governed by the Apache License 2.0, the full text of which is contained in
the file License.txt included in VeraCrypt binary and source distributions.
*/
#include "CoreTest.h"
#include "HostDevice.h"
#include "Platform/MemoryStream.h"
#include "Unix/CoreServiceRequest.h"
#include "Volume/VolumePassword.h"
namespace VeraCrypt
{
void CoreTest::HostDeviceTest ()
{
HostDevice device;
device.Name = L"Device";
device.SystemNumber = 0;
shared_ptr <HostDevice> partition (new HostDevice);
partition->Name = L"Partition";
partition->SystemNumber = 1;
device.Partitions.push_back (partition);
// Exercise real parent/child serialization at the nesting boundary using a
// shallow tree and reserved scopes, without constructing a deep input tree.
for (int attempt = 0; attempt < 2; ++attempt)
{
shared_ptr <Stream> stream (new MemoryStream);
vector < shared_ptr <SerializationScope> > scopes;
if (attempt != 0)
{
for (unsigned int i = 0; i < Serializer::MaxNestingDepth - 2; ++i)
scopes.push_back (shared_ptr <SerializationScope> (new SerializationScope (stream)));
}
device.Serialize (stream);
shared_ptr <HostDevice> result = Serializable::DeserializeNew <HostDevice> (stream);
if (result->Name != device.Name || result->Partitions.size() != 1
|| result->Partitions.front()->Name != partition->Name
|| result->Partitions.front()->SystemNumber != partition->SystemNumber)
throw TestFailed (SRC_POS);
}
for (int direction = 0; direction < 2; ++direction)
{
shared_ptr <Stream> stream (new MemoryStream);
device.Serialize (stream);
vector < shared_ptr <SerializationScope> > scopes;
for (unsigned int i = 0; i < Serializer::MaxNestingDepth - 1; ++i)
scopes.push_back (shared_ptr <SerializationScope> (new SerializationScope (stream)));
try
{
if (direction == 0)
Serializable::DeserializeNew <HostDevice> (stream);
else
device.Serialize (stream);
throw TestFailed (SRC_POS);
}
catch (ParameterIncorrect &) { }
scopes.clear();
SerializationScope reusable (stream);
}
device.Partitions.assign ((size_t) Serializer::MaxCollectionSize + 1, partition);
try
{
shared_ptr <Stream> stream (new MemoryStream);
device.Serialize (stream);
throw TestFailed (SRC_POS);
}
catch (ParameterIncorrect &) { }
}
void CoreTest::VolumePasswordTest ()
{
SecureBuffer password (VolumePassword::MaxSize);
for (size_t i = 0; i < password.Size(); ++i)
password[i] = (uint8) i;
const size_t sizes[] = { 0, VolumePassword::MaxLegacySize, VolumePassword::MaxSize };
for (size_t i = 0; i < array_capacity (sizes); ++i)
{
shared_ptr <Stream> stream (new MemoryStream);
VolumePassword original (password.Ptr(), sizes[i]);
original.Serialize (stream);
shared_ptr <VolumePassword> result = Serializable::DeserializeNew <VolumePassword> (stream);
if (*result != original)
throw TestFailed (SRC_POS);
}
shared_ptr <Stream> stream (new MemoryStream);
Serializer sr (stream);
Serializable::SerializeHeader (sr, "VolumePassword");
sr.Serialize ("PasswordSize", (uint64) VolumePassword::MaxSize + 1);
try
{
Serializable::DeserializeNew <VolumePassword> (stream);
throw TestFailed (SRC_POS);
}
catch (ParameterIncorrect &) { }
try
{
VolumePassword invalid (password.Ptr(), VolumePassword::MaxSize + 1);
throw TestFailed (SRC_POS);
}
catch (PasswordTooLong &) { }
}
void CoreTest::ServiceRequestTest ()
{
shared_ptr <Stream> stream (new MemoryStream);
GetDeviceSizeRequest request (DevicePath (L"/dev/test"));
request.Serialize (stream);
shared_ptr <CoreServiceRequest> result = Serializable::DeserializeNew <CoreServiceRequest> (stream);
GetDeviceSizeRequest *deviceRequest = dynamic_cast <GetDeviceSizeRequest *> (result.get());
if (!deviceRequest || deviceRequest->Path != request.Path)
throw TestFailed (SRC_POS);
}
void CoreTest::TestAll ()
{
HostDeviceTest();
VolumePasswordTest();
ServiceRequestTest();
}
}
+26
View File
@@ -0,0 +1,26 @@
/*
Copyright (c) 2026 AM Crypto. All rights reserved.
Governed by the Apache License 2.0, the full text of which is contained in
the file License.txt included in VeraCrypt binary and source distributions.
*/
#ifndef TC_HEADER_Core_CoreTest
#define TC_HEADER_Core_CoreTest
namespace VeraCrypt
{
class CoreTest
{
public:
static void TestAll ();
private:
CoreTest ();
static void HostDeviceTest ();
static void VolumePasswordTest ();
static void ServiceRequestTest ();
};
}
#endif // TC_HEADER_Core_CoreTest
+7 -4
View File
@@ -15,7 +15,7 @@
namespace VeraCrypt
{
void HostDevice::Deserialize (shared_ptr <Stream> stream)
void HostDevice::DeserializeData (shared_ptr <Stream> stream)
{
Serializer sr (stream);
MountPoint = sr.DeserializeWString ("MountPoint");
@@ -27,13 +27,16 @@ namespace VeraCrypt
uint32 partitionCount;
sr.Deserialize ("Partitions", partitionCount);
Serializer::ValidateCollectionSize (partitionCount);
HostDeviceList partitions;
for (uint32 i = 0; i < partitionCount; i++)
Partitions.push_back (Serializable::DeserializeNew <HostDevice> (stream));
partitions.push_back (Serializable::DeserializeNew <HostDevice> (stream));
Partitions.swap (partitions);
}
void HostDevice::Serialize (shared_ptr <Stream> stream) const
void HostDevice::SerializeData (shared_ptr <Stream> stream) const
{
Serializable::Serialize (stream);
Serializer::ValidateCollectionSize (Partitions.size());
Serializer sr (stream);
sr.Serialize ("MountPoint", wstring (MountPoint));
sr.Serialize ("Name", Name);
+2 -3
View File
@@ -58,7 +58,7 @@ namespace VeraCrypt
TC_CLONE (EMVSupportEnabled);
}
void MountOptions::Deserialize (shared_ptr <Stream> stream)
void MountOptions::DeserializeData (shared_ptr <Stream> stream)
{
Serializer sr (stream);
wstring nameValue;
@@ -132,9 +132,8 @@ namespace VeraCrypt
sr.Deserialize ("ProtectionPim", ProtectionPim);
}
void MountOptions::Serialize (shared_ptr <Stream> stream) const
void MountOptions::SerializeData (shared_ptr <Stream> stream) const
{
Serializable::Serialize (stream);
Serializer sr (stream);
sr.Serialize ("CachePassword", CachePassword);
+19 -9
View File
@@ -574,14 +574,12 @@ namespace VeraCrypt
if (errOutput.empty())
return;
unique_ptr <Serializable> deserializedObject;
Exception *deserializedException = nullptr;
shared_ptr <Exception> deserializedException;
try
{
shared_ptr <Stream> stream (new MemoryStream (ConstBufferPtr ((uint8 *) &errOutput[0], errOutput.size())));
deserializedObject.reset (Serializable::DeserializeNew (stream));
deserializedException = dynamic_cast <Exception*> (deserializedObject.get());
deserializedException = Serializable::DeserializeNew <Exception> (stream);
}
catch (...) { }
@@ -1076,9 +1074,21 @@ namespace VeraCrypt
}
#endif
unique_ptr <Serializable> CoreService::GetResponseObject ()
template <class T>
static bool IsResponseType (const Serializable &object)
{
unique_ptr <Serializable> deserializedObject (Serializable::DeserializeNew (ServiceOutputStream));
return Serializable::IsType <T> (object) || Serializable::IsType <Exception> (object);
}
template <class T>
static bool IsInitialResponseType (const Serializable &object)
{
return IsResponseType <T> (object) || Serializable::IsType <ElevatedServiceStartedResponse> (object);
}
unique_ptr <Serializable> CoreService::GetResponseObject (Serializable::TypeValidator isExpectedType)
{
unique_ptr <Serializable> deserializedObject (Serializable::DeserializeNew (ServiceOutputStream, isExpectedType));
Exception *deserializedException = dynamic_cast <Exception*> (deserializedObject.get());
if (deserializedException)
@@ -1090,7 +1100,7 @@ namespace VeraCrypt
template <class T>
unique_ptr <T> CoreService::GetResponse ()
{
unique_ptr <Serializable> deserializedObject (GetResponseObject());
unique_ptr <Serializable> deserializedObject (GetResponseObject (&IsResponseType <T>));
if (dynamic_cast <T *> (deserializedObject.get()) == nullptr)
throw ParameterIncorrect (SRC_POS);
@@ -1206,7 +1216,7 @@ namespace VeraCrypt
ElevatedServiceStartedResponse().Serialize (outputStream);
request->Serialize (ServiceInputStream);
GetResponse <Serializable>()->Serialize (outputStream);
GetResponse <CoreServiceResponse>()->Serialize (outputStream);
continue;
}
@@ -1500,7 +1510,7 @@ namespace VeraCrypt
{
request.Serialize (ServiceInputStream);
unique_ptr <Serializable> response (GetResponseObject());
unique_ptr <Serializable> response (GetResponseObject (&IsInitialResponseType <T>));
if (dynamic_cast <ElevatedServiceStartedResponse *> (response.get()) != nullptr)
{
// The elevated channel is usable even if the forwarded request fails.
+1 -1
View File
@@ -50,7 +50,7 @@ namespace VeraCrypt
static void Stop ();
protected:
static unique_ptr <Serializable> GetResponseObject ();
static unique_ptr <Serializable> GetResponseObject (Serializable::TypeValidator isExpectedType);
template <class T> static unique_ptr <T> GetResponse ();
template <class T> static unique_ptr <T> SendRequest (CoreServiceRequest &request);
static void StartElevated (const CoreServiceRequest &request);
+50 -51
View File
@@ -16,7 +16,7 @@
namespace VeraCrypt
{
void CoreServiceRequest::Deserialize (shared_ptr <Stream> stream)
void CoreServiceRequest::DeserializeData (shared_ptr <Stream> stream)
{
Serializer sr (stream);
sr.Deserialize ("AdminPassword", AdminPassword);
@@ -28,9 +28,8 @@ namespace VeraCrypt
sr.Deserialize ("AllowInsecureMount", AllowInsecureMount);
}
void CoreServiceRequest::Serialize (shared_ptr <Stream> stream) const
void CoreServiceRequest::SerializeData (shared_ptr <Stream> stream) const
{
Serializable::Serialize (stream);
Serializer sr (stream);
sr.Serialize ("AdminPassword", AdminPassword);
sr.Serialize ("ApplicationExecutablePath", wstring (ApplicationExecutablePath));
@@ -42,9 +41,9 @@ namespace VeraCrypt
}
// CheckFilesystemRequest
void CheckFilesystemRequest::Deserialize (shared_ptr <Stream> stream)
void CheckFilesystemRequest::DeserializeData (shared_ptr <Stream> stream)
{
CoreServiceRequest::Deserialize (stream);
CoreServiceRequest::DeserializeData (stream);
Serializer sr (stream);
MountedVolumeInfo = Serializable::DeserializeNew <VolumeInfo> (stream);
sr.Deserialize ("Repair", Repair);
@@ -58,18 +57,18 @@ namespace VeraCrypt
return !Core->HasAdminPrivileges();
}
void CheckFilesystemRequest::Serialize (shared_ptr <Stream> stream) const
void CheckFilesystemRequest::SerializeData (shared_ptr <Stream> stream) const
{
CoreServiceRequest::Serialize (stream);
CoreServiceRequest::SerializeData (stream);
Serializer sr (stream);
MountedVolumeInfo->Serialize (stream);
sr.Serialize ("Repair", Repair);
}
// DismountFilesystemRequest
void DismountFilesystemRequest::Deserialize (shared_ptr <Stream> stream)
void DismountFilesystemRequest::DeserializeData (shared_ptr <Stream> stream)
{
CoreServiceRequest::Deserialize (stream);
CoreServiceRequest::DeserializeData (stream);
Serializer sr (stream);
sr.Deserialize ("Force", Force);
MountPoint = sr.DeserializeWString ("MountPoint");
@@ -80,18 +79,18 @@ namespace VeraCrypt
return !Core->HasAdminPrivileges();
}
void DismountFilesystemRequest::Serialize (shared_ptr <Stream> stream) const
void DismountFilesystemRequest::SerializeData (shared_ptr <Stream> stream) const
{
CoreServiceRequest::Serialize (stream);
CoreServiceRequest::SerializeData (stream);
Serializer sr (stream);
sr.Serialize ("Force", Force);
sr.Serialize ("MountPoint", wstring (MountPoint));
}
// DismountVolumeRequest
void DismountVolumeRequest::Deserialize (shared_ptr <Stream> stream)
void DismountVolumeRequest::DeserializeData (shared_ptr <Stream> stream)
{
CoreServiceRequest::Deserialize (stream);
CoreServiceRequest::DeserializeData (stream);
Serializer sr (stream);
sr.Deserialize ("IgnoreOpenFiles", IgnoreOpenFiles);
sr.Deserialize ("SyncVolumeInfo", SyncVolumeInfo);
@@ -119,9 +118,9 @@ namespace VeraCrypt
return !Core->HasAdminPrivileges();
}
void DismountVolumeRequest::Serialize (shared_ptr <Stream> stream) const
void DismountVolumeRequest::SerializeData (shared_ptr <Stream> stream) const
{
CoreServiceRequest::Serialize (stream);
CoreServiceRequest::SerializeData (stream);
Serializer sr (stream);
sr.Serialize ("IgnoreOpenFiles", IgnoreOpenFiles);
sr.Serialize ("SyncVolumeInfo", SyncVolumeInfo);
@@ -130,9 +129,9 @@ namespace VeraCrypt
#ifdef TC_LINUX
// EmergencyDismountVolumeRequest
void EmergencyDismountVolumeRequest::Deserialize (shared_ptr <Stream> stream)
void EmergencyDismountVolumeRequest::DeserializeData (shared_ptr <Stream> stream)
{
CoreServiceRequest::Deserialize (stream);
CoreServiceRequest::DeserializeData (stream);
MountedVolumeInfo = Serializable::DeserializeNew <VolumeInfo> (stream);
}
@@ -141,17 +140,17 @@ namespace VeraCrypt
return !Core->HasAdminPrivileges();
}
void EmergencyDismountVolumeRequest::Serialize (shared_ptr <Stream> stream) const
void EmergencyDismountVolumeRequest::SerializeData (shared_ptr <Stream> stream) const
{
CoreServiceRequest::Serialize (stream);
CoreServiceRequest::SerializeData (stream);
MountedVolumeInfo->Serialize (stream);
}
#endif
// GetDeviceSectorSizeRequest
void GetDeviceSectorSizeRequest::Deserialize (shared_ptr <Stream> stream)
void GetDeviceSectorSizeRequest::DeserializeData (shared_ptr <Stream> stream)
{
CoreServiceRequest::Deserialize (stream);
CoreServiceRequest::DeserializeData (stream);
Serializer sr (stream);
Path = sr.DeserializeWString ("Path");
}
@@ -161,17 +160,17 @@ namespace VeraCrypt
return !Core->HasAdminPrivileges();
}
void GetDeviceSectorSizeRequest::Serialize (shared_ptr <Stream> stream) const
void GetDeviceSectorSizeRequest::SerializeData (shared_ptr <Stream> stream) const
{
CoreServiceRequest::Serialize (stream);
CoreServiceRequest::SerializeData (stream);
Serializer sr (stream);
sr.Serialize ("Path", wstring (Path));
}
// GetDeviceSizeRequest
void GetDeviceSizeRequest::Deserialize (shared_ptr <Stream> stream)
void GetDeviceSizeRequest::DeserializeData (shared_ptr <Stream> stream)
{
CoreServiceRequest::Deserialize (stream);
CoreServiceRequest::DeserializeData (stream);
Serializer sr (stream);
Path = sr.DeserializeWString ("Path");
}
@@ -181,17 +180,17 @@ namespace VeraCrypt
return !Core->HasAdminPrivileges();
}
void GetDeviceSizeRequest::Serialize (shared_ptr <Stream> stream) const
void GetDeviceSizeRequest::SerializeData (shared_ptr <Stream> stream) const
{
CoreServiceRequest::Serialize (stream);
CoreServiceRequest::SerializeData (stream);
Serializer sr (stream);
sr.Serialize ("Path", wstring (Path));
}
// GetHostDevicesRequest
void GetHostDevicesRequest::Deserialize (shared_ptr <Stream> stream)
void GetHostDevicesRequest::DeserializeData (shared_ptr <Stream> stream)
{
CoreServiceRequest::Deserialize (stream);
CoreServiceRequest::DeserializeData (stream);
Serializer sr (stream);
sr.Deserialize ("PathListOnly", PathListOnly);
}
@@ -201,29 +200,29 @@ namespace VeraCrypt
return !Core->HasAdminPrivileges();
}
void GetHostDevicesRequest::Serialize (shared_ptr <Stream> stream) const
void GetHostDevicesRequest::SerializeData (shared_ptr <Stream> stream) const
{
CoreServiceRequest::Serialize (stream);
CoreServiceRequest::SerializeData (stream);
Serializer sr (stream);
sr.Serialize ("PathListOnly", PathListOnly);
}
// ExitRequest
void ExitRequest::Deserialize (shared_ptr <Stream> stream)
void ExitRequest::DeserializeData (shared_ptr <Stream> stream)
{
CoreServiceRequest::Deserialize (stream);
CoreServiceRequest::DeserializeData (stream);
}
void ExitRequest::Serialize (shared_ptr <Stream> stream) const
void ExitRequest::SerializeData (shared_ptr <Stream> stream) const
{
CoreServiceRequest::Serialize (stream);
CoreServiceRequest::SerializeData (stream);
}
#ifdef TC_MACOSX
// ExecuteMacOSXAPFSFormatterRequest
void ExecuteMacOSXAPFSFormatterRequest::Deserialize (shared_ptr <Stream> stream)
void ExecuteMacOSXAPFSFormatterRequest::DeserializeData (shared_ptr <Stream> stream)
{
CoreServiceRequest::Deserialize (stream);
CoreServiceRequest::DeserializeData (stream);
Serializer sr (stream);
Device = sr.DeserializeWString ("Device");
sr.Deserialize ("OwnerGroupId", OwnerGroupId);
@@ -235,9 +234,9 @@ namespace VeraCrypt
return !Core->HasAdminPrivileges();
}
void ExecuteMacOSXAPFSFormatterRequest::Serialize (shared_ptr <Stream> stream) const
void ExecuteMacOSXAPFSFormatterRequest::SerializeData (shared_ptr <Stream> stream) const
{
CoreServiceRequest::Serialize (stream);
CoreServiceRequest::SerializeData (stream);
Serializer sr (stream);
sr.Serialize ("Device", wstring (Device));
sr.Serialize ("OwnerGroupId", OwnerGroupId);
@@ -247,9 +246,9 @@ namespace VeraCrypt
#ifdef TC_OPENBSD
// ExecuteOpenBSDFFSFormatterRequest
void ExecuteOpenBSDFFSFormatterRequest::Deserialize (shared_ptr <Stream> stream)
void ExecuteOpenBSDFFSFormatterRequest::DeserializeData (shared_ptr <Stream> stream)
{
CoreServiceRequest::Deserialize (stream);
CoreServiceRequest::DeserializeData (stream);
Serializer sr (stream);
Device = sr.DeserializeWString ("Device");
sr.Deserialize ("OwnerGroupId", OwnerGroupId);
@@ -261,9 +260,9 @@ namespace VeraCrypt
return !Core->HasAdminPrivileges();
}
void ExecuteOpenBSDFFSFormatterRequest::Serialize (shared_ptr <Stream> stream) const
void ExecuteOpenBSDFFSFormatterRequest::SerializeData (shared_ptr <Stream> stream) const
{
CoreServiceRequest::Serialize (stream);
CoreServiceRequest::SerializeData (stream);
Serializer sr (stream);
sr.Serialize ("Device", wstring (Device));
sr.Serialize ("OwnerGroupId", OwnerGroupId);
@@ -272,9 +271,9 @@ namespace VeraCrypt
#endif
// MountVolumeRequest
void MountVolumeRequest::Deserialize (shared_ptr <Stream> stream)
void MountVolumeRequest::DeserializeData (shared_ptr <Stream> stream)
{
CoreServiceRequest::Deserialize (stream);
CoreServiceRequest::DeserializeData (stream);
Serializer sr (stream);
DeserializedOptions = Serializable::DeserializeNew <MountOptions> (stream);
Options = DeserializedOptions.get();
@@ -301,17 +300,17 @@ namespace VeraCrypt
return !Core->HasAdminPrivileges();
}
void MountVolumeRequest::Serialize (shared_ptr <Stream> stream) const
void MountVolumeRequest::SerializeData (shared_ptr <Stream> stream) const
{
CoreServiceRequest::Serialize (stream);
CoreServiceRequest::SerializeData (stream);
Serializer sr (stream);
Options->Serialize (stream);
}
// SetFileOwnerRequest
void SetFileOwnerRequest::Deserialize (shared_ptr <Stream> stream)
void SetFileOwnerRequest::DeserializeData (shared_ptr <Stream> stream)
{
CoreServiceRequest::Deserialize (stream);
CoreServiceRequest::DeserializeData (stream);
Serializer sr (stream);
uint64 owner;
@@ -326,9 +325,9 @@ namespace VeraCrypt
return !Core->HasAdminPrivileges();
}
void SetFileOwnerRequest::Serialize (shared_ptr <Stream> stream) const
void SetFileOwnerRequest::SerializeData (shared_ptr <Stream> stream) const
{
CoreServiceRequest::Serialize (stream);
CoreServiceRequest::SerializeData (stream);
Serializer sr (stream);
uint64 owner = Owner.SystemId;
+22 -33
View File
@@ -16,134 +16,123 @@
namespace VeraCrypt
{
// ElevatedServiceStartedResponse
void ElevatedServiceStartedResponse::Deserialize (shared_ptr <Stream> stream)
void ElevatedServiceStartedResponse::DeserializeData (shared_ptr <Stream> stream)
{
}
void ElevatedServiceStartedResponse::Serialize (shared_ptr <Stream> stream) const
void ElevatedServiceStartedResponse::SerializeData (shared_ptr <Stream> stream) const
{
Serializable::Serialize (stream);
}
// CheckFilesystemResponse
void CheckFilesystemResponse::Deserialize (shared_ptr <Stream> stream)
void CheckFilesystemResponse::DeserializeData (shared_ptr <Stream> stream)
{
}
void CheckFilesystemResponse::Serialize (shared_ptr <Stream> stream) const
void CheckFilesystemResponse::SerializeData (shared_ptr <Stream> stream) const
{
Serializable::Serialize (stream);
}
// DismountFilesystemResponse
void DismountFilesystemResponse::Deserialize (shared_ptr <Stream> stream)
void DismountFilesystemResponse::DeserializeData (shared_ptr <Stream> stream)
{
}
void DismountFilesystemResponse::Serialize (shared_ptr <Stream> stream) const
void DismountFilesystemResponse::SerializeData (shared_ptr <Stream> stream) const
{
Serializable::Serialize (stream);
}
// DismountVolumeResponse
void DismountVolumeResponse::Deserialize (shared_ptr <Stream> stream)
void DismountVolumeResponse::DeserializeData (shared_ptr <Stream> stream)
{
DismountedVolumeInfo = Serializable::DeserializeNew <VolumeInfo> (stream);
}
void DismountVolumeResponse::Serialize (shared_ptr <Stream> stream) const
void DismountVolumeResponse::SerializeData (shared_ptr <Stream> stream) const
{
Serializable::Serialize (stream);
Serializer sr (stream);
DismountedVolumeInfo->Serialize (stream);
}
// GetDeviceSectorSizeResponse
void GetDeviceSectorSizeResponse::Deserialize (shared_ptr <Stream> stream)
void GetDeviceSectorSizeResponse::DeserializeData (shared_ptr <Stream> stream)
{
Serializer sr (stream);
sr.Deserialize ("Size", Size);
}
void GetDeviceSectorSizeResponse::Serialize (shared_ptr <Stream> stream) const
void GetDeviceSectorSizeResponse::SerializeData (shared_ptr <Stream> stream) const
{
Serializable::Serialize (stream);
Serializer sr (stream);
sr.Serialize ("Size", Size);
}
// GetDeviceSizeResponse
void GetDeviceSizeResponse::Deserialize (shared_ptr <Stream> stream)
void GetDeviceSizeResponse::DeserializeData (shared_ptr <Stream> stream)
{
Serializer sr (stream);
sr.Deserialize ("Size", Size);
}
void GetDeviceSizeResponse::Serialize (shared_ptr <Stream> stream) const
void GetDeviceSizeResponse::SerializeData (shared_ptr <Stream> stream) const
{
Serializable::Serialize (stream);
Serializer sr (stream);
sr.Serialize ("Size", Size);
}
// GetHostDevicesResponse
void GetHostDevicesResponse::Deserialize (shared_ptr <Stream> stream)
void GetHostDevicesResponse::DeserializeData (shared_ptr <Stream> stream)
{
Serializable::DeserializeList (stream, HostDevices);
}
void GetHostDevicesResponse::Serialize (shared_ptr <Stream> stream) const
void GetHostDevicesResponse::SerializeData (shared_ptr <Stream> stream) const
{
Serializable::Serialize (stream);
Serializable::SerializeList (stream, HostDevices);
}
#ifdef TC_MACOSX
// ExecuteMacOSXAPFSFormatterResponse
void ExecuteMacOSXAPFSFormatterResponse::Deserialize (shared_ptr <Stream> stream)
void ExecuteMacOSXAPFSFormatterResponse::DeserializeData (shared_ptr <Stream> stream)
{
}
void ExecuteMacOSXAPFSFormatterResponse::Serialize (shared_ptr <Stream> stream) const
void ExecuteMacOSXAPFSFormatterResponse::SerializeData (shared_ptr <Stream> stream) const
{
Serializable::Serialize (stream);
}
#endif
#ifdef TC_OPENBSD
// ExecuteOpenBSDFFSFormatterResponse
void ExecuteOpenBSDFFSFormatterResponse::Deserialize (shared_ptr <Stream> stream)
void ExecuteOpenBSDFFSFormatterResponse::DeserializeData (shared_ptr <Stream> stream)
{
}
void ExecuteOpenBSDFFSFormatterResponse::Serialize (shared_ptr <Stream> stream) const
void ExecuteOpenBSDFFSFormatterResponse::SerializeData (shared_ptr <Stream> stream) const
{
Serializable::Serialize (stream);
}
#endif
// MountVolumeResponse
void MountVolumeResponse::Deserialize (shared_ptr <Stream> stream)
void MountVolumeResponse::DeserializeData (shared_ptr <Stream> stream)
{
Serializer sr (stream);
MountedVolumeInfo = Serializable::DeserializeNew <VolumeInfo> (stream);
}
void MountVolumeResponse::Serialize (shared_ptr <Stream> stream) const
void MountVolumeResponse::SerializeData (shared_ptr <Stream> stream) const
{
Serializable::Serialize (stream);
Serializer sr (stream);
MountedVolumeInfo->Serialize (stream);
}
// SetFileOwnerResponse
void SetFileOwnerResponse::Deserialize (shared_ptr <Stream> stream)
void SetFileOwnerResponse::DeserializeData (shared_ptr <Stream> stream)
{
}
void SetFileOwnerResponse::Serialize (shared_ptr <Stream> stream) const
void SetFileOwnerResponse::SerializeData (shared_ptr <Stream> stream) const
{
Serializable::Serialize (stream);
}
TC_SERIALIZER_FACTORY_ADD_CLASS (ElevatedServiceStartedResponse);
+2
View File
@@ -19,6 +19,7 @@
#include <wx/apptrait.h>
#include <wx/cmdline.h>
#include "Crypto/cpu.h"
#include "Core/CoreTest.h"
#include "Platform/PlatformTest.h"
#include "Common/PCSCException.h"
#ifdef TC_UNIX
@@ -1829,6 +1830,7 @@ const FileManager fileManagers[] = {
if (!PlatformTest::TestAll())
throw TestFailed (SRC_POS);
CoreTest::TestAll();
EncryptionTest::TestAll();
// StringFormatter
+6 -7
View File
@@ -15,33 +15,32 @@
namespace VeraCrypt
{
void Exception::Deserialize (shared_ptr <Stream> stream)
void Exception::DeserializeData (shared_ptr <Stream> stream)
{
Serializer sr (stream);
sr.Deserialize ("Message", Message);
sr.Deserialize ("Subject", Subject);
}
void Exception::Serialize (shared_ptr <Stream> stream) const
void Exception::SerializeData (shared_ptr <Stream> stream) const
{
Serializable::Serialize (stream);
Serializer sr (stream);
sr.Serialize ("Message", Message);
sr.Serialize ("Subject", Subject);
}
void ExecutedProcessFailed::Deserialize (shared_ptr <Stream> stream)
void ExecutedProcessFailed::DeserializeData (shared_ptr <Stream> stream)
{
Exception::Deserialize (stream);
Exception::DeserializeData (stream);
Serializer sr (stream);
sr.Deserialize ("Command", Command);
sr.Deserialize ("ExitCode", ExitCode);
sr.Deserialize ("ErrorOutput", ErrorOutput);
}
void ExecutedProcessFailed::Serialize (shared_ptr <Stream> stream) const
void ExecutedProcessFailed::SerializeData (shared_ptr <Stream> stream) const
{
Exception::Serialize (stream);
Exception::SerializeData (stream);
Serializer sr (stream);
sr.Serialize ("Command", Command);
sr.Serialize ("ExitCode", ExitCode);
+311
View File
@@ -26,6 +26,312 @@
namespace VeraCrypt
{
class TestSerializer : public Serializer
{
public:
TestSerializer (shared_ptr <Stream> stream) : Serializer (stream) { }
string ReadString () { return DeserializeString (); }
wstring ReadWString () { return DeserializeWString (); }
};
static shared_ptr <Stream> CreateStringTestStream (uint64 declaredSize, const ConstBufferPtr &data)
{
shared_ptr <Stream> stream (new MemoryStream);
uint64 fieldSize = Endian::Big (uint64 (sizeof (declaredSize)));
uint64 size = Endian::Big (declaredSize);
stream->Write (ConstBufferPtr ((uint8 *) &fieldSize, sizeof (fieldSize)));
stream->Write (ConstBufferPtr ((uint8 *) &size, sizeof (size)));
if (data.Size() > 0)
stream->Write (data);
return stream;
}
static void SerializerFailureTest ()
{
bool exceptionThrown = false;
try
{
TestSerializer ser (CreateStringTestStream (0, ConstBufferPtr()));
ser.ReadString ();
}
catch (ParameterIncorrect &) { exceptionThrown = true; }
if (!exceptionThrown)
throw TestFailed (SRC_POS);
exceptionThrown = false;
try
{
TestSerializer ser (CreateStringTestStream (1024 * 1024 + 1, ConstBufferPtr()));
ser.ReadString ();
}
catch (ParameterIncorrect &) { exceptionThrown = true; }
if (!exceptionThrown)
throw TestFailed (SRC_POS);
uint8 unterminatedString = 'x';
exceptionThrown = false;
try
{
TestSerializer ser (CreateStringTestStream (1, ConstBufferPtr (&unterminatedString, 1)));
ser.ReadString ();
}
catch (ParameterIncorrect &) { exceptionThrown = true; }
if (!exceptionThrown)
throw TestFailed (SRC_POS);
exceptionThrown = false;
try
{
TestSerializer ser (CreateStringTestStream (sizeof (wchar_t) - 1, ConstBufferPtr()));
ser.ReadWString ();
}
catch (ParameterIncorrect &) { exceptionThrown = true; }
if (!exceptionThrown)
throw TestFailed (SRC_POS);
wchar_t unterminatedWString = L'x';
exceptionThrown = false;
try
{
TestSerializer ser (CreateStringTestStream (sizeof (unterminatedWString), ConstBufferPtr ((uint8 *) &unterminatedWString, sizeof (unterminatedWString))));
ser.ReadWString ();
}
catch (ParameterIncorrect &) { exceptionThrown = true; }
if (!exceptionThrown)
throw TestFailed (SRC_POS);
exceptionThrown = false;
try
{
Serializer::ValidateCollectionSize (65537);
}
catch (ParameterIncorrect &) { exceptionThrown = true; }
if (!exceptionThrown)
throw TestFailed (SRC_POS);
}
static void SerializerStringPolicyTest ()
{
shared_ptr <Stream> stream (new MemoryStream);
Serializer sr (stream);
const string strings[] = { "", "text", string ((size_t) Serializer::MaxStringSize - 1, 'x') };
const wstring wstrings[] = { L"", L"text", wstring ((size_t) Serializer::MaxStringSize / sizeof (wchar_t) - 1, L'x') };
for (size_t i = 0; i < array_capacity (strings); ++i)
{
sr.Serialize ("String", strings[i]);
sr.Serialize ("WString", wstrings[i]);
if (sr.DeserializeString ("String") != strings[i] || sr.DeserializeWString ("WString") != wstrings[i])
throw TestFailed (SRC_POS);
}
const string invalidStrings[] = { string ("x\0y", 3), string (1, '\0'), string ((size_t) Serializer::MaxStringSize, 'x') };
const wstring invalidWStrings[] = { wstring (L"x\0y", 3), wstring (1, L'\0'), wstring ((size_t) Serializer::MaxStringSize / sizeof (wchar_t), L'x') };
for (size_t i = 0; i < array_capacity (invalidStrings); ++i)
{
try
{
sr.Serialize ("String", invalidStrings[i]);
throw TestFailed (SRC_POS);
}
catch (ParameterIncorrect &) { }
try
{
sr.Serialize ("WString", invalidWStrings[i]);
throw TestFailed (SRC_POS);
}
catch (ParameterIncorrect &) { }
try
{
TestSerializer reader (CreateStringTestStream (invalidStrings[i].size() + 1,
ConstBufferPtr ((const uint8 *) invalidStrings[i].c_str(), invalidStrings[i].size() + 1)));
reader.ReadString();
throw TestFailed (SRC_POS);
}
catch (ParameterIncorrect &) { }
try
{
size_t size = (invalidWStrings[i].size() + 1) * sizeof (wchar_t);
TestSerializer reader (CreateStringTestStream (size, ConstBufferPtr ((const uint8 *) invalidWStrings[i].c_str(), size)));
reader.ReadWString();
throw TestFailed (SRC_POS);
}
catch (ParameterIncorrect &) { }
}
try
{
TestSerializer reader (CreateStringTestStream (0, ConstBufferPtr()));
reader.ReadWString();
throw TestFailed (SRC_POS);
}
catch (ParameterIncorrect &) { }
}
static void SerializerCollectionTest ()
{
shared_ptr <Stream> stream (new MemoryStream);
Serializer sr (stream);
list <string> strings ((size_t) Serializer::MaxCollectionSize + 1);
list <wstring> wstrings ((size_t) Serializer::MaxCollectionSize + 1);
list < shared_ptr <Exception> > objects ((size_t) Serializer::MaxCollectionSize + 1);
try
{
sr.Serialize ("Strings", strings);
throw TestFailed (SRC_POS);
}
catch (ParameterIncorrect &) { }
try
{
sr.Serialize ("WStrings", wstrings);
throw TestFailed (SRC_POS);
}
catch (ParameterIncorrect &) { }
try
{
Serializable::SerializeList (stream, objects);
throw TestFailed (SRC_POS);
}
catch (ParameterIncorrect &) { }
strings.pop_back();
wstrings.pop_back();
sr.Serialize ("Strings", strings);
sr.Serialize ("WStrings", wstrings);
if (sr.DeserializeStringList ("Strings") != strings || sr.DeserializeWStringList ("WStrings") != wstrings)
throw TestFailed (SRC_POS);
sr.Serialize ("Strings", Serializer::MaxCollectionSize + 1);
try
{
sr.DeserializeStringList ("Strings");
throw TestFailed (SRC_POS);
}
catch (ParameterIncorrect &) { }
sr.Serialize ("WStrings", Serializer::MaxCollectionSize + 1);
try
{
sr.DeserializeWStringList ("WStrings");
throw TestFailed (SRC_POS);
}
catch (ParameterIncorrect &) { }
Serializable::SerializeHeader (sr, "list<Exception>");
sr.Serialize ("ListSize", Serializer::MaxCollectionSize + 1);
objects.clear();
try
{
Serializable::DeserializeList (stream, objects);
throw TestFailed (SRC_POS);
}
catch (ParameterIncorrect &) { }
}
// Registered only for this test; counters check that rejection happens before parsing
// and that failed reads release the object, including through the raw-pointer API.
class SerializerTestObject : public Serializable
{
public:
SerializerTestObject () { ++LiveCount; }
virtual ~SerializerTestObject () { --LiveCount; }
static Serializable *GetNewSerializable () { return new SerializerTestObject; }
virtual void DeserializeData (shared_ptr <Stream> stream)
{
++ParseCount;
Serializer sr (stream);
sr.DeserializeUInt32 ("Value");
}
static int LiveCount;
static int ParseCount;
};
int SerializerTestObject::LiveCount = 0;
int SerializerTestObject::ParseCount = 0;
static void SerializableTypeTest ()
{
TC_SERIALIZER_FACTORY_ADD (SerializerTestObject);
finally_do ({
SerializerFactory::NameToTypeMap->erase ("SerializerTestObject");
SerializerFactory::TypeToNameMap->erase (StringConverter::GetTypeName (typeid (SerializerTestObject)));
});
SerializerTestObject::ParseCount = 0;
shared_ptr <Stream> stream (new MemoryStream);
Serializer sr (stream);
Serializable::SerializeHeader (sr, "SerializerTestObject");
try
{
Serializable::DeserializeNew <Exception> (stream);
throw TestFailed (SRC_POS);
}
catch (ParameterIncorrect &) { }
if (SerializerTestObject::LiveCount != 0 || SerializerTestObject::ParseCount != 0)
throw TestFailed (SRC_POS);
Serializable::SerializeHeader (sr, "list<Exception>");
sr.Serialize ("ListSize", uint64 (1));
Serializable::SerializeHeader (sr, "SerializerTestObject");
list < shared_ptr <Exception> > objects;
try
{
Serializable::DeserializeList (stream, objects);
throw TestFailed (SRC_POS);
}
catch (ParameterIncorrect &) { }
if (SerializerTestObject::LiveCount != 0 || SerializerTestObject::ParseCount != 0 || !objects.empty())
throw TestFailed (SRC_POS);
for (int i = 0; i < 2; ++i)
{
Serializable::SerializeHeader (sr, "SerializerTestObject");
try
{
if (i == 0)
{
unique_ptr <Serializable> object (Serializable::DeserializeNew (stream));
}
else
Serializable::DeserializeNew <SerializerTestObject> (stream);
throw TestFailed (SRC_POS);
}
catch (InsufficientData &) { }
if (SerializerTestObject::LiveCount != 0 || SerializerTestObject::ParseCount != i + 1)
throw TestFailed (SRC_POS);
}
ExecutedProcessFailed exception ("message", "command", 1, "output");
exception.Serialize (stream);
shared_ptr <Exception> result = Serializable::DeserializeNew <Exception> (stream);
if (!dynamic_cast <ExecutedProcessFailed *> (result.get()))
throw TestFailed (SRC_POS);
}
static void SerializerNestingTest ()
{
shared_ptr <Stream> stream (new MemoryStream);
for (int attempt = 0; attempt < 2; ++attempt)
{
vector < shared_ptr <SerializationScope> > scopes;
for (unsigned int i = 0; i < Serializer::MaxNestingDepth; ++i)
scopes.push_back (shared_ptr <SerializationScope> (new SerializationScope (stream)));
try
{
SerializationScope excess (stream);
throw TestFailed (SRC_POS);
}
catch (ParameterIncorrect &) { }
// Nesting is local to a stream and is restored when scopes unwind.
shared_ptr <Stream> otherStream (new MemoryStream);
SerializationScope other (otherStream);
scopes.clear();
Serializer sr (stream);
sr.Serialize ("Value", uint32 (7));
if (sr.DeserializeUInt32 ("Value") != 7)
throw TestFailed (SRC_POS);
}
}
// make_shared_auto, File, Stream, MemoryStream, Endian, Serializer, Serializable
void PlatformTest::SerializerTest ()
{
@@ -345,6 +651,11 @@ namespace VeraCrypt
}
SerializerTest();
SerializerFailureTest();
SerializerStringPolicyTest();
SerializerCollectionTest();
SerializableTypeTest();
SerializerNestingTest();
ThreadTest();
return true;
+15 -3
View File
@@ -10,30 +10,42 @@
code distribution packages.
*/
#include "Exception.h"
#include "Serializable.h"
#include "SerializerFactory.h"
namespace VeraCrypt
{
void Serializable::Deserialize (shared_ptr <Stream> stream)
{
SerializationScope scope (stream);
DeserializeData (stream);
}
string Serializable::DeserializeHeader (shared_ptr <Stream> stream)
{
Serializer sr (stream);
return sr.DeserializeString ("SerializableName");
}
Serializable *Serializable::DeserializeNew (shared_ptr <Stream> stream)
Serializable *Serializable::DeserializeNew (shared_ptr <Stream> stream, TypeValidator isExpectedType)
{
string name = Serializable::DeserializeHeader (stream);
Serializable *serializable = SerializerFactory::GetNewSerializable (name);
unique_ptr <Serializable> serializable (SerializerFactory::GetNewSerializable (name));
// Allow legitimate subtypes, but never run an unexpected object's parser.
if (isExpectedType && !isExpectedType (*serializable))
throw ParameterIncorrect (SRC_POS);
serializable->Deserialize (stream);
return serializable;
return serializable.release();
}
void Serializable::Serialize (shared_ptr <Stream> stream) const
{
SerializationScope scope (stream);
Serializer sr (stream);
Serializable::SerializeHeader (sr, SerializerFactory::GetName (typeid (*this)));
SerializeData (stream);
}
void Serializable::SerializeHeader (Serializer &serializer, const string &name)
+28 -16
View File
@@ -26,43 +26,50 @@ namespace VeraCrypt
public:
virtual ~Serializable () { }
virtual void Deserialize (shared_ptr <Stream> stream) = 0;
// Non-virtual entry points enforce nesting limits for every object. Derived
// classes implement only the field operations below; Serialize owns the header.
void Deserialize (shared_ptr <Stream> stream);
static string DeserializeHeader (shared_ptr <Stream> stream);
static Serializable *DeserializeNew (shared_ptr <Stream> stream);
typedef bool (*TypeValidator) (const Serializable &object);
static Serializable *DeserializeNew (shared_ptr <Stream> stream, TypeValidator isExpectedType = nullptr);
template <class T>
static bool IsType (const Serializable &object)
{
return dynamic_cast <const T *> (&object) != nullptr;
}
template <class T>
static shared_ptr <T> DeserializeNew (shared_ptr <Stream> stream)
{
shared_ptr <T> p (dynamic_cast <T *> (DeserializeNew (stream)));
if (!p)
throw std::runtime_error (SRC_POS);
return p;
return shared_ptr <T> (dynamic_cast <T *> (DeserializeNew (stream, &IsType <T>)));
}
template <class T>
static void DeserializeList (shared_ptr <Stream> stream, list < shared_ptr <T> > &dataList)
{
SerializationScope scope (stream);
if (DeserializeHeader (stream) != string ("list<") + SerializerFactory::GetName (typeid (T)) + ">")
throw std::runtime_error (SRC_POS);
Serializer sr (stream);
uint64 listSize;
sr.Deserialize ("ListSize", listSize);
Serializer::ValidateCollectionSize (listSize);
for (size_t i = 0; i < listSize; i++)
{
shared_ptr <T> p (dynamic_cast <T *> (DeserializeNew (stream)));
if (!p)
throw std::runtime_error (SRC_POS);
dataList.push_back (p);
}
list < shared_ptr <T> > deserializedList;
for (uint64 i = 0; i < listSize; i++)
deserializedList.push_back (DeserializeNew <T> (stream));
dataList.splice (dataList.end(), deserializedList);
}
virtual void Serialize (shared_ptr <Stream> stream) const;
void Serialize (shared_ptr <Stream> stream) const;
template <class T>
static void SerializeList (shared_ptr <Stream> stream, const list < shared_ptr <T> > &dataList)
{
Serializer::ValidateCollectionSize (dataList.size());
SerializationScope scope (stream);
Serializer sr (stream);
SerializeHeader (sr, string ("list<") + SerializerFactory::GetName (typeid (T)) + ">");
@@ -75,12 +82,17 @@ namespace VeraCrypt
protected:
Serializable () { }
// Call base-class field operations here, never their public entry points.
virtual void DeserializeData (shared_ptr <Stream> stream) = 0;
virtual void SerializeData (shared_ptr <Stream> stream) const { }
};
}
#define TC_SERIALIZABLE(TYPE) \
static Serializable *GetNewSerializable () { return new TYPE(); } \
virtual void Deserialize (shared_ptr <Stream> stream); \
virtual void Serialize (shared_ptr <Stream> stream) const
protected: \
virtual void DeserializeData (shared_ptr <Stream> stream); \
virtual void SerializeData (shared_ptr <Stream> stream) const; \
public:
#endif // TC_HEADER_Platform_Serializable
+51 -7
View File
@@ -10,6 +10,7 @@
code distribution packages.
*/
#include <algorithm>
#include "Exception.h"
#include "ForEach.h"
#include "Memory.h"
@@ -17,6 +18,24 @@
namespace VeraCrypt
{
SerializationScope::SerializationScope (shared_ptr <Stream> stream) : DataStream (stream)
{
if (!DataStream || DataStream->SerializationDepth >= Serializer::MaxNestingDepth)
throw ParameterIncorrect (SRC_POS);
++DataStream->SerializationDepth;
}
SerializationScope::~SerializationScope ()
{
--DataStream->SerializationDepth;
}
Serializer::Serializer (shared_ptr <Stream> stream) : DataStream (stream)
{
if (!DataStream)
throw ParameterIncorrect (SRC_POS);
}
template <typename T>
T Serializer::Deserialize ()
{
@@ -125,11 +144,15 @@ namespace VeraCrypt
string Serializer::DeserializeString ()
{
uint64 size = Deserialize <uint64> ();
if (size == 0 || size > MaxStringSize)
throw ParameterIncorrect (SRC_POS);
vector <char> data ((size_t) size);
DataStream->ReadCompleteBuffer (BufferPtr ((uint8 *) &data[0], (size_t) size));
if (data.back() != 0 || find (data.begin(), data.end() - 1, '\0') != data.end() - 1)
throw ParameterIncorrect (SRC_POS);
return string (&data[0]);
return string (&data[0], data.size() - 1);
}
string Serializer::DeserializeString (const string &name)
@@ -143,8 +166,9 @@ namespace VeraCrypt
ValidateName (name);
list <string> deserializedList;
uint64 listSize = Deserialize <uint64> ();
ValidateCollectionSize (listSize);
for (size_t i = 0; i < listSize; i++)
for (uint64 i = 0; i < listSize; i++)
deserializedList.push_back (DeserializeString ());
return deserializedList;
@@ -153,11 +177,15 @@ namespace VeraCrypt
wstring Serializer::DeserializeWString ()
{
uint64 size = Deserialize <uint64> ();
if (size == 0 || size > MaxStringSize || size % sizeof (wchar_t) != 0)
throw ParameterIncorrect (SRC_POS);
vector <wchar_t> data ((size_t) size / sizeof (wchar_t));
DataStream->ReadCompleteBuffer (BufferPtr ((uint8 *) &data[0], (size_t) size));
if (data.back() != 0 || find (data.begin(), data.end() - 1, L'\0') != data.end() - 1)
throw ParameterIncorrect (SRC_POS);
return wstring (&data[0]);
return wstring (&data[0], data.size() - 1);
}
list <wstring> Serializer::DeserializeWStringList (const string &name)
@@ -165,8 +193,9 @@ namespace VeraCrypt
ValidateName (name);
list <wstring> deserializedList;
uint64 listSize = Deserialize <uint64> ();
ValidateCollectionSize (listSize);
for (size_t i = 0; i < listSize; i++)
for (uint64 i = 0; i < listSize; i++)
deserializedList.push_back (DeserializeWString ());
return deserializedList;
@@ -178,6 +207,12 @@ namespace VeraCrypt
return DeserializeWString ();
}
void Serializer::ValidateCollectionSize (uint64 size)
{
if (size > MaxCollectionSize)
throw ParameterIncorrect (SRC_POS);
}
template <typename T>
void Serializer::Serialize (T data)
{
@@ -249,6 +284,7 @@ namespace VeraCrypt
void Serializer::Serialize (const string &name, const list <string> &stringList)
{
ValidateCollectionSize (stringList.size());
SerializeString (name);
uint64 listSize = stringList.size();
@@ -260,6 +296,7 @@ namespace VeraCrypt
void Serializer::Serialize (const string &name, const list <wstring> &stringList)
{
ValidateCollectionSize (stringList.size());
SerializeString (name);
uint64 listSize = stringList.size();
@@ -281,15 +318,22 @@ namespace VeraCrypt
void Serializer::SerializeString (const string &data)
{
// Embedded NULs would be interpreted differently by C-string consumers.
if (data.size() >= MaxStringSize || data.find ('\0') != string::npos)
throw ParameterIncorrect (SRC_POS);
Serialize ((uint64) data.size() + 1);
DataStream->Write (ConstBufferPtr ((uint8 *) (data.data() ? data.data() : data.c_str()), data.size() + 1));
DataStream->Write (ConstBufferPtr ((const uint8 *) data.c_str(), data.size() + 1));
}
void Serializer::SerializeWString (const wstring &data)
{
uint64 size = (data.size() + 1) * sizeof (wchar_t);
if (data.size() >= MaxStringSize / sizeof (wchar_t) || data.find (L'\0') != wstring::npos)
throw ParameterIncorrect (SRC_POS);
uint64 size = ((uint64) data.size() + 1) * sizeof (wchar_t);
Serialize (size);
DataStream->Write (ConstBufferPtr ((uint8 *) (data.data() ? data.data() : data.c_str()), (size_t) size));
DataStream->Write (ConstBufferPtr ((const uint8 *) data.c_str(), (size_t) size));
}
void Serializer::ValidateName (const string &name)
+21 -1
View File
@@ -20,12 +20,31 @@
namespace VeraCrypt
{
// An object or object-list operation retains this scope across all its fields.
// Sibling operations and separate streams have independent nesting limits.
class SerializationScope
{
public:
explicit SerializationScope (shared_ptr <Stream> stream);
~SerializationScope ();
private:
shared_ptr <Stream> DataStream;
SerializationScope (const SerializationScope &);
SerializationScope &operator= (const SerializationScope &);
};
class Serializer
{
public:
Serializer (shared_ptr <Stream> stream) : DataStream (stream) { }
Serializer (shared_ptr <Stream> stream);
virtual ~Serializer () { }
// Wire sizes include the terminating NUL. The same limits apply in both directions.
static const uint64 MaxCollectionSize = 65536;
static const uint64 MaxStringSize = 1024 * 1024;
static const unsigned int MaxNestingDepth = 64;
void Deserialize (const string &name, bool &data);
void Deserialize (const string &name, uint8 &data);
void Deserialize (const string &name, int32 &data);
@@ -44,6 +63,7 @@ namespace VeraCrypt
list <string> DeserializeStringList (const string &name);
wstring DeserializeWString (const string &name);
list <wstring> DeserializeWStringList (const string &name);
static void ValidateCollectionSize (uint64 size);
void Serialize (const string &name, bool data);
void Serialize (const string &name, uint8 data);
void Serialize (const string &name, const char *data);
+12 -1
View File
@@ -41,7 +41,18 @@ namespace VeraCrypt
: Pointer (nullptr), UseCount (nullptr) { }
explicit SharedPtr (T *pointer)
: Pointer (pointer), UseCount (new SharedVal <uint64> (1)) { }
: Pointer (pointer), UseCount (nullptr)
{
try
{
UseCount = new SharedVal <uint64> (1);
}
catch (...)
{
delete Pointer;
throw;
}
}
SharedPtr (const SharedPtr &source)
{
+4 -1
View File
@@ -27,9 +27,12 @@ namespace VeraCrypt
virtual void Write (const ConstBufferPtr &data) = 0;
protected:
Stream () { };
Stream () : SerializationDepth (0) { }
private:
friend class SerializationScope;
unsigned int SerializationDepth;
Stream (const Stream &);
Stream &operator= (const Stream &);
};
+2 -4
View File
@@ -412,14 +412,12 @@ namespace VeraCrypt
if (!exOutput.empty())
{
unique_ptr <Serializable> deserializedObject;
Exception *deserializedException = nullptr;
shared_ptr <Exception> deserializedException;
try
{
shared_ptr <Stream> stream (new MemoryStream (ConstBufferPtr ((uint8 *) &exOutput[0], exOutput.size())));
deserializedObject.reset (Serializable::DeserializeNew (stream));
deserializedException = dynamic_cast <Exception*> (deserializedObject.get());
deserializedException = Serializable::DeserializeNew <Exception> (stream);
}
catch (...) { }
+4 -4
View File
@@ -38,9 +38,9 @@ namespace VeraCrypt
{
}
void SystemException::Deserialize (shared_ptr <Stream> stream)
void SystemException::DeserializeData (shared_ptr <Stream> stream)
{
Exception::Deserialize (stream);
Exception::DeserializeData (stream);
Serializer sr (stream);
sr.Deserialize ("ErrorCode", ErrorCode);
}
@@ -50,9 +50,9 @@ namespace VeraCrypt
return ErrorCode != 0;
}
void SystemException::Serialize (shared_ptr <Stream> stream) const
void SystemException::SerializeData (shared_ptr <Stream> stream) const
{
Exception::Serialize (stream);
Exception::SerializeData (stream);
Serializer sr (stream);
sr.Serialize ("ErrorCode", ErrorCode);
}
+2 -3
View File
@@ -16,7 +16,7 @@
namespace VeraCrypt
{
void VolumeInfo::Deserialize (shared_ptr <Stream> stream)
void VolumeInfo::DeserializeData (shared_ptr <Stream> stream)
{
Serializer sr (stream);
@@ -63,9 +63,8 @@ namespace VeraCrypt
return first->SerialInstanceNumber > second->SerialInstanceNumber;
}
void VolumeInfo::Serialize (shared_ptr <Stream> stream) const
void VolumeInfo::SerializeData (shared_ptr <Stream> stream) const
{
Serializable::Serialize (stream);
Serializer sr (stream);
const uint32 version = VERSION_NUM;
+6 -3
View File
@@ -36,11 +36,13 @@ namespace VeraCrypt
PasswordBuffer.Allocate (MaxSize);
}
void VolumePassword::Deserialize (shared_ptr <Stream> stream)
void VolumePassword::DeserializeData (shared_ptr <Stream> stream)
{
Serializer sr (stream);
uint64 passwordSize;
sr.Deserialize ("PasswordSize", passwordSize);
if (passwordSize > MaxSize)
throw ParameterIncorrect (SRC_POS);
PasswordSize = static_cast <size_t> (passwordSize);
sr.Deserialize ("PasswordBuffer", BufferPtr (PasswordBuffer));
@@ -48,9 +50,10 @@ namespace VeraCrypt
sr.Deserialize ("WipeData", wipeBuffer);
}
void VolumePassword::Serialize (shared_ptr <Stream> stream) const
void VolumePassword::SerializeData (shared_ptr <Stream> stream) const
{
Serializable::Serialize (stream);
if (PasswordSize > MaxSize)
throw ParameterIncorrect (SRC_POS);
Serializer sr (stream);
sr.Serialize ("PasswordSize", static_cast <uint64> (PasswordSize));
sr.Serialize ("PasswordBuffer", ConstBufferPtr (PasswordBuffer));