Index: third_party/protobuf/objectivec/GPBCodedInputStream.m |
diff --git a/third_party/protobuf/objectivec/GPBCodedInputStream.m b/third_party/protobuf/objectivec/GPBCodedInputStream.m |
index 319ec15ba7c81dbb7627b50339ea603619db853e..e8c8989cc79c2bc18a142bea012794f7975e00e4 100644 |
--- a/third_party/protobuf/objectivec/GPBCodedInputStream.m |
+++ b/third_party/protobuf/objectivec/GPBCodedInputStream.m |
@@ -36,17 +36,42 @@ |
#import "GPBUtilities_PackagePrivate.h" |
#import "GPBWireFormat.h" |
+NSString *const GPBCodedInputStreamException = |
+ GPBNSStringifySymbol(GPBCodedInputStreamException); |
+ |
+NSString *const GPBCodedInputStreamUnderlyingErrorKey = |
+ GPBNSStringifySymbol(GPBCodedInputStreamUnderlyingErrorKey); |
+ |
+NSString *const GPBCodedInputStreamErrorDomain = |
+ GPBNSStringifySymbol(GPBCodedInputStreamErrorDomain); |
+ |
static const NSUInteger kDefaultRecursionLimit = 64; |
+static void RaiseException(NSInteger code, NSString *reason) { |
+ NSDictionary *errorInfo = nil; |
+ if ([reason length]) { |
+ errorInfo = @{ GPBErrorReasonKey: reason }; |
+ } |
+ NSError *error = [NSError errorWithDomain:GPBCodedInputStreamErrorDomain |
+ code:code |
+ userInfo:errorInfo]; |
+ |
+ NSDictionary *exceptionInfo = |
+ @{ GPBCodedInputStreamUnderlyingErrorKey: error }; |
+ [[[NSException alloc] initWithName:GPBCodedInputStreamException |
+ reason:reason |
+ userInfo:exceptionInfo] raise]; |
+} |
+ |
static void CheckSize(GPBCodedInputStreamState *state, size_t size) { |
size_t newSize = state->bufferPos + size; |
if (newSize > state->bufferSize) { |
- [NSException raise:NSParseErrorException format:@""]; |
+ RaiseException(GPBCodedInputStreamErrorInvalidSize, nil); |
} |
if (newSize > state->currentLimit) { |
// Fast forward to end of currentLimit; |
state->bufferPos = state->currentLimit; |
- [NSException raise:NSParseErrorException format:@""]; |
+ RaiseException(GPBCodedInputStreamErrorSubsectionLimitReached, nil); |
} |
} |
@@ -95,8 +120,8 @@ static int32_t ReadRawVarint32(GPBCodedInputStreamState *state) { |
return result; |
} |
} |
- [NSException raise:NSParseErrorException |
- format:@"Unable to read varint32"]; |
+ RaiseException(GPBCodedInputStreamErrorInvalidVarInt, |
+ @"Invalid VarInt32"); |
} |
} |
} |
@@ -115,7 +140,7 @@ static int64_t ReadRawVarint64(GPBCodedInputStreamState *state) { |
} |
shift += 7; |
} |
- [NSException raise:NSParseErrorException format:@"Unable to read varint64"]; |
+ RaiseException(GPBCodedInputStreamErrorInvalidVarInt, @"Invalid VarInt64"); |
return 0; |
} |
@@ -202,8 +227,13 @@ int32_t GPBCodedInputStreamReadTag(GPBCodedInputStreamState *state) { |
state->lastTag = ReadRawVarint32(state); |
if (state->lastTag == 0) { |
// If we actually read zero, that's not a valid tag. |
- [NSException raise:NSParseErrorException |
- format:@"Invalid last tag %d", state->lastTag]; |
+ RaiseException(GPBCodedInputStreamErrorInvalidTag, |
+ @"A zero tag on the wire is invalid."); |
+ } |
+ // Tags have to include a valid wireformat, check that also. |
+ if (!GPBWireFormatIsValidTag(state->lastTag)) { |
+ RaiseException(GPBCodedInputStreamErrorInvalidTag, |
+ @"Invalid wireformat in tag."); |
} |
return state->lastTag; |
} |
@@ -226,8 +256,7 @@ NSString *GPBCodedInputStreamReadRetainedString( |
NSLog(@"UTF-8 failure, is some field type 'string' when it should be " |
@"'bytes'?"); |
#endif |
- [NSException raise:NSParseErrorException |
- format:@"Invalid UTF-8 for a 'string'"]; |
+ RaiseException(GPBCodedInputStreamErrorInvalidUTF8, nil); |
} |
} |
return result; |
@@ -262,8 +291,7 @@ size_t GPBCodedInputStreamPushLimit(GPBCodedInputStreamState *state, |
byteLimit += state->bufferPos; |
size_t oldLimit = state->currentLimit; |
if (byteLimit > oldLimit) { |
- [NSException raise:NSInvalidArgumentException |
- format:@"byteLimit > oldLimit: %tu > %tu", byteLimit, oldLimit]; |
+ RaiseException(GPBCodedInputStreamErrorInvalidSubsectionLimit, nil); |
} |
state->currentLimit = byteLimit; |
return oldLimit; |
@@ -286,8 +314,7 @@ BOOL GPBCodedInputStreamIsAtEnd(GPBCodedInputStreamState *state) { |
void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state, |
int32_t value) { |
if (state->lastTag != value) { |
- [NSException raise:NSParseErrorException |
- format:@"Last tag: %d should be %d", state->lastTag, value]; |
+ RaiseException(GPBCodedInputStreamErrorInvalidTag, @"Unexpected tag read"); |
} |
} |
@@ -316,6 +343,12 @@ void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state, |
[super dealloc]; |
} |
+// Direct access is use for speed, to avoid even internally declaring things |
+// read/write, etc. The warning is enabled in the project to ensure code calling |
+// protos can turn on -Wdirect-ivar-access without issues. |
+#pragma clang diagnostic push |
+#pragma clang diagnostic ignored "-Wdirect-ivar-access" |
+ |
- (int32_t)readTag { |
return GPBCodedInputStreamReadTag(&state_); |
} |
@@ -325,6 +358,7 @@ void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state, |
} |
- (BOOL)skipField:(int32_t)tag { |
+ NSAssert(GPBWireFormatIsValidTag(tag), @"Invalid tag"); |
switch (GPBWireFormatGetTagWireType(tag)) { |
case GPBWireFormatVarint: |
GPBCodedInputStreamReadInt32(&state_); |
@@ -347,8 +381,6 @@ void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state, |
SkipRawData(&state_, sizeof(int32_t)); |
return YES; |
} |
- [NSException raise:NSParseErrorException format:@"Invalid tag %d", tag]; |
- return NO; |
} |
- (void)skipMessage { |
@@ -368,6 +400,14 @@ void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state, |
return state_.bufferPos; |
} |
+- (size_t)pushLimit:(size_t)byteLimit { |
+ return GPBCodedInputStreamPushLimit(&state_, byteLimit); |
+} |
+ |
+- (void)popLimit:(size_t)oldLimit { |
+ GPBCodedInputStreamPopLimit(&state_, oldLimit); |
+} |
+ |
- (double)readDouble { |
return GPBCodedInputStreamReadDouble(&state_); |
} |
@@ -408,9 +448,7 @@ void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state, |
message:(GPBMessage *)message |
extensionRegistry:(GPBExtensionRegistry *)extensionRegistry { |
if (state_.recursionDepth >= kDefaultRecursionLimit) { |
- [NSException raise:NSParseErrorException |
- format:@"recursionDepth(%tu) >= %tu", state_.recursionDepth, |
- kDefaultRecursionLimit]; |
+ RaiseException(GPBCodedInputStreamErrorRecursionDepthExceeded, nil); |
} |
++state_.recursionDepth; |
[message mergeFromCodedInputStream:self extensionRegistry:extensionRegistry]; |
@@ -422,9 +460,7 @@ void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state, |
- (void)readUnknownGroup:(int32_t)fieldNumber |
message:(GPBUnknownFieldSet *)message { |
if (state_.recursionDepth >= kDefaultRecursionLimit) { |
- [NSException raise:NSParseErrorException |
- format:@"recursionDepth(%tu) >= %tu", state_.recursionDepth, |
- kDefaultRecursionLimit]; |
+ RaiseException(GPBCodedInputStreamErrorRecursionDepthExceeded, nil); |
} |
++state_.recursionDepth; |
[message mergeFromCodedInputStream:self]; |
@@ -437,9 +473,7 @@ void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state, |
extensionRegistry:(GPBExtensionRegistry *)extensionRegistry { |
int32_t length = ReadRawVarint32(&state_); |
if (state_.recursionDepth >= kDefaultRecursionLimit) { |
- [NSException raise:NSParseErrorException |
- format:@"recursionDepth(%tu) >= %tu", state_.recursionDepth, |
- kDefaultRecursionLimit]; |
+ RaiseException(GPBCodedInputStreamErrorRecursionDepthExceeded, nil); |
} |
size_t oldLimit = GPBCodedInputStreamPushLimit(&state_, length); |
++state_.recursionDepth; |
@@ -455,9 +489,7 @@ void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state, |
parentMessage:(GPBMessage *)parentMessage { |
int32_t length = ReadRawVarint32(&state_); |
if (state_.recursionDepth >= kDefaultRecursionLimit) { |
- [NSException raise:NSParseErrorException |
- format:@"recursionDepth(%tu) >= %tu", state_.recursionDepth, |
- kDefaultRecursionLimit]; |
+ RaiseException(GPBCodedInputStreamErrorRecursionDepthExceeded, nil); |
} |
size_t oldLimit = GPBCodedInputStreamPushLimit(&state_, length); |
++state_.recursionDepth; |
@@ -496,4 +528,6 @@ void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state, |
return GPBCodedInputStreamReadSInt64(&state_); |
} |
+#pragma clang diagnostic pop |
+ |
@end |