0

XCode detected memory leaks in one of my function: enter image description here

The func is responsible for extracting PKCS7 container. Here the code of the func:

func extractPKCS7Container() throws -> UnsafeMutablePointer<PKCS7> {
    guard let receiptURL = Bundle.main.appStoreReceiptURL,
        let certificateURL = Bundle.main.url(forResource: "AppleIncRootCertificate", withExtension: "cer"),
        let receiptData = NSData(contentsOf: receiptURL),
        let certificateData = NSData(contentsOf: certificateURL) else {
            throw ReceiptError.couldNotFindReceipt
    }
    let bio = BIOWrapper(data: receiptData)
    let p7 = d2i_PKCS7_bio(bio.bio, nil)
    guard p7 != nil else {
        throw ReceiptError.emptyReceiptContents
    }
    OpenSSL_add_all_digests()

    let x509Store = X509StoreWrapper()
    let certificate = X509Wrapper(data: certificateData)
    x509Store.addCert(x509: certificate)
    let payload = BIOWrapper()
    guard PKCS7_verify(p7, nil, x509Store.store, nil, payload.bio, 0) == 1 else {
        throw ReceiptError.receiptNotSigned
    }
    return p7!
}

I also have supplementary classes:

class BIOWrapper {
    let bio = BIO_new(BIO_s_mem())
    init(data:NSData) {
        BIO_write(bio, data.bytes, Int32(data.length))
    }
    init() {}
    deinit {
        BIO_free(bio)
    }
}

class X509StoreWrapper {
    let store = X509_STORE_new()
    deinit {
        X509_STORE_free(store)
    }
    func addCert(x509:X509Wrapper) {
        X509_STORE_add_cert(store, x509.x509)
    }
}

class X509Wrapper {
    let x509 : UnsafeMutablePointer<X509>!
    init(data:NSData){
        let certBIO = BIOWrapper(data: data)
        x509 = d2i_X509_bio(certBIO.bio, nil)
    }
    deinit {
        X509_free(x509)
    }
}

All wrappers has init and deinit section. Other functions is from the build-in Crypto module... Frankly, I have no idea there the leak can be here. Could anyone help me?

Alex
  • 751
  • 1
  • 9
  • 28

1 Answers1

0

You are allocating a PKCS7 object but it seems you are never calling PKCS7_free. For example, you would need to call it right before throw ReceiptError.receiptNotSigned.

Notice in the stack trace on the right there are stack frames missing. You can view them by clicking on the icon the looks like a square with a line above and below that. That way you know exactly which function call is responsible for the allocation (and thus likely what it is that leaked).

DarkDust
  • 90,870
  • 19
  • 190
  • 224
  • I have added PKSC7_free call after `throw ReceiptError.receiptNotSigned`. Unfortunately has no any effect. Also i pressed the button you mentioned. Here is my stack trace - https://ibb.co/g43yR7 . I can't understand - It looks like CRYPTO_malloc cause the problem? The CRYPTO_malloc on the top of my stack. – Alex May 08 '18 at 08:23
  • As I understood malloc allocate more memory than necessary? – Alex May 08 '18 at 08:31
  • If I do everything right the problem is still on the func `extractPKCS7Container()` - screenshot: https://ibb.co/cR8UzS – Alex May 08 '18 at 08:38
  • The call to `PKCS7_free` needs to be inside the `guard` clause but _before_ `throw ReceiptError.receiptNotSigned` (code after a `throw` cannot be reached). The malloc simply isn't free'd. After your call to `extractPKCS7Container()`, you need to `PKCS7_free` your `container` variable. – DarkDust May 08 '18 at 09:18
  • I am sorry - type in it wrong. I insert it as you mentioned: `guard PKCS7_verify(p7, nil, x509Store.store, nil, payload.bio, 0) == 1 else { PKCS7_free(p7) throw ... } ` I am trying to insert `PKCS7_free` on the right place in the main func... – Alex May 08 '18 at 09:30
  • Sir, You have made my day! Thank you a lot :) Also I needed to add the free func on the main func: `func validate() -> (Bool, String?) { let container = try extractPKCS7Container() let extractedReceipt = try parseContainer(container) ... PKCS7_free(container) // <- !very important! ... }` – Alex May 08 '18 at 09:41