Skip to content

Commit 507ea02

Browse files
mmaciolaJoogabYun
authored andcommitted
Fix security vulnerabilities in Lottie file handling
Add validation checks to address potential vulnerabilities in case of a malicious Lottie file Adds: - Type check for CompLayer() before casting to model::Layer - Bounds checking for Gradient::populate() - Frames vector empty check - Rejection of outliers
1 parent e3026b1 commit 507ea02

File tree

4 files changed

+31
-11
lines changed

4 files changed

+31
-11
lines changed

src/lottie/lottieitem.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,7 @@ renderer::CompLayer::CompLayer(model::Layer *layerModel, VArenaAlloc *allocator)
479479
// as lottie model keeps the data in front-toback-order.
480480
for (auto it = mLayerData->mChildren.crbegin();
481481
it != mLayerData->mChildren.rend(); ++it) {
482+
if ((*it)->type() != model::Object::Type::Layer) continue;
482483
auto model = static_cast<model::Layer *>(*it);
483484
auto item = createLayerItem(model, allocator);
484485
if (item) mLayers.push_back(item);

src/lottie/lottiemodel.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,11 +250,16 @@ void model::Gradient::populate(VGradientStops &stops, int frameNo)
250250
auto size = gradData.mGradient.size();
251251
float * ptr = gradData.mGradient.data();
252252
int colorPoints = mColorPoints;
253-
if (colorPoints == -1) { // for legacy bodymovin (ref: lottie-android)
253+
size_t colorPointsSize = colorPoints * 4;
254+
if (!ptr) return;
255+
if (colorPoints < 0 || colorPointsSize > size) { // for legacy bodymovin (ref: lottie-android)
254256
colorPoints = int(size / 4);
255257
}
256-
auto opacityArraySize = size - colorPoints * 4;
257-
float *opacityPtr = ptr + (colorPoints * 4);
258+
auto opacityArraySize = size - colorPointsSize;
259+
if (opacityArraySize % 2 != 0) {
260+
opacityArraySize = 0;
261+
}
262+
float *opacityPtr = ptr + colorPointsSize;
258263
stops.clear();
259264
for (int i = 0; i < colorPoints; i++) {
260265
float colorStop = ptr[0];
@@ -267,6 +272,10 @@ void model::Gradient::populate(VGradientStops &stops, int frameNo)
267272
}
268273
ptr += 4;
269274
}
275+
276+
if (stops.empty()) {
277+
stops.push_back(std::make_pair(0.0f, VColor(255, 255, 255, 255)));
278+
}
270279
}
271280

272281
float model::Gradient::getOpacityAtPosition(float *opacities, size_t opacityArraySize, float position)

src/lottie/lottiemodel.h

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -239,20 +239,23 @@ class KeyFrames {
239239

240240
T value(int frameNo) const
241241
{
242-
if (frames_.front().start_ >= frameNo)
243-
return frames_.front().value_.start_;
244-
if (frames_.back().end_ <= frameNo) return frames_.back().value_.end_;
245-
246-
for (const auto &keyFrame : frames_) {
247-
if (frameNo >= keyFrame.start_ && frameNo < keyFrame.end_)
248-
return keyFrame.value(frameNo);
242+
if (!frames_.empty()) {
243+
if (frames_.front().start_ >= frameNo)
244+
return frames_.front().value_.start_;
245+
if (frames_.back().end_ <= frameNo) return frames_.back().value_.end_;
246+
247+
for (const auto &keyFrame : frames_) {
248+
if (frameNo >= keyFrame.start_ && frameNo < keyFrame.end_)
249+
return keyFrame.value(frameNo);
250+
}
249251
}
250252
return {};
251253
}
252254

253255
float angle(int frameNo) const
254256
{
255-
if ((frames_.front().start_ >= frameNo) ||
257+
if (frames_.empty() ||
258+
(frames_.front().start_ >= frameNo) ||
256259
(frames_.back().end_ <= frameNo))
257260
return 0;
258261

@@ -265,6 +268,8 @@ class KeyFrames {
265268

266269
bool changed(int prevFrame, int curFrame) const
267270
{
271+
if (frames_.empty()) return false;
272+
268273
auto first = frames_.front().start_;
269274
auto last = frames_.back().end_;
270275

src/vector/freetype/v_ft_raster.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,10 @@ static void gray_render_line(RAS_ARG_ TPos to_x, TPos to_y)
537537
dx = to_x - ras.x;
538538
dy = to_y - ras.y;
539539

540+
if (SW_FT_ABS(dx) > 10000000 || SW_FT_ABS(dy) > 10000000) {
541+
goto End;
542+
}
543+
540544
fx1 = ras.x - SUBPIXELS(ex1);
541545
fy1 = ras.y - SUBPIXELS(ey1);
542546

@@ -707,6 +711,7 @@ static void gray_render_conic(RAS_ARG_ const SW_FT_Vector* control,
707711
gray_split_conic(arc);
708712
arc += 2;
709713
top++;
714+
if (top >= 32) return; // levels size is 32
710715
levels[top] = levels[top - 1] = level - 1;
711716
continue;
712717
}

0 commit comments

Comments
 (0)