mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-20 13:19:16 +00:00
[ASLayout] Add additional validation step to intercept incorrect values in production and safely zero them out.
These conditions already had assertions, but at runtime, an insufficiently tested and incorrect ASLayoutSpec could generate values that cause UIKit to enter an infinite loop (e.g. inside of UICollectionView layout validation).
This commit is contained in:
parent
c94490f7bb
commit
678c201dbc
@ -293,9 +293,18 @@
|
|||||||
CGSize size = self.preferredFrameSize;
|
CGSize size = self.preferredFrameSize;
|
||||||
if (CGSizeEqualToSize(size, CGSizeZero)) {
|
if (CGSizeEqualToSize(size, CGSizeZero)) {
|
||||||
size = constrainedSize;
|
size = constrainedSize;
|
||||||
|
|
||||||
|
// FIXME: Need a better way to allow maps to take up the right amount of space in a layout (sizeRange, etc)
|
||||||
|
// These fallbacks protect against inheriting a constrainedSize that contains a CGFLOAT_MAX value.
|
||||||
|
if (!isValidForLayout(size.width)) {
|
||||||
|
size.width = 100.0;
|
||||||
|
}
|
||||||
|
if (!isValidForLayout(size.height)) {
|
||||||
|
size.height = 100.0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
[self setSnapshotSizeWithReloadIfNeeded:size];
|
[self setSnapshotSizeWithReloadIfNeeded:size];
|
||||||
return constrainedSize;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -layout isn't usually needed over -layoutSpecThatFits, but this way we can avoid a needless node wrapper for MKMapView.
|
// -layout isn't usually needed over -layoutSpecThatFits, but this way we can avoid a needless node wrapper for MKMapView.
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
#import <AsyncDisplayKit/ASBaseDefines.h>
|
#import <AsyncDisplayKit/ASBaseDefines.h>
|
||||||
|
|
||||||
@ -34,6 +35,8 @@ typedef struct {
|
|||||||
|
|
||||||
extern ASRelativeDimension const ASRelativeDimensionUnconstrained;
|
extern ASRelativeDimension const ASRelativeDimensionUnconstrained;
|
||||||
|
|
||||||
|
#define isValidForLayout(x) ((isnormal(x) || x == 0.0) && x >= 0.0 && x < (CGFLOAT_MAX / 2.0))
|
||||||
|
|
||||||
ASDISPLAYNODE_EXTERN_C_BEGIN
|
ASDISPLAYNODE_EXTERN_C_BEGIN
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,8 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
#import <AsyncDisplayKit/ASAssert.h>
|
#import <AsyncDisplayKit/ASAssert.h>
|
||||||
#import <AsyncDisplayKit/ASLayoutable.h>
|
#import <AsyncDisplayKit/ASLayoutable.h>
|
||||||
|
|||||||
@ -39,7 +39,15 @@ extern BOOL CGPointIsNull(CGPoint point)
|
|||||||
ASLayout *l = [super new];
|
ASLayout *l = [super new];
|
||||||
if (l) {
|
if (l) {
|
||||||
l->_layoutableObject = layoutableObject;
|
l->_layoutableObject = layoutableObject;
|
||||||
l->_size = CGSizeMake(ASCeilPixelValue(size.width), ASCeilPixelValue(size.height));
|
|
||||||
|
if (!isValidForLayout(size.width) || !isValidForLayout(size.height)) {
|
||||||
|
ASDisplayNodeAssert(NO, @"layoutSize is invalid and unsafe to provide to Core Animation! Production will force to 0, 0. Size = %@, node = %@", NSStringFromCGSize(size), layoutableObject);
|
||||||
|
size = CGSizeZero;
|
||||||
|
} else {
|
||||||
|
size = CGSizeMake(ASCeilPixelValue(size.width), ASCeilPixelValue(size.height));
|
||||||
|
}
|
||||||
|
l->_size = size;
|
||||||
|
|
||||||
if (CGPointIsNull(position) == NO) {
|
if (CGPointIsNull(position) == NO) {
|
||||||
l->_position = CGPointMake(ASCeilPixelValue(position.x), ASCeilPixelValue(position.y));
|
l->_position = CGPointMake(ASCeilPixelValue(position.x), ASCeilPixelValue(position.y));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user