Skip to content

Commit 89b6b6f

Browse files
committed
explicitely cast to uint64_t and prevent overflow
1 parent 80bd20a commit 89b6b6f

2 files changed

Lines changed: 44 additions & 5 deletions

File tree

rclcpp/include/rclcpp/time.hpp

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ class Time
8484
Time(int32_t seconds, uint32_t nanoseconds)
8585
: rcl_time_(get_empty_time_point())
8686
{
87-
uint64_t ns = RCL_S_TO_NS(seconds);
87+
uint64_t ns = RCL_S_TO_NS(static_cast<uint64_t>(seconds));
8888
ns += nanoseconds;
8989
rcl_time_.nanoseconds = ns;
9090
}
@@ -99,7 +99,11 @@ class Time
9999
Time(const builtin_interfaces::msg::Time & time_msg) // NOLINT
100100
: rcl_time_(get_empty_time_point())
101101
{
102-
rcl_time_.nanoseconds = RCL_S_TO_NS(time_msg.sec);
102+
if (time_msg.sec < 0) {
103+
throw std::runtime_error("can't convert a negative time msg to rclcpp::Time");
104+
}
105+
106+
rcl_time_.nanoseconds = RCL_S_TO_NS(static_cast<uint64_t>(time_msg.sec));
103107
rcl_time_.nanoseconds += time_msg.nanosec;
104108
}
105109

@@ -114,8 +118,12 @@ class Time
114118
void
115119
operator=(const builtin_interfaces::msg::Time & time_msg)
116120
{
121+
if (time_msg.sec < 0) {
122+
throw std::runtime_error("can't convert a negative time msg to rclcpp::Time");
123+
}
124+
117125
auto time_point = get_empty_time_point();
118-
time_point.nanoseconds = RCL_S_TO_NS(time_msg.sec);
126+
time_point.nanoseconds = RCL_S_TO_NS(static_cast<uint64_t>(time_msg.sec));
119127
time_point.nanoseconds += time_msg.nanosec;
120128

121129
this->rcl_time_ = time_point;
@@ -164,6 +172,11 @@ class Time
164172
throw std::runtime_error("can't add times with different time sources");
165173
}
166174

175+
auto ns = rcl_time_.nanoseconds + rhs.rcl_time_.nanoseconds;
176+
if (ns < rcl_time_.nanoseconds) {
177+
throw std::runtime_error("addition leads to uint64_t overflow");
178+
}
179+
167180
return Time(rcl_time_.nanoseconds + rhs.rcl_time_.nanoseconds);
168181
}
169182

@@ -174,6 +187,11 @@ class Time
174187
throw std::runtime_error("can't add times with different time sources");
175188
}
176189

190+
auto ns = rcl_time_.nanoseconds - rhs.rcl_time_.nanoseconds;
191+
if (ns > rcl_time_.nanoseconds) {
192+
throw std::runtime_error("subtraction leads to uint64_t underflow");
193+
}
194+
177195
return Time(rcl_time_.nanoseconds - rhs.rcl_time_.nanoseconds);
178196
}
179197

rclcpp/test/test_time.cpp

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include <gtest/gtest.h>
1616

17+
#include <limits>
1718
#include <string>
1819

1920
#include "rcl/error_handling.h"
@@ -30,7 +31,7 @@ class TestTime : public ::testing::Test
3031
}
3132
};
3233

33-
TEST(TestTime, rate_basics) {
34+
TEST(TestTime, time_sources) {
3435
using builtin_interfaces::msg::Time;
3536
// TODO(Karsten1987): Fix this test once ROS_TIME is implemented
3637
EXPECT_ANY_THROW(rclcpp::Time::now<RCL_ROS_TIME>());
@@ -61,8 +62,20 @@ TEST(TestTime, convertions) {
6162
msg.nanosec = 67890;
6263

6364
rclcpp::Time time = msg;
64-
EXPECT_EQ(RCL_S_TO_NS(msg.sec) + static_cast<uint64_t>(msg.nanosec), time.nanoseconds());
65+
EXPECT_EQ(
66+
RCL_S_TO_NS(static_cast<uint64_t>(msg.sec)) + static_cast<uint64_t>(msg.nanosec),
67+
time.nanoseconds());
6568
EXPECT_EQ(msg.sec, RCL_NS_TO_S(time.nanoseconds()));
69+
70+
builtin_interfaces::msg::Time negative_time_msg;
71+
negative_time_msg.sec = -1;
72+
negative_time_msg.nanosec = 1;
73+
try {
74+
rclcpp::Time negative_time = negative_time_msg;
75+
FAIL();
76+
} catch (const std::exception &) {
77+
SUCCEED();
78+
}
6679
}
6780

6881
TEST(TestTime, operators) {
@@ -83,3 +96,11 @@ TEST(TestTime, operators) {
8396
EXPECT_EQ(sub.nanoseconds(), young.nanoseconds() - old.nanoseconds());
8497
EXPECT_EQ(sub, young - old);
8598
}
99+
100+
TEST(TestTime, overflows) {
101+
rclcpp::Time max(std::numeric_limits<uint64_t>::max());
102+
rclcpp::Time one(1);
103+
104+
EXPECT_ANY_THROW(max + one);
105+
EXPECT_ANY_THROW(one - max);
106+
}

0 commit comments

Comments
 (0)