From 49c338f6cf6ff1119e770d4ad25074f227154c79 Mon Sep 17 00:00:00 2001 From: Luke Ingram Date: Tue, 17 Feb 2026 12:49:27 -0400 Subject: [PATCH] [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 --- spine-c/spine-c/src/spine/SkeletonBinary.c | 24 ++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/spine-c/spine-c/src/spine/SkeletonBinary.c b/spine-c/spine-c/src/spine/SkeletonBinary.c index f18802d38..9cea00b1d 100644 --- a/spine-c/spine-c/src/spine/SkeletonBinary.c +++ b/spine-c/spine-c/src/spine/SkeletonBinary.c @@ -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) {