@@ -95,6 +95,20 @@ struct ArenaOffsetHelper {
95
95
PROTOBUF_EXPORT MessageLite* CloneSlow (Arena* arena, const MessageLite& value);
96
96
PROTOBUF_EXPORT std::string* CloneSlow (Arena* arena, const std::string& value);
97
97
98
+ // A utility function for logging that doesn't need any template types.
99
+ PROTOBUF_EXPORT void LogIndexOutOfBounds (int index, int size);
100
+
101
+ // A utility function for logging that doesn't need any template types. Same as
102
+ // LogIndexOutOfBounds, but aborts the program in all cases by logging to FATAL
103
+ // instead of DFATAL.
104
+ [[noreturn]] PROTOBUF_EXPORT void LogIndexOutOfBoundsAndAbort (int index,
105
+ int size);
106
+ PROTOBUF_EXPORT inline void RuntimeAssertInBounds (int index, int size) {
107
+ if (ABSL_PREDICT_FALSE (index < 0 || index >= size)) {
108
+ LogIndexOutOfBoundsAndAbort (index , size);
109
+ }
110
+ }
111
+
98
112
// Defined further below.
99
113
template <typename Type>
100
114
class GenericTypeHandler ;
@@ -184,8 +198,12 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase {
184
198
185
199
template <typename TypeHandler>
186
200
Value<TypeHandler>* Mutable (int index) {
187
- ABSL_DCHECK_GE (index , 0 );
188
- ABSL_DCHECK_LT (index , current_size_);
201
+ if constexpr (GetBoundsCheckMode () == BoundsCheckMode::kAbort ) {
202
+ RuntimeAssertInBounds (index , current_size_);
203
+ } else {
204
+ ABSL_DCHECK_GE (index , 0 );
205
+ ABSL_DCHECK_LT (index , current_size_);
206
+ }
189
207
return cast<TypeHandler>(element_at (index ));
190
208
}
191
209
@@ -251,8 +269,22 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase {
251
269
252
270
template <typename TypeHandler>
253
271
const Value<TypeHandler>& Get (int index) const {
254
- ABSL_DCHECK_GE (index , 0 );
255
- ABSL_DCHECK_LT (index , current_size_);
272
+ if constexpr (GetBoundsCheckMode () == BoundsCheckMode::kReturnDefault ) {
273
+ if (ABSL_PREDICT_FALSE (index < 0 || index >= current_size_)) {
274
+ // `default_instance()` is not supported for MessageLite and Message.
275
+ if constexpr (TypeHandler::has_default_instance ()) {
276
+ LogIndexOutOfBounds (index , current_size_);
277
+ return TypeHandler::default_instance ();
278
+ }
279
+ }
280
+ } else if constexpr (GetBoundsCheckMode () == BoundsCheckMode::kAbort ) {
281
+ // We refactor this to a separate function instead of inlining it so we
282
+ // can measure the performance impact more easily.
283
+ RuntimeAssertInBounds (index , current_size_);
284
+ } else {
285
+ ABSL_DCHECK_GE (index , 0 );
286
+ ABSL_DCHECK_LT (index , current_size_);
287
+ }
256
288
return *cast<TypeHandler>(element_at (index ));
257
289
}
258
290
@@ -847,19 +879,31 @@ class GenericTypeHandler {
847
879
return *static_cast <const GenericType*>(
848
880
MessageTraits<Type>::default_instance ());
849
881
}
882
+
883
+ static constexpr bool has_default_instance () { return true ; }
850
884
};
851
885
852
886
template <>
853
887
inline Arena* GenericTypeHandler<MessageLite>::GetArena(MessageLite* value) {
854
888
return value->GetArena ();
855
889
}
856
890
891
+ template <>
892
+ inline constexpr bool GenericTypeHandler<MessageLite>::has_default_instance() {
893
+ return false ;
894
+ }
895
+
857
896
// Message specialization bodies defined in message.cc. This split is necessary
858
897
// to allow proto2-lite (which includes this header) to be independent of
859
898
// Message.
860
899
template <>
861
900
PROTOBUF_EXPORT Arena* GenericTypeHandler<Message>::GetArena(Message* value);
862
901
902
+ template <>
903
+ inline constexpr bool GenericTypeHandler<Message>::has_default_instance() {
904
+ return false ;
905
+ }
906
+
863
907
PROTOBUF_EXPORT void * NewStringElement (Arena* arena);
864
908
865
909
template <>
@@ -887,6 +931,8 @@ class GenericTypeHandler<std::string> {
887
931
static const Type& default_instance () {
888
932
return GetEmptyStringAlreadyInited ();
889
933
}
934
+
935
+ static constexpr bool has_default_instance () { return true ; }
890
936
};
891
937
892
938
} // namespace internal
@@ -1981,14 +2027,6 @@ class UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator {
1981
2027
RepeatedPtrField<T>* field_;
1982
2028
};
1983
2029
1984
- // A utility function for logging that doesn't need any template types.
1985
- PROTOBUF_EXPORT void LogIndexOutOfBounds (int index, int size);
1986
-
1987
- // A utility function for logging that doesn't need any template types. Same as
1988
- // LogIndexOutOfBounds, but aborts the program in all cases by logging to FATAL
1989
- // instead of DFATAL.
1990
- [[noreturn]] PROTOBUF_EXPORT void LogIndexOutOfBoundsAndAbort (int index,
1991
- int size);
1992
2030
1993
2031
template <typename T>
1994
2032
const T& CheckedGetOrDefault (const RepeatedPtrField<T>& field, int index) {
0 commit comments