8
8
#ifndef GOOGLE_PROTOBUF_PARSE_CONTEXT_H__
9
9
#define GOOGLE_PROTOBUF_PARSE_CONTEXT_H__
10
10
11
+ #include < algorithm>
12
+ #include < climits>
13
+ #include < cstddef>
11
14
#include < cstdint>
12
15
#include < cstring>
16
+ #include < limits>
13
17
#include < string>
14
18
#include < type_traits>
15
19
#include < utility>
16
20
17
21
#include " absl/base/config.h"
22
+ #include " absl/base/prefetch.h"
18
23
#include " absl/log/absl_check.h"
19
24
#include " absl/log/absl_log.h"
20
25
#include " absl/strings/cord.h"
27
32
#include " google/protobuf/inlined_string_field.h"
28
33
#include " google/protobuf/io/coded_stream.h"
29
34
#include " google/protobuf/io/zero_copy_stream.h"
35
+ #include " google/protobuf/message_lite.h"
30
36
#include " google/protobuf/metadata_lite.h"
31
37
#include " google/protobuf/port.h"
32
38
#include " google/protobuf/repeated_field.h"
39
+ #include " google/protobuf/repeated_ptr_field.h"
33
40
#include " google/protobuf/wire_format_lite.h"
34
41
35
42
@@ -103,7 +110,7 @@ class PROTOBUF_EXPORT EpsCopyInputStream {
103
110
ABSL_DCHECK (ptr <= buffer_end_ + kSlopBytes );
104
111
int count;
105
112
if (next_chunk_ == patch_buffer_) {
106
- count = static_cast < int >(buffer_end_ + kSlopBytes - ptr);
113
+ count = BytesAvailable ( ptr);
107
114
} else {
108
115
count = size_ + static_cast <int >(buffer_end_ - ptr);
109
116
}
@@ -170,14 +177,14 @@ class PROTOBUF_EXPORT EpsCopyInputStream {
170
177
}
171
178
172
179
PROTOBUF_NODISCARD const char * Skip (const char * ptr, int size) {
173
- if (size <= buffer_end_ + kSlopBytes - ptr) {
180
+ if (size <= BytesAvailable ( ptr) ) {
174
181
return ptr + size;
175
182
}
176
183
return SkipFallback (ptr, size);
177
184
}
178
185
PROTOBUF_NODISCARD const char * ReadString (const char * ptr, int size,
179
186
std::string* s) {
180
- if (size <= buffer_end_ + kSlopBytes - ptr) {
187
+ if (size <= BytesAvailable ( ptr) ) {
181
188
// Fundamentally we just want to do assign to the string.
182
189
// However micro-benchmarks regress on string reading cases. So we copy
183
190
// the same logic from the old CodedInputStream ReadString. Note: as of
@@ -191,7 +198,7 @@ class PROTOBUF_EXPORT EpsCopyInputStream {
191
198
}
192
199
PROTOBUF_NODISCARD const char * AppendString (const char * ptr, int size,
193
200
std::string* s) {
194
- if (size <= buffer_end_ + kSlopBytes - ptr) {
201
+ if (size <= BytesAvailable ( ptr) ) {
195
202
s->append (ptr, size);
196
203
return ptr + size;
197
204
}
@@ -204,8 +211,7 @@ class PROTOBUF_EXPORT EpsCopyInputStream {
204
211
205
212
PROTOBUF_NODISCARD const char * ReadCord (const char * ptr, int size,
206
213
::absl::Cord* cord) {
207
- if (size <= std::min<int >(static_cast <int >(buffer_end_ + kSlopBytes - ptr),
208
- kMaxCordBytesToCopy )) {
214
+ if (size <= std::min<int >(BytesAvailable (ptr), kMaxCordBytesToCopy )) {
209
215
*cord = absl::string_view (ptr, size);
210
216
return ptr + size;
211
217
}
@@ -345,6 +351,14 @@ class PROTOBUF_EXPORT EpsCopyInputStream {
345
351
// systems. TODO do we need to set this as build flag?
346
352
enum { kSafeStringSize = 50000000 };
347
353
354
+ int BytesAvailable (const char * ptr) const {
355
+ ABSL_DCHECK_NE (ptr, nullptr );
356
+ ptrdiff_t available = buffer_end_ + kSlopBytes - ptr;
357
+ ABSL_DCHECK_GE (available, 0 );
358
+ ABSL_DCHECK_LE (available, INT_MAX);
359
+ return static_cast <int >(available);
360
+ }
361
+
348
362
// Advances to next buffer chunk returns a pointer to the same logical place
349
363
// in the stream as set by overrun. Overrun indicates the position in the slop
350
364
// region the parse was left (0 <= overrun <= kSlopBytes). Returns true if at
@@ -382,7 +396,7 @@ class PROTOBUF_EXPORT EpsCopyInputStream {
382
396
383
397
template <typename A>
384
398
const char * AppendSize (const char * ptr, int size, const A& append) {
385
- int chunk_size = static_cast < int >(buffer_end_ + kSlopBytes - ptr);
399
+ int chunk_size = BytesAvailable ( ptr);
386
400
do {
387
401
ABSL_DCHECK (size > chunk_size);
388
402
if (next_chunk_ == nullptr ) return nullptr ;
@@ -396,7 +410,7 @@ class PROTOBUF_EXPORT EpsCopyInputStream {
396
410
ptr = Next ();
397
411
if (ptr == nullptr ) return nullptr ; // passed the limit
398
412
ptr += kSlopBytes ;
399
- chunk_size = static_cast < int >(buffer_end_ + kSlopBytes - ptr);
413
+ chunk_size = BytesAvailable ( ptr);
400
414
} while (size > chunk_size);
401
415
append (ptr, size);
402
416
return ptr + size;
@@ -411,7 +425,7 @@ class PROTOBUF_EXPORT EpsCopyInputStream {
411
425
const char * AppendUntilEnd (const char * ptr, const A& append) {
412
426
if (ptr - buffer_end_ > limit_) return nullptr ;
413
427
while (limit_ > kSlopBytes ) {
414
- size_t chunk_size = buffer_end_ + kSlopBytes - ptr;
428
+ size_t chunk_size = BytesAvailable ( ptr) ;
415
429
append (ptr, chunk_size);
416
430
ptr = Next ();
417
431
if (ptr == nullptr ) return limit_end_;
@@ -1163,7 +1177,7 @@ template <typename T>
1163
1177
const char * EpsCopyInputStream::ReadPackedFixed (const char * ptr, int size,
1164
1178
RepeatedField<T>* out) {
1165
1179
GOOGLE_PROTOBUF_PARSER_ASSERT (ptr);
1166
- int nbytes = static_cast < int >(buffer_end_ + kSlopBytes - ptr);
1180
+ int nbytes = BytesAvailable ( ptr);
1167
1181
while (size > nbytes) {
1168
1182
int num = nbytes / sizeof (T);
1169
1183
int old_entries = out->size ();
@@ -1181,7 +1195,7 @@ const char* EpsCopyInputStream::ReadPackedFixed(const char* ptr, int size,
1181
1195
ptr = Next ();
1182
1196
if (ptr == nullptr ) return nullptr ;
1183
1197
ptr += kSlopBytes - (nbytes - block_size);
1184
- nbytes = static_cast < int >(buffer_end_ + kSlopBytes - ptr);
1198
+ nbytes = BytesAvailable ( ptr);
1185
1199
}
1186
1200
int num = size / sizeof (T);
1187
1201
int block_size = num * sizeof (T);
0 commit comments