mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-25 22:23:42 +08:00
[c] Fix heap-buffer-overflow in _readVertices for weighted vertices.
The original code allocated vertex/bone buffers using hardcoded multipliers that assumed a maximum of ~3 bones per vertex. Skeletons with vertices exceeding this limit caused a heap-buffer-overflow, corrupting adjacent heap metadata and crashing on subsequent loads. Fix uses a two-pass approach: first scan the binary data to compute exact buffer sizes needed, then rewind and read. This produces exact-fit allocations with zero waste. Fixes #2992
This commit is contained in:
parent
ea452616b4
commit
49c338f6cf
@ -1027,8 +1027,28 @@ static int _readVertices(_dataInput *input, float **vertices, int *verticesLengt
|
||||
return *verticesLength;
|
||||
}
|
||||
|
||||
float *v = MALLOC(float, (*verticesLength) * 3 * 3);
|
||||
int *b = MALLOC(int, (*verticesLength) * 3);
|
||||
/* First pass: scan the binary data to compute exact buffer sizes needed. */
|
||||
const unsigned char *savedCursor = input->cursor;
|
||||
int totalBoneEntries = 0;
|
||||
int totalVertexEntries = 0;
|
||||
for (int i = 0; i < vertexCount; ++i) {
|
||||
int boneCount = readVarint(input, 1);
|
||||
totalBoneEntries += 1 + boneCount; /* 1 for the count + 1 per bone index */
|
||||
totalVertexEntries += boneCount * 3; /* 3 floats (x, y, weight) per bone */
|
||||
for (int ii = 0; ii < boneCount; ++ii) {
|
||||
readVarint(input, 1); /* bone index, skip */
|
||||
readFloat(input); /* x, skip */
|
||||
readFloat(input); /* y, skip */
|
||||
readFloat(input); /* weight, skip */
|
||||
}
|
||||
}
|
||||
|
||||
/* Rewind to start of vertex data. */
|
||||
input->cursor = savedCursor;
|
||||
|
||||
/* Second pass: allocate exact sizes and read. */
|
||||
float *v = MALLOC(float, totalVertexEntries);
|
||||
int *b = MALLOC(int, totalBoneEntries);
|
||||
int boneIdx = 0;
|
||||
int vertexIdx = 0;
|
||||
for (int i = 0; i < vertexCount; ++i) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user