Details
Description
Since we made Fleece C API Calls noexcept(commit), when platform object is encoded using FLEncoder, exceptions thrown inside `fl_encodeToFLEncoder` methods are crashing.
Steps to repro
1. Save doc-1 with blob to db1
2. Save doc-2 with blob from doc-1, to db2
3. Saving a blob from different db throws an exception, and throw is happening inside a noexcept function(`FLEncoder_WriteNSObject`).
//// test which will cause the issue
|
NSError* error = nil;
|
CBLMutableDocument* doc = [self createDocument: @"doc1"];
|
NSData* content = [kDocumentTestBlob dataUsingEncoding: NSUTF8StringEncoding];
|
CBLBlob* blob = [[CBLBlob alloc] initWithContentType: @"text/plain" data: content];
|
[doc setValue: blob forKey: @"blob"];
|
[self.db saveDocument: doc error: &error];
|
|
CBLMutableDocument* mDoc = [[CBLMutableDocument alloc] init];
|
CBLDocument* savedDoc = [self.db documentWithID: @"doc1"];
|
[mDoc setBlob: [savedDoc blobForKey: @"blob"] forKey: @"blobKey"];
|
[otherdb saveDocument: mDoc error: &error];
|
Expected Result
1. `FLEncoder_WriteNSObject` should throw back the exception, so that it will behave like old implementation, Or
2. Return back an error argument, with information about exception/failure. Which will change the signature of the API to accommodate error argument.
Analysis
1. while saving the doc-2(with blob from different database), we encode properties to fleece data.
2. encode method will call the `FLEncoder_WriteNSObject` with the doc properties,
3. `FLEncoder_WriteNSObject` method will callback `fl_encodeToFLEncoder` for each property in the dictionary. `fl_encodeToFLEncoder` is implemented in the CBL side, and call to it will be done from Fleece.
4. When it calls `[CBLBlob fl_encodeToFLEncoder]`, it will throw exception saying, blob is from different database. But the call was made from Fleece method `FLEncoder_WriteNSObject`, which is a nonexcept function.
5. If we remove the `FLAPI` from `FLEncoder_WriteNSObject` method signature, this will not crash.
backtrace
2020-01-24 03:51:35.157066+0530 xctest[71896:1416663] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'A document contains a blob that was saved to a different database. The save operation cannot complete.'
|
*** First throw call stack:
|
(
|
0 CoreFoundation 0x00007fff382038ab __exceptionPreprocess + 250
|
1 libobjc.A.dylib 0x00007fff6e474805 objc_exception_throw + 48
|
2 CoreFoundation 0x00007fff38203701 +[NSException raise:format:] + 189
|
3 CouchbaseLite 0x00000001097db9b5 -[CBLBlob installInDatabase:error:] + 1349
|
4 CouchbaseLite 0x00000001097dce56 -[CBLBlob fl_encodeToFLEncoder:] + 1510
|
5 CouchbaseLite 0x000000010a5303cf __45-[NSDictionary(Fleece) fl_encodeToFLEncoder:]_block_invoke + 943
|
6 CoreFoundation 0x00007fff3814af27 __NSDICTIONARY_IS_CALLING_OUT_TO_A_BLOCK__ + 7
|
7 CoreFoundation 0x00007fff3818aa85 -[__NSDictionaryM enumerateKeysAndObjectsWithOptions:usingBlock:] + 230
|
8 CouchbaseLite 0x000000010a52ff78 -[NSDictionary(Fleece) fl_encodeToFLEncoder:] + 968
|
9 CouchbaseLite 0x000000010a52dbf3 FLEncoder_WriteNSObject + 659
|
10 CouchbaseLite 0x00000001097fb623 -[CBLNewDictionary fl_encodeToFLEncoder:] + 99
|
11 CouchbaseLite 0x00000001097f5018 -[CBLMutableDocument encode:] + 728
|
12 CouchbaseLite 0x00000001097a0012 -[CBLDatabase saveDocument:into:withBaseDocument:asDeletion:error:] + 1154
|
13 CouchbaseLite 0x000000010979ed65 -[CBLDatabase saveDocument:withBaseDocument:concurrencyControl:asDeletion:error:] + 2229
|
14 CouchbaseLite 0x000000010978c144 -[CBLDatabase saveDocument:concurrencyControl:error:] + 724
|
15 CouchbaseLite 0x000000010978bd60 -[CBLDatabase saveDocument:error:] + 480
|
16 CouchbaseLiteTests 0x0000000109108bd4 -[DocumentTest testSetBlob] + 4116
|
17 CoreFoundation 0x00007fff38168fec __invoking___ + 140
|
18 CoreFoundation 0x00007fff38168e83 -[NSInvocation invoke] + 305
|
19 XCTest 0x00000001010b0cc6 __24-[XCTestCase invokeTest]_block_invoke_2.214 + 65
|
20 XCTest 0x000000010113ecb7 -[XCTMemoryChecker _assertInvalidObjectsDeallocatedAfterScope:] + 51
|
21 XCTest 0x00000001010bbbae -[XCTestCase assertInvalidObjectsDeallocatedAfterScope:] + 116
|
22 XCTest 0x00000001010b0c56 __24-[XCTestCase invokeTest]_block_invoke.208 + 204
|
23 XCTest 0x0000000101124da0 -[XCTestCase(Failures) performFailableBlock:testCaseRun:shouldInterruptTest:] + 57
|
24 XCTest 0x0000000101124cbd -[XCTestCase(Failures) _performTurningExceptionsIntoFailuresInterruptAfterHandling:block:] + 96
|
25 XCTest 0x00000001010b0707 __24-[XCTestCase invokeTest]_block_invoke + 1120
|
26 XCTest 0x00000001010b0200 -[XCTestCase testContextPerformInScope:] + 184
|
27 XCTest 0x00000001010b029a -[XCTestCase invokeTest] + 137
|
28 XCTest 0x00000001010b2079 __26-[XCTestCase performTest:]_block_invoke_2 + 43
|
29 XCTest 0x0000000101124da0 -[XCTestCase(Failures) performFailableBlock:testCaseRun:shouldInterruptTest:] + 57
|
30 XCTest 0x0000000101124cbd -[XCTestCase(Failures) _performTurningExceptionsIntoFailuresInterruptAfterHandling:block:] + 96
|
31 XCTest 0x00000001010b1f90 __26-[XCTestCase performTest:]_block_invoke.342 + 88
|
32 XCTest 0x0000000101136380 +[XCTContext runInContextForTestCase:block:] + 219
|
33 XCTest 0x00000001010b1703 -[XCTestCase performTest:] + 668
|
34 XCTest 0x00000001011038e3 -[XCTest runTest] + 57
|
35 XCTest 0x00000001010abda3 __27-[XCTestSuite performTest:]_block_invoke + 365
|
36 XCTest 0x00000001010ab4cd -[XCTestSuite _performProtectedSectionForTest:testSection:] + 54
|
37 XCTest 0x00000001010ab7ca -[XCTestSuite performTest:] + 355
|
38 XCTest 0x00000001011038e3 -[XCTest runTest] + 57
|
39 XCTest 0x00000001010abda3 __27-[XCTestSuite performTest:]_block_invoke + 365
|
40 XCTest 0x00000001010ab4cd -[XCTestSuite _performProtectedSectionForTest:testSection:] + 54
|
41 XCTest 0x00000001010ab7ca -[XCTestSuite performTest:] + 355
|
42 XCTest 0x00000001011038e3 -[XCTest runTest] + 57
|
43 XCTest 0x00000001010abda3 __27-[XCTestSuite performTest:]_block_invoke + 365
|
44 XCTest 0x00000001010ab4cd -[XCTestSuite _performProtectedSectionForTest:testSection:] + 54
|
45 XCTest 0x00000001010ab7ca -[XCTestSuite performTest:] + 355
|
46 XCTest 0x00000001011038e3 -[XCTest runTest] + 57
|
47 XCTest 0x0000000101150886 __44-[XCTTestRunSession runTestsAndReturnError:]_block_invoke + 171
|
48 XCTest 0x0000000101150982 __44-[XCTTestRunSession runTestsAndReturnError:]_block_invoke.84 + 118
|
49 XCTest 0x00000001010d26a7 -[XCTestObservationCenter _observeTestExecutionForBlock:] + 594
|
50 XCTest 0x0000000101150644 -[XCTTestRunSession runTestsAndReturnError:] + 623
|
51 XCTest 0x000000010108ea40 -[XCTestDriver runTestsAndReturnError:] + 458
|
52 XCTest 0x00000001011326c8 _XCTestMain + 2473
|
53 xctest 0x00000001000020ca main + 245
|
54 libdyld.dylib 0x00007fff6f7e27fd start + 1
|
)
|
libc++abi.dylib: terminating with uncaught exception of type NSException
|
Attachments
Issue Links
- relates to
-
CBL-652 Fix unit tests with latest lite core
- Closed