Skip to content

Commit

Permalink
[ObjC] Support errors when merging unknown fields to a message.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 658782615
  • Loading branch information
thomasvl committed Aug 2, 2024
1 parent c5c9c89 commit c46340e
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 27 deletions.
18 changes: 15 additions & 3 deletions objectivec/GPBMessage.h
Original file line number Diff line number Diff line change
Expand Up @@ -507,13 +507,25 @@ CF_EXTERN_C_END
* Merges in the data from an `GPBUnknownFields`, meaning the data from the unknown fields gets
* re-parsed so any known fields will be propertly set.
*
* If the intent is to replace the message's unknown fields, call `-clearUnknownFields` first.
* If the intent is to *replace* the message's unknown fields, call `-clearUnknownFields` first.
*
* Since the data from the GPBUnknownFields will always be well formed, this call will almost never
* fail. What could cause it to fail is if the GPBUnknownFields contains a field values it is
* and error for the message's schema - i.e.: if it contains a length delimited field where the
* field number for the message is defined to be a _string_ field, however the length delimited
* data provide is not a valid UTF8 string.
*
* @param unknownFields The unknown fields to merge the data from.
* @param extensionRegistry The extension registry to use to look up extensions, can be `nil`.
* @param errorPtr An optional error pointer to fill in with a failure
* reason if the data can not be parsed. Will only be
* filled in if the data failed to be parsed.
*
* @return Boolean indicating success. errorPtr will only be fill in on failure.
**/
- (void)mergeUnknownFields:(GPBUnknownFields *)unknownFields
extensionRegistry:(nullable id<GPBExtensionRegistry>)extensionRegistry;
- (BOOL)mergeUnknownFields:(GPBUnknownFields *)unknownFields
extensionRegistry:(nullable id<GPBExtensionRegistry>)extensionRegistry
error:(NSError **)errorPtr;

@end

Expand Down
14 changes: 6 additions & 8 deletions objectivec/GPBMessage.m
Original file line number Diff line number Diff line change
Expand Up @@ -1484,14 +1484,12 @@ - (void)clearUnknownFields {
self.unknownFields = nil;
}

- (void)mergeUnknownFields:(GPBUnknownFields *)unknownFields
extensionRegistry:(nullable id<GPBExtensionRegistry>)extensionRegistry {
NSData *data = [unknownFields serializeAsData];
if (![self mergeFromData:data extensionRegistry:extensionRegistry error:NULL]) {
#if defined(DEBUG) && DEBUG
NSAssert(0, @"Internal error within the library, failed to parse data from unknown fields.");
#endif
};
- (BOOL)mergeUnknownFields:(GPBUnknownFields *)unknownFields
extensionRegistry:(nullable id<GPBExtensionRegistry>)extensionRegistry
error:(NSError **)errorPtr {
return [self mergeFromData:[unknownFields serializeAsData]
extensionRegistry:extensionRegistry
error:errorPtr];
}

- (BOOL)isInitialized {
Expand Down
2 changes: 1 addition & 1 deletion objectivec/GPBUnknownFields.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ __attribute__((objc_subclassing_restricted))
*
* Note: The instance is not linked to the message, any change will not be
* reflected on the message the changes have to be pushed back to the message
* with `-[GPBMessage mergeUnknownFields:error:]`.
* with `-[GPBMessage mergeUnknownFields:extensionRegistry:error:]`.
**/
- (instancetype)initFromMessage:(nonnull GPBMessage *)message;

Expand Down
16 changes: 10 additions & 6 deletions objectivec/Tests/GPBMessageTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ - (void)testDescription {
GPBUnknownFields *ufs = [[[GPBUnknownFields alloc] init] autorelease];
[ufs addFieldNumber:1234 fixed32:1234];
[ufs addFieldNumber:2345 varint:54321];
[message mergeUnknownFields:ufs extensionRegistry:nil];
XCTAssertTrue([message mergeUnknownFields:ufs extensionRegistry:nil error:NULL]);

NSString *description = [message description];
XCTAssertGreaterThan([description length], 0U);
Expand Down Expand Up @@ -997,13 +997,17 @@ - (void)testAutocreatedUnknownFields {
XCTAssertFalse([message hasOptionalNestedMessage]);
GPBUnknownFields *ufs = [[[GPBUnknownFields alloc] init] autorelease];
[ufs addFieldNumber:1 varint:1];
[message.optionalNestedMessage mergeUnknownFields:ufs extensionRegistry:nil];
XCTAssertTrue([message.optionalNestedMessage mergeUnknownFields:ufs
extensionRegistry:nil
error:NULL]);
XCTAssertTrue([message hasOptionalNestedMessage]);

message.optionalNestedMessage = nil;
XCTAssertFalse([message hasOptionalNestedMessage]);
[ufs clear]; // Also make sure merging zero length forces it to become visible.
[message.optionalNestedMessage mergeUnknownFields:ufs extensionRegistry:nil];
XCTAssertTrue([message.optionalNestedMessage mergeUnknownFields:ufs
extensionRegistry:nil
error:NULL]);
XCTAssertTrue([message hasOptionalNestedMessage]);
}

Expand Down Expand Up @@ -1887,7 +1891,7 @@ - (void)testGenerateAndParseUnknownMessage {
[message setUnknownFields:unknowns];
GPBUnknownFields *ufs = [[[GPBUnknownFields alloc] init] autorelease];
[ufs addFieldNumber:1234 varint:5678];
[message mergeUnknownFields:ufs extensionRegistry:nil];
XCTAssertTrue([message mergeUnknownFields:ufs extensionRegistry:nil error:NULL]);
NSData *data = [message data];
GPBMessage *message2 = [GPBMessage parseFromData:data extensionRegistry:nil error:NULL];
XCTAssertEqualObjects(message, message2);
Expand All @@ -1900,7 +1904,7 @@ - (void)testDelimitedWriteAndParseMultipleMessages {
[message1 setUnknownFields:unknowns1];
GPBUnknownFields *ufs1 = [[[GPBUnknownFields alloc] init] autorelease];
[ufs1 addFieldNumber:1234 varint:5678];
[message1 mergeUnknownFields:ufs1 extensionRegistry:nil];
XCTAssertTrue([message1 mergeUnknownFields:ufs1 extensionRegistry:nil error:NULL]);

GPBUnknownFieldSet *unknowns2 = [[[GPBUnknownFieldSet alloc] init] autorelease];
[unknowns2 mergeVarintField:789 value:987];
Expand All @@ -1910,7 +1914,7 @@ - (void)testDelimitedWriteAndParseMultipleMessages {
GPBUnknownFields *ufs2 = [[[GPBUnknownFields alloc] init] autorelease];
[ufs2 addFieldNumber:2345 fixed32:6789];
[ufs2 addFieldNumber:3456 fixed32:7890];
[message2 mergeUnknownFields:ufs2 extensionRegistry:nil];
XCTAssertTrue([message2 mergeUnknownFields:ufs2 extensionRegistry:nil error:NULL]);

NSMutableData *delimitedData = [NSMutableData data];
[delimitedData appendData:[message1 delimitedData]];
Expand Down
39 changes: 33 additions & 6 deletions objectivec/Tests/GPBUnknownFieldsTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -811,7 +811,7 @@ - (void)testMessageMergeUnknowns {
[group addFieldNumber:123456 varint:5432];

TestAllTypes* msg = [TestAllTypes message];
[msg mergeUnknownFields:ufs extensionRegistry:nil];
XCTAssertTrue([msg mergeUnknownFields:ufs extensionRegistry:nil error:NULL]);
XCTAssertEqual(msg.optionalInt64, 100);
XCTAssertEqual(msg.optionalFixed32, 200);
XCTAssertEqual(msg.optionalFixed64, 300);
Expand All @@ -829,7 +829,7 @@ - (void)testMessageMergeUnknowns {
XCTAssertEqual(varint, 5432);

TestEmptyMessage* emptyMessage = [TestEmptyMessage message];
[emptyMessage mergeUnknownFields:ufs extensionRegistry:nil];
XCTAssertTrue([emptyMessage mergeUnknownFields:ufs extensionRegistry:nil error:NULL]);
GPBUnknownFields* ufs3 = [[[GPBUnknownFields alloc] initFromMessage:emptyMessage] autorelease];
XCTAssertEqualObjects(ufs3, ufs); // Round trip through an empty message got us same fields back.
XCTAssertTrue(ufs3 != ufs); // But they are different objects.
Expand All @@ -843,7 +843,7 @@ - (void)testRoundTripLotsOfFields {
TestEmptyMessage* emptyMessage = [TestEmptyMessage parseFromData:allFieldsData error:NULL];
GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] initFromMessage:emptyMessage] autorelease];
TestAllTypes* allFields2 = [TestAllTypes message];
[allFields2 mergeUnknownFields:ufs extensionRegistry:nil];
XCTAssertTrue([allFields2 mergeUnknownFields:ufs extensionRegistry:nil error:NULL]);
XCTAssertEqualObjects(allFields2, allFields);

// Confirm that the they still all end up in unknowns when parsed into a message with extensions
Expand Down Expand Up @@ -891,7 +891,7 @@ - (void)testMismatchedFieldTypes {
// unknown fields again.
{
TestAllTypes* msg = [TestAllTypes message];
[msg mergeUnknownFields:ufsWrongTypes extensionRegistry:nil];
XCTAssertTrue([msg mergeUnknownFields:ufsWrongTypes extensionRegistry:nil error:NULL]);
GPBUnknownFields* ufs2 = [[[GPBUnknownFields alloc] initFromMessage:msg] autorelease];
XCTAssertFalse(ufs2.empty);
XCTAssertEqualObjects(ufs2, ufsWrongTypes); // All back as unknown fields.
Expand All @@ -901,19 +901,46 @@ - (void)testMismatchedFieldTypes {
// into unknown fields.
{
TestAllExtensions* msg = [TestAllExtensions message];
[msg mergeUnknownFields:ufsWrongTypes extensionRegistry:[UnittestRoot extensionRegistry]];
XCTAssertTrue([msg mergeUnknownFields:ufsWrongTypes
extensionRegistry:[UnittestRoot extensionRegistry]
error:NULL]);
GPBUnknownFields* ufs2 = [[[GPBUnknownFields alloc] initFromMessage:msg] autorelease];
XCTAssertFalse(ufs2.empty);
XCTAssertEqualObjects(ufs2, ufsWrongTypes); // All back as unknown fields.
}
}

- (void)testMergeFailures {
// Valid data, pushes to the string just fine.
{
GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease];
[ufs addFieldNumber:TestAllTypes_FieldNumber_OptionalString
lengthDelimited:DataFromCStr("abc")];
TestAllTypes* msg = [TestAllTypes message];
NSError* error = nil;
XCTAssertTrue([msg mergeUnknownFields:ufs extensionRegistry:nil error:&error]);
XCTAssertNil(error);
XCTAssertEqualObjects(msg.optionalString, @"abc");
}

// Invalid UTF-8 causes a failure when pushed to the message.
{
GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease];
[ufs addFieldNumber:TestAllTypes_FieldNumber_OptionalString
lengthDelimited:DataFromBytes(0xC2, 0xF2, 0x0, 0x0, 0x0)];
TestAllTypes* msg = [TestAllTypes message];
NSError* error = nil;
XCTAssertFalse([msg mergeUnknownFields:ufs extensionRegistry:nil error:&error]);
XCTAssertNotNil(error);
}
}

- (void)testLargeVarint {
GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] init] autorelease];
[ufs addFieldNumber:1 varint:0x7FFFFFFFFFFFFFFFL];

TestEmptyMessage* emptyMessage = [TestEmptyMessage message];
[emptyMessage mergeUnknownFields:ufs extensionRegistry:nil];
XCTAssertTrue([emptyMessage mergeUnknownFields:ufs extensionRegistry:nil error:NULL]);

GPBUnknownFields* ufsParsed =
[[[GPBUnknownFields alloc] initFromMessage:emptyMessage] autorelease];
Expand Down
5 changes: 3 additions & 2 deletions objectivec/Tests/GPBUtilitiesTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ - (void)testTextFormatUnknownFields {
[group addFieldNumber:3 fixed32:0x3];
[group addFieldNumber:2 fixed64:0x2];
TestEmptyMessage *message = [TestEmptyMessage message];
[message mergeUnknownFields:ufs extensionRegistry:nil];
XCTAssertTrue([message mergeUnknownFields:ufs extensionRegistry:nil error:NULL]);

NSString *expected = @"# --- Unknown fields ---\n"
@"10: 1\n"
Expand Down Expand Up @@ -255,7 +255,8 @@ - (void)testSetRepeatedFields {
static void AddUnknownFields(GPBMessage *message, int num) {
GPBUnknownFields *ufs = [[GPBUnknownFields alloc] init];
[ufs addFieldNumber:num varint:num];
[message mergeUnknownFields:ufs extensionRegistry:nil];
// Can't fail since it is a varint.
[message mergeUnknownFields:ufs extensionRegistry:nil error:NULL];
[ufs release];
}

Expand Down
4 changes: 3 additions & 1 deletion objectivec/Tests/GPBWireFormatTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,9 @@ - (void)testSerializeMessageSet {
GPBUnknownFields* group = [ufs addGroupWithFieldNumber:GPBWireFormatMessageSetItem];
[group addFieldNumber:GPBWireFormatMessageSetTypeId varint:kUnknownTypeId2];
[group addFieldNumber:GPBWireFormatMessageSetMessage lengthDelimited:DataFromCStr("baz")];
[message_set mergeUnknownFields:ufs extensionRegistry:[MSetUnittestMsetRoot extensionRegistry]];
XCTAssertTrue([message_set mergeUnknownFields:ufs
extensionRegistry:[MSetUnittestMsetRoot extensionRegistry]
error:NULL]);

NSData* data = [message_set data];

Expand Down

0 comments on commit c46340e

Please sign in to comment.