Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C-style uninitialized pointer passing in Apple Swift?

Tags:

swift

I am attempting to implement some AES256 crypto routines in Apple Swift to kinda toy around with the interoperability between ObjC, C, and Swift code and data types, and have run into a bit of an issue and am hoping someone has some suggestions on something I've overlooked.

As most are familiar, common C-style pattern is to declare an uninitialized pointer and then pass that into a function, wherein the function call malloc()s an object and points the pointer to it; after the function call completes the pointer points to the newly-created object. The Common Crypto libraries use this in some places; most notably when creating a new CCCryptor object (really a struct behind the scenes, it looks like, typedef'ed to CCCryptorRef for an opaque reference) - the final argument to the call to CCCryptorCreate() is such a pointer and should, at the conclusion of the function call, contain a pointer to the CCCryptorRef.

Swift puts a wrinkle into this - variables cannot be uninitialized, they always either have a value or are nil(/optional), and thus I've run into a bit of a bump here. The following doesn't work because CCCryptorCreate (rightfully) acts as though I'm just passing nil as the last argument, which I am:

var myCryptorRef: CMutablePointer<Unmanaged<CCCryptorRef>?> = nil
CCCryptorCreate(CCOperation(kCCEncrypt), CCAlgorithm(kCCAlgorithmAES128),
  CCOptions(kCCOptionECBMode), seedData.bytes(), UInt(kCCKeySizeAES256), 
  nil, myCryptorRef)

But neither can you declare it as an optional, like so:

var myCryptorRef: CMutablePointer<Unmanaged<CCCryptorRef>?>?

Or as a non-pointer type:

var myCryptoRef: Unmanaged<CCCryptorRef>?
CCCryptorCreate(CCOperation(kCCEncrypt), CCAlgorithm(kCCAlgorithmAES128),
  CCOptions(kCCOptionECBMode), seedData.bytes(), UInt(kCCKeySizeAES256), 
  nil, &myCryptorRef)

Since what CCCryptorCreate expects is either an uninitialized pointer to a CCCryptorRef or an already-malloc()'ed CCCryptorRef, attempting to pass it the address of a not-yet-initialized object doesn't go very well as you might expect.

So, it comes down to this: can anyone come up with a way to initialize that CCCryptor struct before the call to CCCryptorCreate (the Swift-standard method of struct init by naming all variables inside the struct does not seem to work), or some alternate construction that would allow me to preserve the C concept of the uninitialized pointer for use in this way? Thank you for any suggestions you may have.

Adding for clarity from the comments: Swift interprets the call to CCCryptorCreate() as the following:

CCCryptorCreate(op: CCOperation, alg: CCAlgorithm, options: CCOptions, 
  key: CConstVoidPointer, keyLength: UInt, iv: CConstVoidPointer, 
  cryptorRef: CMutablePointer<Unmanaged<CCCryptor>?>)

An additional edit for some other things I've tried: Just to be truly absurd, I tried the following, but it also did not work (EXC_BAD_ACCESS on the call to fromOpaque):

var someMem = malloc(UInt(sizeof(CCCryptor)))
var crashTime = Unmanaged<CCCryptor>.fromOpaque(someMem)

Also, every place CCCryptor or CCCryptorRef is mentioned, I have tried either one - in CommonCrypto/CommonCryptor.h, CCCryptorRef is defined thusly:

typedef struct _CCCryptor *CCCryptorRef

So while existing Objective-C code examples use CCCryptorRef, I've been trying either.

like image 564
Khaibit Avatar asked Jun 06 '14 20:06

Khaibit


1 Answers

Try this:

var myCryptor: Unmanaged<CCCryptor>?

CCCryptorCreate( .... , &myCryptor )

From Using Swift with Cocoa and Objective-C

If you have declared a function like this one:

func takesAMutablePointer(x: CMutablePointer<Float>) { /*...*/ }

You can call it in any of the following ways:

var x: Float = 0.0 
var p: CMutablePointer<Float> = nil 
var a: Float[] = [1.0, 2.0, 3.0] 
takesAMutablePointer(nil) 
takesAMutablePointer(p) 
takesAMutablePointer(&x) 
takesAMutablePointer(&a)

You should also check out this and convert the Unmanaged reference into something that is managed.

like image 78
Analog File Avatar answered Oct 06 '22 16:10

Analog File