Bläddra i källkod

[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 år sedan
förälder
incheckning
cb0fc7adaa
2 ändrade filer med 24 tillägg och 17 borttagningar
  1. 2 1
      spine-flutter/example/lib/dress_up.dart
  2. 22 16
      spine-sfml/cpp/example/main.cpp

+ 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);