Is there an already existing issue for this?
Expected behavior
SampleLostStatus.total_count should accumulate monotonically and never wrap or overflow. When the per-event lost-sample count is already capped to INT32_MAX by StatelessReader, the cumulative counter should either saturate at INT32_MAX or use a wider type so that repeated additions remain well-defined.
Current behavior
When a StatelessReader-backed DataReader receives a DATA submessage whose sequence number skips by more than INT32_MAX relative to the previous one, StatelessReader correctly caps lost_samples at INT32_MAX. However, DataReaderImpl::update_sample_lost_status adds this value directly to the int32_t field total_count with no overflow check. If total_count is already greater than zero (from any prior lost-sample event), the addition overflows and UBSan aborts the process:
runtime error: signed integer overflow: 1 + 2147483647 cannot be represented in type 'int'
Without UBSan the counter silently wraps to a large negative value.
Steps to reproduce
Proof of Concept:
The following three RTPS UDP packets, sent in order to a Fast-DDS participant port, reproduce the overflow. The key is that packet 3 carries a writerSN.low of 0x80000004 in little-endian encoding, creating a sequence-number gap large enough to saturate the per-event counter at INT32_MAX.
Packet 1 — establish baseline (SN = 1):
# RTPS header
52 54 50 53 # Magic "RTPS"
02 03 # Protocol version 2.3
01 0F # Vendor ID (eProsima)
01 02 03 04 05 06 07 08 09 0A 0B 0C # GUID prefix
# DATA submessage (ID=0x15, flags=0x05: little-endian + data present)
15 05 18 00 # subMsg ID, flags, octetsToNextHeader=24
00 00 # extraFlags
10 00 # octetsToInlineQos = 16
00 00 00 00 # readerEntityId = ENTITYID_UNKNOWN
00 00 00 07 # writerEntityId
00 00 00 00 # writerSN.high = 0
01 00 00 00 # writerSN.low = 1 (SN = 1)
00 01 00 00 # serialized payload (CDR_BE + padding)
Packet 2 — create one lost sample (SN = 3, gap = 1):
52 54 50 53 02 03 01 0F 01 02 03 04 05 06 07 08 09 0A 0B 0C
15 05 18 00 00 00 10 00 00 00 00 00 00 00 00 07
00 00 00 00 03 00 00 00 # writerSN = 3 → total_count becomes 1
00 01 00 00
Packet 3 — trigger overflow (SN = 0x80000004, gap ≈ INT32_MAX):
52 54 50 53 02 03 01 0F 01 02 03 04 05 06 07 08 09 0A 0B 0C
15 05 18 00 00 00 10 00 00 00 00 00 00 00 00 07
00 00 00 00 04 00 00 80 # writerSN.low = 0x80000004 (LE) → gap saturates at INT32_MAX
00 01 00 00 # total_count = 1 + INT32_MAX → UBSan overflow
Fast DDS version/commit
v3.5.0 (tag v3.5.0, branch master)
Fast-CDR v2.3.5
Platform/Architecture
Ubuntu Focal 20.04 amd64
Transport layer
UDPv4
Additional context
No response
XML configuration file
Relevant log output
/home/.../Fast-DDS/src/cpp/fastdds/subscriber/DataReaderImpl.cpp:1577:37:
runtime error: signed integer overflow: 1 + 2147483647 cannot be represented in type 'int'
#0 eprosima::fastdds::dds::DataReaderImpl::update_sample_lost_status(int)
DataReaderImpl.cpp:1577
#1 eprosima::fastdds::dds::DataReaderImpl::InnerDataReaderListener::on_sample_lost(
eprosima::fastdds::rtps::RTPSReader*, int)
DataReaderImpl.cpp:1009
#2 eprosima::fastdds::rtps::StatelessReader::change_received(
eprosima::fastdds::rtps::CacheChange_t*)
StatelessReader.cpp:403
#3 eprosima::fastdds::rtps::StatelessReader::process_data_msg(
eprosima::fastdds::rtps::CacheChange_t*)
StatelessReader.cpp:695
#4 ... MessageReceiver::proc_Submsg_Data(...) MessageReceiver.cpp:898
#5 ... MessageReceiver::processCDRMsg(...) MessageReceiver.cpp:467
#6 ... ReceiverResource::OnDataReceived(...) ReceiverResource.cpp:135
#7 ... UDPChannelResource::perform_listen_operation(...)
#8 start_thread (pthread)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior DataReaderImpl.cpp:1577:37 in
Network traffic capture
No response
Is there an already existing issue for this?
Expected behavior
SampleLostStatus.total_countshould accumulate monotonically and never wrap or overflow. When the per-event lost-sample count is already capped toINT32_MAXbyStatelessReader, the cumulative counter should either saturate atINT32_MAXor use a wider type so that repeated additions remain well-defined.Current behavior
When a
StatelessReader-backedDataReaderreceives a DATA submessage whose sequence number skips by more thanINT32_MAXrelative to the previous one,StatelessReadercorrectly capslost_samplesatINT32_MAX. However,DataReaderImpl::update_sample_lost_statusadds this value directly to theint32_tfieldtotal_countwith no overflow check. Iftotal_countis already greater than zero (from any prior lost-sample event), the addition overflows and UBSan aborts the process:Without UBSan the counter silently wraps to a large negative value.
Steps to reproduce
Proof of Concept:
The following three RTPS UDP packets, sent in order to a Fast-DDS participant port, reproduce the overflow. The key is that packet 3 carries a
writerSN.lowof0x80000004in little-endian encoding, creating a sequence-number gap large enough to saturate the per-event counter atINT32_MAX.Packet 1 — establish baseline (SN = 1):
Packet 2 — create one lost sample (SN = 3, gap = 1):
Packet 3 — trigger overflow (SN = 0x80000004, gap ≈ INT32_MAX):
Fast DDS version/commit
v3.5.0 (tag
v3.5.0, branchmaster)Fast-CDR v2.3.5
Platform/Architecture
Ubuntu Focal 20.04 amd64
Transport layer
UDPv4
Additional context
No response
XML configuration file
Relevant log output
Network traffic capture
No response