Skip to content

Commit 9f8731e

Browse files
jckingcopybara-github
authored andcommitted
Add debug checks for valid duration and timestamp
PiperOrigin-RevId: 730982021
1 parent 7ea8830 commit 9f8731e

File tree

9 files changed

+65
-26
lines changed

9 files changed

+65
-26
lines changed

common/legacy_value.cc

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -988,10 +988,10 @@ absl::Status ModernValue(google::protobuf::Arena* arena,
988988
return absl::OkStatus();
989989
}
990990
case CelValue::Type::kDuration:
991-
result = DurationValue{legacy_value.DurationOrDie()};
991+
result = UnsafeDurationValue(legacy_value.DurationOrDie());
992992
return absl::OkStatus();
993993
case CelValue::Type::kTimestamp:
994-
result = TimestampValue{legacy_value.TimestampOrDie()};
994+
result = UnsafeTimestampValue(legacy_value.TimestampOrDie());
995995
return absl::OkStatus();
996996
case CelValue::Type::kList:
997997
result = ListValue{common_internal::LegacyListValue{
@@ -1077,10 +1077,10 @@ absl::StatusOr<google::api::expr::runtime::CelValue> LegacyValue(
10771077
return common_internal::LegacyTrivialStructValue(arena, modern_value);
10781078
case ValueKind::kDuration:
10791079
return CelValue::CreateUncheckedDuration(
1080-
Cast<DurationValue>(modern_value).NativeValue());
1080+
modern_value.GetDuration().NativeValue());
10811081
case ValueKind::kTimestamp:
10821082
return CelValue::CreateTimestamp(
1083-
Cast<TimestampValue>(modern_value).NativeValue());
1083+
modern_value.GetTimestamp().NativeValue());
10841084
case ValueKind::kList:
10851085
return common_internal::LegacyTrivialListValue(arena, modern_value);
10861086
case ValueKind::kMap:
@@ -1133,9 +1133,9 @@ absl::StatusOr<Value> FromLegacyValue(google::protobuf::Arena* arena,
11331133
reinterpret_cast<uintptr_t>(message_wrapper.legacy_type_info())};
11341134
}
11351135
case CelValue::Type::kDuration:
1136-
return DurationValue(legacy_value.DurationOrDie());
1136+
return UnsafeDurationValue(legacy_value.DurationOrDie());
11371137
case CelValue::Type::kTimestamp:
1138-
return TimestampValue(legacy_value.TimestampOrDie());
1138+
return UnsafeTimestampValue(legacy_value.TimestampOrDie());
11391139
case CelValue::Type::kList:
11401140
return ListValue{common_internal::LegacyListValue{
11411141
reinterpret_cast<uintptr_t>(legacy_value.ListOrDie())}};

common/values/duration_value.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,16 @@
2222
#include <string>
2323

2424
#include "absl/base/nullability.h"
25+
#include "absl/log/absl_check.h"
2526
#include "absl/status/status.h"
2627
#include "absl/strings/cord.h"
2728
#include "absl/strings/string_view.h"
2829
#include "absl/time/time.h"
30+
#include "absl/utility/utility.h"
2931
#include "common/type.h"
3032
#include "common/value_kind.h"
3133
#include "common/values/values.h"
34+
#include "internal/time.h"
3235
#include "google/protobuf/arena.h"
3336
#include "google/protobuf/descriptor.h"
3437
#include "google/protobuf/message.h"
@@ -39,14 +42,20 @@ class Value;
3942
class DurationValue;
4043
class TypeManager;
4144

45+
DurationValue UnsafeDurationValue(absl::Duration value);
46+
4247
// `DurationValue` represents values of the primitive `duration` type.
4348
class DurationValue final : private common_internal::ValueMixin<DurationValue> {
4449
public:
4550
static constexpr ValueKind kKind = ValueKind::kDuration;
4651

47-
explicit DurationValue(absl::Duration value) noexcept : value_(value) {}
52+
explicit DurationValue(absl::Duration value) noexcept
53+
: DurationValue(absl::in_place, value) {
54+
ABSL_DCHECK_OK(internal::ValidateDuration(value));
55+
}
4856

4957
DurationValue& operator=(absl::Duration value) noexcept {
58+
ABSL_DCHECK_OK(internal::ValidateDuration(value));
5059
value_ = value;
5160
return *this;
5261
}
@@ -102,10 +111,17 @@ class DurationValue final : private common_internal::ValueMixin<DurationValue> {
102111

103112
private:
104113
friend class common_internal::ValueMixin<DurationValue>;
114+
friend DurationValue UnsafeDurationValue(absl::Duration value);
115+
116+
DurationValue(absl::in_place_t, absl::Duration value) : value_(value) {}
105117

106118
absl::Duration value_ = absl::ZeroDuration();
107119
};
108120

121+
inline DurationValue UnsafeDurationValue(absl::Duration value) {
122+
return DurationValue(absl::in_place, value);
123+
}
124+
109125
inline bool operator==(DurationValue lhs, DurationValue rhs) {
110126
return static_cast<absl::Duration>(lhs) == static_cast<absl::Duration>(rhs);
111127
}

common/values/timestamp_value.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,16 @@
2222
#include <string>
2323

2424
#include "absl/base/nullability.h"
25+
#include "absl/log/absl_check.h"
2526
#include "absl/status/status.h"
2627
#include "absl/strings/cord.h"
2728
#include "absl/strings/string_view.h"
2829
#include "absl/time/time.h"
30+
#include "absl/utility/utility.h"
2931
#include "common/type.h"
3032
#include "common/value_kind.h"
3133
#include "common/values/values.h"
34+
#include "internal/time.h"
3235
#include "google/protobuf/arena.h"
3336
#include "google/protobuf/descriptor.h"
3437
#include "google/protobuf/message.h"
@@ -39,15 +42,21 @@ class Value;
3942
class TimestampValue;
4043
class TypeManager;
4144

45+
TimestampValue UnsafeTimestampValue(absl::Time value);
46+
4247
// `TimestampValue` represents values of the primitive `timestamp` type.
4348
class TimestampValue final
4449
: private common_internal::ValueMixin<TimestampValue> {
4550
public:
4651
static constexpr ValueKind kKind = ValueKind::kTimestamp;
4752

48-
explicit TimestampValue(absl::Time value) noexcept : value_(value) {}
53+
explicit TimestampValue(absl::Time value) noexcept
54+
: TimestampValue(absl::in_place, value) {
55+
ABSL_DCHECK_OK(internal::ValidateTimestamp(value));
56+
}
4957

5058
TimestampValue& operator=(absl::Time value) noexcept {
59+
ABSL_DCHECK_OK(internal::ValidateTimestamp(value));
5160
value_ = value;
5261
return *this;
5362
}
@@ -101,10 +110,17 @@ class TimestampValue final
101110

102111
private:
103112
friend class common_internal::ValueMixin<TimestampValue>;
113+
friend TimestampValue UnsafeTimestampValue(absl::Time value);
114+
115+
TimestampValue(absl::in_place_t, absl::Time value) : value_(value) {}
104116

105117
absl::Time value_ = absl::UnixEpoch();
106118
};
107119

120+
inline TimestampValue UnsafeTimestampValue(absl::Time value) {
121+
return TimestampValue(absl::in_place, value);
122+
}
123+
108124
inline bool operator==(TimestampValue lhs, TimestampValue rhs) {
109125
return lhs.NativeValue() == rhs.NativeValue();
110126
}

internal/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,7 @@ cc_library(
308308
"@com_google_absl//absl/strings",
309309
"@com_google_absl//absl/strings:str_format",
310310
"@com_google_absl//absl/time",
311+
"@com_google_protobuf//:protobuf",
311312
],
312313
)
313314

internal/time.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@
1818
#include <string>
1919

2020
#include "absl/status/status.h"
21+
#include "absl/status/statusor.h"
2122
#include "absl/strings/str_cat.h"
2223
#include "absl/strings/str_format.h"
24+
#include "absl/strings/string_view.h"
2325
#include "absl/time/time.h"
2426
#include "internal/status_macros.h"
2527

internal/time.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "absl/status/statusor.h"
2222
#include "absl/strings/string_view.h"
2323
#include "absl/time/time.h"
24+
#include "google/protobuf/util/time_util.h"
2425

2526
namespace cel::internal {
2627

@@ -31,7 +32,8 @@ namespace cel::internal {
3132
// google.protobuf.Duration from protocol buffer messages, which this
3233
// implementation currently supports.
3334
// TODO: revisit
34-
return absl::Seconds(315576000000) + absl::Nanoseconds(999999999);
35+
return absl::Seconds(google::protobuf::util::TimeUtil::kDurationMaxSeconds) +
36+
absl::Nanoseconds(google::protobuf::util::TimeUtil::kDurationMaxNanoseconds);
3537
}
3638

3739
inline absl::Duration
@@ -41,18 +43,22 @@ namespace cel::internal {
4143
// google.protobuf.Duration from protocol buffer messages, which this
4244
// implementation currently supports.
4345
// TODO: revisit
44-
return absl::Seconds(-315576000000) + absl::Nanoseconds(-999999999);
46+
return absl::Seconds(google::protobuf::util::TimeUtil::kDurationMinSeconds) +
47+
absl::Nanoseconds(google::protobuf::util::TimeUtil::kDurationMinNanoseconds);
4548
}
4649

4750
inline absl::Time
4851
MaxTimestamp() {
49-
return absl::UnixEpoch() + absl::Seconds(253402300799) +
50-
absl::Nanoseconds(999999999);
52+
return absl::UnixEpoch() +
53+
absl::Seconds(google::protobuf::util::TimeUtil::kTimestampMaxSeconds) +
54+
absl::Nanoseconds(google::protobuf::util::TimeUtil::kTimestampMaxNanoseconds);
5155
}
5256

5357
inline absl::Time
5458
MinTimestamp() {
55-
return absl::UnixEpoch() + absl::Seconds(-62135596800);
59+
return absl::UnixEpoch() +
60+
absl::Seconds(google::protobuf::util::TimeUtil::kTimestampMinSeconds) +
61+
absl::Nanoseconds(google::protobuf::util::TimeUtil::kTimestampMinNanoseconds);
5662
}
5763

5864
absl::Status ValidateDuration(absl::Duration duration);

runtime/internal/convert_constant.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ struct ConvertVisitor {
6060
if (duration >= kDurationHigh || duration <= kDurationLow) {
6161
return ErrorValue(*DurationOverflowError());
6262
}
63-
return DurationValue(duration);
63+
return UnsafeDurationValue(duration);
6464
}
6565
absl::StatusOr<cel::Value> operator()(const absl::Time timestamp) {
66-
return TimestampValue(timestamp);
66+
return UnsafeTimestampValue(timestamp);
6767
}
6868
};
6969

runtime/standard/time_functions.cc

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -400,15 +400,15 @@ absl::Status RegisterUncheckedTimeArithmeticFunctions(
400400
false),
401401
BinaryFunctionAdapter<Value, absl::Time, absl::Duration>::WrapFunction(
402402
[](absl::Time t1, absl::Duration d2) -> Value {
403-
return TimestampValue(t1 + d2);
403+
return UnsafeTimestampValue(t1 + d2);
404404
})));
405405

406406
CEL_RETURN_IF_ERROR(registry.Register(
407407
BinaryFunctionAdapter<Value, absl::Duration,
408408
absl::Time>::CreateDescriptor(builtin::kAdd, false),
409409
BinaryFunctionAdapter<Value, absl::Duration, absl::Time>::WrapFunction(
410410
[](absl::Duration d2, absl::Time t1) -> Value {
411-
return TimestampValue(t1 + d2);
411+
return UnsafeTimestampValue(t1 + d2);
412412
})));
413413

414414
CEL_RETURN_IF_ERROR(registry.Register(
@@ -417,7 +417,7 @@ absl::Status RegisterUncheckedTimeArithmeticFunctions(
417417
false),
418418
BinaryFunctionAdapter<Value, absl::Duration, absl::Duration>::
419419
WrapFunction([](absl::Duration d1, absl::Duration d2) -> Value {
420-
return DurationValue(d1 + d2);
420+
return UnsafeDurationValue(d1 + d2);
421421
})));
422422

423423
CEL_RETURN_IF_ERROR(registry.Register(
@@ -427,7 +427,7 @@ absl::Status RegisterUncheckedTimeArithmeticFunctions(
427427
BinaryFunctionAdapter<Value, absl::Time, absl::Duration>::WrapFunction(
428428

429429
[](absl::Time t1, absl::Duration d2) -> Value {
430-
return TimestampValue(t1 - d2);
430+
return UnsafeTimestampValue(t1 - d2);
431431
})));
432432

433433
CEL_RETURN_IF_ERROR(registry.Register(
@@ -436,15 +436,15 @@ absl::Status RegisterUncheckedTimeArithmeticFunctions(
436436
BinaryFunctionAdapter<Value, absl::Time, absl::Time>::WrapFunction(
437437

438438
[](absl::Time t1, absl::Time t2) -> Value {
439-
return DurationValue(t1 - t2);
439+
return UnsafeDurationValue(t1 - t2);
440440
})));
441441

442442
CEL_RETURN_IF_ERROR(registry.Register(
443443
BinaryFunctionAdapter<Value, absl::Duration, absl::Duration>::
444444
CreateDescriptor(builtin::kSubtract, false),
445445
BinaryFunctionAdapter<Value, absl::Duration, absl::Duration>::
446446
WrapFunction([](absl::Duration d1, absl::Duration d2) -> Value {
447-
return DurationValue(d1 - d2);
447+
return UnsafeDurationValue(d1 - d2);
448448
})));
449449

450450
return absl::OkStatus();

runtime/standard/type_conversion_functions.cc

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,7 @@ namespace {
3939
using ::cel::internal::EncodeDurationToJson;
4040
using ::cel::internal::EncodeTimestampToJson;
4141
using ::cel::internal::MaxTimestamp;
42-
43-
// Time representing `9999-12-31T23:59:59.999999999Z`.
44-
const absl::Time kMaxTime = MaxTimestamp();
42+
using ::cel::internal::MinTimestamp;
4543

4644
absl::Status RegisterBoolConversionFunctions(FunctionRegistry& registry,
4745
const RuntimeOptions&) {
@@ -356,11 +354,11 @@ absl::Status RegisterTimeConversionFunctions(FunctionRegistry& registry,
356354
"String to Timestamp conversion failed"));
357355
}
358356
if (enable_timestamp_duration_overflow_errors) {
359-
if (ts < absl::UniversalEpoch() || ts > kMaxTime) {
357+
if (ts < MinTimestamp() || ts > MaxTimestamp()) {
360358
return ErrorValue(absl::OutOfRangeError("timestamp overflow"));
361359
}
362360
}
363-
return TimestampValue(ts);
361+
return UnsafeTimestampValue(ts);
364362
},
365363
registry);
366364
}

0 commit comments

Comments
 (0)