{"record":{"id":"f9deb2e9a696c8a8","repo":"EllanJiang/GameFramework","slug":"start-index-is-invalid-utility-marshal","errorCode":null,"errorMessage":"Start index is invalid.","messagePattern":"Start index is invalid\\.","errorType":"exception","errorClass":"GameFrameworkException","httpStatus":null,"severity":"error","filePath":"GameFramework/Utility/Utility.Marshal.cs","lineNumber":156,"sourceCode":"            /// <param name=\"structure\">要转换的对象。</param>\n            /// <param name=\"structureSize\">要转换的对象的大小。</param>\n            /// <param name=\"result\">存储转换结果的二进制流。</param>\n            /// <param name=\"startIndex\">写入存储转换结果的二进制流的起始位置。</param>\n            internal static void StructureToBytes<T>(T structure, int structureSize, byte[] result, int startIndex)\n            {\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>","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/EllanJiang/GameFramework/blob/d0c010b05167c58e92350449d04864a91ca13fd2/GameFramework/Utility/Utility.Marshal.cs#L138-L174","documentation":"Utility.Marshal.StructureToBytes validates the startIndex parameter before copying a struct's bytes into the caller-supplied result buffer. A negative startIndex can never address a valid location in the byte array, so the library throws GameFrameworkException immediately. This is a cheap upfront guard against invalid offsets in the unmanaged-memory marshaling path.","triggerScenarios":"Calling Utility.Marshal.StructureToBytes(structure, structureSize, result, startIndex) with a negative startIndex value, e.g. an offset computed from an arithmetic underflow or an uninitialized cursor variable.","commonSituations":"Computing a write offset by subtracting lengths that can go negative; deserializing chunked data where a packet offset variable was not initialized; passing -1 as a sentinel offset by mistake.","solutions":["Inspect the startIndex argument passed to StructureToBytes and ensure it is >= 0 before calling.","Fix the offset computation that produced the negative value (check subtraction order and initialization).","Add a caller-side assertion/parameter validation to reject negative offsets at the API boundary."],"exampleFix":"// before\nint offset = bufferPosition - blockLength; // can be negative\nUtility.Marshal.StructureToBytes(header, headerSize, dest, offset);\n// after\nint offset = bufferPosition - blockLength;\nif (offset < 0) throw new ArgumentOutOfRangeException(nameof(offset));\nUtility.Marshal.StructureToBytes(header, headerSize, dest, offset);","handlingStrategy":"validation","validationCode":"if (startIndex < 0)\n    throw new ArgumentOutOfRangeException(nameof(startIndex));\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 == \"Start index is invalid.\")\n{\n    // log offset computation bug and correct the cursor\n}","preventionTips":["Track buffer offsets in a single cursor variable that is only ever advanced by positive amounts.","Assert offsets are non-negative in debug builds with Debug.Assert(offset >= 0).","Avoid -1 sentinels for offsets; use nullable int instead."],"tags":["argument-validation","marshaling","gameframework"],"backgroundTag":"invalid-argument-value","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"}