Skip to content

Commit

Permalink
Merge pull request protocolbuffers#1391 from thomasvl/string_tweaks
Browse files Browse the repository at this point in the history
ObjC String followups: one test case only addition, behavior change for invalid UTF-8
  • Loading branch information
thomasvl committed Apr 6, 2016
2 parents f98d2f5 + c9167f2 commit 28c5c25
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 9 deletions.
7 changes: 4 additions & 3 deletions objectivec/GPBCodedInputStream.m
Original file line number Diff line number Diff line change
Expand Up @@ -219,15 +219,16 @@ int32_t GPBCodedInputStreamReadTag(GPBCodedInputStreamState *state) {
result = [[NSString alloc] initWithBytes:&state->bytes[state->bufferPos]
length:size
encoding:NSUTF8StringEncoding];
state->bufferPos += size;
if (!result) {
result = @"";
#ifdef DEBUG
// https://developers.google.com/protocol-buffers/docs/proto#scalar
NSLog(@"UTF8 failure, is some field type 'string' when it should be "
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'"];
}
state->bufferPos += size;
}
return result;
}
Expand Down
49 changes: 43 additions & 6 deletions objectivec/Tests/GPBCodedInputStreamTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -283,16 +283,53 @@ - (void)testReadMalformedString {
[output writeRawData:[NSData dataWithBytes:bytes length:sizeof(bytes)]];
[output flush];

NSData* data =
NSData *data =
[rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
NSError *error = nil;
TestAllTypes* message = [TestAllTypes parseFromCodedInputStream:input
extensionRegistry:nil
error:NULL];
XCTAssertNotNil(message);
// Make sure we can read string properties twice without crashing.
XCTAssertEqual([message.defaultString length], (NSUInteger)0);
XCTAssertEqualObjects(@"", message.defaultString);
error:&error];
XCTAssertNotNil(error);
XCTAssertNil(message);
}

- (void)testBOMWithinStrings {
// We've seen servers that end up with BOMs within strings (not always at the
// start, and sometimes in multiple places), make sure they always parse
// correctly. (Again, this is inpart incase a custom string class is ever
// used again.)
const char* strs[] = {
"\xEF\xBB\xBF String with BOM",
"String with \xEF\xBB\xBF in middle",
"String with end bom \xEF\xBB\xBF",
"\xEF\xBB\xBF\xe2\x99\xa1", // BOM White Heart
"\xEF\xBB\xBF\xEF\xBB\xBF String with Two BOM",
};
for (size_t i = 0; i < GPBARRAYSIZE(strs); ++i) {
NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
GPBCodedOutputStream* output =
[GPBCodedOutputStream streamWithOutputStream:rawOutput];

int32_t tag = GPBWireFormatMakeTag(TestAllTypes_FieldNumber_DefaultString,
GPBWireFormatLengthDelimited);
[output writeRawVarint32:tag];
size_t length = strlen(strs[i]);
[output writeRawVarint32:(int32_t)length];
[output writeRawData:[NSData dataWithBytes:strs[i] length:length]];
[output flush];

NSData* data =
[rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
TestAllTypes* message = [TestAllTypes parseFromCodedInputStream:input
extensionRegistry:nil
error:NULL];
XCTAssertNotNil(message, @"Loop %zd", i);
// Ensure the string is there. NSString can consume the BOM in some
// cases, so don't actually check the string for exact equality.
XCTAssertTrue(message.defaultString.length > 0, @"Loop %zd", i);
}
}

@end

0 comments on commit 28c5c25

Please sign in to comment.