[ObjC] Ensure -[GPBCodedOutputStream dealloc] cannot throw exceptions

If `-[GPBCodedOutputStream flush]` failed (e.g., because the filesystem
was out of space), then `-[GPBCodedOutputStream dealloc]` would throw
an exception.

`-dealloc` cannot fail, so the only thing to do in this case is to silently
swallow the exception.

PiperOrigin-RevId: 579916429
pull/14659/head
Protobuf Team Bot 2023-11-06 12:02:18 -08:00 committed by Copybara-Service
parent 349122f777
commit a2815fa13f
2 changed files with 31 additions and 1 deletions

View File

@ -160,7 +160,14 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, int64_t value
}
- (void)dealloc {
[self flush];
@try {
[self flush];
} @catch (NSException *exception) {
// -dealloc methods cannot fail, so swallow any exceptions from flushing.
#if defined(DEBUG) && DEBUG
NSLog(@"GPBCodedOutputStream: Exception while flushing in dealloc: %@", exception);
#endif
}
[state_.output close];
[state_.output release];
[buffer_ release];

View File

@ -393,4 +393,27 @@
NSException, GPBCodedOutputStreamException_WriteFailed);
}
- (void)testThatDeallocNeverThrows {
uint8_t buffer[1] = {0};
// Output stream which can write precisely 1 byte of data before it's full.
NSOutputStream* output = [[[NSOutputStream alloc] initToBuffer:buffer
capacity:sizeof(buffer)] autorelease];
NSMutableData* outputBuffer = [NSMutableData data];
GPBCodedOutputStream* codedOutput =
[[GPBCodedOutputStream alloc] initWithOutputStream:output data:outputBuffer];
[codedOutput writeRawByte:0x23];
[codedOutput flush];
// Put one more byte in the output buffer.
[codedOutput writeRawByte:0x42];
XCTAssertThrowsSpecificNamed([codedOutput flush], NSException,
GPBCodedOutputStreamException_WriteFailed);
// -dealloc must not throw when it flushes, even if a previous flush failed.
XCTAssertNoThrow([codedOutput release]);
}
@end