Skip to content

Commit 6bdfa74

Browse files
kewdewcandillon
andauthored
fix: harden shaders against buffer over-reads (#3066)
* fix: validate length of positions * fix: harden shaders data() --------- Co-authored-by: William Candillon <[email protected]>
1 parent 67432c2 commit 6bdfa74

File tree

1 file changed

+43
-8
lines changed

1 file changed

+43
-8
lines changed

packages/skia/cpp/api/JsiSkShaderFactory.h

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,22 @@ class JsiSkShaderFactory : public JsiSkHostObject {
8484
SkPoint pts[] = {p1, p2};
8585

8686
std::vector<SkColor> colors = getColors(runtime, arguments[2]);
87+
auto colorsSize = colors.size();
88+
if (colorsSize < 2) {
89+
throw std::invalid_argument("colors must have at least 2 colors");
90+
}
8791
std::vector<SkScalar> positions = getPositions(runtime, arguments[3]);
92+
if (!positions.empty() && positions.size() != colorsSize) {
93+
throw std::invalid_argument(
94+
"positions must be empty or have the same size as colors");
95+
}
8896
auto tileMode = getTileMode(arguments, 4, count);
8997
auto flag = getFlag(arguments, 6, count);
9098
auto localMatrix = getLocalMatrix(runtime, arguments, 5, count);
9199

92100
sk_sp<SkShader> gradient = SkGradientShader::MakeLinear(
93-
pts, colors.data(), positions.data(), static_cast<int>(colors.size()),
94-
tileMode, flag, localMatrix);
101+
pts, colors.data(), !positions.empty() ? positions.data() : nullptr,
102+
static_cast<int>(colorsSize), tileMode, flag, localMatrix);
95103
return jsi::Object::createFromHostObject(
96104
runtime,
97105
std::make_shared<JsiSkShader>(getContext(), std::move(gradient)));
@@ -103,14 +111,23 @@ class JsiSkShaderFactory : public JsiSkHostObject {
103111
auto r = arguments[1].asNumber();
104112

105113
std::vector<SkColor> colors = getColors(runtime, arguments[2]);
114+
auto colorsSize = colors.size();
115+
if (colorsSize < 2) {
116+
throw std::invalid_argument("colors must have at least 2 colors");
117+
}
106118
std::vector<SkScalar> positions = getPositions(runtime, arguments[3]);
119+
if (!positions.empty() && positions.size() != colorsSize) {
120+
throw std::invalid_argument(
121+
"positions must be empty or the same size as colors");
122+
}
107123
auto tileMode = getTileMode(arguments, 4, count);
108124
auto flag = getFlag(arguments, 6, count);
109125
auto localMatrix = getLocalMatrix(runtime, arguments, 5, count);
110126

111127
sk_sp<SkShader> gradient = SkGradientShader::MakeRadial(
112-
center, r, colors.data(), positions.data(),
113-
static_cast<int>(colors.size()), tileMode, flag, localMatrix);
128+
center, r, colors.data(),
129+
!positions.empty() ? positions.data() : nullptr,
130+
static_cast<int>(colorsSize), tileMode, flag, localMatrix);
114131
return jsi::Object::createFromHostObject(
115132
runtime,
116133
std::make_shared<JsiSkShader>(getContext(), std::move(gradient)));
@@ -120,7 +137,15 @@ class JsiSkShaderFactory : public JsiSkHostObject {
120137
auto x = arguments[0].asNumber();
121138
auto y = arguments[1].asNumber();
122139
std::vector<SkColor> colors = getColors(runtime, arguments[2]);
140+
auto colorsSize = colors.size();
141+
if (colorsSize < 2) {
142+
throw std::invalid_argument("colors must have at least 2 colors");
143+
}
123144
std::vector<SkScalar> positions = getPositions(runtime, arguments[3]);
145+
if (!positions.empty() && positions.size() != colorsSize) {
146+
throw std::invalid_argument(
147+
"positions must be empty or the same size as colors");
148+
}
124149
auto tileMode = getTileMode(arguments, 4, count);
125150
auto localMatrix = getLocalMatrix(runtime, arguments, 5, count);
126151
auto flag = getFlag(arguments, 6, count);
@@ -130,8 +155,9 @@ class JsiSkShaderFactory : public JsiSkHostObject {
130155
? 360
131156
: arguments[8].asNumber();
132157
sk_sp<SkShader> gradient = SkGradientShader::MakeSweep(
133-
x, y, colors.data(), positions.data(), static_cast<int>(colors.size()),
134-
tileMode, startAngle, endAngle, flag, localMatrix);
158+
x, y, colors.data(), !positions.empty() ? positions.data() : nullptr,
159+
static_cast<int>(colorsSize), tileMode, startAngle, endAngle, flag,
160+
localMatrix);
135161
return jsi::Object::createFromHostObject(
136162
runtime,
137163
std::make_shared<JsiSkShader>(getContext(), std::move(gradient)));
@@ -147,14 +173,23 @@ class JsiSkShaderFactory : public JsiSkHostObject {
147173
auto endRadius = arguments[3].asNumber();
148174

149175
std::vector<SkColor> colors = getColors(runtime, arguments[4]);
176+
auto colorsSize = colors.size();
177+
if (colorsSize < 2) {
178+
throw std::invalid_argument("colors must have at least 2 colors");
179+
}
150180
std::vector<SkScalar> positions = getPositions(runtime, arguments[5]);
181+
if (!positions.empty() && positions.size() != colorsSize) {
182+
throw std::invalid_argument(
183+
"positions must be empty or the same size as colors");
184+
}
151185
auto tileMode = getTileMode(arguments, 6, count);
152186
auto localMatrix = getLocalMatrix(runtime, arguments, 7, count);
153187
auto flag = getFlag(arguments, 8, count);
154188

155189
sk_sp<SkShader> gradient = SkGradientShader::MakeTwoPointConical(
156-
start, startRadius, end, endRadius, colors.data(), positions.data(),
157-
static_cast<int>(colors.size()), tileMode, flag, localMatrix);
190+
start, startRadius, end, endRadius, colors.data(),
191+
!positions.empty() ? positions.data() : nullptr,
192+
static_cast<int>(colorsSize), tileMode, flag, localMatrix);
158193

159194
return jsi::Object::createFromHostObject(
160195
runtime,

0 commit comments

Comments
 (0)