Merge branch 'master' into PSI

This commit is contained in:
zimoch committed 2026-09-25 15:23:11 +02:00
commit 8a5a6fcd27
19 files changed
+333 -130

No files matched your search

+43 -1
View File
@@ -303,15 +303,57 @@ static void testSerialize()
#undef TOFRO
}
static void testDeserializeOversize()
{
testDiag("testDeserializeOversize");
// Size field declares INT32_MAX bytes but no payload follows: 0xFE
// long-form marker + big-endian int32. deserialize() must reject this
// via ensureData() before allocating a ~2GB backing store.
const char msg[] = {(char)0xFE, 0x7F, (char)0xFF, (char)0xFF, (char)0xFF};
BitSet dut;
ByteBuffer buf((char*)msg, sizeof(msg), EPICS_ENDIAN_BIG);
try {
deserializeFromBuffer(&dut, buf);
testFail("oversized BitSet size was not rejected");
} catch(std::exception& e) {
testPass("oversized BitSet size rejected: %s", e.what());
}
}
static void testDeserializeNull()
{
testDiag("testDeserializeNull");
// A NULL size is encoded on the wire as the single byte 0xFF. Without
// the null check in deserialize() this would be cast to UINT32_MAX bytes
// and overflow the allocation size; it must instead yield an empty BitSet.
const char msg[] = {(char)0xFF};
BitSet dut;
dut.set(5); // ensure deserialize actually clears/replaces existing bits
ByteBuffer buf((char*)msg, sizeof(msg), EPICS_ENDIAN_BIG);
try {
deserializeFromBuffer(&dut, buf);
testPass("NULL BitSet size accepted");
} catch(std::exception& e) {
testFail("NULL BitSet size rejected: %s", e.what());
}
testOk1(dut.isEmpty());
testOk(buf.getRemaining()==0, "buffer remaining 0 == %u",
(unsigned)buf.getRemaining());
}
} // namespace
MAIN(testBitSet)
{
testPlan(90);
testPlan(94);
testInitialize();
testGetSetClearFlip();
testOperators();
testLogical();
testSerialize();
testDeserializeOversize();
testDeserializeNull();
return testDone();
}
+52 -1
View File
@@ -849,11 +849,60 @@ void testFromString(int byteOrder)
testOk1(_data->getSubFieldT<PVString>("Y")->get()=="testing");
}
void testDeserializeTypeFail(const char *buf, size_t buflen)
{
std::vector<char> 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
{
std::vector<char> inp(500u);
for(size_t i=0; i<inp.size(); i+=5) {
inp[i+0] = '\x80'; // Struct
inp[i+1] = '\xff'; // null ID String
inp[i+2] = '\x01'; // 1 member field
inp[i+3] = '\x01'; // member name length 1
inp[i+4] = 'x' ; // member name
}
testDeserializeTypeFail(&inp[0], inp.size());
}
{
std::vector<char> inp(500u);
for(size_t i=0; i<inp.size(); i+=5) {
inp[i+0] = '\x81'; // Union
inp[i+1] = '\xff'; // null ID String
inp[i+2] = '\x01'; // 1 member field
inp[i+3] = '\x01'; // member name length 1
inp[i+4] = 'x' ; // member name
}
testDeserializeTypeFail(&inp[0], inp.size());
}
}
} // end namespace
MAIN(testSerialization) {
testPlan(234);
testPlan(238);
flusher = new SerializableControlImpl();
control = new DeserializableControlImpl();
@@ -880,6 +929,8 @@ MAIN(testSerialization) {
testFromString(EPICS_ENDIAN_BIG);
testFromString(EPICS_ENDIAN_LITTLE);
testMalformed();
delete buffer;
delete control;
delete flusher;