From 3b75b9ef1c1eb58fa4098c5e5f566cc575da0d0e Mon Sep 17 00:00:00 2001 From: Andi Gallo Date: Thu, 27 Jul 2023 00:43:26 +0000 Subject: [PATCH] LibWeb: Avoid division by zero when computing table measures For malformed tables which only have cells with span greater than 1, the content sizes for row and column aren't initialized to non-zero values. Avoid undefined behavior in such cases, which sometimes show up on Wikipedia. --- .../avoid-div-by-zero-in-table-measures.txt | 24 +++++++++++++++++++ .../avoid-div-by-zero-in-table-measures.html | 7 ++++++ .../LibWeb/Layout/TableFormattingContext.cpp | 12 ++++++---- 3 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 Tests/LibWeb/Layout/expected/table/avoid-div-by-zero-in-table-measures.txt create mode 100644 Tests/LibWeb/Layout/input/table/avoid-div-by-zero-in-table-measures.html diff --git a/Tests/LibWeb/Layout/expected/table/avoid-div-by-zero-in-table-measures.txt b/Tests/LibWeb/Layout/expected/table/avoid-div-by-zero-in-table-measures.txt new file mode 100644 index 0000000000..de79fbadc9 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/table/avoid-div-by-zero-in-table-measures.txt @@ -0,0 +1,24 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x600 [BFC] children: not-inline + BlockContainer at (8,8) content-size 784x23.46875 children: not-inline + TableWrapper <(anonymous)> at (8,8) content-size 6x23.46875 [BFC] children: not-inline + Box at (8,8) content-size 6x23.46875 table-box [TFC] children: not-inline + BlockContainer <(anonymous)> (not painted) children: inline + TextNode <#text> + Box at (8,8) content-size 0x19.46875 table-row-group children: not-inline + BlockContainer <(anonymous)> (not painted) children: inline + TextNode <#text> + Box at (10,10) content-size 0x19.46875 table-row children: not-inline + BlockContainer <(anonymous)> (not painted) children: inline + TextNode <#text> + BlockContainer
at (11,11) content-size 0x17.46875 table-cell [BFC] children: inline + line 0 width: 14.265625, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 0, length: 1, rect: [11,11 14.265625x17.46875] + "A" + TextNode <#text> + BlockContainer <(anonymous)> (not painted) children: inline + TextNode <#text> + BlockContainer <(anonymous)> (not painted) children: inline + TextNode <#text> + BlockContainer <(anonymous)> (not painted) children: inline + TextNode <#text> diff --git a/Tests/LibWeb/Layout/input/table/avoid-div-by-zero-in-table-measures.html b/Tests/LibWeb/Layout/input/table/avoid-div-by-zero-in-table-measures.html new file mode 100644 index 0000000000..5eb115e602 --- /dev/null +++ b/Tests/LibWeb/Layout/input/table/avoid-div-by-zero-in-table-measures.html @@ -0,0 +1,7 @@ + + + + + + +
A
\ No newline at end of file diff --git a/Userland/Libraries/LibWeb/Layout/TableFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/TableFormattingContext.cpp index d948085b76..ac47709536 100644 --- a/Userland/Libraries/LibWeb/Layout/TableFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/TableFormattingContext.cpp @@ -495,8 +495,10 @@ void TableFormattingContext::compute_table_measures() // the product of: // - the ratio of the max-content size based on cells of span up to N-1 of the column to the baseline max-content size // - the outer min-content size of the cell minus the baseline max-content size and baseline border spacing, or 0 if this is negative - cell_min_contribution += (rows_or_columns[rc_index].max_size / static_cast(baseline_max_content_size)) - * max(CSSPixels(0), cell_min_size(cell) - baseline_max_content_size - baseline_border_spacing); + if (baseline_max_content_size != 0) { + cell_min_contribution += (rows_or_columns[rc_index].max_size / static_cast(baseline_max_content_size)) + * max(CSSPixels(0), cell_min_size(cell) - baseline_max_content_size - baseline_border_spacing); + } // The contribution of the cell is the sum of: // the max-content size of the column based on cells of span up to N-1 @@ -504,8 +506,10 @@ void TableFormattingContext::compute_table_measures() // and the product of: // - the ratio of the max-content size based on cells of span up to N-1 of the column to the baseline max-content size // - the outer max-content size of the cell minus the baseline max-content size and the baseline border spacing, or 0 if this is negative - cell_max_contribution += (rows_or_columns[rc_index].max_size / static_cast(baseline_max_content_size)) - * max(CSSPixels(0), cell_max_size(cell) - baseline_max_content_size - baseline_border_spacing); + if (baseline_max_content_size != 0) { + cell_max_contribution += (rows_or_columns[rc_index].max_size / static_cast(baseline_max_content_size)) + * max(CSSPixels(0), cell_max_size(cell) - baseline_max_content_size - baseline_border_spacing); + } cell_min_contributions_by_rc_index[rc_index].append(cell_min_contribution); cell_max_contributions_by_rc_index[rc_index].append(cell_max_contribution); }