From 04a7740de89965a7e1e1548e23b6f2a02fb36dad Mon Sep 17 00:00:00 2001 From: Frank Wang Date: Mon, 17 Jun 2024 08:48:03 -0700 Subject: [PATCH] Restrict the maximum number of layout passes in MDCAlertController to 10. PiperOrigin-RevId: 644022588 --- components/Dialogs/src/MDCAlertController.m | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/components/Dialogs/src/MDCAlertController.m b/components/Dialogs/src/MDCAlertController.m index 314284ad731..6dc47b86bc3 100644 --- a/components/Dialogs/src/MDCAlertController.m +++ b/components/Dialogs/src/MDCAlertController.m @@ -34,6 +34,8 @@ NS_ASSUME_NONNULL_BEGIN +const int MAX_LAYOUT_PASSES = 10; + // The Bundle for string resources. static NSString *const kMaterialDialogsBundle = @"MaterialDialogs.bundle"; @@ -105,6 +107,13 @@ @interface MDCAlertController () @property(nonatomic, nonnull, strong) MDCAlertActionManager *actionManager; @property(nonatomic, nullable, strong) UIView *titleIconView; +/** + This counter caps the maximum number of layout passes that can be done in a single layout cycle. + + This variable is added as a direct fix for b/345505157. + */ +@property(nonatomic) int layoutPassCounter; + - (nonnull instancetype)initWithTitle:(nullable NSString *)title message:(nullable NSString *)message; @@ -173,6 +182,7 @@ - (nonnull instancetype)initWithTitle:(nullable NSString *)title { if (self) { _transitionController = [[MDCDialogTransitionController alloc] init]; + _layoutPassCounter = 0; _alertTitle = [title copy]; _titleAlignment = NSTextAlignmentNatural; _messageAlignment = NSTextAlignmentNatural; @@ -726,6 +736,12 @@ - (void)viewDidDisappear:(BOOL)animated { } - (void)viewDidLayoutSubviews { + // Increments the counter to account for an additional layout pass. + self.layoutPassCounter += 1; + // Abort if the layout pass counter is too high. + if (self.layoutPassCounter > MAX_LAYOUT_PASSES) { + return; + } // Recalculate preferredContentSize and potentially the view frame. BOOL boundsSizeChanged = !CGSizeEqualToSize(CGRectStandardize(self.view.bounds).size, _previousLayoutSize); @@ -752,6 +768,8 @@ - (void)viewDidLayoutSubviews { - (void)viewWillLayoutSubviews { [super viewWillLayoutSubviews]; + // Resets counter as this function is called at the beginning of a new layout cycle. + self.layoutPassCounter = 0; // Recalculate preferredSize, which is based on width available, if the viewSize has changed. if (CGRectGetWidth(self.view.bounds) != _previousLayoutSize.width ||