@@ -989,6 +989,103 @@ TEST(TransportUDP, MaliciousDataFragUnalignedSizes)
989989 reader.block_for_all ();
990990}
991991
992+ // Regression test for redmine issue #24030
993+ TEST (TransportUDP, MaliciousDataFragLastFragment)
994+ {
995+ // Force using UDP transport
996+ auto udp_transport = std::make_shared<UDPv4TransportDescriptor>();
997+
998+ PubSubWriter<UnboundedHelloWorldPubSubType> writer (TEST_TOPIC_NAME);
999+ PubSubReader<UnboundedHelloWorldPubSubType> reader (TEST_TOPIC_NAME);
1000+
1001+ struct MaliciousDataFragInconsistentLastFragmentLength
1002+ {
1003+ std::array<char , 4 > rtps_id{ {' R' , ' T' , ' P' , ' S' } };
1004+ std::array<uint8_t , 2 > protocol_version{ {2 , 3 } };
1005+ std::array<uint8_t , 2 > vendor_id{ {0x01 , 0x0F } };
1006+ GuidPrefix_t sender_prefix{};
1007+
1008+ struct DataFragSubMsg
1009+ {
1010+ struct Header
1011+ {
1012+ uint8_t submessage_id = 0x16 ;
1013+ #if FASTDDS_IS_BIG_ENDIAN_TARGET
1014+ uint8_t flags = 0x00 ;
1015+ #else
1016+ uint8_t flags = 0x01 ;
1017+ #endif // FASTDDS_IS_BIG_ENDIAN_TARGET
1018+ uint16_t octets_to_next_header = 0x24 ;
1019+ uint16_t extra_flags = 0 ;
1020+ uint16_t octets_to_inline_qos = 0x1c ;
1021+ EntityId_t reader_id{};
1022+ EntityId_t writer_id{};
1023+ SequenceNumber_t sn{100 };
1024+ uint32_t fragment_starting_num = 1 ;
1025+ uint16_t fragments_in_submessage = 8 ;
1026+ uint16_t fragment_size = 65504 ;
1027+ uint32_t sample_size = 65504 * 8 ;
1028+ };
1029+
1030+ struct SerializedData
1031+ {
1032+ octet data[4 ] {0xA0 , 0xA1 , 0xA2 , 0xA3 };
1033+ };
1034+
1035+ Header header;
1036+ SerializedData payload;
1037+ }
1038+ data;
1039+ };
1040+
1041+ UDPMessageSender fake_msg_sender;
1042+
1043+ // Set common QoS
1044+ reader.disable_builtin_transport ().add_user_transport_to_pparams (udp_transport)
1045+ .history_depth (10 ).reliability (eprosima::fastdds::dds::RELIABLE_RELIABILITY_QOS);
1046+ writer.history_depth (10 ).reliability (eprosima::fastdds::dds::RELIABLE_RELIABILITY_QOS);
1047+
1048+ // Set custom reader locator so we can send malicious data to a known location
1049+ Locator_t reader_locator;
1050+ ASSERT_TRUE (IPLocator::setIPv4 (reader_locator, " 127.0.0.1" ));
1051+ reader_locator.port = 7000 ;
1052+ reader.add_to_unicast_locator_list (" 127.0.0.1" , 7000 );
1053+
1054+ // Initialize and wait for discovery
1055+ reader.init ();
1056+ ASSERT_TRUE (reader.isInitialized ());
1057+ writer.init ();
1058+ ASSERT_TRUE (writer.isInitialized ());
1059+
1060+ reader.wait_discovery ();
1061+ writer.wait_discovery ();
1062+
1063+ auto data = default_unbounded_helloworld_data_generator ();
1064+ reader.startReception (data);
1065+ writer.send (data);
1066+ ASSERT_TRUE (data.empty ());
1067+
1068+ // Send malicious data
1069+ {
1070+ auto writer_guid = writer.datawriter_guid ();
1071+
1072+ MaliciousDataFragInconsistentLastFragmentLength malicious_packet{};
1073+ malicious_packet.sender_prefix = writer_guid.guidPrefix ;
1074+ malicious_packet.data .header .writer_id = writer_guid.entityId ;
1075+ malicious_packet.data .header .reader_id = reader.datareader_guid ().entityId ;
1076+
1077+ CDRMessage_t msg (0 );
1078+ uint32_t msg_len = static_cast <uint32_t >(sizeof (malicious_packet));
1079+ msg.init (reinterpret_cast <octet*>(&malicious_packet), msg_len);
1080+ msg.length = msg_len;
1081+ msg.pos = msg_len;
1082+ fake_msg_sender.send (msg, reader_locator);
1083+ }
1084+
1085+ // Block reader until reception finished or timeout.
1086+ reader.block_for_all ();
1087+ }
1088+
9921089// Regression test for redmine issue #23917
9931090TEST (TransportUDP, MaliciousHeartbeatBigStart)
9941091{
0 commit comments