Prechádzať zdrojové kódy

[spine-c] Fix crashes in skins or animations error handling (#2491)

* Fix android-specific rotation issue. bone->arotation == NaN, in some specific cases during update bones, cause squared value can been very smoll but still negative anyway and create NaN value

* Fix crash at spSkeletonData_dispose() while handling problems in skeleton in SkeletonBinary/SkeletonJson.
Use increase counts instead directly put counts value for avoid problems at early dispose vectors

* additional commit for prev revision
Dmitro Sechin 1 rok pred
rodič
commit
f67807f1e7

+ 7 - 0
spine-c/spine-c/src/spine/SkeletonBinary.c

@@ -1369,6 +1369,8 @@ spSkeletonData *spSkeletonBinary_readSkeletonData(spSkeletonBinary *self, const
 		skeletonData->version = 0;
 		skeletonData->version = 0;
 	} else {
 	} else {
 		if (!string_starts_with(skeletonData->version, SPINE_VERSION_STRING)) {
 		if (!string_starts_with(skeletonData->version, SPINE_VERSION_STRING)) {
+			FREE(input);
+			spSkeletonData_dispose(skeletonData);
 			char errorMsg[255];
 			char errorMsg[255];
 			snprintf(errorMsg, 255, "Skeleton version %s does not match runtime version %s", skeletonData->version, SPINE_VERSION_STRING);
 			snprintf(errorMsg, 255, "Skeleton version %s does not match runtime version %s", skeletonData->version, SPINE_VERSION_STRING);
 			_spSkeletonBinary_setError(self, errorMsg, NULL);
 			_spSkeletonBinary_setError(self, errorMsg, NULL);
@@ -1596,6 +1598,8 @@ spSkeletonData *spSkeletonBinary_readSkeletonData(spSkeletonBinary *self, const
 	/* Default skin. */
 	/* Default skin. */
 	skeletonData->defaultSkin = spSkeletonBinary_readSkin(self, input, -1, skeletonData, nonessential);
 	skeletonData->defaultSkin = spSkeletonBinary_readSkin(self, input, -1, skeletonData, nonessential);
 	if (self->attachmentLoader->error1) {
 	if (self->attachmentLoader->error1) {
+		FREE(input);
+		spSkin_dispose(skeletonData->defaultSkin);
 		spSkeletonData_dispose(skeletonData);
 		spSkeletonData_dispose(skeletonData);
 		_spSkeletonBinary_setError(self, self->attachmentLoader->error1, self->attachmentLoader->error2);
 		_spSkeletonBinary_setError(self, self->attachmentLoader->error1, self->attachmentLoader->error2);
 		return NULL;
 		return NULL;
@@ -1614,6 +1618,8 @@ spSkeletonData *spSkeletonBinary_readSkeletonData(spSkeletonBinary *self, const
 	for (i = skeletonData->defaultSkin ? 1 : 0; i < skeletonData->skinsCount; ++i) {
 	for (i = skeletonData->defaultSkin ? 1 : 0; i < skeletonData->skinsCount; ++i) {
 		spSkin *skin = spSkeletonBinary_readSkin(self, input, 0, skeletonData, nonessential);
 		spSkin *skin = spSkeletonBinary_readSkin(self, input, 0, skeletonData, nonessential);
 		if (self->attachmentLoader->error1) {
 		if (self->attachmentLoader->error1) {
+			FREE(input);
+			skeletonData->skinsCount = i + 1;
 			spSkeletonData_dispose(skeletonData);
 			spSkeletonData_dispose(skeletonData);
 			_spSkeletonBinary_setError(self, self->attachmentLoader->error1, self->attachmentLoader->error2);
 			_spSkeletonBinary_setError(self, self->attachmentLoader->error1, self->attachmentLoader->error2);
 			return NULL;
 			return NULL;
@@ -1672,6 +1678,7 @@ spSkeletonData *spSkeletonBinary_readSkeletonData(spSkeletonBinary *self, const
 		FREE(name);
 		FREE(name);
 		if (!animation) {
 		if (!animation) {
 			FREE(input);
 			FREE(input);
+			skeletonData->animationsCount = i + 1;
 			spSkeletonData_dispose(skeletonData);
 			spSkeletonData_dispose(skeletonData);
 			_spSkeletonBinary_setError(self, "Animation corrupted: ", name);
 			_spSkeletonBinary_setError(self, "Animation corrupted: ", name);
 			return NULL;
 			return NULL;

+ 17 - 6
spine-c/spine-c/src/spine/SkeletonJson.c

@@ -1177,7 +1177,6 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
 	slots = Json_getItem(root, "slots");
 	slots = Json_getItem(root, "slots");
 	if (slots) {
 	if (slots) {
 		Json *slotMap;
 		Json *slotMap;
-		skeletonData->slotsCount = slots->size;
 		skeletonData->slots = MALLOC(spSlotData *, slots->size);
 		skeletonData->slots = MALLOC(spSlotData *, slots->size);
 		for (slotMap = slots->child, i = 0; slotMap; slotMap = slotMap->next, ++i) {
 		for (slotMap = slots->child, i = 0; slotMap; slotMap = slotMap->next, ++i) {
 			spSlotData *data;
 			spSlotData *data;
@@ -1237,6 +1236,7 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
 			data->visible = Json_getInt(slotMap, "visible", -1);
 			data->visible = Json_getInt(slotMap, "visible", -1);
 			data->path = pathName;
 			data->path = pathName;
 			skeletonData->slots[i] = data;
 			skeletonData->slots[i] = data;
+			skeletonData->slotsCount++;
 		}
 		}
 	}
 	}
 
 
@@ -1244,7 +1244,6 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
 	ik = Json_getItem(root, "ik");
 	ik = Json_getItem(root, "ik");
 	if (ik) {
 	if (ik) {
 		Json *constraintMap;
 		Json *constraintMap;
-		skeletonData->ikConstraintsCount = ik->size;
 		skeletonData->ikConstraints = MALLOC(spIkConstraintData *, ik->size);
 		skeletonData->ikConstraints = MALLOC(spIkConstraintData *, ik->size);
 		for (constraintMap = ik->child, i = 0; constraintMap; constraintMap = constraintMap->next, ++i) {
 		for (constraintMap = ik->child, i = 0; constraintMap; constraintMap = constraintMap->next, ++i) {
 			const char *targetName;
 			const char *targetName;
@@ -1259,6 +1258,7 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
 			for (boneMap = boneMap->child, ii = 0; boneMap; boneMap = boneMap->next, ++ii) {
 			for (boneMap = boneMap->child, ii = 0; boneMap; boneMap = boneMap->next, ++ii) {
 				data->bones[ii] = spSkeletonData_findBone(skeletonData, boneMap->valueString);
 				data->bones[ii] = spSkeletonData_findBone(skeletonData, boneMap->valueString);
 				if (!data->bones[ii]) {
 				if (!data->bones[ii]) {
+					spIkConstraintData_dispose(data);
 					spSkeletonData_dispose(skeletonData);
 					spSkeletonData_dispose(skeletonData);
 					_spSkeletonJson_setError(self, root, "IK bone not found: ", boneMap->valueString);
 					_spSkeletonJson_setError(self, root, "IK bone not found: ", boneMap->valueString);
 					return NULL;
 					return NULL;
@@ -1268,6 +1268,7 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
 			targetName = Json_getString(constraintMap, "target", 0);
 			targetName = Json_getString(constraintMap, "target", 0);
 			data->target = spSkeletonData_findBone(skeletonData, targetName);
 			data->target = spSkeletonData_findBone(skeletonData, targetName);
 			if (!data->target) {
 			if (!data->target) {
+				spIkConstraintData_dispose(data);
 				spSkeletonData_dispose(skeletonData);
 				spSkeletonData_dispose(skeletonData);
 				_spSkeletonJson_setError(self, root, "Target bone not found: ", targetName);
 				_spSkeletonJson_setError(self, root, "Target bone not found: ", targetName);
 				return NULL;
 				return NULL;
@@ -1281,6 +1282,7 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
 			data->softness = Json_getFloat(constraintMap, "softness", 0) * self->scale;
 			data->softness = Json_getFloat(constraintMap, "softness", 0) * self->scale;
 
 
 			skeletonData->ikConstraints[i] = data;
 			skeletonData->ikConstraints[i] = data;
+			skeletonData->ikConstraintsCount++;
 		}
 		}
 	}
 	}
 
 
@@ -1288,7 +1290,6 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
 	transform = Json_getItem(root, "transform");
 	transform = Json_getItem(root, "transform");
 	if (transform) {
 	if (transform) {
 		Json *constraintMap;
 		Json *constraintMap;
-		skeletonData->transformConstraintsCount = transform->size;
 		skeletonData->transformConstraints = MALLOC(spTransformConstraintData *, transform->size);
 		skeletonData->transformConstraints = MALLOC(spTransformConstraintData *, transform->size);
 		for (constraintMap = transform->child, i = 0; constraintMap; constraintMap = constraintMap->next, ++i) {
 		for (constraintMap = transform->child, i = 0; constraintMap; constraintMap = constraintMap->next, ++i) {
 			const char *name;
 			const char *name;
@@ -1304,6 +1305,7 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
 			for (boneMap = boneMap->child, ii = 0; boneMap; boneMap = boneMap->next, ++ii) {
 			for (boneMap = boneMap->child, ii = 0; boneMap; boneMap = boneMap->next, ++ii) {
 				data->bones[ii] = spSkeletonData_findBone(skeletonData, boneMap->valueString);
 				data->bones[ii] = spSkeletonData_findBone(skeletonData, boneMap->valueString);
 				if (!data->bones[ii]) {
 				if (!data->bones[ii]) {
+					spTransformConstraintData_dispose(data);
 					spSkeletonData_dispose(skeletonData);
 					spSkeletonData_dispose(skeletonData);
 					_spSkeletonJson_setError(self, root, "Transform bone not found: ", boneMap->valueString);
 					_spSkeletonJson_setError(self, root, "Transform bone not found: ", boneMap->valueString);
 					return NULL;
 					return NULL;
@@ -1313,6 +1315,7 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
 			name = Json_getString(constraintMap, "target", 0);
 			name = Json_getString(constraintMap, "target", 0);
 			data->target = spSkeletonData_findBone(skeletonData, name);
 			data->target = spSkeletonData_findBone(skeletonData, name);
 			if (!data->target) {
 			if (!data->target) {
+				spTransformConstraintData_dispose(data);
 				spSkeletonData_dispose(skeletonData);
 				spSkeletonData_dispose(skeletonData);
 				_spSkeletonJson_setError(self, root, "Target bone not found: ", name);
 				_spSkeletonJson_setError(self, root, "Target bone not found: ", name);
 				return NULL;
 				return NULL;
@@ -1335,6 +1338,7 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
 			data->mixShearY = Json_getFloat(constraintMap, "mixShearY", 1);
 			data->mixShearY = Json_getFloat(constraintMap, "mixShearY", 1);
 
 
 			skeletonData->transformConstraints[i] = data;
 			skeletonData->transformConstraints[i] = data;
+			skeletonData->transformConstraintsCount++;
 		}
 		}
 	}
 	}
 
 
@@ -1342,7 +1346,6 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
 	pathJson = Json_getItem(root, "path");
 	pathJson = Json_getItem(root, "path");
 	if (pathJson) {
 	if (pathJson) {
 		Json *constraintMap;
 		Json *constraintMap;
-		skeletonData->pathConstraintsCount = pathJson->size;
 		skeletonData->pathConstraints = MALLOC(spPathConstraintData *, pathJson->size);
 		skeletonData->pathConstraints = MALLOC(spPathConstraintData *, pathJson->size);
 		for (constraintMap = pathJson->child, i = 0; constraintMap; constraintMap = constraintMap->next, ++i) {
 		for (constraintMap = pathJson->child, i = 0; constraintMap; constraintMap = constraintMap->next, ++i) {
 			const char *name;
 			const char *name;
@@ -1358,6 +1361,7 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
 			for (boneMap = boneMap->child, ii = 0; boneMap; boneMap = boneMap->next, ++ii) {
 			for (boneMap = boneMap->child, ii = 0; boneMap; boneMap = boneMap->next, ++ii) {
 				data->bones[ii] = spSkeletonData_findBone(skeletonData, boneMap->valueString);
 				data->bones[ii] = spSkeletonData_findBone(skeletonData, boneMap->valueString);
 				if (!data->bones[ii]) {
 				if (!data->bones[ii]) {
+					spPathConstraintData_dispose(data);
 					spSkeletonData_dispose(skeletonData);
 					spSkeletonData_dispose(skeletonData);
 					_spSkeletonJson_setError(self, root, "Path bone not found: ", boneMap->valueString);
 					_spSkeletonJson_setError(self, root, "Path bone not found: ", boneMap->valueString);
 					return NULL;
 					return NULL;
@@ -1367,6 +1371,7 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
 			name = Json_getString(constraintMap, "target", 0);
 			name = Json_getString(constraintMap, "target", 0);
 			data->target = spSkeletonData_findSlot(skeletonData, name);
 			data->target = spSkeletonData_findSlot(skeletonData, name);
 			if (!data->target) {
 			if (!data->target) {
+				spPathConstraintData_dispose(data);
 				spSkeletonData_dispose(skeletonData);
 				spSkeletonData_dispose(skeletonData);
 				_spSkeletonJson_setError(self, root, "Target slot not found: ", name);
 				_spSkeletonJson_setError(self, root, "Target slot not found: ", name);
 				return NULL;
 				return NULL;
@@ -1404,6 +1409,7 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
 			data->mixY = Json_getFloat(constraintMap, "mixY", data->mixX);
 			data->mixY = Json_getFloat(constraintMap, "mixY", data->mixX);
 
 
 			skeletonData->pathConstraints[i] = data;
 			skeletonData->pathConstraints[i] = data;
+			skeletonData->pathConstraintsCount++;
 		}
 		}
 	}
 	}
 
 
@@ -1471,6 +1477,7 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
 				for (skinPart = skinPart->child; skinPart; skinPart = skinPart->next) {
 				for (skinPart = skinPart->child; skinPart; skinPart = skinPart->next) {
 					spBoneData *bone = spSkeletonData_findBone(skeletonData, skinPart->valueString);
 					spBoneData *bone = spSkeletonData_findBone(skeletonData, skinPart->valueString);
 					if (!bone) {
 					if (!bone) {
+						spSkin_dispose(skin);
 						spSkeletonData_dispose(skeletonData);
 						spSkeletonData_dispose(skeletonData);
 						_spSkeletonJson_setError(self, root, "Skin bone constraint not found: ", skinPart->valueString);
 						_spSkeletonJson_setError(self, root, "Skin bone constraint not found: ", skinPart->valueString);
 						return NULL;
 						return NULL;
@@ -1485,6 +1492,7 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
 					spIkConstraintData *constraint = spSkeletonData_findIkConstraint(skeletonData,
 					spIkConstraintData *constraint = spSkeletonData_findIkConstraint(skeletonData,
 																					 skinPart->valueString);
 																					 skinPart->valueString);
 					if (!constraint) {
 					if (!constraint) {
+						spSkin_dispose(skin);
 						spSkeletonData_dispose(skeletonData);
 						spSkeletonData_dispose(skeletonData);
 						_spSkeletonJson_setError(self, root, "Skin IK constraint not found: ", skinPart->valueString);
 						_spSkeletonJson_setError(self, root, "Skin IK constraint not found: ", skinPart->valueString);
 						return NULL;
 						return NULL;
@@ -1499,6 +1507,7 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
 					spPathConstraintData *constraint = spSkeletonData_findPathConstraint(skeletonData,
 					spPathConstraintData *constraint = spSkeletonData_findPathConstraint(skeletonData,
 																						 skinPart->valueString);
 																						 skinPart->valueString);
 					if (!constraint) {
 					if (!constraint) {
+						spSkin_dispose(skin);
 						spSkeletonData_dispose(skeletonData);
 						spSkeletonData_dispose(skeletonData);
 						_spSkeletonJson_setError(self, root, "Skin path constraint not found: ", skinPart->valueString);
 						_spSkeletonJson_setError(self, root, "Skin path constraint not found: ", skinPart->valueString);
 						return NULL;
 						return NULL;
@@ -1513,6 +1522,7 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
 					spTransformConstraintData *constraint = spSkeletonData_findTransformConstraint(skeletonData,
 					spTransformConstraintData *constraint = spSkeletonData_findTransformConstraint(skeletonData,
 																								   skinPart->valueString);
 																								   skinPart->valueString);
 					if (!constraint) {
 					if (!constraint) {
+						spSkin_dispose(skin);
 						spSkeletonData_dispose(skeletonData);
 						spSkeletonData_dispose(skeletonData);
 						_spSkeletonJson_setError(self, root, "Skin transform constraint not found: ",
 						_spSkeletonJson_setError(self, root, "Skin transform constraint not found: ",
 												 skinPart->valueString);
 												 skinPart->valueString);
@@ -1766,13 +1776,13 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
 		spSkin *skin = !linkedMesh->skin ? skeletonData->defaultSkin : spSkeletonData_findSkin(skeletonData, linkedMesh->skin);
 		spSkin *skin = !linkedMesh->skin ? skeletonData->defaultSkin : spSkeletonData_findSkin(skeletonData, linkedMesh->skin);
 		if (!skin) {
 		if (!skin) {
 			spSkeletonData_dispose(skeletonData);
 			spSkeletonData_dispose(skeletonData);
-			_spSkeletonJson_setError(self, 0, "Skin not found: ", linkedMesh->skin);
+			_spSkeletonJson_setError(self, root, "Skin not found: ", linkedMesh->skin);
 			return NULL;
 			return NULL;
 		}
 		}
 		parent = spSkin_getAttachment(skin, linkedMesh->slotIndex, linkedMesh->parent);
 		parent = spSkin_getAttachment(skin, linkedMesh->slotIndex, linkedMesh->parent);
 		if (!parent) {
 		if (!parent) {
 			spSkeletonData_dispose(skeletonData);
 			spSkeletonData_dispose(skeletonData);
-			_spSkeletonJson_setError(self, 0, "Parent mesh not found: ", linkedMesh->parent);
+			_spSkeletonJson_setError(self, root, "Parent mesh not found: ", linkedMesh->parent);
 			return NULL;
 			return NULL;
 		}
 		}
 		linkedMesh->mesh->super.timelineAttachment = linkedMesh->inheritTimeline ? parent
 		linkedMesh->mesh->super.timelineAttachment = linkedMesh->inheritTimeline ? parent
@@ -1815,6 +1825,7 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
 			spAnimation *animation = _spSkeletonJson_readAnimation(self, animationMap, skeletonData);
 			spAnimation *animation = _spSkeletonJson_readAnimation(self, animationMap, skeletonData);
 			if (!animation) {
 			if (!animation) {
 				spSkeletonData_dispose(skeletonData);
 				spSkeletonData_dispose(skeletonData);
+				_spSkeletonJson_setError(self, root, "Animation broken: ", animationMap->name);
 				return NULL;
 				return NULL;
 			}
 			}
 			skeletonData->animations[skeletonData->animationsCount++] = animation;
 			skeletonData->animations[skeletonData->animationsCount++] = animation;