{"record":{"id":"68433d82ef923ba1","repo":"EllanJiang/GameFramework","slug":"result-length-is-not-enough","errorCode":null,"errorMessage":"Result length is not enough.","messagePattern":"Result length is not enough\\.","errorType":"exception","errorClass":"GameFrameworkException","httpStatus":null,"severity":"error","filePath":"GameFramework/Utility/Utility.Marshal.cs","lineNumber":161,"sourceCode":"            {\n                if (structureSize < 0)\n                {\n                    throw new GameFrameworkException(\"Structure size is invalid.\");\n                }\n\n                if (result == null)\n                {\n                    throw new GameFrameworkException(\"Result is invalid.\");\n                }\n\n                if (startIndex < 0)\n                {\n                    throw new GameFrameworkException(\"Start index is invalid.\");\n                }\n\n                if (startIndex + structureSize > result.Length)\n                {\n                    throw new GameFrameworkException(\"Result length is not enough.\");\n                }\n\n                EnsureCachedHGlobalSize(structureSize);\n                System.Runtime.InteropServices.Marshal.StructureToPtr(structure, s_CachedHGlobalPtr, true);\n                System.Runtime.InteropServices.Marshal.Copy(s_CachedHGlobalPtr, result, startIndex, structureSize);\n            }\n\n            /// <summary>\n            /// 将数据从二进制流转换为对象。\n            /// </summary>\n            /// <typeparam name=\"T\">要转换的对象的类型。</typeparam>\n            /// <param name=\"buffer\">要转换的二进制流。</param>\n            /// <returns>存储转换结果的对象。</returns>\n            public static T BytesToStructure<T>(byte[] buffer)\n            {\n                return BytesToStructure<T>(System.Runtime.InteropServices.Marshal.SizeOf(typeof(T)), buffer, 0);\n            }\n","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/EllanJiang/GameFramework/blob/d0c010b05167c58e92350449d04864a91ca13fd2/GameFramework/Utility/Utility.Marshal.cs#L143-L179","documentation":"After validating startIndex, StructureToBytes checks that the destination byte array has room for structureSize bytes starting at startIndex. If startIndex + structureSize exceeds result.Length, the library throws instead of letting the unmanaged copy overflow. The struct bytes are staged in a cached HGlobal buffer and copied via Marshal.Copy, which requires the destination range to fit exactly.","triggerScenarios":"Calling Utility.Marshal.StructureToBytes where result.Length < startIndex + structureSize — e.g. a too-small byte array allocated for a smaller struct, or writing a large struct at a nonzero offset in a fixed-size buffer.","commonSituations":"Struct definition grew (added fields) but the destination buffer size constant was not updated; writing multiple structs sequentially into a packet buffer and running past the end; wrong sizeof estimate for a struct with Blittable/unicode fields.","solutions":["Allocate result with at least startIndex + structureSize bytes (use Marshal.SizeOf<T> or the structureSize you pass).","Lower startIndex or split the write so the range fits within the existing buffer.","Recheck struct size after any struct field changes and update buffer-size constants."],"exampleFix":"// before\nbyte[] dest = new byte[16]; // too small after struct grew\nUtility.Marshal.StructureToBytes(header, Marshal.SizeOf<Header>(), dest, 0);\n// after\nint size = Marshal.SizeOf<Header>();\nbyte[] dest = new byte[size];\nUtility.Marshal.StructureToBytes(header, size, dest, 0);","handlingStrategy":"validation","validationCode":"int needed = startIndex + structureSize;\nif (result == null || result.Length < needed)\n    result = new byte[needed];\nUtility.Marshal.StructureToBytes(structure, structureSize, result, startIndex);","typeGuard":null,"tryCatchPattern":"try\n{\n    Utility.Marshal.StructureToBytes(structure, size, dest, offset);\n}\ncatch (GameFrameworkException ex) when (ex.Message == \"Result length is not enough.\")\n{\n    dest = new byte[offset + size];\n    Utility.Marshal.StructureToBytes(structure, size, dest, offset);\n}","preventionTips":["Always size buffers from Marshal.SizeOf<T>() rather than hardcoded constants.","Re-derive buffer sizes whenever a struct definition changes; add a unit test asserting buffer capacity.","Reserve capacity once when building multi-struct packet buffers."],"tags":["buffer-size","marshaling","gameframework"],"backgroundTag":"value-out-of-range","analyzedSha":"d0c010b05167c58e92350449d04864a91ca13fd2","analyzedAt":"2026-09-15T13:37:15.352Z","contentChangedAt":"2026-09-15T13:37:15.352Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}