From aee512007878e1ca051590bbcd7578a3b7fb7429 Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Tue, 20 Feb 2024 21:50:48 +0100 Subject: [PATCH] LibWeb: Fix infinite recursion when grid has "max-width: max-content" With this change "max-width: max-content" is treated as "none" when the available width is also "max-content". This fix prevents a stack overflow in the grid track size maximization algorithm by avoiding recursive calls to calculate_max_width() when determining the maximum grid container size. --- .../grid/container-max-width-max-content.txt | 14 +++++++++++ .../grid/container-max-width-max-content.html | 14 +++++++++++ .../LibWeb/Layout/FormattingContext.cpp | 2 ++ .../LibWeb/Layout/GridFormattingContext.cpp | 23 +++++++++++-------- 4 files changed, 43 insertions(+), 10 deletions(-) create mode 100644 Tests/LibWeb/Layout/expected/grid/container-max-width-max-content.txt create mode 100644 Tests/LibWeb/Layout/input/grid/container-max-width-max-content.html diff --git a/Tests/LibWeb/Layout/expected/grid/container-max-width-max-content.txt b/Tests/LibWeb/Layout/expected/grid/container-max-width-max-content.txt new file mode 100644 index 0000000000..2fceffb3f7 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/grid/container-max-width-max-content.txt @@ -0,0 +1,14 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x116 [BFC] children: not-inline + BlockContainer at (8,8) content-size 784x100 children: not-inline + Box at (8,8) content-size 100x100 [GFC] children: not-inline + BlockContainer at (8,8) content-size 100x100 [BFC] children: not-inline + BlockContainer <(anonymous)> at (8,108) content-size 784x0 children: inline + TextNode <#text> + +ViewportPaintable (Viewport<#document>) [0,0 800x600] + PaintableWithLines (BlockContainer) [0,0 800x116] + PaintableWithLines (BlockContainer) [8,8 784x100] + PaintableBox (Box
.grid) [8,8 100x100] + PaintableWithLines (BlockContainer
.item) [8,8 100x100] + PaintableWithLines (BlockContainer(anonymous)) [8,108 784x0] diff --git a/Tests/LibWeb/Layout/input/grid/container-max-width-max-content.html b/Tests/LibWeb/Layout/input/grid/container-max-width-max-content.html new file mode 100644 index 0000000000..4265af963a --- /dev/null +++ b/Tests/LibWeb/Layout/input/grid/container-max-width-max-content.html @@ -0,0 +1,14 @@ + + +
diff --git a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp index 4e8eccf0dd..77438e81f4 100644 --- a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp @@ -1857,6 +1857,8 @@ bool FormattingContext::should_treat_max_width_as_none(Box const& box, Available auto const& max_width = box.computed_values().max_width(); if (max_width.is_none()) return true; + if (available_width.is_max_content() && max_width.is_max_content()) + return true; if (box.is_absolutely_positioned()) return false; if (max_width.contains_percentage()) { diff --git a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp index 81f523d268..5f39fa0033 100644 --- a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp @@ -1197,16 +1197,19 @@ void GridFormattingContext::maximize_tracks(GridDimension const dimension) return should_treat_max_width_as_none(grid_container(), available_size); return !computed_values.max_height().is_auto(); }(); - auto maximum_size = calculate_grid_container_maximum_size(dimension); - if (!should_treat_grid_container_maximum_size_as_none && grid_container_inner_size > maximum_size) { - for (size_t i = 0; i < tracks.size(); i++) - tracks[i].base_size = saved_base_sizes[i]; - auto available_space_with_max_width = *m_available_space; - if (dimension == GridDimension::Column) - available_space_with_max_width.width = AvailableSize::make_definite(maximum_size); - else - available_space_with_max_width.height = AvailableSize::make_definite(maximum_size); - maximize_tracks_using_available_size(available_space_with_max_width, dimension); + + if (!should_treat_grid_container_maximum_size_as_none) { + auto maximum_size = calculate_grid_container_maximum_size(dimension); + if (grid_container_inner_size > maximum_size) { + for (size_t i = 0; i < tracks.size(); i++) + tracks[i].base_size = saved_base_sizes[i]; + auto available_space_with_max_width = *m_available_space; + if (dimension == GridDimension::Column) + available_space_with_max_width.width = AvailableSize::make_definite(maximum_size); + else + available_space_with_max_width.height = AvailableSize::make_definite(maximum_size); + maximize_tracks_using_available_size(available_space_with_max_width, dimension); + } } }