Skip to content

Commit 2d7bf71

Browse files
authored
[_ASDisplayLayer] Add protection around setting a layer’s position and transform (#2116)
There is built in protection around setting invalid bounds for `_ASDisplayLayer`. Let’s extend this to also include protecting against setting an invalid position and an invalid transform.
1 parent f8d9181 commit 2d7bf71

File tree

3 files changed

+142
-0
lines changed

3 files changed

+142
-0
lines changed

Source/Details/_ASDisplayLayer.mm

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,26 @@ - (void)setDisplaySuspended:(BOOL)displaySuspended
3939
}
4040
}
4141

42+
- (void)setPosition:(CGPoint)position
43+
{
44+
BOOL valid = ASDisplayNodeAssertNonFatal(ASIsCGPositionValidForLayout(position), @"Caught attempt to set invalid position %@ on %@.", NSStringFromCGPoint(position), self);
45+
if (!valid) {
46+
return;
47+
}
48+
49+
[super setPosition:position];
50+
}
51+
52+
- (void)setTransform:(CATransform3D)transform
53+
{
54+
BOOL valid = ASDisplayNodeAssertNonFatal(ASIsTransformValidForLayout(transform), @"Caught attempt to set invalid transform on %@.", self);
55+
if (!valid) {
56+
return;
57+
}
58+
59+
[super setTransform:transform];
60+
}
61+
4262
- (void)setBounds:(CGRect)bounds
4363
{
4464
BOOL valid = ASDisplayNodeAssertNonFatal(ASIsCGRectValidForLayout(bounds), @"Caught attempt to set invalid bounds %@ on %@.", NSStringFromCGRect(bounds), self);

Source/Layout/ASDimension.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#import <AsyncDisplayKit/ASAvailability.h>
1313
#import <AsyncDisplayKit/ASBaseDefines.h>
1414
#import <AsyncDisplayKit/ASAssert.h>
15+
#import <QuartzCore/QuartzCore.h>
1516

1617
NS_ASSUME_NONNULL_BEGIN
1718

@@ -54,6 +55,14 @@ ASDISPLAYNODE_INLINE BOOL ASIsCGRectValidForLayout(CGRect rect)
5455
return (ASIsCGPositionValidForLayout(rect.origin) && ASIsCGSizeValidForLayout(rect.size));
5556
}
5657

58+
ASDISPLAYNODE_INLINE BOOL ASIsTransformValidForLayout(CATransform3D t)
59+
{
60+
return !isnan(t.m11) && !isnan(t.m12) && !isnan(t.m13) && !isnan(t.m14) &&
61+
!isnan(t.m21) && !isnan(t.m22) && !isnan(t.m23) && !isnan(t.m24) &&
62+
!isnan(t.m31) && !isnan(t.m32) && !isnan(t.m33) && !isnan(t.m34) &&
63+
!isnan(t.m41) && !isnan(t.m42) && !isnan(t.m43) && !isnan(t.m44);
64+
}
65+
5766
#pragma mark - ASDimension
5867

5968
/**

Tests/ASDisplayLayerTests.mm

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,4 +595,117 @@ - (void)testSuspendResumeSync
595595
[self checkSuspendResume:NO];
596596
}
597597

598+
- (void)testSetPosition
599+
{
600+
_ASDisplayLayer *layer = [[_ASDisplayLayer alloc] init];
601+
CGPoint origin = CGPointMake(20, 20);
602+
layer.position = CGPointZero; // Make sure CGPointZero doesn't throw
603+
604+
layer.position = origin;
605+
XCTAssertTrue(CGPointEqualToPoint(layer.position, origin));
606+
607+
XCTAssertThrows(layer.position = CGPointMake(NAN, 50));
608+
XCTAssertTrue(CGPointEqualToPoint(layer.position, origin));
609+
610+
XCTAssertThrows(layer.position = CGPointMake(NAN, NAN));
611+
XCTAssertTrue(CGPointEqualToPoint(layer.position, origin));
612+
613+
XCTAssertThrows(layer.position = CGPointMake(50, NAN));
614+
XCTAssertTrue(CGPointEqualToPoint(layer.position, origin));
615+
616+
origin = CGPointMake(10, 10);
617+
layer.position = origin;
618+
XCTAssertTrue(CGPointEqualToPoint(layer.position, origin));
619+
}
620+
621+
- (void)testSetTransform
622+
{
623+
_ASDisplayLayer *layer = [[_ASDisplayLayer alloc] init];
624+
625+
CATransform3D transform = CATransform3DIdentity;
626+
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
627+
628+
transform.m11 = NAN;
629+
XCTAssertThrows(layer.transform = transform);
630+
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
631+
transform = CATransform3DIdentity;
632+
633+
transform.m12 = NAN;
634+
XCTAssertThrows(layer.transform = transform);
635+
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
636+
transform = CATransform3DIdentity;
637+
638+
transform.m13 = NAN;
639+
XCTAssertThrows(layer.transform = transform);
640+
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
641+
transform = CATransform3DIdentity;
642+
643+
transform.m14 = NAN;
644+
XCTAssertThrows(layer.transform = transform);
645+
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
646+
transform = CATransform3DIdentity;
647+
648+
transform.m21 = NAN;
649+
XCTAssertThrows(layer.transform = transform);
650+
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
651+
transform = CATransform3DIdentity;
652+
653+
transform.m22 = NAN;
654+
XCTAssertThrows(layer.transform = transform);
655+
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
656+
transform = CATransform3DIdentity;
657+
658+
transform.m23 = NAN;
659+
XCTAssertThrows(layer.transform = transform);
660+
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
661+
transform = CATransform3DIdentity;
662+
663+
transform.m24 = NAN;
664+
XCTAssertThrows(layer.transform = transform);
665+
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
666+
transform = CATransform3DIdentity;
667+
668+
transform.m31 = NAN;
669+
XCTAssertThrows(layer.transform = transform);
670+
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
671+
transform = CATransform3DIdentity;
672+
673+
transform.m32 = NAN;
674+
XCTAssertThrows(layer.transform = transform);
675+
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
676+
transform = CATransform3DIdentity;
677+
678+
transform.m33 = NAN;
679+
XCTAssertThrows(layer.transform = transform);
680+
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
681+
transform = CATransform3DIdentity;
682+
683+
transform.m34 = NAN;
684+
XCTAssertThrows(layer.transform = transform);
685+
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
686+
transform = CATransform3DIdentity;
687+
688+
transform.m41 = NAN;
689+
XCTAssertThrows(layer.transform = transform);
690+
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
691+
transform = CATransform3DIdentity;
692+
693+
transform.m42 = NAN;
694+
XCTAssertThrows(layer.transform = transform);
695+
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
696+
transform = CATransform3DIdentity;
697+
698+
transform.m43 = NAN;
699+
XCTAssertThrows(layer.transform = transform);
700+
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
701+
transform = CATransform3DIdentity;
702+
703+
transform.m44 = NAN;
704+
XCTAssertThrows(layer.transform = transform);
705+
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
706+
transform = CATransform3DIdentity;
707+
708+
layer.transform = transform;
709+
}
710+
598711
@end

0 commit comments

Comments
 (0)