Skip to content

Check remaining buffer size before allocating C wstring sequences (backport #910) - #911

Merged
fujitatomoya merged 1 commit into
lyricalfrom
mergify/bp/lyrical/pr-910
Sep 10, 2026
Merged

fujitatomoya merged 1 commit into
lyricalfrom
mergify/bp/lyrical/pr-910

Conversation

@mergify

@mergify mergify Bot commented Sep 8, 2026

Copy link
Copy Markdown

Description

#827 added check_sequence_size() to the dynamic sequence deserializers so the serialized length is checked against the remaining input buffer before anything is allocated. The C introspection wstring[] specialization, deserialize_field<std::wstring>(const rosidl_typesupport_introspection_c__MessageMember *, ...), was missed: it reads the 32-bit length and passes it straight to rosidl_runtime_c__U16String__Sequence__init(), which allocates the element array and then calls rosidl_runtime_c__U16String__init() (one 2-byte allocation each) for every element before a single element is read from the wire.

A participant on the same domain can send a sample whose wstring[] field is a length with no element data. Every rmw_fastrtps_dynamic_cpp subscriber using the C type support (rclpy, rclc, C nodes) then dies in one of two ways depending on the length:

  • if the element array does not fit the allocator (e.g. 0xFFFFFF00 elements, ~100 GB),
    __Sequence__init() fails and the resulting std::runtime_error escapes deserializeROSmessage(), which only catches Fast-CDR exceptions and std::bad_alloc, and propagates through Fast-DDS and rmw_take(), which catch nothing;
  • if it does fit, the per-element initialisation commits memory until the process is OOM-killed.

Either way the subscriber is gone before Fast-CDR reports the truncated buffer (CWE-400 / CWE-770).

This adds the same check_sequence_size() call used by the other sequence paths. A truncated sample now throws NotEnoughMemoryException, which deserializeROSmessage() already catches, so rmw_take() reports the sample as not taken and nothing is allocated.

test_deserialize_sequence_size feeds a hand-built XCDRv1 sample of test_msgs/msg/WStrings whose unbounded_sequence_of_wstrings claims 0x00FFFFFF elements with no element data to the C and C++ introspection type supports and checks that deserialization fails and the sequence stays empty. The length is large enough that an unfixed build allocates about 1 GB and fails the test, and small enough not to take down a CI host.

Verified on rolling (Ubuntu 26.04, Fast-CDR 2.3.6): the test fails with the fix reverted and passes with it; the package test suite including linters passes; populated WStrings messages still round-trip on both type supports.

The same change is needed on jazzy, kilted and lyrical, and on humble, where the file is rmw_fastrtps_dynamic_cpp/include/rmw_fastrtps_dynamic_cpp/TypeSupport_impl.hpp.


This is an automatic backport of pull request #910 done by [Mergify](https://mergify.com).

The C introspection wstring[] deserializer passed the on-the-wire length
straight to rosidl_runtime_c__U16String__Sequence__init() without the
check_sequence_size() guard that #827 added to the other sequence paths.
A truncated sample (a huge length with no element data) therefore either
failed the array allocation and let a std::runtime_error escape
deserializeROSmessage() and rmw_take(), or allocated and initialised
that many elements until the process was OOM-killed, in both cases
before Fast-CDR reported the short buffer (CWE-400 / CWE-770).

Add the guard, so the sample is rejected with NotEnoughMemoryException
before anything is allocated, and a regression test covering the C and
C++ introspection type supports.

Signed-off-by: Florencia Cabral <florencia.a.cabral@gmail.com>
(cherry picked from commit 5dd2ed1)
@ahcorde

ahcorde commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Pulls: #911
Gist: https://gist.githubusercontent.com/ahcorde/37fc498f73b37b983db19f93cdd1219d/raw/1449dc9f81fa1eb6feccb12eae1843b5c8611b45/ros2.repos
BUILD args: --packages-above-and-dependencies rmw_fastrtps_dynamic_cpp
TEST args: --packages-above rmw_fastrtps_dynamic_cpp
ROS Distro: lyrical
Job: ci_launcher
ci_launcher ran: https://ci.ros2.org/job/ci_launcher/20366

  • Linux Build Status
  • Linux-aarch64 Build Status
  • Linux-rhel Build Status
  • Windows Build Status

@ahcorde

ahcorde commented Sep 9, 2026

Copy link
Copy Markdown
Contributor
  • Linux Build Status
  • Linux-aarch64 Build Status
  • Linux-rhel Build Status
  • Windows Build Status

@fujitatomoya
fujitatomoya merged commit 2e98bda into lyrical Sep 10, 2026
2 checks passed
@ahcorde
ahcorde deleted the mergify/bp/lyrical/pr-910 branch September 10, 2026 08:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants