Dear LTS Team,

Several flaws caused by C++ undefined behaviour in the rlottie package that I
maintain were reported as CVEs. rLottie is a platform-independent library for
rendering vector-based animations and art. Its format is used by Telegram
Desktop, the only reverse dependency in Debian.

I uploaded the fixes to these issues into unstable almost month ago.
Afterwards, I prepared the updates to trixie and bookworm. And now I propose to
apply the fixes to bullseye, the current LTS. Along with the fixes I have
backported other patches from newer releases that improve overall stability.

I pushed the changes to Salsa and, when CI built the package [1], tested it in
Debian 11.11 booted from Live ISO image in VirtualBox. No visual glitches were
seen on animated stickers in Telegram Desktop 4.6.5 from bullseye-backports.

You will find the complete debdiff attached to this email. Though, I think it
is difficult to read disparate patches from the debian/ folder, so I am also
attaching the difference in the upstream source tree with all patches applied.

 [1]: 
https://salsa.debian.org/debian/rlottie/-/jobs/9923623/artifacts/browse/debian/output/
diffstat for rlottie-0.1+dfsg rlottie-0.1+dfsg

 changelog                                                    |   27 +++
 patches/Atomic-render.patch                                  |   46 +++++
 patches/Avoid-assertion-failures.patch                       |   46 +++++
 patches/Check-buffer-length.patch                            |    8 
 patches/Check-empty-frames.patch                             |   16 +
 patches/Empty-animation-data.patch                           |   27 +++
 patches/Finite-loop-in-VBezier-tAtLength.patch               |   31 +++
 patches/Fix-crash-on-invalid-data.patch                      |   12 -
 patches/Fix-heap-buffer-overflow-from-short-truncation.patch |   31 +++
 patches/Fixed-signed-shift-issue.patch                       |   64 +++++++
 patches/Fixed-vpath-potential-issue.patch                    |   29 +++
 patches/Fortify-FreeType-raster.patch                        |   84 +++++++++
 patches/Freetype-raster.patch                                |   56 ------
 patches/Ignore-unspecified-type.patch                        |   19 ++
 patches/Init-keyframe.patch                                  |   18 ++
 patches/Limit-recursion-in-LOTLayerItem.patch                |   39 ++++
 patches/No-cyclic-structures.patch                           |   97 +++++++++++
 patches/No-deadlock.patch                                    |   15 +
 patches/Positive-points.patch                                |   20 ++
 patches/Reject-reversed-frames.patch                         |   19 ++
 patches/Stop-VBezier-length-overflow.patch                   |   65 +++++++
 patches/Zero-corrupt-point.patch                             |   19 --
 patches/series                                               |   19 +-
 23 files changed, 715 insertions(+), 92 deletions(-)

diff -Nru rlottie-0.1+dfsg/debian/changelog rlottie-0.1+dfsg/debian/changelog
--- rlottie-0.1+dfsg/debian/changelog	2026-02-08 12:05:10.000000000 +0300
+++ rlottie-0.1+dfsg/debian/changelog	2026-07-07 16:48:09.000000000 +0300
@@ -1,3 +1,30 @@
+rlottie (0.1+dfsg-2+deb11u2) bullseye-security; urgency=medium
+
+  * Apply fixes and improve stability.
+  * Backported patches:
+    - Atomic-render.patch
+    - Avoid-assertion-failures.patch (closes: #1138916, fixes: CVE-2026-8916)
+    - Check-empty-frames.patch
+    - Finite-loop-in-VBezier-tAtLength.patch
+    - Fix-heap-buffer-overflow-from-short-truncation.patch
+    - Fixed-signed-shift-issue.patch (closes: #1139179, fixes: CVE-2026-10305)
+    - Fixed-vpath-potential-issue.patch (closes: #1138919, fixes: CVE-2026-47319)
+    - Ignore-unspecified-type.patch
+    - Init-keyframe.patch
+    - Limit-recursion-in-LOTLayerItem.patch (closes: #1138920, fixes: CVE-2026-47320)
+    - No-cyclic-structures.patch (closes: #1138917, fixes: CVE-2026-47306)
+    - No-deadlock.patch
+    - Positive-points.patch
+    - Reject-reversed-frames.patch
+    - Stop-VBezier-length-overflow.patch
+  * Amended patches:
+    - Check-buffer-length.patch
+    - Fortify-FreeType-raster.patch (closes: #1138918, fixes: CVE-2026-47318)
+  * Replace Zero-corrupt-point.patch with Empty-animation-data.patch based on
+    Subhransu Mohanty's commit (closes: #994614).
+
+ -- Nicholas Guriev <[email protected]>  Tue, 07 Jul 2026 16:48:09 +0300
+
 rlottie (0.1+dfsg-2+deb11u1) bullseye-security; urgency=high
 
   * Non-maintainer upload by the LTS Team.
diff -Nru rlottie-0.1+dfsg/debian/patches/Atomic-render.patch rlottie-0.1+dfsg/debian/patches/Atomic-render.patch
--- rlottie-0.1+dfsg/debian/patches/Atomic-render.patch	1970-01-01 03:00:00.000000000 +0300
+++ rlottie-0.1+dfsg/debian/patches/Atomic-render.patch	2026-07-07 15:10:19.000000000 +0300
@@ -0,0 +1,46 @@
+Description: Make the render() method really atomic
+ Value of the mRenderInProgress flag should be checked and updated in a single
+ operation or its atomic characteristics will not work.
+Author: Nicholas Guriev <[email protected]>
+Last-Update: Sat, 10 Sep 2022 18:41:59 +0300
+
+--- a/src/lottie/lottieanimation.cpp
++++ b/src/lottie/lottieanimation.cpp
+@@ -74,7 +74,7 @@ private:
+     std::shared_ptr<LOTModel>    mModel;
+     std::unique_ptr<LOTCompItem> mCompItem;
+     SharedRenderTask             mTask;
+-    std::atomic<bool>            mRenderInProgress;
++    std::atomic_flag             mRenderInProgress;
+ };
+ 
+ void AnimationImpl::setValue(const std::string &keypath, LOTVariant &&value)
+@@ -104,17 +104,15 @@ bool AnimationImpl::update(size_t frameN
+ 
+ Surface AnimationImpl::render(size_t frameNo, const Surface &surface, bool keepAspectRatio)
+ {
+-    bool renderInProgress = mRenderInProgress.load();
+-    if (renderInProgress) {
++    if (mRenderInProgress.test_and_set()) {
+         vCritical << "Already Rendering Scheduled for this Animation";
+         return surface;
+     }
+ 
+-    mRenderInProgress.store(true);
+     update(frameNo,
+            VSize(int(surface.drawRegionWidth()), int(surface.drawRegionHeight())), keepAspectRatio);
+     mCompItem->render(surface);
+-    mRenderInProgress.store(false);
++    mRenderInProgress.clear();
+ 
+     return surface;
+ }
+@@ -123,7 +121,7 @@ void AnimationImpl::init(const std::shar
+ {
+     mModel = model;
+     mCompItem = std::make_unique<LOTCompItem>(mModel.get());
+-    mRenderInProgress = false;
++    mRenderInProgress.clear();
+ }
+ 
+ #ifdef LOTTIE_THREAD_SUPPORT
diff -Nru rlottie-0.1+dfsg/debian/patches/Avoid-assertion-failures.patch rlottie-0.1+dfsg/debian/patches/Avoid-assertion-failures.patch
--- rlottie-0.1+dfsg/debian/patches/Avoid-assertion-failures.patch	1970-01-01 03:00:00.000000000 +0300
+++ rlottie-0.1+dfsg/debian/patches/Avoid-assertion-failures.patch	2026-07-07 15:09:36.000000000 +0300
@@ -0,0 +1,46 @@
+Description: Touch up some incorrect values that result to assertion violations
+Author: Nicholas Guriev <[email protected]>
+Last-Modified: Fri, 04 Mar 2022 18:11:48 +0300
+
+--- a/src/lottie/lottiemodel.h
++++ b/src/lottie/lottiemodel.h
+@@ -1025,16 +1025,16 @@ public:
+     LOTTrimData::TrimType type() const {return mTrimType;}
+ private:
+     Segment noloop(float start, float end) const{
+-        assert(start >= 0);
+-        assert(end >= 0);
++        if (!(start >= 0)) start = 0;
++        if (!(end >= 0)) end = 0;
+         Segment s;
+         s.start = std::min(start, end);
+         s.end = std::max(start, end);
+         return s;
+     }
+     Segment loop(float start, float end) const{
+-        assert(start >= 0);
+-        assert(end >= 0);
++        if (!(start >= 0)) start = 0;
++        if (!(end >= 0)) end = 0;
+         Segment s;
+         s.start = std::max(start, end);
+         s.end = std::min(start, end);
+--- a/src/vector/freetype/v_ft_stroker.cpp
++++ b/src/vector/freetype/v_ft_stroker.cpp
+@@ -18,6 +18,7 @@
+ 
+ #include "v_ft_stroker.h"
+ #include <assert.h>
++#include <limits.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include "v_ft_math.h"
+@@ -631,6 +632,8 @@ Fail:
+ static void ft_stroke_border_export(SW_FT_StrokeBorder border,
+                                     SW_FT_Outline*     outline)
+ {
++    if ((ulong)outline->n_points + border->num_points > SHRT_MAX) return;
++
+     /* copy point locations */
+     memcpy(outline->points + outline->n_points, border->points,
+            border->num_points * sizeof(SW_FT_Vector));
diff -Nru rlottie-0.1+dfsg/debian/patches/Check-buffer-length.patch rlottie-0.1+dfsg/debian/patches/Check-buffer-length.patch
--- rlottie-0.1+dfsg/debian/patches/Check-buffer-length.patch	2021-05-22 19:07:06.000000000 +0300
+++ rlottie-0.1+dfsg/debian/patches/Check-buffer-length.patch	2026-07-07 15:08:38.000000000 +0300
@@ -19,7 +19,7 @@
      while (count--) {
          int    x = spans->x + offsetX;
          int    l = spans->len;
-+        if (x > bufferLen || l > bufferLen || x + l > bufferLen) {
++        if (x < 0 || x + l > bufferLen) {
 +            return;
 +        }
          uchar *ptr = buffer + x;
@@ -36,7 +36,7 @@
      while (count--) {
          int    x = spans->x + offsetX;
          int    l = spans->len;
-+        if (x > bufferLen || l > bufferLen || x + l > bufferLen) {
++        if (x < 0 || x + l > bufferLen) {
 +            return;
 +        }
          uchar *ptr = buffer + x;
@@ -52,7 +52,7 @@
      while (count--) {
          int    x = spans->x + offsetX;
          int    l = spans->len;
-+        if (x > bufferLen || l > bufferLen || x + l > bufferLen) {
++        if (x < 0 || x + l > bufferLen) {
 +            return;
 +        }
          uchar *ptr = buffer + x;
@@ -68,7 +68,7 @@
      while (count--) {
          int    x = spans->x + offsetX;
          int    l = spans->len;
-+        if (x > bufferLen || l > bufferLen || x + l > bufferLen || x + l < 0) {
++        if (x < 0 || x + l > bufferLen) {
 +            return;
 +        }
          uchar *ptr = buffer + x;
diff -Nru rlottie-0.1+dfsg/debian/patches/Check-empty-frames.patch rlottie-0.1+dfsg/debian/patches/Check-empty-frames.patch
--- rlottie-0.1+dfsg/debian/patches/Check-empty-frames.patch	1970-01-01 03:00:00.000000000 +0300
+++ rlottie-0.1+dfsg/debian/patches/Check-empty-frames.patch	2026-07-07 15:08:38.000000000 +0300
@@ -0,0 +1,16 @@
+Description: Check that animation has frames before accessing
+Bug: https://github.com/Samsung/rlottie/issues/522
+Origin: https://github.com/Samsung/rlottie/pull/523/commits/7446363b482978746bd6e7b5dbc4f49553f9f50f
+Author: Nicholas Guriev <[email protected]>
+Last-Update: Wed, 02 Mar 2022 19:12:30 +0300
+
+--- a/src/lottie/lottiemodel.h
++++ b/src/lottie/lottiemodel.h
+@@ -380,6 +380,7 @@ public:
+             value().toPath(path);
+         } else {
+             const auto &vec = animation().mKeyFrames;
++            if (vec.empty()) return;
+             if (vec.front().mStartFrame >= frameNo)
+                 return vec.front().mValue.mStartValue.toPath(path);
+             if(vec.back().mEndFrame <= frameNo)
diff -Nru rlottie-0.1+dfsg/debian/patches/Empty-animation-data.patch rlottie-0.1+dfsg/debian/patches/Empty-animation-data.patch
--- rlottie-0.1+dfsg/debian/patches/Empty-animation-data.patch	1970-01-01 03:00:00.000000000 +0300
+++ rlottie-0.1+dfsg/debian/patches/Empty-animation-data.patch	2026-07-07 15:07:10.000000000 +0300
@@ -0,0 +1,27 @@
+Subject: Fix crash when path animation data is empty
+From: Subhransu Mohanty <[email protected]>
+Date: Mon, 25 Jan 2021 10:47:25 +0900
+Bug: https://github.com/Samsung/rlottie/issues/460
+Bug-Debian: https://bugs.debian.org/974095
+Bug-Debian: https://bugs.debian.org/994614
+Origin: https://github.com/Samsung/rlottie/commit/1cb2021d6883ebe41c17e710fc90a225f038cb51
+Last-Update: Sat, 27 Nov 2021 16:41:51 +0300
+
+---
+ src/lottie/lottiemodel.h | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/src/lottie/lottiemodel.h
++++ b/src/lottie/lottiemodel.h
+@@ -124,6 +124,11 @@ public:
+     static void lerp(const LottieShapeData& start, const LottieShapeData& end, float t, VPath& result)
+     {
+         result.reset();
++        // test for empty animation data.
++        if (start.mPoints.empty() || end.mPoints.empty())
++        {
++            return;
++        }
+         auto size = std::min(start.mPoints.size(), end.mPoints.size());
+         /* reserve exact memory requirement at once
+          * ptSize = size + 1(size + close)
diff -Nru rlottie-0.1+dfsg/debian/patches/Finite-loop-in-VBezier-tAtLength.patch rlottie-0.1+dfsg/debian/patches/Finite-loop-in-VBezier-tAtLength.patch
--- rlottie-0.1+dfsg/debian/patches/Finite-loop-in-VBezier-tAtLength.patch	1970-01-01 03:00:00.000000000 +0300
+++ rlottie-0.1+dfsg/debian/patches/Finite-loop-in-VBezier-tAtLength.patch	2026-07-07 15:07:41.000000000 +0300
@@ -0,0 +1,31 @@
+Description: Finite loop in VBezier::tAtLength()
+Origin: https://github.com/Samsung/rlottie/commit/625bc4c48a2d5d45661fd56202f8a1af78b01195
+Forwarded: https://github.com/Samsung/rlottie/pull/483
+Author: Nicholas Guriev <[email protected]>
+Last-Update: Wed, 16 Feb 2022 23:14:47 +0300
+
+--- a/src/vector/vbezier.cpp
++++ b/src/vector/vbezier.cpp
+@@ -85,12 +85,12 @@ float VBezier::tAtLength(float l) const
+     t *= 0.5;
+ 
+     float lastBigger = 1.0;
+-    while (1) {
++    for (int num = 0; num < 100500; num++) {
+         VBezier right = *this;
+         VBezier left;
+         right.parameterSplitLeft(t, &left);
+         float lLen = left.length();
+-        if (fabs(lLen - l) < error) break;
++        if (fabs(lLen - l) < error) return t;
+ 
+         if (lLen < l) {
+             t += (lastBigger - t) * 0.5f;
+@@ -99,6 +99,7 @@ float VBezier::tAtLength(float l) const
+             t -= t * 0.5f;
+         }
+     }
++    vWarning << "no convergence";
+     return t;
+ }
+ 
diff -Nru rlottie-0.1+dfsg/debian/patches/Fix-crash-on-invalid-data.patch rlottie-0.1+dfsg/debian/patches/Fix-crash-on-invalid-data.patch
--- rlottie-0.1+dfsg/debian/patches/Fix-crash-on-invalid-data.patch	2021-05-22 19:07:06.000000000 +0300
+++ rlottie-0.1+dfsg/debian/patches/Fix-crash-on-invalid-data.patch	2026-07-07 15:16:09.000000000 +0300
@@ -52,17 +52,7 @@
  void LOTGradient::update(std::unique_ptr<VGradient> &grad, int frameNo)
 --- a/src/vector/vdrawhelper.cpp
 +++ b/src/vector/vdrawhelper.cpp
-@@ -146,6 +146,9 @@ bool VGradientCache::generateGradientCol
-                                                 float                 opacity,
-                                                 uint32_t *colorTable, int size)
- {
-+    if (stops.empty()) {
-+        return false;
-+    }
-     int                  dist, idist, pos = 0;
-     size_t i;
-     bool                 alpha = false;
-@@ -165,7 +168,7 @@ bool VGradientCache::generateGradientCol
+@@ -165,7 +165,7 @@ bool VGradientCache::generateGradientCol
  
      colorTable[pos++] = curColor;
  
diff -Nru rlottie-0.1+dfsg/debian/patches/Fixed-signed-shift-issue.patch rlottie-0.1+dfsg/debian/patches/Fixed-signed-shift-issue.patch
--- rlottie-0.1+dfsg/debian/patches/Fixed-signed-shift-issue.patch	1970-01-01 03:00:00.000000000 +0300
+++ rlottie-0.1+dfsg/debian/patches/Fixed-signed-shift-issue.patch	2026-07-07 15:16:09.000000000 +0300
@@ -0,0 +1,64 @@
+Description: Fixed signed shift issue, CVE-2026-10305
+Author: Michal Szczecinski <[email protected]>
+Origin: https://github.com/Samsung/rlottie/commit/b4f5101a4d1a8da60cc14cfd05608551b3448c77
+Forwarded: https://github.com/Samsung/rlottie/pull/587
+Bug-Debian: https://bugs.debian.org/1139179
+Acked-By: Nicholas Guriev <[email protected]>
+Last-Update: Tue, 09 Jun 2026 16:16:06 +0300
+
+--- a/src/vector/freetype/v_ft_raster.cpp
++++ b/src/vector/freetype/v_ft_raster.cpp
+@@ -198,17 +198,17 @@ typedef struct SW_FT_Outline_Funcs_ {
+ #define ONE_PIXEL (1L << PIXEL_BITS)
+ #define PIXEL_MASK (-1L << PIXEL_BITS)
+ #define TRUNC(x) ((TCoord)((x) >> PIXEL_BITS))
+-#define SUBPIXELS(x) ((TPos)(x) << PIXEL_BITS)
++#define SUBPIXELS(x) ((TPos)((unsigned long)(x) << PIXEL_BITS))
+ #define FLOOR(x) ((x) & -ONE_PIXEL)
+ #define CEILING(x) (((x) + ONE_PIXEL - 1) & -ONE_PIXEL)
+ #define ROUND(x) (((x) + ONE_PIXEL / 2) & -ONE_PIXEL)
+ 
+ #if PIXEL_BITS >= 6
+-#define UPSCALE(x) ((x) << (PIXEL_BITS - 6))
++#define UPSCALE(x)   ((TPos)((unsigned long)(x) << (PIXEL_BITS - 6)))
+ #define DOWNSCALE(x) ((x) >> (PIXEL_BITS - 6))
+ #else
+-#define UPSCALE(x) ((x) >> (6 - PIXEL_BITS))
+-#define DOWNSCALE(x) ((x) << (6 - PIXEL_BITS))
++#define UPSCALE(x)   ((x) >> (6 - PIXEL_BITS))
++#define DOWNSCALE(x) ((TPos)((unsigned long)(x) << (6 - PIXEL_BITS)))
+ #endif
+ 
+ /* Compute `dividend / divisor' and return both its quotient and     */
+@@ -1072,7 +1072,7 @@ static int SW_FT_Outline_Decompose(const
+                                    void*                      user)
+ {
+ #undef SCALED
+-#define SCALED(x) (((x) << shift) - delta)
++#define SCALED(x) ((TPos)((unsigned long)(x) << shift) - delta)
+ 
+     SW_FT_Vector v_last;
+     SW_FT_Vector v_control;
+--- a/src/vector/vdrawhelper.cpp
++++ b/src/vector/vdrawhelper.cpp
+@@ -156,6 +156,11 @@ bool VGradientCache::generateGradientCol
+ 
+     if (!vCompare(opacity, 1.0f)) alpha = true;
+ 
++    if (stopCount == 0) {
++        for (int j = 0; j < size; ++j) colorTable[j] = 0;
++        return alpha;
++    }
++
+     start = stops.data();
+     curr = start;
+     if (!curr->second.isOpaque()) alpha = true;
+@@ -171,7 +176,7 @@ bool VGradientCache::generateGradientCol
+         fpos += incr;
+     }
+ 
+-    for (i = 0; i < stopCount - 1; ++i) {
++    for (i = 0; i + 1 < stopCount; ++i) {
+         curr = (start + i);
+         next = (start + i + 1);
+         delta = 1 / (next->first - curr->first);
diff -Nru rlottie-0.1+dfsg/debian/patches/Fixed-vpath-potential-issue.patch rlottie-0.1+dfsg/debian/patches/Fixed-vpath-potential-issue.patch
--- rlottie-0.1+dfsg/debian/patches/Fixed-vpath-potential-issue.patch	1970-01-01 03:00:00.000000000 +0300
+++ rlottie-0.1+dfsg/debian/patches/Fixed-vpath-potential-issue.patch	2026-07-07 15:16:04.000000000 +0300
@@ -0,0 +1,29 @@
+Description: Fix potential huge memory allocation in VPath
+ Fixes CVE-2026-47319
+Author: Michal Szczecinski <[email protected]>
+Origin: https://github.com/Samsung/rlottie/commit/5def9f402b1cb5b09f52655e414f0afba4ffd959
+Forwarded: https://github.com/Samsung/rlottie/pull/588
+Bug-Debian: https://bugs.debian.org/1138919
+Acked-By: Nicholas Guriev <[email protected]>
+Last-Update: Tue, 09 Jun 2026 16:16:04 +0300
+
+--- a/src/vector/vpath.cpp
++++ b/src/vector/vpath.cpp
+@@ -514,6 +514,8 @@ void VPath::VPathData::addPolystar(float
+                                    float outerRoundness, float startAngle,
+                                    float cx, float cy, VPath::Direction dir)
+ {
++    constexpr float    MAX_POLY_POINTS = 1024.0f;
++    if (points > MAX_POLY_POINTS) points = MAX_POLY_POINTS;
+     const static float POLYSTAR_MAGIC_NUMBER = 0.47829f / 0.28f;
+     float              currentAngle = (startAngle - 90.0f) * K_PI / 180.0f;
+     float              x;
+@@ -619,6 +621,8 @@ void VPath::VPathData::addPolygon(float
+                                   VPath::Direction dir)
+ {
+     // TODO: Need to support floating point number for number of points
++    constexpr float    MAX_POLY_POINTS = 1024.0f;
++    if (points > MAX_POLY_POINTS) points = MAX_POLY_POINTS;
+     const static float POLYGON_MAGIC_NUMBER = 0.25;
+     float              currentAngle = (startAngle - 90.0f) * K_PI / 180.0f;
+     float              x;
diff -Nru rlottie-0.1+dfsg/debian/patches/Fix-heap-buffer-overflow-from-short-truncation.patch rlottie-0.1+dfsg/debian/patches/Fix-heap-buffer-overflow-from-short-truncation.patch
--- rlottie-0.1+dfsg/debian/patches/Fix-heap-buffer-overflow-from-short-truncation.patch	1970-01-01 03:00:00.000000000 +0300
+++ rlottie-0.1+dfsg/debian/patches/Fix-heap-buffer-overflow-from-short-truncation.patch	2026-07-07 15:16:09.000000000 +0300
@@ -0,0 +1,31 @@
+Description: Fix heap buffer overflow from short truncation of span Y coordinate
+ SW_FT_Span.y is a 16-bit short, so limit our coordinates appropriately.  The
+ clamp (and its "is an integer" comment) was inherited from upstream FreeType's
+ ftgrays.c, where FT_Span has no y field and the scanline y is carried
+ separately as an int. rLottie added a `short y` to the span struct without
+ adapting the clamp, so the INT_MAX bound never prevented the (short) narrowing
+ at the store site.
+ .
+ This patch based on Michal Maciola's pull request with the numeral literals
+ replaced by the standard macro from the <limits.h> header.
+Forwarded: https://github.com/Samsung/rlottie/pull/595
+Author: Michal Maciola <[email protected]>
+Acked-By: Nicholas Guriev <[email protected]>
+Last-Updated: Thu, 02 Jul 2026 07:55:03 +0300
+
+--- a/src/vector/freetype/v_ft_raster.cpp
++++ b/src/vector/freetype/v_ft_raster.cpp
+@@ -935,10 +935,10 @@ static void gray_hline(RAS_ARG_ TCoord x
+     x += (TCoord)ras.min_ex;
+ 
+     /* SW_FT_Span.x is a 16-bit short, so limit our coordinates appropriately */
+-    if (x >= 32767) x = 32767;
++    if (x >= SHRT_MAX) x = SHRT_MAX;
+ 
+-    /* SW_FT_Span.y is an integer, so limit our coordinates appropriately */
+-    if (y >= SW_FT_INT_MAX) y = SW_FT_INT_MAX;
++    /* SW_FT_Span.y is a 16-bit short, so limit our coordinates appropriately */
++    if (y >= SHRT_MAX) y = SHRT_MAX;
+ 
+     if (coverage) {
+         SW_FT_Span* span;
diff -Nru rlottie-0.1+dfsg/debian/patches/Fortify-FreeType-raster.patch rlottie-0.1+dfsg/debian/patches/Fortify-FreeType-raster.patch
--- rlottie-0.1+dfsg/debian/patches/Fortify-FreeType-raster.patch	1970-01-01 03:00:00.000000000 +0300
+++ rlottie-0.1+dfsg/debian/patches/Fortify-FreeType-raster.patch	2026-07-07 15:13:24.000000000 +0300
@@ -0,0 +1,84 @@
+Description: Verify array length before writing in Freetype
+ An attempt to fix CVE-2021-31321 based on John Preston's commit.
+ https://github.com/desktop-app/rlottie/commit/d369d84e868352886cee48eecb60b462f6dfe067
+ .
+ Also check the number of ycells in gray_find_cell().
+Author: Nicholas Guriev <[email protected]>
+Last-Update: Thu, 23 Apr 2026 13:06:37 +0300
+
+--- a/src/vector/freetype/v_ft_raster.cpp
++++ b/src/vector/freetype/v_ft_raster.cpp
+@@ -67,6 +67,17 @@
+     }                   \
+     while (0)
+ 
++#include <iterator>
++#if 201103L <= __cplusplus && __cplusplus < 201703L
++namespace std {
++
++// Taken from https://stackoverflow.com/a/18078435/5000805
++template<class T, size_t N>
++constexpr size_t size(T (&)[N]) { return N; }
++
++}
++#endif
++
+ #include <limits.h>
+ #include <setjmp.h>
+ #include <stddef.h>
+@@ -360,6 +371,7 @@ static void gray_init_cells(RAS_ARG_ voi
+     ras.buffer_size = byte_size;
+ 
+     ras.ycells = (PCell*)buffer;
++    ras.ycount = byte_size / sizeof(PCell);
+     ras.cells = NULL;
+     ras.max_cells = 0;
+     ras.num_cells = 0;
+@@ -421,6 +433,7 @@ static PCell gray_find_cell(RAS_ARG)
+     TPos   x = ras.ex;
+ 
+     if (x > ras.count_ex) x = ras.count_ex;
++    if (ras.ey < 0 || ras.ey >= ras.ycount) ft_longjmp(ras.jump_buffer, 1);
+ 
+     pcell = &ras.ycells[ras.ey];
+     for (;;) {
+@@ -707,6 +720,9 @@ static void gray_render_conic(RAS_ARG_ c
+             gray_split_conic(arc);
+             arc += 2;
+             top++;
++
++            if (top >= static_cast<int>(std::size(ras.lev_stack))) return;
++
+             levels[top] = levels[top - 1] = level - 1;
+             continue;
+         }
+@@ -833,6 +849,8 @@ static void gray_render_cubic(RAS_ARG_ c
+         }
+ 
+     Split:
++        if (arc + 6 >= std::end(ras.bez_stack)) return;
++
+         gray_split_cubic(arc);
+         arc += 3;
+         continue;
+@@ -840,9 +858,8 @@ static void gray_render_cubic(RAS_ARG_ c
+     Draw:
+         gray_render_line(RAS_VAR_ arc[0].x, arc[0].y);
+ 
+-        if (arc == ras.bez_stack) return;
+-
+         arc -= 3;
++        if (arc < std::begin(ras.bez_stack)) return;
+     }
+ }
+ 
+@@ -1378,7 +1395,9 @@ static int gray_raster_render(gray_PRast
+     SW_FT_UNUSED(raster);
+     const SW_FT_Outline* outline = (const SW_FT_Outline*)params->source;
+ 
++#ifndef SW_FT_STATIC_RASTER
+     gray_TWorker worker[1];
++#endif
+ 
+     TCell buffer[SW_FT_RENDER_POOL_SIZE / sizeof(TCell)];
+     long  buffer_size = sizeof(buffer);
diff -Nru rlottie-0.1+dfsg/debian/patches/Freetype-raster.patch rlottie-0.1+dfsg/debian/patches/Freetype-raster.patch
--- rlottie-0.1+dfsg/debian/patches/Freetype-raster.patch	2021-05-29 11:13:17.000000000 +0300
+++ rlottie-0.1+dfsg/debian/patches/Freetype-raster.patch	1970-01-01 03:00:00.000000000 +0300
@@ -1,56 +0,0 @@
-Description: Verify array length before writing in Freetype
- An attempt to fix CVE-2021-31321 based on John Preston's commit.
- https://github.com/desktop-app/rlottie/commit/d369d84e868352886cee48eecb60b462f6dfe067
-Author: Nicholas Guriev <[email protected]>
-Last-Update: Sat, 22 May 2021 19:07:06 +0300
-
---- a/src/vector/freetype/v_ft_raster.cpp
-+++ b/src/vector/freetype/v_ft_raster.cpp
-@@ -67,6 +67,17 @@
-     }                   \
-     while (0)
- 
-+#include <iterator>
-+#if 201103L <= __cplusplus && __cplusplus < 201703L
-+namespace std {
-+
-+// Taken from https://stackoverflow.com/a/18078435/5000805
-+template<class T, size_t N>
-+constexpr size_t size(T (&)[N]) { return N; }
-+
-+}
-+#endif
-+
- #include <limits.h>
- #include <setjmp.h>
- #include <stddef.h>
-@@ -707,6 +718,9 @@ static void gray_render_conic(RAS_ARG_ c
-             gray_split_conic(arc);
-             arc += 2;
-             top++;
-+
-+            if (top >= static_cast<int>(std::size(ras.lev_stack))) return;
-+
-             levels[top] = levels[top - 1] = level - 1;
-             continue;
-         }
-@@ -835,6 +849,9 @@ static void gray_render_cubic(RAS_ARG_ c
-     Split:
-         gray_split_cubic(arc);
-         arc += 3;
-+
-+        if (arc + 4 > std::end(ras.bez_stack)) return;
-+
-         continue;
- 
-     Draw:
-@@ -1378,7 +1395,9 @@ static int gray_raster_render(gray_PRast
-     SW_FT_UNUSED(raster);
-     const SW_FT_Outline* outline = (const SW_FT_Outline*)params->source;
- 
-+#ifndef SW_FT_STATIC_RASTER
-     gray_TWorker worker[1];
-+#endif
- 
-     TCell buffer[SW_FT_RENDER_POOL_SIZE / sizeof(TCell)];
-     long  buffer_size = sizeof(buffer);
diff -Nru rlottie-0.1+dfsg/debian/patches/Ignore-unspecified-type.patch rlottie-0.1+dfsg/debian/patches/Ignore-unspecified-type.patch
--- rlottie-0.1+dfsg/debian/patches/Ignore-unspecified-type.patch	1970-01-01 03:00:00.000000000 +0300
+++ rlottie-0.1+dfsg/debian/patches/Ignore-unspecified-type.patch	2026-07-07 15:07:41.000000000 +0300
@@ -0,0 +1,19 @@
+Description: Ignore animations with objects of unspecified type
+Origin: https://github.com/Samsung/rlottie/commit/d1636c7b47481e69d4100f3bff2a7a3be7680286
+Forwarded: https://github.com/Samsung/rlottie/pull/515
+Author: Nicholas Guriev <[email protected]>
+Last-Update: Wed, 16 Feb 2022 23:14:47 +0300
+
+--- a/src/lottie/lottieparser.cpp
++++ b/src/lottie/lottieparser.cpp
+@@ -1140,6 +1140,10 @@ LOTData* LottieParserImpl::parseObjectTy
+ {
+     RAPIDJSON_ASSERT(PeekType() == kStringType);
+     const char *type = GetString();
++    if (!type) {
++        vWarning << "No object type specified";
++        return nullptr;
++    }
+     if (0 == strcmp(type, "gr")) {
+         return parseGroupObject();
+     } else if (0 == strcmp(type, "rc")) {
diff -Nru rlottie-0.1+dfsg/debian/patches/Init-keyframe.patch rlottie-0.1+dfsg/debian/patches/Init-keyframe.patch
--- rlottie-0.1+dfsg/debian/patches/Init-keyframe.patch	1970-01-01 03:00:00.000000000 +0300
+++ rlottie-0.1+dfsg/debian/patches/Init-keyframe.patch	2026-07-07 15:08:38.000000000 +0300
@@ -0,0 +1,18 @@
+Description: Do default initialization of key frame values
+Bug: https://github.com/Samsung/rlottie/issues/522
+Author: Nicholas Guriev <[email protected]>
+Last-Update: Wed, 02 Mar 2022 19:12:30 +0300
+
+--- a/src/lottie/lottiemodel.h
++++ b/src/lottie/lottiemodel.h
+@@ -178,8 +178,8 @@ inline T lerp(const T& start, const T& e
+ template <typename T>
+ struct LOTKeyFrameValue
+ {
+-    T mStartValue;
+-    T mEndValue;
++    T mStartValue{};
++    T mEndValue{};
+     T value(float t) const {
+         return lerp(mStartValue, mEndValue, t);
+     }
diff -Nru rlottie-0.1+dfsg/debian/patches/Limit-recursion-in-LOTLayerItem.patch rlottie-0.1+dfsg/debian/patches/Limit-recursion-in-LOTLayerItem.patch
--- rlottie-0.1+dfsg/debian/patches/Limit-recursion-in-LOTLayerItem.patch	1970-01-01 03:00:00.000000000 +0300
+++ rlottie-0.1+dfsg/debian/patches/Limit-recursion-in-LOTLayerItem.patch	2026-07-07 15:16:09.000000000 +0300
@@ -0,0 +1,39 @@
+Description: Limit recurion depth in LOTLayerItem
+ This patch is based on Michal Szczecinski's commit and adapted to version 0.1
+ before Lottie model refactoring. Should fix CVE-2026-47320.
+ .
+ https://github.com/Samsung/rlottie/commit/bf689b72b8482c5ea674235854bd11b6d1b42588
+Author: Nicholas Guriev <[email protected]>
+Forwarded: not-needed
+Bug-Debian: https://bugs.debian.org/1138920
+Last-Update: Tue, 09 Jun 2026 16:16:05 +0300
+
+--- a/src/lottie/lottieitem.cpp
++++ b/src/lottie/lottieitem.cpp
+@@ -419,8 +419,13 @@ void LOTLayerItem::update(int frameNumbe
+ 
+ VMatrix LOTLayerItem::matrix(int frameNo) const
+ {
+-    return mParentLayer
+-               ? (mLayerData->matrix(frameNo) * mParentLayer->matrix(frameNo))
++    return matrix(frameNo, 0);
++}
++
++VMatrix LOTLayerItem::matrix(int frameNo, int depth) const
++{
++    return mParentLayer && depth < 64
++               ? mLayerData->matrix(frameNo) * mParentLayer->matrix(frameNo, depth + 1)
+                : mLayerData->matrix(frameNo);
+ }
+ 
+--- a/src/lottie/lottieitem.h
++++ b/src/lottie/lottieitem.h
+@@ -180,6 +180,8 @@ protected:
+    float opacity(int frameNo) const {return mLayerData->opacity(frameNo);}
+    inline DirtyFlag flag() const {return mDirtyFlag;}
+    bool skipRendering() const {return (!visible() || vIsZero(combinedAlpha()));}
++private:
++   VMatrix matrix(int frameNo, int depth) const;
+ protected:
+    std::unique_ptr<LOTLayerMaskItem>           mLayerMask;
+    LOTLayerData                               *mLayerData{nullptr};
diff -Nru rlottie-0.1+dfsg/debian/patches/No-cyclic-structures.patch rlottie-0.1+dfsg/debian/patches/No-cyclic-structures.patch
--- rlottie-0.1+dfsg/debian/patches/No-cyclic-structures.patch	1970-01-01 03:00:00.000000000 +0300
+++ rlottie-0.1+dfsg/debian/patches/No-cyclic-structures.patch	2026-07-07 15:10:19.000000000 +0300
@@ -0,0 +1,97 @@
+Description: Deal with cyclic structures, avoid stack overflow in Lottie model
+Bug: https://github.com/Samsung/rlottie/issues/522
+Author: Nicholas Guriev <[email protected]>
+Last-Update: Sat, 10 Sep 2022 18:26:32 +0300
+
+--- a/src/lottie/lottiemodel.cpp
++++ b/src/lottie/lottiemodel.cpp
+@@ -19,10 +19,26 @@
+ #include "lottiemodel.h"
+ #include <cassert>
+ #include <iterator>
++#include <set>
+ #include <stack>
+ #include "vimageloader.h"
+ #include "vline.h"
+ 
++bool LOTData::includes(const LOTData *pointer) const {
++    if (this == pointer) {
++        return true;
++    }
++    if (type() != Type::ShapeGroup && type() != Type::Layer) {
++        return false;
++    }
++    for (LOTData *child : static_cast<const LOTGroupData *>(this)->mChildren) {
++        if (child->includes(pointer)) {
++            return true;
++        }
++    }
++    return false;
++}
++
+ /*
+  * We process the iterator objects in the children list
+  * by iterating from back to front. when we find a repeater object
+@@ -73,6 +89,8 @@ public:
+ 
+     void visit(LOTData *obj)
+     {
++        if (!mVisited.insert(obj).second) return;
++
+         switch (obj->type()) {
+         case LOTData::Type::ShapeGroup:
+         case LOTData::Type::Layer: {
+@@ -83,6 +101,9 @@ public:
+             break;
+         }
+     }
++
++private:
++    std::set<LOTData*> mVisited;
+ };
+ 
+ class LottieUpdateStatVisitor {
+@@ -120,6 +141,8 @@ public:
+     }
+     void visit(LOTData *obj)
+     {
++        if (!mVisited.insert(obj).second) return;
++
+         switch (obj->type()) {
+         case LOTData::Type::Layer: {
+             visitLayer(static_cast<LOTLayerData *>(obj));
+@@ -138,6 +161,8 @@ public:
+         }
+     }
+ 
++private:
++    std::set<LOTData*> mVisited;
+ };
+ 
+ void LOTCompositionData::processRepeaterObjects()
+--- a/src/lottie/lottiemodel.h
++++ b/src/lottie/lottiemodel.h
+@@ -460,6 +460,7 @@ public:
+         }
+     }
+     const char* name() const {return shortString() ? mData._buffer : mPtr;}
++    bool includes(const LOTData *) const;
+ private:
+     static constexpr unsigned char maxShortStringLength = 14;
+     void setShortString(bool value) {mData._shortString = value;}
+--- a/src/lottie/lottieparser.cpp
++++ b/src/lottie/lottieparser.cpp
+@@ -608,7 +608,12 @@ void LottieParserImpl::resolveLayerRefs(
+             if (layer->mLayerType == LayerType::Image) {
+                 layer->extra()->mAsset = search->second;
+             } else if (layer->mLayerType == LayerType::Precomp) {
+-                layer->mChildren = search->second->mLayers;
++                layer->mChildren.clear();
++                layer->mChildren.reserve(search->second->mLayers.size());
++                for (LOTData *candidate : search->second->mLayers) {
++                    if (candidate->includes(layer)) continue;
++                    layer->mChildren.push_back(candidate);
++                }
+                 layer->setStatic(layer->isStatic() &&
+                                  search->second->isStatic());
+             }
diff -Nru rlottie-0.1+dfsg/debian/patches/No-deadlock.patch rlottie-0.1+dfsg/debian/patches/No-deadlock.patch
--- rlottie-0.1+dfsg/debian/patches/No-deadlock.patch	1970-01-01 03:00:00.000000000 +0300
+++ rlottie-0.1+dfsg/debian/patches/No-deadlock.patch	2026-07-07 15:10:17.000000000 +0300
@@ -0,0 +1,15 @@
+Description: Realize a lock at any end of VRleTask
+Forwarded: https://github.com/Samsung/rlottie/pull/523/commits/0b7d6354c3f76848d87fac4a15e12c7b3401a17f
+Author: Nicholas Guriev <[email protected]>
+Last-Update: Sun, 29 May 2022 14:24:41 +0300
+
+--- a/src/vector/vraster.cpp
++++ b/src/vector/vraster.cpp
+@@ -370,6 +370,7 @@ struct VRleTask {
+     {
+         if (mPath.points().size() > SHRT_MAX ||
+             mPath.points().size() + mPath.segments() > SHRT_MAX) {
++            mRle.notify();
+             return;
+         }
+ 
diff -Nru rlottie-0.1+dfsg/debian/patches/Positive-points.patch rlottie-0.1+dfsg/debian/patches/Positive-points.patch
--- rlottie-0.1+dfsg/debian/patches/Positive-points.patch	1970-01-01 03:00:00.000000000 +0300
+++ rlottie-0.1+dfsg/debian/patches/Positive-points.patch	2026-07-07 15:08:38.000000000 +0300
@@ -0,0 +1,20 @@
+Description: Points counter must be positive
+Bug: https://github.com/Samsung/rlottie/issues/522
+Origin: https://github.com/Samsung/rlottie/pull/523/commits/19fc8e9c2804ccfba5bee3eb18bc952a87684490
+Author: Nicholas Guriev <[email protected]>
+Last-Update: Wed, 02 Mar 2022 19:12:30 +0300
+
+--- a/src/lottie/lottieitem.cpp
++++ b/src/lottie/lottieitem.cpp
+@@ -1151,6 +1151,11 @@ void LOTPolystarItem::updatePath(VPath &
+     path.reset();
+     VMatrix m;
+ 
++    if (!(points > 0)) {
++        vWarning << "The number of path points is below zero or NaN at all";
++        return;
++    }
++
+     if (mData->mPolyType == LOTPolystarData::PolyType::Star) {
+         path.addPolystar(points, innerRadius, outerRadius, innerRoundness,
+                          outerRoundness, 0.0, 0.0, 0.0, mData->direction());
diff -Nru rlottie-0.1+dfsg/debian/patches/Reject-reversed-frames.patch rlottie-0.1+dfsg/debian/patches/Reject-reversed-frames.patch
--- rlottie-0.1+dfsg/debian/patches/Reject-reversed-frames.patch	1970-01-01 03:00:00.000000000 +0300
+++ rlottie-0.1+dfsg/debian/patches/Reject-reversed-frames.patch	2026-07-07 15:07:41.000000000 +0300
@@ -0,0 +1,19 @@
+Description: Reject reversed frames
+Origin: https://github.com/Samsung/rlottie/commit/327fb7dbaad225555d5ca567b9adee9ce5f879f4
+Forwarded: https://github.com/Samsung/rlottie/pull/483
+Author: Nicholas Guriev <[email protected]>
+Last-Update: Wed, 16 Feb 2022 23:14:47 +0300
+
+--- a/src/lottie/lottieparser.cpp
++++ b/src/lottie/lottieparser.cpp
+@@ -661,6 +661,10 @@ void LottieParserImpl::parseComposition(
+         // don't have a valid bodymovin header
+         return;
+     }
++    if (comp->mStartFrame > comp->mEndFrame) {
++        // reversed animation? missing data?
++        return;
++    }
+     if (!IsValid()) {
+         return;
+     }
diff -Nru rlottie-0.1+dfsg/debian/patches/series rlottie-0.1+dfsg/debian/patches/series
--- rlottie-0.1+dfsg/debian/patches/series	2025-11-18 21:23:20.000000000 +0300
+++ rlottie-0.1+dfsg/debian/patches/series	2026-07-07 15:16:09.000000000 +0300
@@ -6,11 +6,26 @@
 Check-buffer-length.patch
 Fix-crash-in-malformed-animations.patch
 Fix-crash-on-invalid-data.patch
-Freetype-raster.patch
+Fortify-FreeType-raster.patch
 Fortify-lottie-parser.patch
 Extend-mDash-array.patch
 Include-limits-header.patch
-Zero-corrupt-point.patch
 Avoid-nullptr-in-solidColor.patch
+Empty-animation-data.patch
+Finite-loop-in-VBezier-tAtLength.patch
+Reject-reversed-frames.patch
+Ignore-unspecified-type.patch
+Init-keyframe.patch
+Check-empty-frames.patch
+No-cyclic-structures.patch
+Positive-points.patch
+Stop-VBezier-length-overflow.patch
+Avoid-assertion-failures.patch
+No-deadlock.patch
+Atomic-render.patch
 
 CVE-2025-0634-CVE-2025-53074-CVE-2025-53075.patch
+Fixed-vpath-potential-issue.patch
+Limit-recursion-in-LOTLayerItem.patch
+Fixed-signed-shift-issue.patch
+Fix-heap-buffer-overflow-from-short-truncation.patch
diff -Nru rlottie-0.1+dfsg/debian/patches/Stop-VBezier-length-overflow.patch rlottie-0.1+dfsg/debian/patches/Stop-VBezier-length-overflow.patch
--- rlottie-0.1+dfsg/debian/patches/Stop-VBezier-length-overflow.patch	1970-01-01 03:00:00.000000000 +0300
+++ rlottie-0.1+dfsg/debian/patches/Stop-VBezier-length-overflow.patch	2026-07-07 15:08:38.000000000 +0300
@@ -0,0 +1,65 @@
+Description:  Stop computing Bézier curve length when float overflow occurs after splitting
+Bug: https://github.com/Samsung/rlottie/issues/522
+Origin: https://github.com/Samsung/rlottie/pull/523/commits/f7b72f1ed133882f1d5a75ede5fe6b6fc4cbea1d
+Author: Nicholas Guriev <[email protected]>
+Last-Update: Wed, 02 Mar 2022 19:12:30 +0300
+
+--- a/src/vector/vbezier.cpp
++++ b/src/vector/vbezier.cpp
+@@ -42,7 +42,7 @@ float VBezier::length() const
+     VBezier left, right; /* bez poly splits */
+     float   len = 0.0;   /* arc length */
+     float   chord;       /* chord length */
+-    float   length;
++    float   length = 0;
+ 
+     len = len + VLine::length(x1, y1, x2, y2);
+     len = len + VLine::length(x2, y2, x3, y3);
+@@ -52,9 +52,10 @@ float VBezier::length() const
+ 
+     if ((len - chord) > 0.01) {
+         split(&left, &right);    /* split in two */
+-        length = left.length() + /* try left side */
+-                 right.length(); /* try right side */
+-
++        if (*this != left)
++            length += left.length();  /* try left side */
++        if (*this != right)
++            length += right.length();  /* try right side */
+         return length;
+     }
+ 
+--- a/src/vector/vbezier.h
++++ b/src/vector/vbezier.h
+@@ -19,11 +19,14 @@
+ #ifndef VBEZIER_H
+ #define VBEZIER_H
+ 
++#include <tuple>
+ #include <vpoint.h>
+ 
+ V_BEGIN_NAMESPACE
+ 
+ class VBezier {
++    friend bool operator == (const VBezier &l, const VBezier &r);
++
+ public:
+     VBezier() = default;
+     VPointF     pointAt(float t) const;
+@@ -129,6 +132,16 @@ inline void VBezier::split(VBezier *firs
+     firstHalf->y4 = secondHalf->y1 = (firstHalf->y3 + secondHalf->y2) * 0.5f;
+ }
+ 
++inline bool operator == (const VBezier &l, const VBezier &r)
++{
++    return std::tie(l.x1, l.y1, l.x2, l.y2, l.x3, l.y3, l.x4, l.y4)
++        == std::tie(r.x1, r.y1, r.x2, r.y2, r.x3, r.y3, r.x4, r.y4);
++}
++inline bool operator != (const VBezier &l, const VBezier &r)
++{
++    return !(l == r);
++}
++
+ V_END_NAMESPACE
+ 
+ #endif  // VBEZIER_H
diff -Nru rlottie-0.1+dfsg/debian/patches/Zero-corrupt-point.patch rlottie-0.1+dfsg/debian/patches/Zero-corrupt-point.patch
--- rlottie-0.1+dfsg/debian/patches/Zero-corrupt-point.patch	2021-05-29 11:13:17.000000000 +0300
+++ rlottie-0.1+dfsg/debian/patches/Zero-corrupt-point.patch	1970-01-01 03:00:00.000000000 +0300
@@ -1,19 +0,0 @@
-Description: Put zero point in case of corrupted shape data
- Upstream rlottie at the master branch seems to be not affected by the crash.
- They refactored the corresponding code.
-Bug-Debian: https://bugs.debian.org/974095
-Forwarded: not-needed
-Author: Nicholas Guriev <[email protected]>
-Last-Update: Mon, 24 May 2021 18:09:20 +0300
-
---- a/src/lottie/lottieparser.cpp
-+++ b/src/lottie/lottieparser.cpp
-@@ -1914,7 +1914,7 @@ void LottieParserImpl::getValue(LottieSh
-     if (mInPoint.size() != mOutPoint.size() ||
-         mInPoint.size() != mVertices.size()) {
-         vCritical << "The Shape data are corrupted";
--        points = std::vector<VPointF>();
-+        points.emplace_back();
-     } else {
-         auto size = mVertices.size();
-         points.reserve(3 * size + 4);
diffstat for rlottie_0.1+dfsg-2+deb11u1 rlottie_0.1+dfsg-2+deb11u2

 lottie/lottieanimation.cpp       |   10 ++++------
 lottie/lottieitem.cpp            |   14 ++++++++++++--
 lottie/lottieitem.h              |    2 ++
 lottie/lottiemodel.cpp           |   25 +++++++++++++++++++++++++
 lottie/lottiemodel.h             |   19 +++++++++++++------
 lottie/lottieparser.cpp          |   17 +++++++++++++++--
 vector/freetype/v_ft_raster.cpp  |   26 +++++++++++++-------------
 vector/freetype/v_ft_stroker.cpp |    3 +++
 vector/vbezier.cpp               |   14 ++++++++------
 vector/vbezier.h                 |   13 +++++++++++++
 vector/vdrawhelper.cpp           |   10 ++++++----
 vector/vpath.cpp                 |    4 ++++
 vector/vraster.cpp               |    1 +
 vector/vrle.cpp                  |    8 ++++----
 14 files changed, 123 insertions(+), 43 deletions(-)

diff --unified -r -p -x .git -x .pc -x debian rlottie_0.1+dfsg-2+deb11u1/src/lottie/lottieanimation.cpp rlottie_0.1+dfsg-2+deb11u2/src/lottie/lottieanimation.cpp
--- rlottie_0.1+dfsg-2+deb11u1/src/lottie/lottieanimation.cpp	2026-07-07 16:14:58.510885381 +0300
+++ rlottie_0.1+dfsg-2+deb11u2/src/lottie/lottieanimation.cpp	2026-07-07 16:15:06.111042839 +0300
@@ -74,7 +74,7 @@ private:
     std::shared_ptr<LOTModel>    mModel;
     std::unique_ptr<LOTCompItem> mCompItem;
     SharedRenderTask             mTask;
-    std::atomic<bool>            mRenderInProgress;
+    std::atomic_flag             mRenderInProgress;
 };
 
 void AnimationImpl::setValue(const std::string &keypath, LOTVariant &&value)
@@ -104,17 +104,15 @@ bool AnimationImpl::update(size_t frameN
 
 Surface AnimationImpl::render(size_t frameNo, const Surface &surface, bool keepAspectRatio)
 {
-    bool renderInProgress = mRenderInProgress.load();
-    if (renderInProgress) {
+    if (mRenderInProgress.test_and_set()) {
         vCritical << "Already Rendering Scheduled for this Animation";
         return surface;
     }
 
-    mRenderInProgress.store(true);
     update(frameNo,
            VSize(int(surface.drawRegionWidth()), int(surface.drawRegionHeight())), keepAspectRatio);
     mCompItem->render(surface);
-    mRenderInProgress.store(false);
+    mRenderInProgress.clear();
 
     return surface;
 }
@@ -123,7 +121,7 @@ void AnimationImpl::init(const std::shar
 {
     mModel = model;
     mCompItem = std::make_unique<LOTCompItem>(mModel.get());
-    mRenderInProgress = false;
+    mRenderInProgress.clear();
 }
 
 #ifdef LOTTIE_THREAD_SUPPORT
diff --unified -r -p -x .git -x .pc -x debian rlottie_0.1+dfsg-2+deb11u1/src/lottie/lottieitem.cpp rlottie_0.1+dfsg-2+deb11u2/src/lottie/lottieitem.cpp
--- rlottie_0.1+dfsg-2+deb11u1/src/lottie/lottieitem.cpp	2026-07-07 16:14:58.642888116 +0300
+++ rlottie_0.1+dfsg-2+deb11u2/src/lottie/lottieitem.cpp	2026-07-07 16:15:06.191044497 +0300
@@ -419,8 +419,13 @@ void LOTLayerItem::update(int frameNumbe
 
 VMatrix LOTLayerItem::matrix(int frameNo) const
 {
-    return mParentLayer
-               ? (mLayerData->matrix(frameNo) * mParentLayer->matrix(frameNo))
+    return matrix(frameNo, 0);
+}
+
+VMatrix LOTLayerItem::matrix(int frameNo, int depth) const
+{
+    return mParentLayer && depth < 64
+               ? mLayerData->matrix(frameNo) * mParentLayer->matrix(frameNo, depth + 1)
                : mLayerData->matrix(frameNo);
 }
 
@@ -1137,6 +1142,11 @@ void LOTPolystarItem::updatePath(VPath &
     path.reset();
     VMatrix m;
 
+    if (!(points > 0)) {
+        vWarning << "The number of path points is below zero or NaN at all";
+        return;
+    }
+
     if (mData->mPolyType == LOTPolystarData::PolyType::Star) {
         path.addPolystar(points, innerRadius, outerRadius, innerRoundness,
                          outerRoundness, 0.0, 0.0, 0.0, mData->direction());
diff --unified -r -p -x .git -x .pc -x debian rlottie_0.1+dfsg-2+deb11u1/src/lottie/lottieitem.h rlottie_0.1+dfsg-2+deb11u2/src/lottie/lottieitem.h
--- rlottie_0.1+dfsg-2+deb11u1/src/lottie/lottieitem.h	2026-07-07 16:14:58.562886459 +0300
+++ rlottie_0.1+dfsg-2+deb11u2/src/lottie/lottieitem.h	2026-07-07 16:15:06.191044497 +0300
@@ -180,6 +180,8 @@ protected:
    float opacity(int frameNo) const {return mLayerData->opacity(frameNo);}
    inline DirtyFlag flag() const {return mDirtyFlag;}
    bool skipRendering() const {return (!visible() || vIsZero(combinedAlpha()));}
+private:
+   VMatrix matrix(int frameNo, int depth) const;
 protected:
    std::unique_ptr<LOTLayerMaskItem>           mLayerMask;
    LOTLayerData                               *mLayerData{nullptr};
diff --unified -r -p -x .git -x .pc -x debian rlottie_0.1+dfsg-2+deb11u1/src/lottie/lottiemodel.cpp rlottie_0.1+dfsg-2+deb11u2/src/lottie/lottiemodel.cpp
--- rlottie_0.1+dfsg-2+deb11u1/src/lottie/lottiemodel.cpp	2026-07-07 16:14:58.722889773 +0300
+++ rlottie_0.1+dfsg-2+deb11u2/src/lottie/lottiemodel.cpp	2026-07-07 16:15:05.975040022 +0300
@@ -19,10 +19,26 @@
 #include "lottiemodel.h"
 #include <cassert>
 #include <iterator>
+#include <set>
 #include <stack>
 #include "vimageloader.h"
 #include "vline.h"
 
+bool LOTData::includes(const LOTData *pointer) const {
+    if (this == pointer) {
+        return true;
+    }
+    if (type() != Type::ShapeGroup && type() != Type::Layer) {
+        return false;
+    }
+    for (LOTData *child : static_cast<const LOTGroupData *>(this)->mChildren) {
+        if (child->includes(pointer)) {
+            return true;
+        }
+    }
+    return false;
+}
+
 /*
  * We process the iterator objects in the children list
  * by iterating from back to front. when we find a repeater object
@@ -73,6 +89,8 @@ public:
 
     void visit(LOTData *obj)
     {
+        if (!mVisited.insert(obj).second) return;
+
         switch (obj->type()) {
         case LOTData::Type::ShapeGroup:
         case LOTData::Type::Layer: {
@@ -83,6 +101,9 @@ public:
             break;
         }
     }
+
+private:
+    std::set<LOTData*> mVisited;
 };
 
 class LottieUpdateStatVisitor {
@@ -120,6 +141,8 @@ public:
     }
     void visit(LOTData *obj)
     {
+        if (!mVisited.insert(obj).second) return;
+
         switch (obj->type()) {
         case LOTData::Type::Layer: {
             visitLayer(static_cast<LOTLayerData *>(obj));
@@ -138,6 +161,8 @@ public:
         }
     }
 
+private:
+    std::set<LOTData*> mVisited;
 };
 
 void LOTCompositionData::processRepeaterObjects()
diff --unified -r -p -x .git -x .pc -x debian rlottie_0.1+dfsg-2+deb11u1/src/lottie/lottiemodel.h rlottie_0.1+dfsg-2+deb11u2/src/lottie/lottiemodel.h
--- rlottie_0.1+dfsg-2+deb11u1/src/lottie/lottiemodel.h	2026-07-07 16:14:58.802891431 +0300
+++ rlottie_0.1+dfsg-2+deb11u2/src/lottie/lottiemodel.h	2026-07-07 16:15:06.055041678 +0300
@@ -124,6 +124,11 @@ public:
     static void lerp(const LottieShapeData& start, const LottieShapeData& end, float t, VPath& result)
     {
         result.reset();
+        // test for empty animation data.
+        if (start.mPoints.empty() || end.mPoints.empty())
+        {
+            return;
+        }
         auto size = std::min(start.mPoints.size(), end.mPoints.size());
         /* reserve exact memory requirement at once
          * ptSize = size + 1(size + close)
@@ -173,8 +178,8 @@ inline T lerp(const T& start, const T& e
 template <typename T>
 struct LOTKeyFrameValue
 {
-    T mStartValue;
-    T mEndValue;
+    T mStartValue{};
+    T mEndValue{};
     T value(float t) const {
         return lerp(mStartValue, mEndValue, t);
     }
@@ -375,6 +380,7 @@ public:
             value().toPath(path);
         } else {
             const auto &vec = animation().mKeyFrames;
+            if (vec.empty()) return;
             if (vec.front().mStartFrame >= frameNo)
                 return vec.front().mValue.mStartValue.toPath(path);
             if(vec.back().mEndFrame <= frameNo)
@@ -454,6 +460,7 @@ public:
         }
     }
     const char* name() const {return shortString() ? mData._buffer : mPtr;}
+    bool includes(const LOTData *) const;
 private:
     static constexpr unsigned char maxShortStringLength = 14;
     void setShortString(bool value) {mData._shortString = value;}
@@ -1018,16 +1025,16 @@ public:
     LOTTrimData::TrimType type() const {return mTrimType;}
 private:
     Segment noloop(float start, float end) const{
-        assert(start >= 0);
-        assert(end >= 0);
+        if (!(start >= 0)) start = 0;
+        if (!(end >= 0)) end = 0;
         Segment s;
         s.start = std::min(start, end);
         s.end = std::max(start, end);
         return s;
     }
     Segment loop(float start, float end) const{
-        assert(start >= 0);
-        assert(end >= 0);
+        if (!(start >= 0)) start = 0;
+        if (!(end >= 0)) end = 0;
         Segment s;
         s.start = std::max(start, end);
         s.end = std::min(start, end);
diff --unified -r -p -x .git -x .pc -x debian rlottie_0.1+dfsg-2+deb11u1/src/lottie/lottieparser.cpp rlottie_0.1+dfsg-2+deb11u2/src/lottie/lottieparser.cpp
--- rlottie_0.1+dfsg-2+deb11u1/src/lottie/lottieparser.cpp	2026-07-07 16:14:58.778890934 +0300
+++ rlottie_0.1+dfsg-2+deb11u2/src/lottie/lottieparser.cpp	2026-07-07 16:15:05.975040022 +0300
@@ -608,7 +608,12 @@ void LottieParserImpl::resolveLayerRefs(
             if (layer->mLayerType == LayerType::Image) {
                 layer->extra()->mAsset = search->second;
             } else if (layer->mLayerType == LayerType::Precomp) {
-                layer->mChildren = search->second->mLayers;
+                layer->mChildren.clear();
+                layer->mChildren.reserve(search->second->mLayers.size());
+                for (LOTData *candidate : search->second->mLayers) {
+                    if (candidate->includes(layer)) continue;
+                    layer->mChildren.push_back(candidate);
+                }
                 layer->setStatic(layer->isStatic() &&
                                  search->second->isStatic());
             }
@@ -661,6 +666,10 @@ void LottieParserImpl::parseComposition(
         // don't have a valid bodymovin header
         return;
     }
+    if (comp->mStartFrame > comp->mEndFrame) {
+        // reversed animation? missing data?
+        return;
+    }
     if (!IsValid()) {
         return;
     }
@@ -1136,6 +1145,10 @@ LOTData* LottieParserImpl::parseObjectTy
 {
     RAPIDJSON_ASSERT(PeekType() == kStringType);
     const char *type = GetString();
+    if (!type) {
+        vWarning << "No object type specified";
+        return nullptr;
+    }
     if (0 == strcmp(type, "gr")) {
         return parseGroupObject();
     } else if (0 == strcmp(type, "rc")) {
@@ -1914,7 +1927,7 @@ void LottieParserImpl::getValue(LottieSh
     if (mInPoint.size() != mOutPoint.size() ||
         mInPoint.size() != mVertices.size()) {
         vCritical << "The Shape data are corrupted";
-        points.emplace_back();
+        points = std::vector<VPointF>();
     } else {
         auto size = mVertices.size();
         points.reserve(3 * size + 4);
diff --unified -r -p -x .git -x .pc -x debian rlottie_0.1+dfsg-2+deb11u1/src/vector/freetype/v_ft_raster.cpp rlottie_0.1+dfsg-2+deb11u2/src/vector/freetype/v_ft_raster.cpp
--- rlottie_0.1+dfsg-2+deb11u1/src/vector/freetype/v_ft_raster.cpp	2026-07-07 16:14:58.830892011 +0300
+++ rlottie_0.1+dfsg-2+deb11u2/src/vector/freetype/v_ft_raster.cpp	2026-07-07 16:15:06.243045574 +0300
@@ -198,17 +198,17 @@ typedef struct SW_FT_Outline_Funcs_ {
 #define ONE_PIXEL (1L << PIXEL_BITS)
 #define PIXEL_MASK (-1L << PIXEL_BITS)
 #define TRUNC(x) ((TCoord)((x) >> PIXEL_BITS))
-#define SUBPIXELS(x) ((TPos)(x) << PIXEL_BITS)
+#define SUBPIXELS(x) ((TPos)((unsigned long)(x) << PIXEL_BITS))
 #define FLOOR(x) ((x) & -ONE_PIXEL)
 #define CEILING(x) (((x) + ONE_PIXEL - 1) & -ONE_PIXEL)
 #define ROUND(x) (((x) + ONE_PIXEL / 2) & -ONE_PIXEL)
 
 #if PIXEL_BITS >= 6
-#define UPSCALE(x) ((x) << (PIXEL_BITS - 6))
+#define UPSCALE(x)   ((TPos)((unsigned long)(x) << (PIXEL_BITS - 6)))
 #define DOWNSCALE(x) ((x) >> (PIXEL_BITS - 6))
 #else
-#define UPSCALE(x) ((x) >> (6 - PIXEL_BITS))
-#define DOWNSCALE(x) ((x) << (6 - PIXEL_BITS))
+#define UPSCALE(x)   ((x) >> (6 - PIXEL_BITS))
+#define DOWNSCALE(x) ((TPos)((unsigned long)(x) << (6 - PIXEL_BITS)))
 #endif
 
 /* Compute `dividend / divisor' and return both its quotient and     */
@@ -371,6 +371,7 @@ static void gray_init_cells(RAS_ARG_ voi
     ras.buffer_size = byte_size;
 
     ras.ycells = (PCell*)buffer;
+    ras.ycount = byte_size / sizeof(PCell);
     ras.cells = NULL;
     ras.max_cells = 0;
     ras.num_cells = 0;
@@ -432,6 +433,7 @@ static PCell gray_find_cell(RAS_ARG)
     TPos   x = ras.ex;
 
     if (x > ras.count_ex) x = ras.count_ex;
+    if (ras.ey < 0 || ras.ey >= ras.ycount) ft_longjmp(ras.jump_buffer, 1);
 
     pcell = &ras.ycells[ras.ey];
     for (;;) {
@@ -851,19 +853,17 @@ static void gray_render_cubic(RAS_ARG_ c
         }
 
     Split:
+        if (arc + 6 >= std::end(ras.bez_stack)) return;
+
         gray_split_cubic(arc);
         arc += 3;
-
-        if (arc + 4 > std::end(ras.bez_stack)) return;
-
         continue;
 
     Draw:
         gray_render_line(RAS_VAR_ arc[0].x, arc[0].y);
 
-        if (arc == ras.bez_stack) return;
-
         arc -= 3;
+        if (arc < std::begin(ras.bez_stack)) return;
     }
 }
 
@@ -935,10 +935,10 @@ static void gray_hline(RAS_ARG_ TCoord x
     x += (TCoord)ras.min_ex;
 
     /* SW_FT_Span.x is a 16-bit short, so limit our coordinates appropriately */
-    if (x >= 32767) x = 32767;
+    if (x >= SHRT_MAX) x = SHRT_MAX;
 
-    /* SW_FT_Span.y is an integer, so limit our coordinates appropriately */
-    if (y >= SW_FT_INT_MAX) y = SW_FT_INT_MAX;
+    /* SW_FT_Span.y is a 16-bit short, so limit our coordinates appropriately */
+    if (y >= SHRT_MAX) y = SHRT_MAX;
 
     if (coverage) {
         SW_FT_Span* span;
@@ -1072,7 +1072,7 @@ static int SW_FT_Outline_Decompose(const
                                    void*                      user)
 {
 #undef SCALED
-#define SCALED(x) (((x) << shift) - delta)
+#define SCALED(x) ((TPos)((unsigned long)(x) << shift) - delta)
 
     SW_FT_Vector v_last;
     SW_FT_Vector v_control;
diff --unified -r -p -x .git -x .pc -x debian rlottie_0.1+dfsg-2+deb11u1/src/vector/freetype/v_ft_stroker.cpp rlottie_0.1+dfsg-2+deb11u2/src/vector/freetype/v_ft_stroker.cpp
--- rlottie_0.1+dfsg-2+deb11u1/src/vector/freetype/v_ft_stroker.cpp	2026-07-07 16:14:43.662577759 +0300
+++ rlottie_0.1+dfsg-2+deb11u2/src/vector/freetype/v_ft_stroker.cpp	2026-07-07 16:15:06.059041762 +0300
@@ -18,6 +18,7 @@
 
 #include "v_ft_stroker.h"
 #include <assert.h>
+#include <limits.h>
 #include <stdlib.h>
 #include <string.h>
 #include "v_ft_math.h"
@@ -631,6 +632,8 @@ Fail:
 static void ft_stroke_border_export(SW_FT_StrokeBorder border,
                                     SW_FT_Outline*     outline)
 {
+    if ((ulong)outline->n_points + border->num_points > SHRT_MAX) return;
+
     /* copy point locations */
     memcpy(outline->points + outline->n_points, border->points,
            border->num_points * sizeof(SW_FT_Vector));
diff --unified -r -p -x .git -x .pc -x debian rlottie_0.1+dfsg-2+deb11u1/src/vector/vbezier.cpp rlottie_0.1+dfsg-2+deb11u2/src/vector/vbezier.cpp
--- rlottie_0.1+dfsg-2+deb11u1/src/vector/vbezier.cpp	2026-07-07 16:14:43.666577842 +0300
+++ rlottie_0.1+dfsg-2+deb11u2/src/vector/vbezier.cpp	2026-07-07 16:15:06.031041182 +0300
@@ -42,7 +42,7 @@ float VBezier::length() const
     VBezier left, right; /* bez poly splits */
     float   len = 0.0;   /* arc length */
     float   chord;       /* chord length */
-    float   length;
+    float   length = 0;
 
     len = len + VLine::length(x1, y1, x2, y2);
     len = len + VLine::length(x2, y2, x3, y3);
@@ -52,9 +52,10 @@ float VBezier::length() const
 
     if ((len - chord) > 0.01) {
         split(&left, &right);    /* split in two */
-        length = left.length() + /* try left side */
-                 right.length(); /* try right side */
-
+        if (*this != left)
+            length += left.length();  /* try left side */
+        if (*this != right)
+            length += right.length();  /* try right side */
         return length;
     }
 
@@ -85,12 +86,12 @@ float VBezier::tAtLength(float l) const
     t *= 0.5;
 
     float lastBigger = 1.0;
-    while (1) {
+    for (int num = 0; num < 100500; num++) {
         VBezier right = *this;
         VBezier left;
         right.parameterSplitLeft(t, &left);
         float lLen = left.length();
-        if (fabs(lLen - l) < error) break;
+        if (fabs(lLen - l) < error) return t;
 
         if (lLen < l) {
             t += (lastBigger - t) * 0.5f;
@@ -99,6 +100,7 @@ float VBezier::tAtLength(float l) const
             t -= t * 0.5f;
         }
     }
+    vWarning << "no convergence";
     return t;
 }
 
diff --unified -r -p -x .git -x .pc -x debian rlottie_0.1+dfsg-2+deb11u1/src/vector/vbezier.h rlottie_0.1+dfsg-2+deb11u2/src/vector/vbezier.h
--- rlottie_0.1+dfsg-2+deb11u1/src/vector/vbezier.h	2026-07-07 16:14:43.666577842 +0300
+++ rlottie_0.1+dfsg-2+deb11u2/src/vector/vbezier.h	2026-07-07 16:15:06.031041182 +0300
@@ -19,11 +19,14 @@
 #ifndef VBEZIER_H
 #define VBEZIER_H
 
+#include <tuple>
 #include <vpoint.h>
 
 V_BEGIN_NAMESPACE
 
 class VBezier {
+    friend bool operator == (const VBezier &l, const VBezier &r);
+
 public:
     VBezier() = default;
     VPointF     pointAt(float t) const;
@@ -129,6 +132,16 @@ inline void VBezier::split(VBezier *firs
     firstHalf->y4 = secondHalf->y1 = (firstHalf->y3 + secondHalf->y2) * 0.5f;
 }
 
+inline bool operator == (const VBezier &l, const VBezier &r)
+{
+    return std::tie(l.x1, l.y1, l.x2, l.y2, l.x3, l.y3, l.x4, l.y4)
+        == std::tie(r.x1, r.y1, r.x2, r.y2, r.x3, r.y3, r.x4, r.y4);
+}
+inline bool operator != (const VBezier &l, const VBezier &r)
+{
+    return !(l == r);
+}
+
 V_END_NAMESPACE
 
 #endif  // VBEZIER_H
diff --unified -r -p -x .git -x .pc -x debian rlottie_0.1+dfsg-2+deb11u1/src/vector/vdrawhelper.cpp rlottie_0.1+dfsg-2+deb11u2/src/vector/vdrawhelper.cpp
--- rlottie_0.1+dfsg-2+deb11u1/src/vector/vdrawhelper.cpp	2026-07-07 16:14:58.642888116 +0300
+++ rlottie_0.1+dfsg-2+deb11u2/src/vector/vdrawhelper.cpp	2026-07-07 16:15:06.215044994 +0300
@@ -146,9 +146,6 @@ bool VGradientCache::generateGradientCol
                                                 float                 opacity,
                                                 uint32_t *colorTable, int size)
 {
-    if (stops.empty()) {
-        return false;
-    }
     int                  dist, idist, pos = 0;
     size_t i;
     bool                 alpha = false;
@@ -159,6 +156,11 @@ bool VGradientCache::generateGradientCol
 
     if (!vCompare(opacity, 1.0f)) alpha = true;
 
+    if (stopCount == 0) {
+        for (int j = 0; j < size; ++j) colorTable[j] = 0;
+        return alpha;
+    }
+
     start = stops.data();
     curr = start;
     if (!curr->second.isOpaque()) alpha = true;
@@ -174,7 +176,7 @@ bool VGradientCache::generateGradientCol
         fpos += incr;
     }
 
-    for (i = 0; i < stopCount - 1; ++i) {
+    for (i = 0; i + 1 < stopCount; ++i) {
         curr = (start + i);
         next = (start + i + 1);
         delta = 1 / (next->first - curr->first);
diff --unified -r -p -x .git -x .pc -x debian rlottie_0.1+dfsg-2+deb11u1/src/vector/vpath.cpp rlottie_0.1+dfsg-2+deb11u2/src/vector/vpath.cpp
--- rlottie_0.1+dfsg-2+deb11u1/src/vector/vpath.cpp	2026-07-07 16:14:43.674578008 +0300
+++ rlottie_0.1+dfsg-2+deb11u2/src/vector/vpath.cpp	2026-07-07 16:15:06.163043917 +0300
@@ -514,6 +514,8 @@ void VPath::VPathData::addPolystar(float
                                    float outerRoundness, float startAngle,
                                    float cx, float cy, VPath::Direction dir)
 {
+    constexpr float    MAX_POLY_POINTS = 1024.0f;
+    if (points > MAX_POLY_POINTS) points = MAX_POLY_POINTS;
     const static float POLYSTAR_MAGIC_NUMBER = 0.47829f / 0.28f;
     float              currentAngle = (startAngle - 90.0f) * K_PI / 180.0f;
     float              x;
@@ -619,6 +621,8 @@ void VPath::VPathData::addPolygon(float
                                   VPath::Direction dir)
 {
     // TODO: Need to support floating point number for number of points
+    constexpr float    MAX_POLY_POINTS = 1024.0f;
+    if (points > MAX_POLY_POINTS) points = MAX_POLY_POINTS;
     const static float POLYGON_MAGIC_NUMBER = 0.25;
     float              currentAngle = (startAngle - 90.0f) * K_PI / 180.0f;
     float              x;
diff --unified -r -p -x .git -x .pc -x debian rlottie_0.1+dfsg-2+deb11u1/src/vector/vraster.cpp rlottie_0.1+dfsg-2+deb11u2/src/vector/vraster.cpp
--- rlottie_0.1+dfsg-2+deb11u1/src/vector/vraster.cpp	2026-07-07 16:14:43.674578008 +0300
+++ rlottie_0.1+dfsg-2+deb11u2/src/vector/vraster.cpp	2026-07-07 16:15:06.083042259 +0300
@@ -370,6 +370,7 @@ struct VRleTask {
     {
         if (mPath.points().size() > SHRT_MAX ||
             mPath.points().size() + mPath.segments() > SHRT_MAX) {
+            mRle.notify();
             return;
         }
 
diff --unified -r -p -x .git -x .pc -x debian rlottie_0.1+dfsg-2+deb11u1/src/vector/vrle.cpp rlottie_0.1+dfsg-2+deb11u2/src/vector/vrle.cpp
--- rlottie_0.1+dfsg-2+deb11u1/src/vector/vrle.cpp	2026-07-07 16:14:58.750890354 +0300
+++ rlottie_0.1+dfsg-2+deb11u2/src/vector/vrle.cpp	2026-07-07 16:15:05.763035629 +0300
@@ -503,7 +503,7 @@ void blitXor(VRle::Span *spans, int coun
     while (count--) {
         int    x = spans->x + offsetX;
         int    l = spans->len;
-        if (x > bufferLen || l > bufferLen || x + l > bufferLen) {
+        if (x < 0 || x + l > bufferLen) {
             return;
         }
         uchar *ptr = buffer + x;
@@ -523,7 +523,7 @@ void blitDestinationOut(VRle::Span *span
     while (count--) {
         int    x = spans->x + offsetX;
         int    l = spans->len;
-        if (x > bufferLen || l > bufferLen || x + l > bufferLen) {
+        if (x < 0 || x + l > bufferLen) {
             return;
         }
         uchar *ptr = buffer + x;
@@ -540,7 +540,7 @@ void blitSrcOver(VRle::Span *spans, int
     while (count--) {
         int    x = spans->x + offsetX;
         int    l = spans->len;
-        if (x > bufferLen || l > bufferLen || x + l > bufferLen) {
+        if (x < 0 || x + l > bufferLen) {
             return;
         }
         uchar *ptr = buffer + x;
@@ -557,7 +557,7 @@ void blit(VRle::Span *spans, int count,
     while (count--) {
         int    x = spans->x + offsetX;
         int    l = spans->len;
-        if (x > bufferLen || l > bufferLen || x + l > bufferLen || x + l < 0) {
+        if (x < 0 || x + l > bufferLen) {
             return;
         }
         uchar *ptr = buffer + x;

Attachment: signature.asc
Description: This is a digitally signed message part.

Reply via email to