summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMacDue <macdue@dueutil.tech>2023-05-27 16:37:32 +0100
committerAndreas Kling <kling@serenityos.org>2023-05-27 18:40:41 +0200
commit6f8c2dc3223b4f0e767200d694c8b0353c2cf0af (patch)
tree077f5b5ee03257813ff440b6b070b607da87f7e3
parent33500bb6dbbeddc36ad8c12643a5a536e3a78ec9 (diff)
downloadserenity-6f8c2dc3223b4f0e767200d694c8b0353c2cf0af.zip
LibWeb: Make SVG transform parser less crashy
Previously, this would blindly use parse_number() without checking if there was a number to parse. This meant we would crash on transforms like: rotate(BAD 32 0) Now the attribute just gracefully fails to parse.
-rw-r--r--Userland/Libraries/LibWeb/SVG/AttributeParser.cpp81
1 files changed, 62 insertions, 19 deletions
diff --git a/Userland/Libraries/LibWeb/SVG/AttributeParser.cpp b/Userland/Libraries/LibWeb/SVG/AttributeParser.cpp
index eb111fbb75..957ce7a518 100644
--- a/Userland/Libraries/LibWeb/SVG/AttributeParser.cpp
+++ b/Userland/Libraries/LibWeb/SVG/AttributeParser.cpp
@@ -519,7 +519,8 @@ Optional<Vector<Transform>> AttributeParser::parse_transform()
m_lexer.consume_specific(',');
consume_whitespace();
};
- // FIXME: AttributeParser currently does not handle invalid parses in most cases (e.g. parse_number()) and just crashes.
+
+ // FIXME: This parsing is quite lenient, so will accept (with default values) some transforms that should be rejected.
auto parse_optional_number = [&](float default_value = 0.0f) {
consume_comma_whitespace();
if (match_number())
@@ -527,12 +528,21 @@ Optional<Vector<Transform>> AttributeParser::parse_transform()
return default_value;
};
+ auto try_parse_number = [&]() -> Optional<float> {
+ if (match_number())
+ return parse_number();
+ return {};
+ };
+
auto parse_function = [&](auto body) -> Optional<Transform> {
consume_whitespace();
if (!m_lexer.consume_specific('('))
return {};
consume_whitespace();
- Transform transform { .operation = Transform::Operation { body() } };
+ auto maybe_operation = body();
+ if (!maybe_operation.has_value())
+ return {};
+ Transform transform { .operation = Transform::Operation { *maybe_operation } };
consume_whitespace();
if (m_lexer.consume_specific(')'))
return transform;
@@ -545,53 +555,86 @@ Optional<Vector<Transform>> AttributeParser::parse_transform()
while (!done()) {
Optional<Transform> maybe_transform;
if (m_lexer.consume_specific("translate"sv)) {
- maybe_transform = parse_function([&] {
+ maybe_transform = parse_function([&]() -> Optional<Transform::Translate> {
Transform::Translate translate {};
- translate.x = parse_number();
+ auto maybe_x = try_parse_number();
+ if (!maybe_x.has_value())
+ return {};
+ translate.x = *maybe_x;
translate.y = parse_optional_number();
return translate;
});
} else if (m_lexer.consume_specific("scale"sv)) {
- maybe_transform = parse_function([&] {
+ maybe_transform = parse_function([&]() -> Optional<Transform::Scale> {
Transform::Scale scale {};
- scale.x = parse_number();
+ auto maybe_x = try_parse_number();
+ if (!maybe_x.has_value())
+ return {};
+ scale.x = *maybe_x;
scale.y = parse_optional_number(scale.x);
return scale;
});
} else if (m_lexer.consume_specific("rotate"sv)) {
- maybe_transform = parse_function([&] {
+ maybe_transform = parse_function([&]() -> Optional<Transform::Rotate> {
Transform::Rotate rotate {};
- rotate.a = parse_number();
+ auto maybe_a = try_parse_number();
+ if (!maybe_a.has_value())
+ return {};
+ rotate.a = *maybe_a;
rotate.x = parse_optional_number();
rotate.y = parse_optional_number();
return rotate;
});
} else if (m_lexer.consume_specific("skewX"sv)) {
- maybe_transform = parse_function([&] {
+ maybe_transform = parse_function([&]() -> Optional<Transform::SkewX> {
Transform::SkewX skew_x {};
- skew_x.a = parse_number();
+ auto maybe_a = try_parse_number();
+ if (!maybe_a.has_value())
+ return {};
+ skew_x.a = *maybe_a;
return skew_x;
});
} else if (m_lexer.consume_specific("skewY"sv)) {
- maybe_transform = parse_function([&] {
+ maybe_transform = parse_function([&]() -> Optional<Transform::SkewY> {
Transform::SkewY skew_y {};
- skew_y.a = parse_number();
+ auto maybe_a = try_parse_number();
+ if (!maybe_a.has_value())
+ return {};
+ skew_y.a = *maybe_a;
return skew_y;
});
} else if (m_lexer.consume_specific("matrix"sv)) {
- maybe_transform = parse_function([&] {
+ maybe_transform = parse_function([&]() -> Optional<Transform::Matrix> {
Transform::Matrix matrix;
- matrix.a = parse_number();
+ auto maybe_a = try_parse_number();
+ if (!maybe_a.has_value())
+ return {};
+ matrix.a = *maybe_a;
consume_comma_whitespace();
- matrix.b = parse_number();
+ auto maybe_b = try_parse_number();
+ if (!maybe_b.has_value())
+ return {};
+ matrix.b = *maybe_b;
consume_comma_whitespace();
- matrix.c = parse_number();
+ auto maybe_c = try_parse_number();
+ if (!maybe_c.has_value())
+ return {};
+ matrix.c = *maybe_c;
consume_comma_whitespace();
- matrix.d = parse_number();
+ auto maybe_d = try_parse_number();
+ if (!maybe_d.has_value())
+ return {};
+ matrix.d = *maybe_d;
consume_comma_whitespace();
- matrix.e = parse_number();
+ auto maybe_e = try_parse_number();
+ if (!maybe_e.has_value())
+ return {};
+ matrix.e = *maybe_e;
consume_comma_whitespace();
- matrix.f = parse_number();
+ auto maybe_f = try_parse_number();
+ if (!maybe_f.has_value())
+ return {};
+ matrix.f = *maybe_f;
return matrix;
});
}