Skip to content

Commit b1f954e

Browse files
committed
Improves coverage of GPBCodedInputStream
1 parent b189389 commit b1f954e

5 files changed

+182
-85
lines changed

objectivec/GPBCodedInputStream.m

+14-47
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ static void RaiseException(NSInteger code, NSString *reason) {
6868
userInfo:exceptionInfo] raise];
6969
}
7070

71+
static void CheckRecursionLimit(GPBCodedInputStreamState *state) {
72+
if (state->recursionDepth >= kDefaultRecursionLimit) {
73+
RaiseException(GPBCodedInputStreamErrorRecursionDepthExceeded, nil);
74+
}
75+
}
76+
7177
static void CheckSize(GPBCodedInputStreamState *state, size_t size) {
7278
size_t newSize = state->bufferPos + size;
7379
if (newSize > state->bufferSize) {
@@ -99,41 +105,6 @@ static int64_t ReadRawLittleEndian64(GPBCodedInputStreamState *state) {
99105
return value;
100106
}
101107

102-
static int32_t ReadRawVarint32(GPBCodedInputStreamState *state) {
103-
int8_t tmp = ReadRawByte(state);
104-
if (tmp >= 0) {
105-
return tmp;
106-
}
107-
int32_t result = tmp & 0x7f;
108-
if ((tmp = ReadRawByte(state)) >= 0) {
109-
result |= tmp << 7;
110-
} else {
111-
result |= (tmp & 0x7f) << 7;
112-
if ((tmp = ReadRawByte(state)) >= 0) {
113-
result |= tmp << 14;
114-
} else {
115-
result |= (tmp & 0x7f) << 14;
116-
if ((tmp = ReadRawByte(state)) >= 0) {
117-
result |= tmp << 21;
118-
} else {
119-
result |= (tmp & 0x7f) << 21;
120-
result |= (tmp = ReadRawByte(state)) << 28;
121-
if (tmp < 0) {
122-
// Discard upper 32 bits.
123-
for (int i = 0; i < 5; i++) {
124-
if (ReadRawByte(state) >= 0) {
125-
return result;
126-
}
127-
}
128-
RaiseException(GPBCodedInputStreamErrorInvalidVarInt,
129-
@"Invalid VarInt32");
130-
}
131-
}
132-
}
133-
}
134-
return result;
135-
}
136-
137108
static int64_t ReadRawVarint64(GPBCodedInputStreamState *state) {
138109
int32_t shift = 0;
139110
int64_t result = 0;
@@ -149,6 +120,10 @@ static int64_t ReadRawVarint64(GPBCodedInputStreamState *state) {
149120
return 0;
150121
}
151122

123+
static int32_t ReadRawVarint32(GPBCodedInputStreamState *state) {
124+
return (int32_t)ReadRawVarint64(state);
125+
}
126+
152127
static void SkipRawData(GPBCodedInputStreamState *state, size_t size) {
153128
CheckSize(state, size);
154129
state->bufferPos += size;
@@ -452,9 +427,7 @@ - (NSString *)readString {
452427
- (void)readGroup:(int32_t)fieldNumber
453428
message:(GPBMessage *)message
454429
extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
455-
if (state_.recursionDepth >= kDefaultRecursionLimit) {
456-
RaiseException(GPBCodedInputStreamErrorRecursionDepthExceeded, nil);
457-
}
430+
CheckRecursionLimit(&state_);
458431
++state_.recursionDepth;
459432
[message mergeFromCodedInputStream:self extensionRegistry:extensionRegistry];
460433
GPBCodedInputStreamCheckLastTagWas(
@@ -464,9 +437,7 @@ - (void)readGroup:(int32_t)fieldNumber
464437

465438
- (void)readUnknownGroup:(int32_t)fieldNumber
466439
message:(GPBUnknownFieldSet *)message {
467-
if (state_.recursionDepth >= kDefaultRecursionLimit) {
468-
RaiseException(GPBCodedInputStreamErrorRecursionDepthExceeded, nil);
469-
}
440+
CheckRecursionLimit(&state_);
470441
++state_.recursionDepth;
471442
[message mergeFromCodedInputStream:self];
472443
GPBCodedInputStreamCheckLastTagWas(
@@ -476,10 +447,8 @@ - (void)readUnknownGroup:(int32_t)fieldNumber
476447

477448
- (void)readMessage:(GPBMessage *)message
478449
extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
450+
CheckRecursionLimit(&state_);
479451
int32_t length = ReadRawVarint32(&state_);
480-
if (state_.recursionDepth >= kDefaultRecursionLimit) {
481-
RaiseException(GPBCodedInputStreamErrorRecursionDepthExceeded, nil);
482-
}
483452
size_t oldLimit = GPBCodedInputStreamPushLimit(&state_, length);
484453
++state_.recursionDepth;
485454
[message mergeFromCodedInputStream:self extensionRegistry:extensionRegistry];
@@ -492,10 +461,8 @@ - (void)readMapEntry:(id)mapDictionary
492461
extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
493462
field:(GPBFieldDescriptor *)field
494463
parentMessage:(GPBMessage *)parentMessage {
464+
CheckRecursionLimit(&state_);
495465
int32_t length = ReadRawVarint32(&state_);
496-
if (state_.recursionDepth >= kDefaultRecursionLimit) {
497-
RaiseException(GPBCodedInputStreamErrorRecursionDepthExceeded, nil);
498-
}
499466
size_t oldLimit = GPBCodedInputStreamPushLimit(&state_, length);
500467
++state_.recursionDepth;
501468
GPBDictionaryReadEntry(mapDictionary, self, extensionRegistry, field,

objectivec/Tests/GPBCodedInputStreamTests.m

+155-30
Original file line numberDiff line numberDiff line change
@@ -62,52 +62,101 @@ - (NSData*)bytes_with_sentinel:(int32_t)unused, ... {
6262
#define bytes(...) [self bytes_with_sentinel:0, __VA_ARGS__, 256]
6363

6464
- (void)testDecodeZigZag {
65-
XCTAssertEqual(0, GPBDecodeZigZag32(0));
66-
XCTAssertEqual(-1, GPBDecodeZigZag32(1));
67-
XCTAssertEqual(1, GPBDecodeZigZag32(2));
68-
XCTAssertEqual(-2, GPBDecodeZigZag32(3));
69-
XCTAssertEqual((int32_t)0x3FFFFFFF, GPBDecodeZigZag32(0x7FFFFFFE));
70-
XCTAssertEqual((int32_t)0xC0000000, GPBDecodeZigZag32(0x7FFFFFFF));
71-
XCTAssertEqual((int32_t)0x7FFFFFFF, GPBDecodeZigZag32(0xFFFFFFFE));
72-
XCTAssertEqual((int32_t)0x80000000, GPBDecodeZigZag32(0xFFFFFFFF));
73-
74-
XCTAssertEqual((int64_t)0, GPBDecodeZigZag64(0));
75-
XCTAssertEqual((int64_t)-1, GPBDecodeZigZag64(1));
76-
XCTAssertEqual((int64_t)1, GPBDecodeZigZag64(2));
77-
XCTAssertEqual((int64_t)-2, GPBDecodeZigZag64(3));
78-
XCTAssertEqual((int64_t)0x000000003FFFFFFFL,
79-
GPBDecodeZigZag64(0x000000007FFFFFFEL));
80-
XCTAssertEqual((int64_t)0xFFFFFFFFC0000000L,
81-
GPBDecodeZigZag64(0x000000007FFFFFFFL));
82-
XCTAssertEqual((int64_t)0x000000007FFFFFFFL,
83-
GPBDecodeZigZag64(0x00000000FFFFFFFEL));
84-
XCTAssertEqual((int64_t)0xFFFFFFFF80000000L,
85-
GPBDecodeZigZag64(0x00000000FFFFFFFFL));
86-
XCTAssertEqual((int64_t)0x7FFFFFFFFFFFFFFFL,
87-
GPBDecodeZigZag64(0xFFFFFFFFFFFFFFFEL));
88-
XCTAssertEqual((int64_t)0x8000000000000000L,
89-
GPBDecodeZigZag64(0xFFFFFFFFFFFFFFFFL));
65+
[self assertReadZigZag32:bytes(0x0) value:0];
66+
[self assertReadZigZag32:bytes(0x1) value:-1];
67+
[self assertReadZigZag32:bytes(0x2) value:1];
68+
[self assertReadZigZag32:bytes(0x3) value:-2];
69+
70+
[self assertReadZigZag32:bytes(0xFE, 0xFF, 0xFF, 0xFF, 0x07) value:(int32_t)0x3FFFFFFF];
71+
[self assertReadZigZag32:bytes(0xFF, 0xFF, 0xFF, 0xFF, 0x07) value:(int32_t)0xC0000000];
72+
[self assertReadZigZag32:bytes(0xFE, 0xFF, 0xFF, 0xFF, 0x0F) value:(int32_t)0x7FFFFFFF];
73+
[self assertReadZigZag32:bytes(0xFF, 0xFF, 0xFF, 0xFF, 0x0F) value:(int32_t)0x80000000];
74+
75+
[self assertReadZigZag64:bytes(0x0) value:0];
76+
[self assertReadZigZag64:bytes(0x1) value:-1];
77+
[self assertReadZigZag64:bytes(0x2) value:1];
78+
[self assertReadZigZag64:bytes(0x3) value:-2];
79+
80+
[self assertReadZigZag64:bytes(0xFE, 0xFF, 0xFF, 0xFF, 0x07) value:(int32_t)0x3FFFFFFF];
81+
[self assertReadZigZag64:bytes(0xFF, 0xFF, 0xFF, 0xFF, 0x07) value:(int32_t)0xC0000000];
82+
[self assertReadZigZag64:bytes(0xFE, 0xFF, 0xFF, 0xFF, 0x0F) value:(int32_t)0x7FFFFFFF];
83+
[self assertReadZigZag64:bytes(0xFF, 0xFF, 0xFF, 0xFF, 0x0F) value:(int32_t)0x80000000];
84+
85+
[self assertReadZigZag64:bytes(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01) value:0x7FFFFFFFFFFFFFFFL];
86+
[self assertReadZigZag64:bytes(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01) value:0x8000000000000000L];
9087
}
9188

9289
- (void)assertReadVarint:(NSData*)data value:(int64_t)value {
93-
{
90+
if (value <= INT32_MAX && value >= INT32_MIN) {
91+
{
92+
GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
93+
XCTAssertEqual((int32_t)value, [input readInt32]);
94+
}
95+
{
96+
GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
97+
XCTAssertEqual((int32_t)value, [input readEnum]);
98+
}
99+
}
100+
if (value <= UINT32_MAX && value >= 0) {
94101
GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
95-
XCTAssertEqual((int32_t)value, [input readInt32]);
102+
XCTAssertEqual((uint32_t)value, [input readUInt32]);
96103
}
97104
{
98105
GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
99106
XCTAssertEqual(value, [input readInt64]);
100107
}
108+
if (value >= 0) {
109+
GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
110+
XCTAssertEqual((uint64_t)value, [input readUInt64]);
111+
}
101112
}
102113

103114
- (void)assertReadLittleEndian32:(NSData*)data value:(int32_t)value {
104-
GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
105-
XCTAssertEqual(value, [input readSFixed32]);
115+
{
116+
GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
117+
XCTAssertEqual(value, [input readSFixed32]);
118+
}
119+
{
120+
GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
121+
XCTAssertEqual(GPBConvertInt32ToFloat(value), [input readFloat]);
122+
}
123+
{
124+
GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
125+
XCTAssertEqual((uint32_t)value, [input readFixed32]);
126+
}
127+
{
128+
GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
129+
XCTAssertEqual(value, [input readSFixed32]);
130+
}
106131
}
107132

108133
- (void)assertReadLittleEndian64:(NSData*)data value:(int64_t)value {
134+
{
135+
GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
136+
XCTAssertEqual(value, [input readSFixed64]);
137+
}
138+
{
139+
GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
140+
XCTAssertEqual(GPBConvertInt64ToDouble(value), [input readDouble]);
141+
}
142+
{
143+
GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
144+
XCTAssertEqual((uint64_t)value, [input readFixed64]);
145+
}
146+
{
147+
GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
148+
XCTAssertEqual(value, [input readSFixed64]);
149+
}
150+
}
151+
152+
- (void)assertReadZigZag32:(NSData*)data value:(int64_t)value {
153+
GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
154+
XCTAssertEqual((int32_t)value, [input readSInt32]);
155+
}
156+
157+
- (void)assertReadZigZag64:(NSData*)data value:(int64_t)value {
109158
GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
110-
XCTAssertEqual(value, [input readSFixed64]);
159+
XCTAssertEqual(value, [input readSInt64]);
111160
}
112161

113162
- (void)assertReadVarintFailure:(NSData*)data {
@@ -128,12 +177,28 @@ - (void)testBytes {
128177
XCTAssertEqual(((uint8_t*)data.bytes)[1], (uint8_t)0x74);
129178
}
130179

180+
- (void)testReadBool {
181+
{
182+
GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:bytes(0x00)];
183+
XCTAssertEqual(NO, [input readBool]);
184+
}
185+
{
186+
GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:bytes(0x01)];
187+
XCTAssertEqual(YES, [input readBool]);
188+
}
189+
}
190+
131191
- (void)testReadVarint {
132192
[self assertReadVarint:bytes(0x00) value:0];
133193
[self assertReadVarint:bytes(0x01) value:1];
134194
[self assertReadVarint:bytes(0x7f) value:127];
135195
// 14882
136196
[self assertReadVarint:bytes(0xa2, 0x74) value:(0x22 << 0) | (0x74 << 7)];
197+
// 1904930
198+
[self assertReadVarint:bytes(0xa2, 0xa2, 0x74) value:(0x22 << 0) | (0x22 << 7) | (0x74 << 14)];
199+
// 243831074
200+
[self assertReadVarint:bytes(0xa2, 0xa2, 0xa2, 0x74)
201+
value:(0x22 << 0) | (0x22 << 7) | (0x22 << 14) | (0x74 << 21)];
137202
// 2961488830
138203
[self assertReadVarint:bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b)
139204
value:(0x3e << 0) | (0x77 << 7) | (0x12 << 14) |
@@ -163,6 +228,45 @@ - (void)testReadVarint {
163228
[self assertReadVarintFailure:bytes(0x80)];
164229
}
165230

231+
- (void)testReadVarint32FromVarint64 {
232+
{
233+
// Turn on lower 31 bits of the upper half on a 64 bit varint.
234+
NSData* data = bytes(0x80, 0x80, 0x80, 0x80, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E);
235+
236+
int32_t value32 = 0x0;
237+
GPBCodedInputStream* input32 = [GPBCodedInputStream streamWithData:data];
238+
XCTAssertEqual(value32, [input32 readInt32]);
239+
240+
int64_t value64 = INT64_MAX & 0xFFFFFFFF00000000;
241+
GPBCodedInputStream* input64 = [GPBCodedInputStream streamWithData:data];
242+
XCTAssertEqual(value64, [input64 readInt64]);
243+
}
244+
{
245+
// Turn on lower 31 bits and lower 31 bits on upper half on a 64 bit varint.
246+
NSData* data = bytes(0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E);
247+
248+
int32_t value32 = INT32_MAX;
249+
GPBCodedInputStream* input32 = [GPBCodedInputStream streamWithData:data];
250+
XCTAssertEqual(value32, [input32 readInt32]);
251+
252+
int64_t value64 = INT64_MAX & 0xFFFFFFFF7FFFFFFF;
253+
GPBCodedInputStream* input64 = [GPBCodedInputStream streamWithData:data];
254+
XCTAssertEqual(value64, [input64 readInt64]);
255+
}
256+
{
257+
// Turn on bits 32 and 64 bit on a 64 bit varint.
258+
NSData* data = bytes(0x80, 0x80, 0x80, 0x80, 0x88, 0x80, 0x80, 0x80, 0x80, 0x01);
259+
260+
int32_t value32 = INT32_MIN;
261+
GPBCodedInputStream* input32 = [GPBCodedInputStream streamWithData:data];
262+
XCTAssertEqual(value32, [input32 readInt32]);
263+
264+
int64_t value64 = INT64_MIN | (0x01L << 31);
265+
GPBCodedInputStream* input64 = [GPBCodedInputStream streamWithData:data];
266+
XCTAssertEqual(value64, [input64 readInt64]);
267+
}
268+
}
269+
166270
- (void)testReadLittleEndian {
167271
[self assertReadLittleEndian32:bytes(0x78, 0x56, 0x34, 0x12)
168272
value:0x12345678];
@@ -265,6 +369,27 @@ - (void)testReadMaliciouslyLargeBlob {
265369
XCTAssertThrows([input readBytes]);
266370
}
267371

372+
- (void)testReadEmptyString {
373+
NSData *data = bytes(0x00);
374+
GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
375+
XCTAssertEqualObjects(@"", [input readString]);
376+
}
377+
378+
- (void)testInvalidGroupEndTagThrows {
379+
NSData *data = bytes(0x0B, 0x1A, 0x02, 0x4B, 0x50, 0x14);
380+
GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
381+
XCTAssertThrowsSpecificNamed([input skipMessage],
382+
NSException,
383+
GPBCodedInputStreamException,
384+
@"should throw a GPBCodedInputStreamException exception ");
385+
}
386+
387+
- (void)testBytesWithNegativeSize {
388+
NSData *data = bytes(0xFF, 0xFF, 0xFF, 0xFF, 0x0F);
389+
GPBCodedInputStream *input = [GPBCodedInputStream streamWithData:data];
390+
XCTAssertNil([input readBytes]);
391+
}
392+
268393
// Verifies fix for b/10315336.
269394
// Note: Now that there isn't a custom string class under the hood, this test
270395
// isn't as critical, but it does cover bad input and if a custom class is added

objectivec/Tests/GPBMessageTests+Serialization.m

+10-4
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,6 @@
4242
#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
4343
#import "google/protobuf/UnittestRuntimeProto3.pbobjc.h"
4444

45-
static NSData *DataFromCStr(const char *str) {
46-
return [NSData dataWithBytes:str length:strlen(str)];
47-
}
48-
4945
@interface MessageSerializationTests : GPBTestCase
5046
@end
5147

@@ -980,6 +976,16 @@ - (void)testErrorRecursionDepthReached {
980976
XCTAssertEqual(error.code, GPBCodedInputStreamErrorRecursionDepthExceeded);
981977
}
982978

979+
- (void)testParseDelimitedDataWithNegativeSize {
980+
NSData *data = DataFromCStr("\xFF\xFF\xFF\xFF\x0F");
981+
GPBCodedInputStream *input = [GPBCodedInputStream streamWithData:data];
982+
NSError *error;
983+
[GPBMessage parseDelimitedFromCodedInputStream:input
984+
extensionRegistry:nil
985+
error:&error];
986+
XCTAssertNil(error);
987+
}
988+
983989
#ifdef DEBUG
984990
- (void)testErrorMissingRequiredField {
985991
NSData *data = DataFromCStr("");

objectivec/Tests/GPBTestUtilities.h

+3
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939
@class TestUnpackedExtensions;
4040
@class GPBExtensionRegistry;
4141

42+
static inline NSData *DataFromCStr(const char *str) {
43+
return [NSData dataWithBytes:str length:strlen(str)];
44+
}
4245

4346
// Helper for uses of C arrays in tests cases.
4447
#ifndef GPBARRAYSIZE

objectivec/Tests/GPBUnknownFieldSetTest.m

-4
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,6 @@
3434
#import "GPBUnknownFieldSet_PackagePrivate.h"
3535
#import "google/protobuf/Unittest.pbobjc.h"
3636

37-
static NSData *DataFromCStr(const char *str) {
38-
return [NSData dataWithBytes:str length:strlen(str)];
39-
}
40-
4137
@interface GPBUnknownFieldSet (GPBUnknownFieldSetTest)
4238
- (void)getTags:(int32_t*)tags;
4339
@end

0 commit comments

Comments
 (0)