From 777c9215350e4ff1118fded7ecc27fa51f21bf24 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Thu, 2 Jul 2026 18:40:52 -0700 Subject: [PATCH] Check for match of complex element types eg. Array of Structure must have Structure elements. --- src/factory/FieldCreateFactory.cpp | 8 ++++++-- testApp/misc/testSerialization.cpp | 31 +++++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/factory/FieldCreateFactory.cpp b/src/factory/FieldCreateFactory.cpp index 561e8ee..b584ad9 100644 --- a/src/factory/FieldCreateFactory.cpp +++ b/src/factory/FieldCreateFactory.cpp @@ -1564,7 +1564,9 @@ FieldConstPtr FieldCreate::deserialize(ByteBuffer* buffer, DeserializableControl throw std::invalid_argument("fixed and bounded structure array not supported"); // Type type = Type.structureArray; - StructureConstPtr elementStructure = std::tr1::static_pointer_cast(control->cachedDeserialize(buffer)); + StructureConstPtr elementStructure = std::tr1::dynamic_pointer_cast(control->cachedDeserialize(buffer)); + if(!elementStructure) + throw std::invalid_argument("Expected Structure"); // TODO use std::make_shared std::tr1::shared_ptr sp(new StructureArray(elementStructure)); Helper::cache(this, sp); @@ -1577,7 +1579,9 @@ FieldConstPtr FieldCreate::deserialize(ByteBuffer* buffer, DeserializableControl throw std::invalid_argument("fixed and bounded structure array not supported"); // Type type = Type.unionArray; - UnionConstPtr elementUnion = std::tr1::static_pointer_cast(control->cachedDeserialize(buffer)); + UnionConstPtr elementUnion = std::tr1::dynamic_pointer_cast(control->cachedDeserialize(buffer)); + if(!elementUnion) + throw std::invalid_argument("Expected Union"); // TODO use std::make_shared std::tr1::shared_ptr sp(new UnionArray(elementUnion)); Helper::cache(this, sp); diff --git a/testApp/misc/testSerialization.cpp b/testApp/misc/testSerialization.cpp index dcbef23..617586a 100644 --- a/testApp/misc/testSerialization.cpp +++ b/testApp/misc/testSerialization.cpp @@ -849,11 +849,38 @@ void testFromString(int byteOrder) testOk1(_data->getSubFieldT("Y")->get()=="testing"); } +void testDeserializeTypeFail(const char *buf, size_t buflen) +{ + + std::vector bytes(buf, buf + buflen); + ByteBuffer B(&bytes[0], bytes.size(), EPICS_ENDIAN_BIG); + + try{ + FieldConstPtr ptr(getFieldCreate()->deserialize(&B, control)); + }catch(std::exception& e) { + testPass("Expected exception: %s", e.what()); + return; + } + testFail("Unexpected success? %d", __LINE__); +} + +void testMalformed() +{ + testDiag("testMalformed()"); + +#define CASE(STR) testDeserializeTypeFail(STR, sizeof(STR)-1) + // a structure array where the element type is not a structure + CASE("\x88\x83\x2b\x01\x01"); + // a union array where ... + CASE("\x89\x83\x2b\x01\x01"); +#undef CASE +} + } // end namespace MAIN(testSerialization) { - testPlan(234); + testPlan(236); flusher = new SerializableControlImpl(); control = new DeserializableControlImpl(); @@ -880,6 +907,8 @@ MAIN(testSerialization) { testFromString(EPICS_ENDIAN_BIG); testFromString(EPICS_ENDIAN_LITTLE); + testMalformed(); + delete buffer; delete control; delete flusher;