From fd34c0e2f97f6a06cf63ff9802631fb2c7b5a2b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Fri, 16 Jan 2026 12:52:34 +0100 Subject: [PATCH] fix: cancel CDN download tasks on dealloc to prevent use-after-free Track active URLSession tasks and cancel them when CDNFileAssetLoader deallocates to prevent accessing invalid C++ objects. --- Source/Renderer/CDNFileAssetLoader.mm | 37 ++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/Source/Renderer/CDNFileAssetLoader.mm b/Source/Renderer/CDNFileAssetLoader.mm index bc800b21..c71d728d 100644 --- a/Source/Renderer/CDNFileAssetLoader.mm +++ b/Source/Renderer/CDNFileAssetLoader.mm @@ -12,15 +12,32 @@ #import @implementation CDNFileAssetLoader -{} +{ + NSMutableArray* _activeTasks; +} + +- (instancetype)init +{ + if (self = [super init]) + { + _activeTasks = [NSMutableArray array]; + } + return self; +} + +- (void)dealloc +{ + for (NSURLSessionTask* task in _activeTasks) + { + [task cancel]; + } +} - (bool)loadContentsWithAsset:(RiveFileAsset*)asset andData:(NSData*)data andFactory:(RiveFactory*)factory { // TODO: Error handling - // TODO: Track tasks, so we can cancel them if we garbage collect the asset - // loader if ([[asset cdnUuid] length] > 0) { @@ -28,10 +45,17 @@ - (bool)loadContentsWithAsset:(RiveFileAsset*)asset [NSURL URLWithString:[NSString stringWithFormat:@"%@/%@", [asset cdnBaseUrl], [asset cdnUuid]]]; - NSURLSessionTask* task = [[NSURLSession sharedSession] + __block NSURLSessionTask* task = nil; + __weak CDNFileAssetLoader* weakSelf = self; + task = [[NSURLSession sharedSession] downloadTaskWithURL:URL completionHandler:^( NSURL* location, NSURLResponse* response, NSError* error) { + CDNFileAssetLoader* strongSelf = weakSelf; + if (strongSelf) + { + [strongSelf->_activeTasks removeObject:task]; + } if (!error) { // Load the data into the reader @@ -65,9 +89,8 @@ - (bool)loadContentsWithAsset:(RiveFileAsset*)asset } }]; - // Kick off the http download - // QUESTION: Do we need to tie this into the RiveFile so we can wait for - // these loads to be completed? + // Track and start the download + [_activeTasks addObject:task]; [task resume]; return true; }