Skip to content

Commit de666d2

Browse files
authored
Check for negative time in rclcpp::Time(int64_t nanoseconds, ...) constructor (#2510)
Signed-off-by: Nursharmin Ramli <[email protected]>
1 parent 5593961 commit de666d2

File tree

3 files changed

+17
-76
lines changed

3 files changed

+17
-76
lines changed

rclcpp/include/rclcpp/time.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class Time
4949
/**
5050
* \param nanoseconds since time epoch
5151
* \param clock_type clock type
52+
* \throws std::runtime_error if nanoseconds are negative
5253
*/
5354
RCLCPP_PUBLIC
5455
explicit Time(int64_t nanoseconds = 0, rcl_clock_type_t clock_type = RCL_SYSTEM_TIME);

rclcpp/src/rclcpp/time.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ Time::Time(int32_t seconds, uint32_t nanoseconds, rcl_clock_type_t clock_type)
6060
Time::Time(int64_t nanoseconds, rcl_clock_type_t clock_type)
6161
: rcl_time_(init_time_point(clock_type))
6262
{
63+
if (nanoseconds < 0) {
64+
throw std::runtime_error("cannot store a negative time point in rclcpp::Time");
65+
}
66+
6367
rcl_time_.nanoseconds = nanoseconds;
6468
}
6569

@@ -249,6 +253,9 @@ Time::operator+=(const rclcpp::Duration & rhs)
249253
}
250254

251255
rcl_time_.nanoseconds += rhs.nanoseconds();
256+
if (rcl_time_.nanoseconds < 0) {
257+
throw std::runtime_error("cannot store a negative time point in rclcpp::Time");
258+
}
252259

253260
return *this;
254261
}
@@ -264,6 +271,9 @@ Time::operator-=(const rclcpp::Duration & rhs)
264271
}
265272

266273
rcl_time_.nanoseconds -= rhs.nanoseconds();
274+
if (rcl_time_.nanoseconds < 0) {
275+
throw std::runtime_error("cannot store a negative time point in rclcpp::Time");
276+
}
267277

268278
return *this;
269279
}

rclcpp/test/rclcpp/test_time.cpp

Lines changed: 6 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@ TEST_F(TestTime, conversions) {
138138

139139
EXPECT_ANY_THROW(rclcpp::Time(-1, 1));
140140

141+
EXPECT_ANY_THROW(rclcpp::Time(-1));
142+
141143
EXPECT_ANY_THROW(
142144
{
143145
rclcpp::Time assignment(1, 2);
@@ -168,48 +170,6 @@ TEST_F(TestTime, conversions) {
168170
EXPECT_EQ(time_msg.nanosec, HALF_SEC_IN_NS);
169171
EXPECT_EQ(rclcpp::Time(time_msg).nanoseconds(), ONE_AND_HALF_SEC_IN_NS);
170172
}
171-
172-
{
173-
// Can rclcpp::Time be negative or not? The following constructor works:
174-
rclcpp::Time time(-HALF_SEC_IN_NS);
175-
auto time_msg = static_cast<builtin_interfaces::msg::Time>(time);
176-
EXPECT_EQ(time_msg.sec, -1);
177-
EXPECT_EQ(time_msg.nanosec, HALF_SEC_IN_NS);
178-
179-
// The opposite conversion throws...
180-
EXPECT_ANY_THROW(
181-
{
182-
rclcpp::Time negative_time(time_msg);
183-
});
184-
}
185-
186-
{
187-
// Can rclcpp::Time be negative or not? The following constructor works:
188-
rclcpp::Time time(-ONE_SEC_IN_NS);
189-
auto time_msg = static_cast<builtin_interfaces::msg::Time>(time);
190-
EXPECT_EQ(time_msg.sec, -1);
191-
EXPECT_EQ(time_msg.nanosec, 0u);
192-
193-
// The opposite conversion throws...
194-
EXPECT_ANY_THROW(
195-
{
196-
rclcpp::Time negative_time(time_msg);
197-
});
198-
}
199-
200-
{
201-
// Can rclcpp::Time be negative or not? The following constructor works:
202-
rclcpp::Time time(-ONE_AND_HALF_SEC_IN_NS);
203-
auto time_msg = static_cast<builtin_interfaces::msg::Time>(time);
204-
EXPECT_EQ(time_msg.sec, -2);
205-
EXPECT_EQ(time_msg.nanosec, HALF_SEC_IN_NS);
206-
207-
// The opposite conversion throws...
208-
EXPECT_ANY_THROW(
209-
{
210-
rclcpp::Time negative_time(time_msg);
211-
});
212-
}
213173
}
214174

215175
TEST_F(TestTime, operators) {
@@ -326,31 +286,18 @@ TEST_F(TestTime, overflow_detectors) {
326286

327287
TEST_F(TestTime, overflows) {
328288
rclcpp::Time max_time(std::numeric_limits<rcl_time_point_value_t>::max());
329-
rclcpp::Time min_time(std::numeric_limits<rcl_time_point_value_t>::min());
330289
rclcpp::Duration one(1ns);
331290
rclcpp::Duration two(2ns);
332291

333-
// Cross min/max
292+
// Cross max
334293
EXPECT_THROW(max_time + one, std::overflow_error);
335-
EXPECT_THROW(min_time - one, std::underflow_error);
336-
EXPECT_THROW(max_time - min_time, std::overflow_error);
337-
EXPECT_THROW(min_time - max_time, std::underflow_error);
338294
EXPECT_THROW(rclcpp::Time(max_time) += one, std::overflow_error);
339-
EXPECT_THROW(rclcpp::Time(min_time) -= one, std::underflow_error);
340295
EXPECT_NO_THROW(max_time - max_time);
341-
EXPECT_NO_THROW(min_time - min_time);
342296

343-
// Cross zero in both directions
297+
// Cross zero
344298
rclcpp::Time one_time(1);
345-
EXPECT_NO_THROW(one_time - two);
346-
EXPECT_NO_THROW(rclcpp::Time(one_time) -= two);
347-
348-
rclcpp::Time minus_one_time(-1);
349-
EXPECT_NO_THROW(minus_one_time + two);
350-
EXPECT_NO_THROW(rclcpp::Time(minus_one_time) += two);
351-
352-
EXPECT_NO_THROW(one_time - minus_one_time);
353-
EXPECT_NO_THROW(minus_one_time - one_time);
299+
EXPECT_THROW(one_time - two, std::runtime_error);
300+
EXPECT_THROW(rclcpp::Time(one_time) -= two, std::runtime_error);
354301

355302
rclcpp::Time two_time(2);
356303
EXPECT_NO_THROW(one_time - two_time);
@@ -432,41 +379,24 @@ TEST_F(TestTime, test_overflow_underflow_throws) {
432379
RCLCPP_EXPECT_THROW_EQ(
433380
test_time = rclcpp::Time(INT64_MAX) + rclcpp::Duration(1ns),
434381
std::overflow_error("addition leads to int64_t overflow"));
435-
RCLCPP_EXPECT_THROW_EQ(
436-
test_time = rclcpp::Time(INT64_MIN) + rclcpp::Duration(-1ns),
437-
std::underflow_error("addition leads to int64_t underflow"));
438382

439383
RCLCPP_EXPECT_THROW_EQ(
440384
test_time = rclcpp::Time(INT64_MAX) - rclcpp::Duration(-1ns),
441385
std::overflow_error("time subtraction leads to int64_t overflow"));
442-
RCLCPP_EXPECT_THROW_EQ(
443-
test_time = rclcpp::Time(INT64_MIN) - rclcpp::Duration(1ns),
444-
std::underflow_error("time subtraction leads to int64_t underflow"));
445386

446387
test_time = rclcpp::Time(INT64_MAX);
447388
RCLCPP_EXPECT_THROW_EQ(
448389
test_time += rclcpp::Duration(1ns),
449390
std::overflow_error("addition leads to int64_t overflow"));
450-
test_time = rclcpp::Time(INT64_MIN);
451-
RCLCPP_EXPECT_THROW_EQ(
452-
test_time += rclcpp::Duration(-1ns),
453-
std::underflow_error("addition leads to int64_t underflow"));
454391

455392
test_time = rclcpp::Time(INT64_MAX);
456393
RCLCPP_EXPECT_THROW_EQ(
457394
test_time -= rclcpp::Duration(-1ns),
458395
std::overflow_error("time subtraction leads to int64_t overflow"));
459-
test_time = rclcpp::Time(INT64_MIN);
460-
RCLCPP_EXPECT_THROW_EQ(
461-
test_time -= rclcpp::Duration(1ns),
462-
std::underflow_error("time subtraction leads to int64_t underflow"));
463396

464397
RCLCPP_EXPECT_THROW_EQ(
465398
test_time = rclcpp::Duration::from_nanoseconds(INT64_MAX) + rclcpp::Time(1),
466399
std::overflow_error("addition leads to int64_t overflow"));
467-
RCLCPP_EXPECT_THROW_EQ(
468-
test_time = rclcpp::Duration::from_nanoseconds(INT64_MIN) + rclcpp::Time(-1),
469-
std::underflow_error("addition leads to int64_t underflow"));
470400
}
471401

472402
class TestClockSleep : public ::testing::Test

0 commit comments

Comments
 (0)