From 3850aded0be6466fa78f1668a885b9d02492bcf8 Mon Sep 17 00:00:00 2001 From: Dmitry Slepichev Date: Tue, 8 Sep 2026 05:05:41 +0400 Subject: [PATCH] [fix] validate RGBDSettings::depth_camera_id against the rig The RGBD branch of the Odometry constructor pushed depth_camera_id into the frustum graph without checking it. The default -1 means "not set", and static_cast turns it into a huge unsigned id; FrustumIntersectionGraph then registers it as a primary camera, so is_valid() passes and a camera index that names no camera reaches the odometry. Check the id the way the Multisensor branch right below already does - rejecting negatives and anything past the end of the rig - and name the offending value in the message. RgbdModeRequiresCudaBuild constructed with the default config, so in a USE_CUDA=OFF build it now hits this check before the mode switch and never sees the USE_CUDA message it asserts on. Give it a valid depth camera id, the same way MultisensorModeRequiresCunlsBuild already sets depth_camera_ids. Co-Authored-By: Claude Opus 5 (1M context) --- libs/cuvslam/cuvslam2.cpp | 6 +++++- libs/cuvslam/test/tracker_test.cpp | 12 ++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/libs/cuvslam/cuvslam2.cpp b/libs/cuvslam/cuvslam2.cpp index 7a725b9a..48add638 100644 --- a/libs/cuvslam/cuvslam2.cpp +++ b/libs/cuvslam/cuvslam2.cpp @@ -527,7 +527,11 @@ Odometry::Odometry(const Rig& rig, const Config& cfg) { std::vector depth_ids; bool enable_depth_stereo_tracking_fig = false; if (cfg.odometry_mode == OdometryMode::RGBD) { - depth_ids.push_back(static_cast(cfg.rgbd_settings.depth_camera_id)); + const int32_t depth_camera_id = cfg.rgbd_settings.depth_camera_id; + THROW_INVALID_ARG_IF( + depth_camera_id < 0 || static_cast(depth_camera_id) >= rig.cameras.size(), + "RGBDSettings::depth_camera_id (" + std::to_string(depth_camera_id) + ") is not a camera id of the rig"); + depth_ids.push_back(static_cast(depth_camera_id)); enable_depth_stereo_tracking_fig = cfg.rgbd_settings.enable_depth_stereo_tracking; } else if (cfg.odometry_mode == OdometryMode::Multisensor) { depth_ids.reserve(cfg.multisensor_settings.depth_camera_ids.size()); diff --git a/libs/cuvslam/test/tracker_test.cpp b/libs/cuvslam/test/tracker_test.cpp index e0d7f586..9003f6ea 100644 --- a/libs/cuvslam/test/tracker_test.cpp +++ b/libs/cuvslam/test/tracker_test.cpp @@ -171,6 +171,17 @@ TEST_F(TrackerTest, RejectsSlamConfigInOdometryOnlyMode) { EXPECT_THROW(Tracker(rig, Mode::OdometryOnlyRealtime, realtime, &slam), std::invalid_argument); } +TEST_F(TrackerTest, RgbdModeChecksDepthCameraId) { + // The depth camera id has to name a camera of the rig: the default -1 means "not set", and an id + // past the end of the rig would reach the frustum graph as a camera that does not exist. + Odometry::Config cfg; + cfg.odometry_mode = Odometry::OdometryMode::RGBD; + EXPECT_THROW(Tracker(rig, Mode::OdometryOnlyRealtime, cfg), std::invalid_argument); + + cfg.rgbd_settings.depth_camera_id = static_cast(rig.cameras.size()); + EXPECT_THROW(Tracker(rig, Mode::OdometryOnlyRealtime, cfg), std::invalid_argument); +} + TEST_F(TrackerTest, RejectsNonFiniteCalibration) { constexpr float kNan = std::numeric_limits::quiet_NaN(); @@ -292,6 +303,7 @@ TEST_F(TrackerTest, RgbdModeRequiresCudaBuild) { // rather than silently constructing a tracker that cannot run it. Odometry::Config cfg; cfg.odometry_mode = Odometry::OdometryMode::RGBD; + cfg.rgbd_settings.depth_camera_id = 0; try { Tracker{rig, Mode::OdometryOnlyRealtime, cfg}; FAIL() << "RGBD mode was accepted by a build without CUDA";