Skip to content

get_all_data_impl() does not handle null pointers properly, causing segmentation fault #2829

@zhihaoshang

Description

@zhihaoshang

Operating System:

Linux shangzh-VMware-Virtual-Platform 6.11.0-24-generic #24~24.04.1-Ubuntu SMP PREEMPT_DYNAMIC Tue Mar 25 20:14:34 UTC 2 x86_64 x86_64 x86_64 GNU/Linux

ROS version or commit hash:

ros2 jazzy

RMW implementation (if applicable):

No response

RMW Configuration (if applicable):

No response

Client library (if applicable):

rclcpp

'ros2 doctor --report' output

ros2 doc --report
 NETWORK CONFIGURATION
inet         : 127.0.0.1
inet4        : ['127.0.0.1']
inet6        : ['::1']
netmask      : 255.0.0.0
device       : lo
flags        : 73<UP,LOOPBACK,RUNNING>
mtu          : 65536
inet         : 192.168.148.137
inet4        : ['192.168.148.137']
ether        : 00:0c:29:be:c8:19
inet6        : ['fe80::20c:29ff:febe:c819%ens33']
netmask      : 255.255.255.0
device       : ens33
flags        : 4163<UP,MULTICAST,RUNNING,BROADCAST>
mtu          : 1500
broadcast    : 192.168.148.255

   PLATFORM INFORMATION
system           : Linux
platform info    : Linux-6.11.0-24-generic-x86_64-with-glibc2.39
release          : 6.11.0-24-generic
processor        : x86_64

   QOS COMPATIBILITY LIST
compatibility status    : No publisher/subscriber pairs found

   RMW MIDDLEWARE
middleware name    : rmw_fastrtps_cpp

   TOPIC LIST
topic               : none
publisher count     : 0
subscriber count    : 0

Steps to reproduce issue

Environment

OS Version: Ubuntu 24.04
rclcpp version: ros2 jazzy
Compiler name and version number: Ubuntu clang version 18.1.3
Source or binary build?
source build
build options: --mixin asan-gcc

Description

The function rclcpp::experimental::buffers::RingBufferImplementation::get_all_data_impl() dereferences elements in the internal buffer without checking for null pointers.

Test Case

#include <memory>
#include <utility>
#include "gtest/gtest.h"
#include "rclcpp/experimental/buffers/buffer_implementation_base.hpp"
#include "rclcpp/experimental/buffers/ring_buffer_implementation.hpp"

TEST(TestRingBufferImplementation, handle_nullptr_deletion) {
  rclcpp::experimental::buffers::RingBufferImplementation<std::unique_ptr<int>> rb(3);
  rb.enqueue(std::make_unique<int>(42));
  rb.enqueue(nullptr);  // intentionally enqueuing nullptr
  rb.enqueue(std::make_unique<int>(84));
  auto all_data = rb.get_all_data();
  EXPECT_EQ(3u, all_data.size());
  EXPECT_EQ(42, *(all_data[0]));
  EXPECT_EQ(nullptr, all_data[1]);
  EXPECT_EQ(84, *(all_data[2]));
}

Output

[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from TestRingBufferImplementation
[ RUN      ] TestRingBufferImplementation.handle_nullptr_deletion
AddressSanitizer:DEADLYSIGNAL
=================================================================
==4175429==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x5e92f3fa00a7 bp 0x7fffd29fddb0 sp 0x7fffd29fdcd0 T0)
==4175429==The signal is caused by a READ memory access.
==4175429==Hint: address points to the zero page.
    #0 0x5e92f3fa00a7 in std::vector<std::unique_ptr<int, std::default_delete<int> >, std::allocator<std::unique_ptr<int, std::default_delete<int> > > > rclcpp::experimental::buffers::RingBufferImplementation<std::unique_ptr<int, std::default_delete<int> > >::get_all_data_impl<std::unique_ptr<int, std::default_delete<int> >, (void*)0>() (/home/shangzh/rclcpp_cov2/build/rclcpp/test/rclcpp/test_ring_buffer_implementation+0x920a7) (BuildId: 73a642e3fe307a2989bc6b09aadf037d55ff05de)
    #1 0x5e92f3f9f0e7 in rclcpp::experimental::buffers::RingBufferImplementation<std::unique_ptr<int, std::default_delete<int> > >::get_all_data() (/home/shangzh/rclcpp_cov2/build/rclcpp/test/rclcpp/test_ring_buffer_implementation+0x910e7) (BuildId: 73a642e3fe307a2989bc6b09aadf037d55ff05de)
    #2 0x5e92f3f9c5bd in TestRingBufferImplementation_handle_nullptr_deletion_Test::TestBody() /home/shangzh/rclcpp_cov2/rclcpp/rclcpp/test/rclcpp/test_ring_buffer_implementation.cpp:12
    #3 0x5e92f4042941 in void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /home/shangzh/ros2_jazzy/install/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2612
    #4 0x5e92f402fb47 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) /home/shangzh/ros2_jazzy/install/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2648
    #5 0x5e92f3fd5527 in testing::Test::Run() /home/shangzh/ros2_jazzy/install/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2687
    #6 0x5e92f3fd6d03 in testing::TestInfo::Run() /home/shangzh/ros2_jazzy/install/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2836
    #7 0x5e92f3fd805c in testing::TestSuite::Run() /home/shangzh/ros2_jazzy/install/gtest_vendor/src/gtest_vendor/./src/gtest.cc:3015
    #8 0x5e92f3ffed87 in testing::internal::UnitTestImpl::RunAllTests() /home/shangzh/ros2_jazzy/install/gtest_vendor/src/gtest_vendor/./src/gtest.cc:5920
    #9 0x5e92f4045d9c in bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /home/shangzh/ros2_jazzy/install/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2612
    #10 0x5e92f4032de4 in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) /home/shangzh/ros2_jazzy/install/gtest_vendor/src/gtest_vendor/./src/gtest.cc:2648
    #11 0x5e92f3ffb391 in testing::UnitTest::Run() /home/shangzh/ros2_jazzy/install/gtest_vendor/src/gtest_vendor/./src/gtest.cc:5484
    #12 0x5e92f3fa5833 in RUN_ALL_TESTS() /home/shangzh/ros2_jazzy/install/gtest_vendor/src/gtest_vendor/include/gtest/gtest.h:2317
    #13 0x5e92f3fa577f in main /home/shangzh/ros2_jazzy/install/gtest_vendor/src/gtest_vendor/src/gtest_main.cc:64
    #14 0x7ac61042a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #15 0x7ac61042a28a in __libc_start_main_impl ../csu/libc-start.c:360
    #16 0x5e92f3f9c074 in _start (/home/shangzh/rclcpp_cov2/build/rclcpp/test/rclcpp/test_ring_buffer_implementation+0x8e074) (BuildId: 73a642e3fe307a2989bc6b09aadf037d55ff05de)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/home/shangzh/rclcpp_cov2/build/rclcpp/test/rclcpp/test_ring_buffer_implementation+0x920a7) (BuildId: 73a642e3fe307a2989bc6b09aadf037d55ff05de) in std::vector<std::unique_ptr<int, std::default_delete<int> >, std::allocator<std::unique_ptr<int, std::default_delete<int> > > > rclcpp::experimental::buffers::RingBufferImplementation<std::unique_ptr<int, std::default_delete<int> > >::get_all_data_impl<std::unique_ptr<int, std::default_delete<int> >, (void*)0>()
==4175429==ABORTING

Expected behavior

no crash

Actual behavior

crash

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinghelp wantedExtra attention is needed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions