From 8ca5b56e3af7342d201919c3cc250fe707775d88 Mon Sep 17 00:00:00 2001 From: roytam1 Date: Sun, 23 Mar 2025 13:03:53 +0800 Subject: [PATCH] ported from UXP: Issue #2713 - Check for NaN before std::min/max() in DOMQuad and DOMRect. (f1c456c6) --- dom/base/DOMQuad.cpp | 10 +++++----- dom/base/DOMRect.h | 10 +++++----- mfbt/FloatingPoint.h | 25 +++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 10 deletions(-) diff --git a/dom/base/DOMQuad.cpp b/dom/base/DOMQuad.cpp index c8499e1a5..d7945c5e2 100644 --- a/dom/base/DOMQuad.cpp +++ b/dom/base/DOMQuad.cpp @@ -10,7 +10,7 @@ #include "mozilla/dom/DOMPoint.h" #include "mozilla/dom/DOMRect.h" #include "mozilla/dom/DOMRectBinding.h" -#include +#include "mozilla/FloatingPoint.h" using namespace mozilla; using namespace mozilla::dom; @@ -108,8 +108,8 @@ DOMQuad::GetHorizontalMinMax(double* aX1, double* aX2) const x1 = x2 = Point(0)->X(); for (uint32_t i = 1; i < 4; ++i) { double x = Point(i)->X(); - x1 = std::min(x1, x); - x2 = std::max(x2, x); + x1 = NaNSafeMin(x1, x); + x2 = NaNSafeMax(x2, x); } *aX1 = x1; *aX2 = x2; @@ -122,8 +122,8 @@ DOMQuad::GetVerticalMinMax(double* aY1, double* aY2) const y1 = y2 = Point(0)->Y(); for (uint32_t i = 1; i < 4; ++i) { double y = Point(i)->Y(); - y1 = std::min(y1, y); - y2 = std::max(y2, y); + y1 = NaNSafeMin(y1, y); + y2 = NaNSafeMax(y2, y); } *aY1 = y1; *aY2 = y2; diff --git a/dom/base/DOMRect.h b/dom/base/DOMRect.h index 912271f34..d5b9ca10c 100644 --- a/dom/base/DOMRect.h +++ b/dom/base/DOMRect.h @@ -17,7 +17,7 @@ #include "mozilla/Attributes.h" #include "mozilla/dom/BindingDeclarations.h" #include "mozilla/ErrorResult.h" -#include +#include "mozilla/FloatingPoint.h" struct nsRect; @@ -80,22 +80,22 @@ public: double Left() const { double x = X(), w = Width(); - return std::min(x, x + w); + return NaNSafeMin(x, x + w); } double Top() const { double y = Y(), h = Height(); - return std::min(y, y + h); + return NaNSafeMin(y, y + h); } double Right() const { double x = X(), w = Width(); - return std::max(x, x + w); + return NaNSafeMax(x, x + w); } double Bottom() const { double y = Y(), h = Height(); - return std::max(y, y + h); + return NaNSafeMax(y, y + h); } bool WriteStructuredClone(JSStructuredCloneWriter* aWriter) const; diff --git a/mfbt/FloatingPoint.h b/mfbt/FloatingPoint.h index e37dba4ac..04b5c3502 100644 --- a/mfbt/FloatingPoint.h +++ b/mfbt/FloatingPoint.h @@ -15,6 +15,7 @@ #include "mozilla/MathAlgorithms.h" #include "mozilla/Types.h" +#include #include namespace mozilla { @@ -451,6 +452,30 @@ EqualOrBothNaN(T aValue1, T aValue2) return aValue1 == aValue2; } +/** + * Return NaN if either |aValue1| or |aValue2| is NaN, or the minimum of + * |aValue1| and |aValue2| otherwise. + */ +template +static inline T NaNSafeMin(T aValue1, T aValue2) { + if (IsNaN(aValue1) || IsNaN(aValue2)) { + return UnspecifiedNaN(); + } + return std::min(aValue1, aValue2); +} + +/** + * Return NaN if either |aValue1| or |aValue2| is NaN, or the maximum of + * |aValue1| and |aValue2| otherwise. + */ +template +static inline T NaNSafeMax(T aValue1, T aValue2) { + if (IsNaN(aValue1) || IsNaN(aValue2)) { + return UnspecifiedNaN(); + } + return std::max(aValue1, aValue2); +} + namespace detail { template