Handle unknown pNext structs more gracefully in serialisation

* It's illegal for an application to pass an unknown pNext struct since they
  must correspond to enabled extensions and we disallow all unsupported
  extensions.
* Rather than crashing or corrupting the serialisation though we strip and don't
  serialise the extension struct. This may or may not succeed but the
  application is already in undefined territory.
* When we encounter an unsupported extension on replay this cannot be handled
  since we don't know how to skip its serialisation. This becomes a fatal error.
This commit is contained in:
baldurk
2020-07-01 18:09:24 +01:00
parent 270700c290
commit 05c48b44a1
3 changed files with 22 additions and 4 deletions
+18 -3
View File
@@ -1244,12 +1244,15 @@ static void SerialiseNext(SerialiserType &ser, VkStructureType &sType, const voi
// thing user-facing.
ser.Named("pNextType"_lit).Hidden();
// if we encounter an unsupported struct on read we *cannot* continue since we don't know the
// members that got serialised after it
#define PNEXT_UNSUPPORTED(StructType) \
case StructType: \
{ \
RDCERR("No support for " #StructType " is available in this build"); \
pNext = NULL; \
break; \
ser.SetErrored(); \
return; \
}
// if we come across a struct we should process, then serialise a pointer to it.
@@ -1287,12 +1290,15 @@ static void SerialiseNext(SerialiserType &ser, VkStructureType &sType, const voi
}
else // ser.IsWriting()
{
// if we hit an unsupported struct, error and then just skip it entirely from the chain and move
// onto the next one in the list
#undef PNEXT_UNSUPPORTED
#define PNEXT_UNSUPPORTED(StructType) \
case StructType: \
{ \
RDCERR("No support for " #StructType " is available in this build"); \
return; \
handled = true; \
break; \
}
// if we come across a struct we should process, then serialise a pointer to its type (to tell the
@@ -1326,7 +1332,8 @@ static void SerialiseNext(SerialiserType &ser, VkStructureType &sType, const voi
case VK_STRUCTURE_TYPE_MAX_ENUM: break;
}
RDCERR("Invalid pNext structure sType: %u", next->sType);
if(!handled)
RDCERR("Invalid pNext structure sType: %u", next->sType);
// walk to the next item if we didn't serialise the current one
next = (VkBaseInStructure *)next->pNext;
@@ -1352,6 +1359,14 @@ static inline void DeserialiseNext(const void *pNext)
if(pNext == NULL)
return;
#undef PNEXT_UNSUPPORTED
#define PNEXT_UNSUPPORTED(StructType) \
case StructType: \
{ \
RDCERR("No support for " #StructType " is available in this build"); \
return; \
}
#undef PNEXT_STRUCT
#define PNEXT_STRUCT(StructType, StructName) \
case StructType: \
+1
View File
@@ -115,6 +115,7 @@ public:
Serialiser(const Serialiser &other) = delete;
bool IsErrored() { return IsReading() ? m_Read->IsErrored() : m_Write->IsErrored(); }
void SetErrored() { IsReading() ? m_Read->SetErrored() : m_Write->SetErrored(); }
bool IsDummy() { return m_Dummy; }
StreamWriter *GetWriter() { return m_Write; }
StreamReader *GetReader() { return m_Read; }
+3 -1
View File
@@ -92,6 +92,7 @@ public:
~StreamReader();
bool IsErrored() { return m_HasError; }
void SetErrored() { m_HasError = true; }
void SetOffset(uint64_t offs);
inline uint64_t GetOffset() { return m_BufferHead - m_BufferBase + m_ReadOffset; }
@@ -129,7 +130,7 @@ public:
if(numBytes == 0 || m_Dummy)
return true;
if(!m_BufferBase)
if(!m_BufferBase || m_HasError)
{
// read 0s if we're in an error state
if(data)
@@ -296,6 +297,7 @@ public:
StreamWriter(Compressor *compressor, Ownership own);
bool IsErrored() { return m_HasError; }
void SetErrored() { m_HasError = true; }
static const int DefaultScratchSize = 32 * 1024;
~StreamWriter();