Uploaded image for project: 'Couchbase Lite'
  1. Couchbase Lite
  2. CBL-649

exceptions thrown from `fl_encodeToFLEncoder` are crashing

    XMLWordPrintable

Details

    • Task
    • Resolution: Fixed
    • Major
    • 2.8.0
    • 2.8.0
    • iOS
    • Security Level: Public
    • None
    • CBL Sprint 12, CBL Sprint 13
    • 3

    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

          No reviews matched the request. Check your Options in the drop-down menu of this sections header.

          Activity

            People

              Jayahari.Vavachan Jay Vavachan
              Jayahari.Vavachan Jay Vavachan
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Gerrit Reviews

                  There are no open Gerrit changes

                  PagerDuty