Implemented better testing and fixed skipepd frames

This commit is contained in:
Martino Ferrari
2026-07-01 16:39:34 +02:00
parent 7a326c5d78
commit 0bea41f866
46 changed files with 4358 additions and 1739 deletions
@@ -220,6 +220,9 @@ void UDPSourceSession::ParseConfigPayload(const uint8 *payload, uint32 size) {
memcpy(&sigDescs_[i],
payload + 4u + i * UDPS_SIGNAL_DESC_SIZE,
UDPS_SIGNAL_DESC_SIZE);
/* MD-3: force null-termination of name/unit to prevent intra-struct OOB read */
sigDescs_[i].name[sizeof(sigDescs_[i].name) - 1u] = '\0';
sigDescs_[i].unit[sizeof(sigDescs_[i].unit) - 1u] = '\0';
}
publishMode_ = payload[4u + numSigs * UDPS_SIGNAL_DESC_SIZE];
numSignals_ = numSigs;
@@ -237,8 +240,11 @@ void UDPSourceSession::ParseConfigPayload(const uint8 *payload, uint32 size) {
/* (Re)allocate the time-signal decode scratch to the largest element count. */
uint32 maxElems = 1u;
for (uint32 i = 0u; i < numSigs; i++) {
uint32 ne = sigDescs_[i].numRows * sigDescs_[i].numCols;
if (ne > maxElems) { maxElems = ne; }
uint64 ne = static_cast<uint64>(sigDescs_[i].numRows) *
static_cast<uint64>(sigDescs_[i].numCols);
if (ne == 0u) { ne = 1u; }
if (ne > 0x100000u) { ne = 0x100000u; /* sanity cap */ }
if (ne > maxElems) { maxElems = static_cast<uint32>(ne); }
}
if (maxElems > timeScratchLen_) {
delete[] timeScratch_;
@@ -343,22 +349,36 @@ void UDPSourceSession::ParseDataPayload(const uint8 *payload, uint32 size) {
uint32 off = offset;
for (uint32 s = 0u; s < nSigs; s++) {
const UDPSSignalDescriptor &desc = descs[s];
uint32 numElements = desc.numRows * desc.numCols;
if (numElements == 0u) { numElements = 1u; }
/* HI-1: use 64-bit multiply to avoid overflow on attacker-controlled numRows/numCols */
uint64 numElements64 = static_cast<uint64>(desc.numRows) *
static_cast<uint64>(desc.numCols);
if (numElements64 == 0u) { numElements64 = 1u; }
if (numElements64 > 0x100000u) { return; /* sanity cap: 1M elements */ }
uint32 numElements = static_cast<uint32>(numElements64);
uint32 wireElemBytes = (desc.quantType != UDPS_QUANT_NONE)
? QuantWireBytes(desc.quantType)
: MARTe::UDPSTypeCodeByteSize(desc.typeCode);
if (wireElemBytes == 0u) { return; }
uint32 elemsToRead = ((pm == UDPS_PUBLISH_ACCUMULATE) && (numElements == 1u))
? numSamples
: numElements;
/* Accumulate mode batches one full snapshot (all elements) per RT
* cycle for every signal (scalar or array) — see UDPStreamer's
* SerializeAccumulated. HI-1: 64-bit multiply to avoid overflow on
* attacker-controlled numSamples. */
uint64 elemsToRead64 = (pm == UDPS_PUBLISH_ACCUMULATE)
? (numElements64 * static_cast<uint64>(numSamples))
: numElements64;
if (elemsToRead64 > 0x100000u) { return; /* sanity cap: 1M elements */ }
uint32 elemsToRead = static_cast<uint32>(elemsToRead64);
if (off + elemsToRead * wireElemBytes > size) { return; }
/* HI-1: 64-bit bounds check to prevent uint32 multiply overflow */
uint64 bytesNeeded = static_cast<uint64>(off) +
static_cast<uint64>(elemsToRead) *
static_cast<uint64>(wireElemBytes);
if (bytesNeeded > static_cast<uint64>(size)) { return; }
sigOff[s] = off;
sigElems[s] = elemsToRead;
off += elemsToRead * wireElemBytes;
off += static_cast<uint32>(elemsToRead * wireElemBytes);
}
/* The decode scratch is sized at CONFIG time to the largest per-signal
@@ -389,8 +409,10 @@ void UDPSourceSession::ParseDataPayload(const uint8 *payload, uint32 size) {
for (uint32 s = 0u; s < nSigs; s++) {
const UDPSSignalDescriptor &desc = descs[s];
uint32 numElements = desc.numRows * desc.numCols;
if (numElements == 0u) { numElements = 1u; }
uint64 ne64 = static_cast<uint64>(desc.numRows) *
static_cast<uint64>(desc.numCols);
if (ne64 == 0u) { ne64 = 1u; }
uint32 numElements = static_cast<uint32>(ne64);
const uint32 nElems = sigElems[s];
const bool isFirstLast = (numElements > 1u) &&