Skip to content

Commit

Permalink
[_ASDisplayLayer] Add protection around setting a layer’s position an…
Browse files Browse the repository at this point in the history
…d 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.
  • Loading branch information
rcancro authored Sep 4, 2024
1 parent f8d9181 commit 2d7bf71
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 0 deletions.
20 changes: 20 additions & 0 deletions Source/Details/_ASDisplayLayer.mm
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,26 @@ - (void)setDisplaySuspended:(BOOL)displaySuspended
}
}

- (void)setPosition:(CGPoint)position
{
BOOL valid = ASDisplayNodeAssertNonFatal(ASIsCGPositionValidForLayout(position), @"Caught attempt to set invalid position %@ on %@.", NSStringFromCGPoint(position), self);
if (!valid) {
return;
}

[super setPosition:position];
}

- (void)setTransform:(CATransform3D)transform
{
BOOL valid = ASDisplayNodeAssertNonFatal(ASIsTransformValidForLayout(transform), @"Caught attempt to set invalid transform on %@.", self);
if (!valid) {
return;
}

[super setTransform:transform];
}

- (void)setBounds:(CGRect)bounds
{
BOOL valid = ASDisplayNodeAssertNonFatal(ASIsCGRectValidForLayout(bounds), @"Caught attempt to set invalid bounds %@ on %@.", NSStringFromCGRect(bounds), self);
Expand Down
9 changes: 9 additions & 0 deletions Source/Layout/ASDimension.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#import <AsyncDisplayKit/ASAvailability.h>
#import <AsyncDisplayKit/ASBaseDefines.h>
#import <AsyncDisplayKit/ASAssert.h>
#import <QuartzCore/QuartzCore.h>

NS_ASSUME_NONNULL_BEGIN

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

ASDISPLAYNODE_INLINE BOOL ASIsTransformValidForLayout(CATransform3D t)
{
return !isnan(t.m11) && !isnan(t.m12) && !isnan(t.m13) && !isnan(t.m14) &&
!isnan(t.m21) && !isnan(t.m22) && !isnan(t.m23) && !isnan(t.m24) &&
!isnan(t.m31) && !isnan(t.m32) && !isnan(t.m33) && !isnan(t.m34) &&
!isnan(t.m41) && !isnan(t.m42) && !isnan(t.m43) && !isnan(t.m44);
}

#pragma mark - ASDimension

/**
Expand Down
113 changes: 113 additions & 0 deletions Tests/ASDisplayLayerTests.mm
Original file line number Diff line number Diff line change
Expand Up @@ -595,4 +595,117 @@ - (void)testSuspendResumeSync
[self checkSuspendResume:NO];
}

- (void)testSetPosition
{
_ASDisplayLayer *layer = [[_ASDisplayLayer alloc] init];
CGPoint origin = CGPointMake(20, 20);
layer.position = CGPointZero; // Make sure CGPointZero doesn't throw

layer.position = origin;
XCTAssertTrue(CGPointEqualToPoint(layer.position, origin));

XCTAssertThrows(layer.position = CGPointMake(NAN, 50));
XCTAssertTrue(CGPointEqualToPoint(layer.position, origin));

XCTAssertThrows(layer.position = CGPointMake(NAN, NAN));
XCTAssertTrue(CGPointEqualToPoint(layer.position, origin));

XCTAssertThrows(layer.position = CGPointMake(50, NAN));
XCTAssertTrue(CGPointEqualToPoint(layer.position, origin));

origin = CGPointMake(10, 10);
layer.position = origin;
XCTAssertTrue(CGPointEqualToPoint(layer.position, origin));
}

- (void)testSetTransform
{
_ASDisplayLayer *layer = [[_ASDisplayLayer alloc] init];

CATransform3D transform = CATransform3DIdentity;
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));

transform.m11 = NAN;
XCTAssertThrows(layer.transform = transform);
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
transform = CATransform3DIdentity;

transform.m12 = NAN;
XCTAssertThrows(layer.transform = transform);
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
transform = CATransform3DIdentity;

transform.m13 = NAN;
XCTAssertThrows(layer.transform = transform);
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
transform = CATransform3DIdentity;

transform.m14 = NAN;
XCTAssertThrows(layer.transform = transform);
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
transform = CATransform3DIdentity;

transform.m21 = NAN;
XCTAssertThrows(layer.transform = transform);
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
transform = CATransform3DIdentity;

transform.m22 = NAN;
XCTAssertThrows(layer.transform = transform);
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
transform = CATransform3DIdentity;

transform.m23 = NAN;
XCTAssertThrows(layer.transform = transform);
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
transform = CATransform3DIdentity;

transform.m24 = NAN;
XCTAssertThrows(layer.transform = transform);
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
transform = CATransform3DIdentity;

transform.m31 = NAN;
XCTAssertThrows(layer.transform = transform);
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
transform = CATransform3DIdentity;

transform.m32 = NAN;
XCTAssertThrows(layer.transform = transform);
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
transform = CATransform3DIdentity;

transform.m33 = NAN;
XCTAssertThrows(layer.transform = transform);
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
transform = CATransform3DIdentity;

transform.m34 = NAN;
XCTAssertThrows(layer.transform = transform);
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
transform = CATransform3DIdentity;

transform.m41 = NAN;
XCTAssertThrows(layer.transform = transform);
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
transform = CATransform3DIdentity;

transform.m42 = NAN;
XCTAssertThrows(layer.transform = transform);
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
transform = CATransform3DIdentity;

transform.m43 = NAN;
XCTAssertThrows(layer.transform = transform);
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
transform = CATransform3DIdentity;

transform.m44 = NAN;
XCTAssertThrows(layer.transform = transform);
XCTAssertTrue(CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity));
transform = CATransform3DIdentity;

layer.transform = transform;
}

@end

0 comments on commit 2d7bf71

Please sign in to comment.