From 7dbcadc2c0523dc3c3bcc0a8cd7ceea9f44fc655 Mon Sep 17 00:00:00 2001 From: Max Date: Sat, 9 May 2015 23:27:05 +0200 Subject: Fix a possible crash caused by a use-after-free in some rare cases when closing a connection tab. --- Source/NoodleLineNumberView.m | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'Source') diff --git a/Source/NoodleLineNumberView.m b/Source/NoodleLineNumberView.m index 24b76be1..8b678434 100644 --- a/Source/NoodleLineNumberView.m +++ b/Source/NoodleLineNumberView.m @@ -59,6 +59,7 @@ typedef NSRange (*RangeOfLineIMP)(id object, SEL selector, NSRange range); - (void)invalidateLineIndices; - (void)calculateLines; - (void)updateGutterThicknessConstants; +- (void)setRuleThicknessNumber:(NSNumber *)aNum; @end @@ -112,6 +113,7 @@ typedef NSRange (*RangeOfLineIMP)(id object, SEL selector, NSRange range); - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; + [NSObject cancelPreviousPerformRequestsWithTarget:self]; if (lineIndices) [lineIndices release]; if (textAttributes) [textAttributes release]; @@ -566,17 +568,23 @@ typedef NSRange (*RangeOfLineIMP)(id object, SEL selector, NSRange range); currentRuleThickness = newThickness; // Not a good idea to resize the view during calculations (which can happen during - // display). Do a delayed perform (using NSInvocation since arg is a float). - NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:@selector(setRuleThickness:)]]; - [invocation setSelector:@selector(setRuleThickness:)]; - [invocation setTarget:self]; - [invocation setArgument:&newThickness atIndex:2]; - - [invocation performSelector:@selector(invoke) withObject:nil afterDelay:0.0]; + // display). Do a delayed perform. + [self performSelector:@selector(setRuleThicknessNumber:) withObject:[NSNumber numberWithFloat:newThickness] afterDelay:0.0]; } } } +- (void)setRuleThicknessNumber:(NSNumber *)aNum +{ + // We want to do a delayed perform, but setRuleThickness: does take a CGFloat + // and not an object. In the past we used NSInvocation to work around that, + // however that has one major issue: >>This class does not retain the arguments + // for the contained invocation by default.<< (NSInvocation doc). + // A perform with delay 0.0 is queued with the run loop, so a dealloc can very + // well happen before that! + [self setRuleThickness:[aNum floatValue]]; +} + - (void)updateGutterThicknessConstants { maxWidthOfGlyph1 = ceilf(MAX(DEFAULT_THICKNESS, maxWidthOfGlyph + RULER_MARGIN2)); -- cgit v1.2.3