Will the call to SecTrustCreateWithCertificates cause a memory leak in Alamofire? - alamofire

In Alamofire,
extension AlamofireExtension where ExtendedType == SecCertificate {
public var publicKey: SecKey? {
let policy = SecPolicyCreateBasicX509()
var trust: SecTrust?
let trustCreationStatus = SecTrustCreateWithCertificates(type, policy, &trust)
guard let createdTrust = trust, trustCreationStatus == errSecSuccess else { return nil }
return SecTrustCopyPublicKey(createdTrust)
}
}
SecTrustCreateWithCertificates call create a trust object. According to Apple's official documentation:
trust
On return, points to the newly created trust management object.
Call the CFRelease function to release this object when you are
finished with it.
The trust object should be released by calling the CFRelease function (like this: CFRelease(createdTrust)),but it is not called here.
Will there be a memory leak?

CoreFoundation objects are automatically memory managed when used from Swift.

Related

Invalid pointer operation when freeing TStreamAdapter

Can anyone clarify why do I get "Invalid pointer operation" when I attempt to delete TStreamAdapter? Or... how to properly free the memory from TStreamAdapter? It works, if I remove the delete but that causes a memory leak. Even if I use boost::scoped_ptr it also fails with the same error.
Note: I also tried initializing TStreamAdapter with soOwned value, same error.
The code:
HRESULT LoadFromStr(TWebBrowser* WB, const UnicodeString& HTML)
{
if (!WB->Document)
{
WB->Navigate("about:blank");
while (!WB->Document) { Application->ProcessMessages(); }
}
DelphiInterface<IHTMLDocument2> diDoc = WB->Document;
if (diDoc)
{
boost::scoped_ptr<TMemoryStream> ms(new TMemoryStream);
{
boost::scoped_ptr<TStringList> sl(new TStringList);
sl->Text = HTML;
sl->SaveToStream(ms.get(), TEncoding::Unicode);
ms->Position = 0;
}
DelphiInterface<IPersistStreamInit> diPSI;
if (SUCCEEDED(diDoc->QueryInterface(IID_IPersistStreamInit, (void**)&diPSI)) && diPSI)
{
TStreamAdapter* sa = new TStreamAdapter(ms.get(), soReference);
diPSI->Load(*sa);
delete sa; // <-- invalid pointer operation here???
// UPDATED (solution) - instead of the above!!!
// DelphiInterface<IStream> sa(*(new TStreamAdapter(ms.get(), soReference)));
// diPSI->Load(sa);
// DelphiInterface is automatically freed on function end
return S_OK;
}
}
return E_FAIL;
}
Update: I found the solution here - http://www.cyberforum.ru/cpp-builder/thread743255.html
The solution is to use
_di_IStream sa(*(new TStreamAdapter(ms.get(), soReference)));
or...
DelphiInterface<IStream> sa(*(new TStreamAdapter(ms.get(), soReference)));
As it will automatically free the IStream once it is out of scope. At least it should - is there a possible memory leak here? (CodeGuard did not detect any memory leaks).
TStreamAdapter is a TInterfacedObject descendant, which implements reference counting semantics. You are not supposed to delete it at all, you need to let reference counting free the object when it is no longer being referenced by anyone.
Using _di_IStream (which is just an alias for DelphiInterface<IStream>) is the correct way to automate that with a smart pointer. TComInterface<IStream> and CComPtr<IStream> would also work, too.

How to use an Objective-C function with block in Swift4 in a #noescap way?

I'm developing an iOS app in Swift4 with an Object-C framework called 'YapDatabase'. There is an Object-C function with a block like this in class 'YapDatabaseConnection':
- (void)readWithBlock:(void (^)(YapDatabaseReadTransaction *transaction))block;
I use the function in this way:
static func readNovelIds() -> [String]? {
let account = XFAccountManager.share().account
var events: [XFNovelClickEvent]?
OTRDatabaseManager.shared.readOnlyDatabaseConnection?.read({ (transaction) in
events = XFNovelClickEvent.allNovelClickEvents(accountId: account.uniqueId, transaction: transaction)
})
guard let clickEvents = events else {
return nil
}
let readNovelsIds = clickEvents.map {
$0.bookId ?? ""
}
return readNovelsIds
}
I thought the closure will be executed immediately after the 'events' parameter declared. In fact, the closure doesn't be executed before result returns. To search the reason, I open the file named 'YapDatabaseConnection.h(Interface)' generated by Xcode (with cmd+shift+o), found the function has been translate to Swift in this way:
open func read(_ block: #escaping (YapDatabaseReadTransaction) -> Void)
So, how do I use this function in a #noescap way?
As the caller, you can't change when the closure is executed. That's up to the read() function. If you control that function, you'll need to modify it to call the closure immediately. If you don't control it, then you can't modify how it behaves.
You can convert an asynchronous call into a synchronous call using a DispatchGroup as described in Waiting until the task finishes. However, you can't make a database call on the main queue; you risk crashing the app. As a general rule, you should just use async calls in this case (i.e. make readNovelIds also be asynchronous and take a completion handler).
The reason why Xcode bridged the objective-c block as #escaping is because the block may be executed after the function return.
Since you don’t own YapDatabase, you couldn’t modify the source code to make it non-escaped, so you may wanna make your readNovelIds function takes a closure as parameter and pass the return value through closure.
static func readNovelIds(resultHandler: #escaping ([String]?) -> ()) {
let account = XFAccountManager.share().account
var events: [XFNovelClickEvent]?
OTRDatabaseManager.shared.readOnlyDatabaseConnection?.read({ (transaction) in
events = XFNovelClickEvent.allNovelClickEvents(accountId: account.uniqueId, transaction: transaction)
if let clickEvents = events {
let readNovelsIds = clickEvents.map {
$0.bookId ?? ""
}
resultHandler(readNovelsIds)
}
resultHandler(nil)
})
}
If the method is in fact synchronous (i.e. it will not allow the block to escape its context), the Objective C header method should be decorated with NS_NOESCAPE. Looking at the documentation (which does say it is synchronous), and the implementation, it should be annotated that way.
- (void)readWithBlock:(void (NS_NOESCAPE ^)(YapDatabaseReadTransaction *transaction))block;
That, I believe, should allow the Swift interface importer to add the #noescaping declaration. You should probably file a bug request on the YapDatabase project; they can change it there.

Close SSL connection correctly with OpenSSL

I have SSL connection in main thread and have memory leak.
I close connection in this way (_ssl — SSL* object):
SSL_shutdown(_ssl);
SSL_free (_ssl);
But memory isn't freed correctly — after every new client some memory (~20kb) doesn't freed. I made an experiment: make many connections(~7000) and close them after establishing. Graph shows that memory was really growing up during all time. It's very important for me that memory will be unchangeable from connection to connection. Any suggestions?
Graph:
UPD:
All functions that I use:
It's executed once when server is start (I think it can't reason for increasing memory from connection to connection):
SSL_load_error_strings();
SSLeay_add_ssl_algorithms();
SSL_METHOD* meth = TLSv1_server_method();
_ctx = SSL_CTX_new (meth);
SSL_CTX_set_verify(_ctx, SSL_VERIFY_PEER, NULL);
SSL_CTX_set_verify_depth(_ctx, 1);
if (!_ctx) {
ERR_print_errors_fp(stderr);
exit(2);
}
if (SSL_CTX_load_verify_locations(_ctx, "keys/c1.crt", NULL) <= 0)
{
ERR_print_errors_fp(stderr);
exit(3);
}
SSL_CTX_set_verify(_ctx, SSL_VERIFY_PEER, NULL);
SSL_CTX_set_verify_depth(_ctx,1);
if (SSL_CTX_use_certificate_file(_ctx, CERTF, SSL_FILETYPE_PEM) <= 0) {
ERR_print_errors_fp(stderr);
exit(3);
}
if (SSL_CTX_use_PrivateKey_file(_ctx, KEYF, SSL_FILETYPE_PEM) <= 0) {
ERR_print_errors_fp(stderr);
exit(4);
}
if (!SSL_CTX_check_private_key(_ctx)) {
fprintf(stderr, "Private key does not match the certificate public key\n");
exit(5);
}
It's executed for every connection in the start:
ERR_remove_state(0);
_ssl = SSL_new (ctx);
if (_ssl == NULL)
{
_isValid = false;
return;
}
SSL_set_fd (_ssl, _sd->get_num());
int err = SSL_accept (_ssl);
if (err == -1)
{
ERR_print_errors_fp(stderr);
_isValid = false;
return;
}
You have to release all resources which you used in this connection. OpenSSL has a reference counter on these resources and some functions returns you something with an increased counter and some not, so you have to really look at the (often insufficient) documentation. OpenSSL which not keep track which resources you've allocated within this connection and give them automatically back once you've called SSL_free, you have to take care of this yourself.
There is not enough information of what you are really doing in your code to see where if there really is a leak and where it comes from. But as an example: if you called SSL_get_peer_certificate to get the certificate you have to explicitly free the memory because (from the documentation):
The reference count of the X509 object is incremented by one, so that it will not be destroyed when the session containing the peer certificate is freed. The X509 object must be explicitly freed using X509_free().
Contrary to that the similar function SSL_get_peer_chain will not increase the reference counter so you should not attempt to free the resources yourself:
The reference count of the STACK_OF(X509) object is not incremented. If the corresponding session is freed, the pointer must not be used any longer.
So you have to actually look at each function you use and check if you need to free allocated resources explicitly or not.

How do I prevent certain kinds of analyzer leak reports?

I am wrapping a certain C API in Objective-C. I have a convenience method that takes some CFTypeRef from the procedural API and returns a wrapping object from the OOP API. This object keeps the passed CFTypeRef and releases it upon its own deallocation. The convenience method looks like this:
+ (id) wrapFoo: (CFTypeRef) foo;
I have a lot of methods that simply get some CFTypeRef and return the wrapping object:
- (id) doSomething {
CFTypeRef foo = CFCreateSomeObject();
id wrapper = [WrappingClass wrapFoo:foo];
CFRelease(foo);
return wrapper;
}
This is a bit clumsy, so that I came up with another convenience method:
+ (id) wrapNonRetainedFoo: (CFTypeRef) foo {
id wrapper = [self wrapFoo:foo]; // CFRetains foo
CFRelease(foo);
return wrapper;
}
Now I can rewrite the doSomething method like this:
- (id) doSomething {
return [WrappingClass wrapNonRetainedFoo:CFCreateSomeObject()]; // XXX
}
I like this. I’m not really proud of the wrapNonRetainedFoo method, but it’s not a part of the public interface of the package and saves me several lines of boilerplate code in several methods.
The downside is that the static analyzer flags the XXX line as a potential leak. What can I do better? I tried to toy with the cf_consumed argument attribute to let the analyzer know that I’m releasing the object later, but it does not seem to work.
1) AFAIK cf_consumed is still not supported in versions of analyzer Apple uses.
2) I've noticed that if you make wrapNonRetainedFoo instance method warning will mysteriously disappear. But since wrap... is better to be a class method this is of no use to us.
3) Only solution I can think of is this ugly macro (not for production, just as proof of concept):
#define WRAP_CFTYPE(klass, valExpr) ({ CFTypeRef val = valExpr; id result = [klass wrap:val]; CFRelease(val); result; })
Usage:
WrappingClass *wrapper = WRAP_CFTYPE(WrappingClass, CFArrayCreate(NULL, NULL, 0, NULL))

How can my app detect a change to another app's window?

In Cocoa on the Mac, I'd like to detect when a window belonging to another app is moved, resized, or repainted. How can I do this?
You would need to use the Accessibility APIs, which are plain-C, located inside the ApplicationServices framework. For instance:
First you create an application object:
AXUIElementRef app = AXUIElementCreateApplication( targetApplicationProcessID );
Then you get the window from this. You can request the window list and enumerate, or you can get the frontmost window (look in AXAttributeConstants.h for all the attribute names you'd use).
AXUIElementRef frontWindow = NULL;
AXError err = AXUIElementCopyAttributeValue( app, kAXMainWindowAttribute, &frontWindow );
if ( err != kAXErrorSuccess )
// it failed -- maybe no main window (yet)
Now you can request notification via a C callback function when a property of this window changes. This is a four-step process:
First you need a callback function to receive the notifications:
void MyAXObserverCallback( AXObserverRef observer, AXUIElementRef element,
CFStringRef notificationName, void * contextData )
{
// handle the notification appropriately
// when using ObjC, your contextData might be an object, therefore you can do:
SomeObject * obj = (SomeObject *) contextData;
// now do something with obj
}
Next you need an AXObserverRef, which manages the callback routine. This requires the same process ID you used to create the 'app' element above:
AXObserverRef observer = NULL;
AXError err = AXObserverCreate( applicationProcessID, MyObserverCallback, &observer );
if ( err != kAXErrorSuccess )
// handle the error
Having got your observer, the next step is to request notification of certain things. See AXNotificationConstants.h for the full list, but for window changes you'll probably only need these two:
AXObserverAddNotification( observer, frontWindow, kAXMovedNotification, self );
AXObserverAddNotification( observer, frontWindow, kAXResizedNotification, self );
Note that the last parameter there is passing an assumed 'self' object as the contextData. This is not retained, so it's important to call AXObserverRemoveNotification when this object goes away.
Having got your observer and added notification requests, you now want to attach the observer to your runloop so you can be sent these notifications in an asynchronous manner (or indeed at all):
CFRunLoopAddSource( [[NSRunLoop currentRunLoop] getCFRunLoop],
AXObserverGetRunLoopSource(observer),
kCFRunLoopDefaultMode );
AXUIElementRefs are CoreFoundation-style objects, so you need to use CFRelease() to dispose of them cleanly. For cleanliness here, for example, you would use CFRelease(app) once you've obtained the frontWindow element, since you'll no longer need the app.
A note about Garbage-Collection: To keep an AXUIElementRef as a member variable, declare it like so:
__strong AXUIElementRef frontWindow;
This instructs the garbage collector to keep track of this reference to it. When assigning it, for compatibility with GC and non-GC, use this:
frontWindow = (AXUIElementRef) CFMakeCollectable( CFRetain(theElement) );
Further research turned up "Quartz Display Services"
The interesting function for my needs is CGRegisterScreenRefreshCallback.