Skip to content

Segfault due to incompatible tinyxml2 version #1014

@wentasah

Description

@wentasah

Describe the bug

BehaviorTree.CPP vendors tinyxml2 version 10.0.0. If a library user uses tinyxml2 too, but links to version 11.0.0, it can result in segfaults. This happens when ROS, and specifically nav2_behavior_tree is compiled against tinyxml2 11.0.0. See the backtrace below.

I can see two possible solutions:

  1. Allow (optional) compilation of BehaviorTree.CPP against system-provided tinyxml2.
  2. Export the tinyxml2 header and library used by BehaviorTree.CPP so that library users can link to the correct version.

IMO, solution 1 would be simpler.

Backtrace:

#0  0x00007ffff40a85be in __GI___libc_free (mem=0x1) at malloc.c:3375
#1  0x00007ffff64fdde7 in tinyxml2::DynArray<char, 20>::~DynArray (this=0x7fffffff03f0, __in_chrg=<optimized out>)
    at /build/behaviortree_cpp_v4-release-release-jazzy-behaviortree_cpp-4.7.1-1/3rdparty/tinyxml2/tinyxml2.h:215
#2  tinyxml2::XMLPrinter::~XMLPrinter (this=0x7fffffff02e0, __in_chrg=<optimized out>) at /build/behaviortree_cpp_v4-release-release-jazzy-behaviortree_cpp-4.7.1-1/3rdparty/tinyxml2/tinyxml2.h:2251
#3  0x00007ffff6431bd1 in BT::XMLParser::PImpl::loadDocImpl (this=<optimized out>, doc=<optimized out>, add_includes=add_includes@entry=true)
    at /nix/store/2agih0y5ns3sgbviw2xhivdgg59b41g9-gcc-14-20241116/include/c++/14-20241116/bits/allocator.h:182
#4  0x00007ffff64fbda8 in BT::XMLParser::loadFromFile (this=<optimized out>, filepath=..., add_includes=true)
    at /build/behaviortree_cpp_v4-release-release-jazzy-behaviortree_cpp-4.7.1-1/src/xml_parsing.cpp:164
#5  0x00007ffff6473309 in BT::BehaviorTreeFactory::createTreeFromFile (this=0xbcaf28, file_path=..., blackboard=...)
    at /build/behaviortree_cpp_v4-release-release-jazzy-behaviortree_cpp-4.7.1-1/src/bt_factory.cpp:366
#6  0x00007ffff7ec3f96 in nav2_behavior_tree::BehaviorTreeEngine::createTreeFromFile(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::shared_ptr<BT::Blackboard>) () from /nix/store/n5f670fwvkp9f34hq0fm8gcb7b0clqk3-ros-env/lib/libnav2_behavior_tree.so
#7  0x00007fffe67a6912 in nav2_behavior_tree::BtActionServer<nav2_msgs::action::NavigateToPose>::loadBehaviorTree (this=this@entry=0x6981e0, bt_xml_filename=...)
    at /nix/store/c25zd27c7w79gca25qbsq6cdz0fvxlqv-ros-jazzy-nav2-behavior-tree-1.3.9-r1/include/nav2_behavior_tree/bt_action_server_impl.hpp:246
#8  0x00007fffe67b8101 in nav2_behavior_tree::BtActionServer<nav2_msgs::action::NavigateToPose>::on_activate (this=0x6981e0)
    at /nix/store/c25zd27c7w79gca25qbsq6cdz0fvxlqv-ros-jazzy-nav2-behavior-tree-1.3.9-r1/include/nav2_behavior_tree/bt_action_server_impl.hpp:195
#9  0x00007fffe67b82d2 in nav2_core::BehaviorTreeNavigator<nav2_msgs::action::NavigateToPose>::on_activate (this=0xa148f0)
    at /nix/store/avdw81296sr8l0k9nplvzrmdcg59mg3i-ros-jazzy-nav2-core-1.3.9-r1/include/nav2_core/behavior_tree_navigator.hpp:239
#10 0x00007ffff4d9b869 in nav2_bt_navigator::BtNavigator::on_activate (this=0x5e22a0, state=...) at /build/navigation2-release-release-jazzy-nav2_bt_navigator-1.3.9-1/src/bt_navigator.cpp:149
#11 0x00007ffff547e593 in std::function<rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn(rclcpp_lifecycle::State const&)>::operator() (this=0x7fffffff2530, __args#0=...)
    at /nix/store/2agih0y5ns3sgbviw2xhivdgg59b41g9-gcc-14-20241116/include/c++/14-20241116/bits/std_function.h:591
#12 rclcpp_lifecycle::LifecycleNode::LifecycleNodeInterfaceImpl::execute_callback (this=this@entry=0x8ceba0, cb_id=cb_id@entry=13, previous_state=...)
    at /build/rclcpp-release-release-jazzy-rclcpp_lifecycle-28.1.12-1/src/lifecycle_node_interface_impl.cpp:514
#13 0x00007ffff547e985 in rclcpp_lifecycle::LifecycleNode::LifecycleNodeInterfaceImpl::change_state (this=this@entry=0x8ceba0, transition_id=transition_id@entry=3 '\003', 
    cb_return_code=@0x7fffffff3887: 0) at /build/rclcpp-release-release-jazzy-rclcpp_lifecycle-28.1.12-1/src/lifecycle_node_interface_impl.cpp:447
#14 0x00007ffff547f325 in rclcpp_lifecycle::LifecycleNode::LifecycleNodeInterfaceImpl::on_change_state (this=0x8ceba0, header=..., req=..., resp=...)
    at /build/rclcpp-release-release-jazzy-rclcpp_lifecycle-28.1.12-1/src/lifecycle_node_interface_impl.cpp:242
#15 0x00007ffff5481d28 in std::__invoke_impl<void, void (rclcpp_lifecycle::LifecycleNode::LifecycleNodeInterfaceImpl::*&)(std::shared_ptr<rmw_request_id_s>, std::shared_ptr<lifecycle_msgs::srv::ChangeState_Request_<std::allocator<void> > >, std::shared_ptr<lifecycle_msgs::srv::ChangeState_Response_<std::allocator<void> > >), rclcpp_lifecycle::LifecycleNode::LifecycleNodeInterfaceImpl*&, std::shared_ptr<rmw_request_id_s>, std::shared_ptr<lifecycle_msgs::srv::ChangeState_Request_<std::allocator<void> > >, std::shared_ptr<lifecycle_msgs::srv::ChangeState_Response_<std::allocator<void> > > > (
    __f=<optimized out>, __t=<optimized out>) at /nix/store/2agih0y5ns3sgbviw2xhivdgg59b41g9-gcc-14-20241116/include/c++/14-20241116/bits/invoke.h:74
#16 std::__invoke<void (rclcpp_lifecycle::LifecycleNode::LifecycleNodeInterfaceImpl::*&)(std::shared_ptr<rmw_request_id_s>, std::shared_ptr<lifecycle_msgs::srv::ChangeState_Request_<std::allocator<void> > >, std::shared_ptr<lifecycle_msgs::srv::ChangeState_Response_<std::allocator<void> > >), rclcpp_lifecycle::LifecycleNode::LifecycleNodeInterfaceImpl*&, std::shared_ptr<rmw_request_id_s>, std::shared_ptr<lifecycle_msgs::srv::ChangeState_Request_<std::allocator<void> > >, std::shared_ptr<lifecycle_msgs::srv::ChangeState_Response_<std::allocator<void> > > > (__fn=<optimized out>)
    at /nix/store/2agih0y5ns3sgbviw2xhivdgg59b41g9-gcc-14-20241116/include/c++/14-20241116/bits/invoke.h:96
#17 std::_Bind<void (rclcpp_lifecycle::LifecycleNode::LifecycleNodeInterfaceImpl::*(rclcpp_lifecycle::LifecycleNode::LifecycleNodeInterfaceImpl*, std::_Placeholder<1>, std::_Placeholder<2>, std::_Placeholder<3>))(std::shared_ptr<rmw_request_id_s>, std::shared_ptr<lifecycle_msgs::srv::ChangeState_Request_<std::allocator<void> > >, std::shared_ptr<lifecycle_msgs::srv::ChangeState_Response_<std::allocator<void> > >)>::__call<void, std::shared_ptr<rmw_request_id_s>&&, std::shared_ptr<lifecycle_msgs::srv::ChangeState_Request_<std::allocator<void> > >&&, std::shared_ptr<lifecycle_msgs::srv::ChangeState_Response_<std::allocator<void> > >&&, 0ul, 1ul, 2ul, 3ul>(std::tuple<std::shared_ptr<rmw_request_id_s>&&, std::shared_ptr<lifecycle_msgs::srv::ChangeState_Request_<std::allocator<void> > >&&, std::shared_ptr<lifecycle_msgs::srv::ChangeState_Response_<std::allocator<void> > >&&>&&, std::_Index_tuple<0ul, 1ul, 2ul, 3ul>) (this=<optimized out>, __args=...)
    at /nix/store/2agih0y5ns3sgbviw2xhivdgg59b41g9-gcc-14-20241116/include/c++/14-20241116/functional:513

How to Reproduce

The bug and its reproducer was originally reported in lopsided98/nix-ros-overlay#648. The summary is:

Compile nav2_behavior_tree against tinyxml2 11.0.0 and run:

  • Terminal 1: ros2 run --prefix "gdb -ex run --args" nav2_bt_navigator bt_navigator
  • Terminal 2: ros2 run nav2_util lifecycle_bringup bt_navigator

Observe bt_navigator segfault.

This can be easily reproduced with the Nix package manager by using the following flake.nix, running nix develop (perhaps with --experimental-features 'nix-command flakes') and then the above commands.

{
  inputs = {
    nix-ros-overlay.url = "github:lopsided98/nix-ros-overlay/730baddd51dff4e1e59b7dfa871ca234e9d95df4";
    nixpkgs.follows = "nix-ros-overlay/nixpkgs"; 
  };
  outputs = { self, nix-ros-overlay, nixpkgs }:
    nix-ros-overlay.inputs.flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = import nixpkgs { inherit system; overlays = [ nix-ros-overlay.overlays.default ]; };
      in {
        devShells.default = pkgs.mkShell {
          name = "Example project";
          packages = [
            pkgs.colcon
            (with pkgs.rosPackages.jazzy; buildEnv {
              paths = [ nav2-bt-navigator nav2-util ros-core ];
            })
          ];
        };
      });
  nixConfig = {
    extra-substituters = [ "https://ros.cachix.org" ];
    extra-trusted-public-keys = [ "ros.cachix.org-1:dSyZxI8geDCJrwgvCOHDoAfOm5sV1wCPjBkKL+38Rvo=" ];
  };
}

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