Skip to content

Commit

Permalink
Prevent counter values from over/underflowing
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=258730
rdar://111743827

Reviewed by Chris Dumez.

We will ignore the counter-increment() operation if
this would result in overflow/underflow for compatibility
with other vendors (w3c/csswg-drafts#9029).

 * LayoutTests/imported/w3c/web-platform-tests/css/css-lists/counter-reset-increment-overflow-underflow-expected.html: Added.
 * LayoutTests/imported/w3c/web-platform-tests/css/css-lists/counter-reset-increment-overflow-underflow-ref.html: Added.
 * LayoutTests/imported/w3c/web-platform-tests/css/css-lists/counter-reset-increment-overflow-underflow.html: Added.
 * Source/WTF/wtf/CheckedArithmetic.h:
 (WTF::sumIfNoOverflowOrFirstValue):
 * Source/WebCore/rendering/CounterNode.cpp:
 (WebCore::CounterNode::computeCountInParent const):

Canonical link: https://commits.webkit.org/266817@main
  • Loading branch information
vitorroriz committed Aug 11, 2023
1 parent 8aeeea8 commit a3717f0
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE HTML>
<link rel="author" title="Vitor Roriz" href="https://github.com/vitorroriz">
<link rel="help" href="https://drafts.csswg.org/css-lists-3/#auto-numbering">
<div>
<h3>2050000000</h3>
<h3>2100000000</h3>
<h3>2100000000</h3>
</div>
<div>
<h3>-2050000000</h3>
<h3>-2100000000</h3>
<h3>-2100000000</h3>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE HTML>
<link rel="author" title="Vitor Roriz" href="https://github.com/vitorroriz">
<link rel="help" href="https://drafts.csswg.org/css-lists-3/#auto-numbering">
<div>
<h3>2050000000</h3>
<h3>2100000000</h3>
<h3>2100000000</h3>
</div>
<div>
<h3>-2050000000</h3>
<h3>-2100000000</h3>
<h3>-2100000000</h3>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<!DOCTYPE HTML>
<link rel="author" title="Vitor Roriz" href="https://github.com/vitorroriz">
<link rel="help" href="https://drafts.csswg.org/css-lists-3/#auto-numbering">
<link rel="match" href="counter-reset-increment-overflow-underflow-ref.html">
<style>
.overflow {
counter-reset: over-counter 2000000000;
}
.overflow h3:before {
counter-increment: over-counter 50000000;
}
.overflow h3::before {
content: counter(over-counter);
}

.underflow {
counter-reset: under-counter -2000000000
}
.underflow h3:before {
counter-increment: under-counter -50000000;
}
.underflow h3::before {
content: counter(under-counter);
}
</style>
<div class="overflow">
<h3></h3>
<h3></h3>
<h3></h3>
</div>
<div class="underflow">
<h3></h3>
<h3></h3>
<h3></h3>
</div>
6 changes: 6 additions & 0 deletions Source/WTF/wtf/CheckedArithmetic.h
Original file line number Diff line number Diff line change
Expand Up @@ -1013,6 +1013,12 @@ template<typename T, typename U> bool differenceOverflows(U left, U right)
return checkedDifference<T>(left, right).hasOverflowed();
}

template<typename T> T sumIfNoOverflowOrFirstValue(T firstValue, T secondValue)
{
auto result = Checked<T, RecordOverflow>(firstValue) + Checked<T, RecordOverflow>(secondValue);
return result.hasOverflowed() ? firstValue : result.value();
}

template<typename T, typename U>
Checked<T, RecordOverflow> checkedProduct(U value)
{
Expand Down
8 changes: 6 additions & 2 deletions Source/WebCore/rendering/CounterNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "RenderElement.h"
#include "RenderView.h"
#include <stdio.h>
#include <wtf/CheckedArithmetic.h>

namespace WebCore {

Expand Down Expand Up @@ -140,10 +141,13 @@ CounterNode* CounterNode::previousInPreOrder() const
int CounterNode::computeCountInParent() const
{
int increment = actsAsReset() ? 0 : m_value;
// In case the sum overflows we need to ignore the operation instead
// of just clamping the result, as per spec resolution.
// See https://github.com/w3c/csswg-drafts/issues/9029
if (m_previousSibling)
return m_previousSibling->m_countInParent + increment;
return WTF::sumIfNoOverflowOrFirstValue(m_previousSibling->m_countInParent, increment);
ASSERT(m_parent->m_firstChild == this);
return m_parent->m_value + increment;
return WTF::sumIfNoOverflowOrFirstValue(m_parent->m_value, increment);
}

void CounterNode::addRenderer(RenderCounter& renderer)
Expand Down

0 comments on commit a3717f0

Please sign in to comment.