From fe0bcec98fff1f50712f5ddf3c709d3cd251c8a2 Mon Sep 17 00:00:00 2001 From: appleguy Date: Mon, 13 Feb 2017 10:43:46 -0800 Subject: [PATCH] [NSArray+Diffing] Use heap-based allocation for array diff. (#2926) This avoids compiler warnings when using the strictest clang settings. It also ensures that stack overflow can't occur even with the largest datasets. --- AsyncDisplayKit/Details/NSArray+Diffing.m | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/AsyncDisplayKit/Details/NSArray+Diffing.m b/AsyncDisplayKit/Details/NSArray+Diffing.m index 44abf7ed71..b1b3b64e98 100644 --- a/AsyncDisplayKit/Details/NSArray+Diffing.m +++ b/AsyncDisplayKit/Details/NSArray+Diffing.m @@ -60,18 +60,19 @@ NSInteger arrayCount = array.count; // Allocate the diff map in the heap so we don't blow the stack for large arrays. - NSInteger (*lengths)[arrayCount+1] = NULL; - size_t lengthsSize = ((selfCount+1) * sizeof(*lengths)); - // Would rather use initWithCapacity: to skip the zeroing, but TECHNICALLY - // `mutableBytes` is only guaranteed to be non-NULL if the data object has a non-zero length. - NS_VALID_UNTIL_END_OF_SCOPE NSMutableData *lengthsData = [[NSMutableData alloc] initWithLength:lengthsSize]; - lengths = lengthsData.mutableBytes; + NSInteger **lengths = NULL; + lengths = (NSInteger **)malloc(sizeof(NSInteger*) * (selfCount+1)); if (lengths == NULL) { - ASDisplayNodeFailAssert(@"Failed to allocate memory for diffing with size %tu", lengthsSize); + ASDisplayNodeFailAssert(@"Failed to allocate memory for diffing"); return nil; } for (NSInteger i = 0; i <= selfCount; i++) { + lengths[i] = (NSInteger *)malloc(sizeof(NSInteger) * (arrayCount+1)); + if (lengths[i] == NULL) { + ASDisplayNodeFailAssert(@"Failed to allocate memory for diffing"); + return nil; + } id selfObj = i > 0 ? self[i-1] : nil; for (NSInteger j = 0; j <= arrayCount; j++) { if (i == 0 || j == 0) { @@ -96,7 +97,11 @@ j--; } } - + + for (NSInteger i = 0; i <= selfCount; i++) { + free(lengths[i]); + } + free(lengths); return common; }