Index: third_party/protobuf/objectivec/GPBCodedOutputStream.m |
diff --git a/third_party/protobuf/objectivec/GPBCodedOutputStream.m b/third_party/protobuf/objectivec/GPBCodedOutputStream.m |
index 7c3ab44715c40397eb3cdb4bc7efec9a55181d87..fd9ed66ca23b494622c65d64670c2657f1cc0d76 100644 |
--- a/third_party/protobuf/objectivec/GPBCodedOutputStream.m |
+++ b/third_party/protobuf/objectivec/GPBCodedOutputStream.m |
@@ -144,6 +144,22 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, |
GPBWriteRawByte(state, (int32_t)(value >> 56) & 0xFF); |
} |
+#if DEBUG && !defined(NS_BLOCK_ASSERTIONS) |
++ (void)load { |
+ // This test exists to verify that CFStrings with embedded NULLs will work |
+ // for us. If this Assert fails, all code below that depends on |
+ // CFStringGetCStringPtr will NOT work properly on strings that contain |
+ // embedded NULLs, and we do get that in some protobufs. |
+ // Note that this will not be compiled in release. |
+ // We didn't feel that just keeping it in a unit test was sufficient because |
+ // the Protobuf unit tests are only run when somebody is actually working |
+ // on protobufs. |
+ CFStringRef zeroTest = CFSTR("Test\0String"); |
+ const char *cString = CFStringGetCStringPtr(zeroTest, kCFStringEncodingUTF8); |
+ NSAssert(cString == NULL, @"Serious Error"); |
+} |
+#endif // DEBUG && !defined(NS_BLOCK_ASSERTIONS) |
+ |
- (void)dealloc { |
[self flush]; |
[state_.output close]; |
@@ -187,12 +203,6 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, |
return [[[self alloc] initWithData:data] autorelease]; |
} |
-// 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" |
- |
- (void)writeDoubleNoTag:(double)value { |
GPBWriteRawLittleEndian64(&state_, GPBConvertDoubleToInt64(value)); |
} |
@@ -266,15 +276,19 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, |
} |
- (void)writeStringNoTag:(const NSString *)value { |
- size_t length = [value lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; |
+ // If you are concerned about embedded NULLs see the test in |
+ // +load above. |
+ const char *quickString = |
+ CFStringGetCStringPtr((CFStringRef)value, kCFStringEncodingUTF8); |
+ size_t length = (quickString != NULL) |
+ ? strlen(quickString) |
+ : [value lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; |
GPBWriteRawVarint32(&state_, (int32_t)length); |
+ |
if (length == 0) { |
return; |
} |
- const char *quickString = |
- CFStringGetCStringPtr((CFStringRef)value, kCFStringEncodingUTF8); |
- |
// Fast path: Most strings are short, if the buffer already has space, |
// add to it directly. |
NSUInteger bufferBytesLeft = state_.size - state_.position; |
@@ -290,7 +304,7 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, |
maxLength:bufferBytesLeft |
usedLength:&usedBufferLength |
encoding:NSUTF8StringEncoding |
- options:(NSStringEncodingConversionOptions)0 |
+ options:0 |
range:NSMakeRange(0, [value length]) |
remainingRange:NULL]; |
} |
@@ -967,8 +981,6 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, |
GPBWriteRawLittleEndian64(&state_, value); |
} |
-#pragma clang diagnostic pop |
- |
@end |
size_t GPBComputeDoubleSizeNoTag(Float64 value) { |
@@ -1018,7 +1030,14 @@ size_t GPBComputeBoolSizeNoTag(BOOL value) { |
} |
size_t GPBComputeStringSizeNoTag(NSString *value) { |
- NSUInteger length = [value lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; |
+ // If you are concerned about embedded NULLs see the test in |
+ // +load above. |
+ const char *quickString = |
+ CFStringGetCStringPtr((CFStringRef)value, kCFStringEncodingUTF8); |
+ NSUInteger length = |
+ (quickString != NULL) |
+ ? strlen(quickString) |
+ : [value lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; |
return GPBComputeRawVarint32SizeForInteger(length) + length; |
} |