File: Check-buffer-length.patch

package info (click to toggle)
rlottie 0.1%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 9,864 kB
  • sloc: cpp: 20,368; asm: 221; ansic: 194; makefile: 15
file content (132 lines) | stat: -rw-r--r-- 5,549 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
Description: Check buffer length in vrle.
 Should fix CVE-2021-31315 related issues.
Origin: https://github.com/desktop-app/rlottie/commit/0ee2e9c5843257ccd11672611829b9bb5d02aa98
        https://github.com/desktop-app/rlottie/commit/75b31e49b3c69355c4971ee2029eff23a22fcb75
        https://github.com/desktop-app/rlottie/commit/839dcab7f083a51b8130061ea5ec245195af6c58
Author: John Preston <johnprestonmail@gmail.com>
Acked-By: Nicholas Guriev <guriev-ns@ya.ru>
Last-Update: Sat, 22 May 2021 19:07:06 +0300

--- a/src/vector/vrle.cpp
+++ b/src/vector/vrle.cpp
@@ -497,11 +497,14 @@ static void rleIntersectWithRect(const V
     result->size = result->alloc - available;
 }
 
-void blitXor(VRle::Span *spans, int count, uchar *buffer, int offsetX)
+void blitXor(VRle::Span *spans, int count, uchar *buffer, int bufferLen, int offsetX)
 {
     while (count--) {
         int    x = spans->x + offsetX;
         int    l = spans->len;
+        if (x < 0 || x + l > bufferLen) {
+            return;
+        }
         uchar *ptr = buffer + x;
         while (l--) {
             int da = *ptr;
@@ -513,12 +516,15 @@ void blitXor(VRle::Span *spans, int coun
     }
 }
 
-void blitDestinationOut(VRle::Span *spans, int count, uchar *buffer,
+void blitDestinationOut(VRle::Span *spans, int count, uchar *buffer, int bufferLen,
                         int offsetX)
 {
     while (count--) {
         int    x = spans->x + offsetX;
         int    l = spans->len;
+        if (x < 0 || x + l > bufferLen) {
+            return;
+        }
         uchar *ptr = buffer + x;
         while (l--) {
             *ptr = divBy255((255 - spans->coverage) * (*ptr));
@@ -528,11 +534,14 @@ void blitDestinationOut(VRle::Span *span
     }
 }
 
-void blitSrcOver(VRle::Span *spans, int count, uchar *buffer, int offsetX)
+void blitSrcOver(VRle::Span *spans, int count, uchar *buffer, int bufferLen, int offsetX)
 {
     while (count--) {
         int    x = spans->x + offsetX;
         int    l = spans->len;
+        if (x < 0 || x + l > bufferLen) {
+            return;
+        }
         uchar *ptr = buffer + x;
         while (l--) {
             *ptr = spans->coverage + divBy255((255 - spans->coverage) * (*ptr));
@@ -542,11 +551,14 @@ void blitSrcOver(VRle::Span *spans, int
     }
 }
 
-void blit(VRle::Span *spans, int count, uchar *buffer, int offsetX)
+void blit(VRle::Span *spans, int count, uchar *buffer, int bufferLen, int offsetX)
 {
     while (count--) {
         int    x = spans->x + offsetX;
         int    l = spans->len;
+        if (x < 0 || x + l > bufferLen) {
+            return;
+        }
         uchar *ptr = buffer + x;
         while (l--) {
             *ptr = std::max(spans->coverage, *ptr);
@@ -556,13 +568,16 @@ void blit(VRle::Span *spans, int count,
     }
 }
 
-size_t bufferToRle(uchar *buffer, int size, int offsetX, int y, VRle::Span *out)
+size_t bufferToRle(uchar *buffer, int bufferLen, int size, int offsetX, int y, VRle::Span *out)
 {
     size_t count = 0;
     uchar  value = buffer[0];
     int    curIndex = 0;
 
     size = offsetX < 0 ? size + offsetX : size;
+    if (size > bufferLen) {
+        return count;
+    }
     for (int i = 0; i < size; i++) {
         uchar curValue = buffer[0];
         if (value != curValue) {
@@ -620,14 +635,15 @@ static void rleOpGeneric(VRleHelper *a,
             int bLength = (bPtr - 1)->x + (bPtr - 1)->len;
             int offset = std::min(aStart->x, bStart->x);
 
-            std::array<uchar, 1024> array = {{0}};
-            blit(aStart, (aPtr - aStart), array.data(), -offset);
+            constexpr auto kBufferSize = 1024;
+            std::array<uchar, kBufferSize> array = {{0}};
+            blit(aStart, (aPtr - aStart), array.data(), kBufferSize, -offset);
             if (op == Operation::Add)
-                blitSrcOver(bStart, (bPtr - bStart), array.data(), -offset);
+                blitSrcOver(bStart, (bPtr - bStart), array.data(), kBufferSize, -offset);
             else if (op == Operation::Xor)
-                blitXor(bStart, (bPtr - bStart), array.data(), -offset);
+                blitXor(bStart, (bPtr - bStart), array.data(), kBufferSize, -offset);
             VRle::Span *tResult = temp.data();
-            size_t size = bufferToRle(array.data(), std::max(aLength, bLength),
+            size_t size = bufferToRle(array.data(), kBufferSize, std::max(aLength, bLength),
                                       offset, y, tResult);
             if (available >= size) {
                 while (size--) {
@@ -683,11 +699,12 @@ static void rleSubstractWithRle(VRleHelp
             int bLength = (bPtr - 1)->x + (bPtr - 1)->len;
             int offset = std::min(aStart->x, bStart->x);
 
-            std::array<uchar, 1024> array = {{0}};
-            blit(aStart, (aPtr - aStart), array.data(), -offset);
-            blitDestinationOut(bStart, (bPtr - bStart), array.data(), -offset);
+            constexpr auto kBufferSize = 1024;
+            std::array<uchar, kBufferSize> array = {{0}};
+            blit(aStart, (aPtr - aStart), array.data(), kBufferSize, -offset);
+            blitDestinationOut(bStart, (bPtr - bStart), array.data(), kBufferSize, -offset);
             VRle::Span *tResult = temp.data();
-            size_t size = bufferToRle(array.data(), std::max(aLength, bLength),
+            size_t size = bufferToRle(array.data(), kBufferSize, std::max(aLength, bLength),
                                       offset, y, tResult);
             if (available >= size) {
                 while (size--) {