Kaynağa Gözat

[flutter] Closes #2526, fix use after free error in dress-up.

When setting a new skin in _toggleSkin, we first dispose the old skin, then set the new skin. However, setting the new skin will compare attachments against the still set but already freed old skin. We end up with use after free memory access.
Mario Zechner 1 yıl önce
ebeveyn
işleme
cb0fc7adaa

+ 2 - 1
spine-flutter/example/lib/dress_up.dart

@@ -69,6 +69,7 @@ class DressUpState extends State<DressUp> {
 
   void _toggleSkin(String skinName) {
     _selectedSkins[skinName] = !_selectedSkins[skinName]!;
+    _drawable.skeleton.setSkinByName("default");
     if (_customSkin != null) _customSkin?.dispose();
     _customSkin = Skin("custom-skin");
     for (var skinName in _selectedSkins.keys) {
@@ -78,7 +79,7 @@ class DressUpState extends State<DressUp> {
       }
     }
     _drawable.skeleton.setSkin(_customSkin!);
-    _drawable.skeleton.setToSetupPose();
+    _drawable.skeleton.setSlotsToSetupPose();
   }
 
   @override

+ 22 - 16
spine-sfml/cpp/example/main.cpp

@@ -573,19 +573,11 @@ void mixAndMatch(SkeletonData *skeletonData, Atlas *atlas) {
 
 	Skeleton *skeleton = drawable.skeleton;
 
-	Skin skin("mix-and-match");
-	skin.addSkin(skeletonData->findSkin("skin-base"));
-	skin.addSkin(skeletonData->findSkin("nose/short"));
-	skin.addSkin(skeletonData->findSkin("eyelids/girly"));
-	skin.addSkin(skeletonData->findSkin("eyes/violet"));
-	skin.addSkin(skeletonData->findSkin("hair/brown"));
-	skin.addSkin(skeletonData->findSkin("clothes/hoodie-orange"));
-	skin.addSkin(skeletonData->findSkin("legs/pants-jeans"));
-	skin.addSkin(skeletonData->findSkin("accessories/bag"));
-	skin.addSkin(skeletonData->findSkin("accessories/hat-red-yellow"));
-
-	skeleton->setSkin(&skin);
-	skeleton->setSlotsToSetupPose();
+	Skin *skin = new Skin("mix-and-match");
+    skin->addSkin(skeletonData->findSkin("full-skins/girl"));
+    skin->addSkin(skeletonData->findSkin("accessories/cape-blue"));
+	skeleton->setSkin(skin);
+	skeleton->setToSetupPose();
 
 	skeleton->setPosition(320, 590);
 	skeleton->updateWorldTransform(Physics_Update);
@@ -596,9 +588,21 @@ void mixAndMatch(SkeletonData *skeletonData, Atlas *atlas) {
 	window.setFramerateLimit(60);
 	sf::Event event;
 	sf::Clock deltaClock;
+    bool isCapeEquipped = true;
 	while (window.isOpen()) {
-		while (window.pollEvent(event))
-			if (event.type == sf::Event::Closed) window.close();
+        while (window.pollEvent(event)) {
+            if (event.type == sf::Event::Closed) window.close();
+            if (event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left) {
+                skeleton->setSkin(nullptr);
+                delete skin;
+                isCapeEquipped = !isCapeEquipped;
+                skin = new Skin("mix-and-match");
+                skin->addSkin(skeletonData->findSkin("full-skins/girl"));
+                if (isCapeEquipped) skin->addSkin(skeletonData->findSkin("accessories/cape-blue"));
+                skeleton->setSkin(skin);
+                skeleton->setSlotsToSetupPose();
+            }
+        }
 
 		float delta = deltaClock.getElapsedTime().asSeconds();
 		deltaClock.restart();
@@ -609,6 +613,8 @@ void mixAndMatch(SkeletonData *skeletonData, Atlas *atlas) {
 		window.draw(drawable);
 		window.display();
 	}
+
+    delete skin;
 }
 
 void celestialCircus(SkeletonData *skeletonData, Atlas *atlas) {
@@ -771,6 +777,7 @@ DebugExtension dbgExtension(SpineExtension::getInstance());
 int main() {
 	SpineExtension::setInstance(&dbgExtension);
 
+    testcase(mixAndMatch, "data/mix-and-match-pro.json", "data/mix-and-match-pro.skel", "data/mix-and-match-pma.atlas", 0.5f);
 	testcase(cloudpot, "data/cloud-pot.json", "data/cloud-pot.skel", "data/cloud-pot-pma.atlas", 0.2);
 	testcase(sack, "data/sack-pro.json", "data/sack-pro.skel", "data/sack-pma.atlas", 0.2f);
 	testcase(celestialCircus, "data/celestial-circus-pro.json", "data/celestial-circus-pro.skel", "data/celestial-circus-pma.atlas", 0.2f);
@@ -781,7 +788,6 @@ int main() {
 	testcase(vine, "data/vine-pro.json", "data/vine-pro.skel", "data/vine-pma.atlas", 0.5f);
 	testcase(dragon, "data/dragon-ess.json", "data/dragon-ess.skel", "data/dragon-pma.atlas", 0.6f);
 	testcase(owl, "data/owl-pro.json", "data/owl-pro.skel", "data/owl-pma.atlas", 0.5f);
-	testcase(mixAndMatch, "data/mix-and-match-pro.json", "data/mix-and-match-pro.skel", "data/mix-and-match-pma.atlas", 0.5f);
 	testcase(coin, "data/coin-pro.json", "data/coin-pro.skel", "data/coin-pma.atlas", 0.5f);
 	testcase(raptor, "data/raptor-pro.json", "data/raptor-pro.skel", "data/raptor-pma.atlas", 0.5f);
 	testcase(tank, "data/tank-pro.json", "data/tank-pro.skel", "data/tank-pma.atlas", 0.2f);