aboutsummaryrefslogtreecommitdiffhomepage
path: root/experimental
diff options
context:
space:
mode:
authorGravatar Florin Malita <fmalita@chromium.org>2018-05-10 18:40:35 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-05-11 02:40:56 +0000
commit0cc01b753ac6750e8decbcb92e4e33de1b147e20 (patch)
tree517b4f309268d2ffd53cea9cfc9005eff3cf926f /experimental
parent03e7f36ee95e934c9d88af23530f7d4436896238 (diff)
[skottie] Guard against asset cycles
Track assets being attached, and break cycles. Bug: oss-fuzz:8220 Change-Id: I146cf35eba8cfea487c00544fe82f89c3a859803 Reviewed-on: https://skia-review.googlesource.com/127381 Reviewed-by: Kevin Lubick <kjlubick@google.com> Commit-Queue: Florin Malita <fmalita@chromium.org>
Diffstat (limited to 'experimental')
-rw-r--r--experimental/skottie/Skottie.cpp77
1 files changed, 42 insertions, 35 deletions
diff --git a/experimental/skottie/Skottie.cpp b/experimental/skottie/Skottie.cpp
index 18c8c193c0..8396b5ba90 100644
--- a/experimental/skottie/Skottie.cpp
+++ b/experimental/skottie/Skottie.cpp
@@ -52,7 +52,12 @@ namespace skottie {
namespace {
-using AssetMap = SkTHashMap<SkString, json::ValueRef>;
+struct AssetInfo {
+ json::ValueRef fAsset;
+ mutable bool fIsAttaching; // Used for cycle detection
+};
+
+using AssetMap = SkTHashMap<SkString, AssetInfo>;
struct AttachContext {
const ResourceProvider& fResources;
@@ -756,16 +761,41 @@ sk_sp<sksg::RenderNode> AttachNestedAnimation(const char* path, AttachContext* c
return sk_make_sp<SkottieSGAdapter>(std::move(animation));
}
-sk_sp<sksg::RenderNode> AttachCompLayer(const json::ValueRef& jlayer, AttachContext* ctx,
- float* time_bias, float* time_scale) {
- SkASSERT(jlayer.isObject());
+sk_sp<sksg::RenderNode> AttachAssetRef(const json::ValueRef& jlayer, AttachContext* ctx,
+ sk_sp<sksg::RenderNode>(*attach_proc)(const json::ValueRef& comp, AttachContext* ctx)) {
- SkString refId;
- if (!jlayer["refId"].to(&refId) || refId.isEmpty()) {
- LOG("!! Comp layer missing refId\n");
+ const auto refId = jlayer["refId"].toDefault(SkString());
+ if (refId.isEmpty()) {
+ LOG("!! Layer missing refId\n");
return nullptr;
}
+ if (refId.startsWith("$")) {
+ return AttachNestedAnimation(refId.c_str() + 1, ctx);
+ }
+
+ const auto* asset_info = ctx->fAssets.find(refId);
+ if (!asset_info) {
+ LOG("!! Asset not found: '%s'\n", refId.c_str());
+ return nullptr;
+ }
+
+ if (asset_info->fIsAttaching) {
+ LOG("!! Asset cycle detected for: '%s'\n", refId.c_str());
+ return nullptr;
+ }
+
+ asset_info->fIsAttaching = true;
+ auto asset = attach_proc(asset_info->fAsset, ctx);
+ asset_info->fIsAttaching = false;
+
+ return asset;
+}
+
+sk_sp<sksg::RenderNode> AttachCompLayer(const json::ValueRef& jlayer, AttachContext* ctx,
+ float* time_bias, float* time_scale) {
+ SkASSERT(jlayer.isObject());
+
const auto start_time = jlayer["st"].toDefault(0.0f),
stretch_time = jlayer["sr"].toDefault(1.0f);
@@ -775,18 +805,7 @@ sk_sp<sksg::RenderNode> AttachCompLayer(const json::ValueRef& jlayer, AttachCont
*time_scale = 1;
}
- if (refId.startsWith("$")) {
- return AttachNestedAnimation(refId.c_str() + 1, ctx);
- }
-
- const auto* comp = ctx->fAssets.find(refId);
- if (!comp) {
- LOG("!! Pre-comp not found: '%s'\n", refId.c_str());
- return nullptr;
- }
-
- // TODO: cycle detection
- return AttachComposition(*comp, ctx);
+ return AttachAssetRef(jlayer, ctx, AttachComposition);
}
sk_sp<sksg::RenderNode> AttachSolidLayer(const json::ValueRef& jlayer, AttachContext*,
@@ -831,23 +850,11 @@ sk_sp<sksg::RenderNode> AttachImageAsset(const json::ValueRef& jimage, AttachCon
SkImage::MakeFromEncoded(SkData::MakeFromStream(resStream.get(), resStream->getLength())));
}
-sk_sp<sksg::RenderNode> AttachImageLayer(const json::ValueRef& layer, AttachContext* ctx,
+sk_sp<sksg::RenderNode> AttachImageLayer(const json::ValueRef& jlayer, AttachContext* ctx,
float*, float*) {
- SkASSERT(layer.isObject());
-
- SkString refId;
- if (!layer["refId"].to(&refId) || refId.isEmpty()) {
- LOG("!! Image layer missing refId\n");
- return nullptr;
- }
-
- const auto* jimage = ctx->fAssets.find(refId);
- if (!jimage) {
- LOG("!! Image asset not found: '%s'\n", refId.c_str());
- return nullptr;
- }
+ SkASSERT(jlayer.isObject());
- return AttachImageAsset(*jimage, ctx);
+ return AttachAssetRef(jlayer, ctx, AttachImageAsset);
}
sk_sp<sksg::RenderNode> AttachNullLayer(const json::ValueRef& layer, AttachContext*, float*, float*) {
@@ -1268,7 +1275,7 @@ Animation::Animation(const ResourceProvider& resources,
AssetMap assets;
for (const json::ValueRef asset : json["assets"]) {
if (asset.isObject()) {
- assets.set(asset["id"].toDefault(SkString()), asset);
+ assets.set(asset["id"].toDefault(SkString()), { asset, false });
}
}