High firefox Logic Error 🔧 Commit mapped

Overview

High
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
Impacthigh
DescriptionIncorrect boundary conditions in the Graphics: Canvas2D component
ComponentGraphics
Bug ClassLogic Error
Tracker2016351
Fix commit68f3b4322ab6 (firefox) +50/-15
CISA KEVNot listed
CreditedSajeeb Lohani
Disclosed2026-03-24

Changed Functions

FunctionChangeNotes
switch
gfx/2d/FilterNodeSoftware.cpp
modified

Files Changed

  • gfx/2d/FilterNodeSoftware.cpp
  • gfx/2d/FilterNodeSoftware.h
diff --git a/gfx/2d/FilterNodeSoftware.cpp b/gfx/2d/FilterNodeSoftware.cpp
index 0130e7853b1..1d4a61cf49a 100644
--- a/gfx/2d/FilterNodeSoftware.cpp
+++ b/gfx/2d/FilterNodeSoftware.cpp
@@ -3313,7 +3313,8 @@ static inline Point3D Normalized(const Point3D& vec) {
 template <typename LightType, typename LightingType>
 FilterNodeLightingSoftware<LightType, LightingType>::FilterNodeLightingSoftware(
     const char* aTypeName)
-    : mSurfaceScale(0)
+    : mSurfaceScale(0),
+      mKernelUnitLength(1.0f, 1.0f)
 #if defined(MOZILLA_INTERNAL_API) && defined(NS_BUILD_REFCNT_LOGGING)
       ,
       mTypeName(aTypeName)
@@ -3366,6 +3367,23 @@ void FilterNodeLightingSoftware<LightType, LightingType>::SetAttribute(
   switch (aIndex) {
     case ATT_LIGHTING_KERNEL_UNIT_LENGTH:
       mKernelUnitLength = aKernelUnitLength;
+      // Spec for fe*Lighting:
+      // The first number is the <dx> value. The second number is the <dy>
+      // value. If the <dy> value is not specified, it defaults to the same
+      // value as <dx>. If kernelUnitLength is not specified, the dx and dy
+      // values should represent very small deltas relative to a given (x,y)
+      // position, which might be implemented in some cases as one pixel in the
+      // intermediate image offscreen bitmap, which is a pixel-based coordinate
+      // system, and thus potentially not scalable. If a negative or zero value
+      // is specified the default value will be used instead.
+      if (mKernelUnitLength.width <= 0.0f ||
+          !std::isfinite(mKernelUnitLength.width)) {
+        mKernelUnitLength.width = 1.0f;
+      }
+      if (mKernelUnitLength.height <= 0.0f ||
+          !std::isfinite(mKernelUnitLength.height)) {
+        mKernelUnitLength.height = mKernelUnitLength.width;
+      }
       break;
     default:
       MOZ_CRASH("GFX: FilterNodeLightingSoftware::SetAttribute size");
@@ -3522,22 +3540,33 @@ FilterNodeLightingSoftware<LightType, LightingType>::Render(
   return DoRender(aRect, mKernelUnitLength.width, mKernelUnitLength.height);
 }
 
+template <typename LightType, typename LightingType>
+MarginDouble FilterNodeLightingSoftware<
+    LightType, LightingType>::GetInflateSourceMargin() const {
+  double kulX = ceil(double(mKernelUnitLength.width));
+  double kulY = ceil(double(mKernelUnitLength.height));
+  return MarginDouble(kulY, kulX, kulY, kulX);
+}
+
+template <typename LightType, typename LightingType>
+IntRect FilterNodeLightingSoftware<LightType, LightingType>::InflatedSourceRect(
+    const IntRect& aDestRect) {
+  RectDouble srcRect(aDestRect);
+  srcRect.Inflate(GetInflateSourceMargin());
+  return RectIsInt32Safe(srcRect) ? TruncatedToInt(srcRect) : aDestRect;
+}
+
 template <typename LightType, typename LightingType>
 void FilterNodeLightingSoftware<
     LightType, LightingType>::RequestFromInputsForRect(const IntRect& aRect) {
-  IntRect srcRect = aRect;
-  srcRect.Inflate(ceil(mKernelUnitLength.width),
-                  ceil(mKernelUnitLength.height));
-  RequestInputRect(IN_LIGHTING_IN, srcRect);
+  RequestInputRect(IN_LIGHTING_IN, InflatedSourceRect(aRect));
 }
 
 template <typename LightType, typename LightingType>
 IntRect FilterNodeLightingSoftware<LightType, LightingType>::MapRectToSource(
     const IntRect& aRect, const IntRect& aMax, FilterNode* aSourceNode) {
-  IntRect srcRect = aRect;
-  srcRect.Inflate(ceil(mKernelUnitLength.width),
-                  ceil(mKernelUnitLength.height));
-  return MapInputRectToSource(IN_LIGHTING_IN, srcRect, aMax, aSourceNode);
+  return MapInputRectToSource(IN_LIGHTING_IN, InflatedSourceRect(aRect), aMax,
+                              aSourceNode);
 }
 
 template <typename LightType, typename LightingType>
@@ -3551,14 +3580,17 @@ FilterNodeLightingSoftware<LightType, LightingType>::DoRender(
   MOZ_ASSERT(aKernelUnitLengthY > 0,
              "aKernelUnitLengthY can be a negative or zero value");
 
-  IntRect srcRect = aRect;
-  IntSize size = aRect.Size();
-  srcRect.Inflate(ceil(float(aKernelUnitLengthX)),
-                  ceil(float(aKernelUnitLengthY)));
-
+  RectDouble srcRectD(aRect);
+  srcRectD.Inflate(GetInflateSourceMargin());
   // Inflate the source rect by another pixel because the bilinear filtering in
   // ColorComponentAtPoint may want to access the margins.
-  srcRect.Inflate(1);
+  srcRectD.Inflate(1);
+  if (!RectIsInt32Safe(srcRectD)) {
+    return nullptr;
+  }
+  IntRect srcRect = TruncatedToInt(srcRectD);
+
+  IntSize size = aRect.Size();
 
   IntRect srcRectInRenderRect = srcRect.Intersect(mRenderRect);
 
diff --git a/gfx/2d/FilterNodeSoftware.h b/gfx/2d/FilterNodeSoftware.h
index 280320bd148..6c655d74ae3 100644
--- a/gfx/2d/FilterNodeSoftware.h
+++ b/gfx/2d/FilterNodeSoftware.h
@@ -766,6 +766,9 @@ class FilterNodeLightingSoftware : public FilterNodeSoftware {
                                                CoordType aKernelUnitLengthX,
                                                CoordType aKernelUnitLengthY);
 
+  MarginDouble GetInflateSourceMargin() const;
+  IntRect InflatedSourceRect(const IntRect& aDestRect);
+
   LightType mLight;
   LightingType mLighting;
   Float mSurfaceScale;
Loading diff…