{"record":{"id":"76eb9625ae2f63ea","repo":"tursodatabase/turso","slug":"offset-and-count-were-out-of-bounds-for-the-array","errorCode":null,"errorMessage":"Offset and count were out of bounds for the array.","messagePattern":"Offset and count were out of bounds for the array\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"bindings/dotnet/src/Turso.Data.Sqlite/SqliteBlob.cs","lineNumber":158,"sourceCode":"        var value = command.ExecuteScalar();\n        return value switch\n        {\n            byte[] bytes => bytes,\n            string text => Encoding.UTF8.GetBytes(text),\n            null or DBNull => throw new SqliteException(Properties.Resources.SqliteNativeError(1, \"no such rowid: \" + rowId), 1),\n            _ => Encoding.UTF8.GetBytes(Convert.ToString(value, System.Globalization.CultureInfo.InvariantCulture) ?? string.Empty)\n        };\n    }\n\n    private static void ValidateBuffer(byte[] buffer, int offset, int count)\n    {\n        ArgumentNullException.ThrowIfNull(buffer);\n        if (offset < 0)\n            throw new ArgumentOutOfRangeException(nameof(offset), offset, message: null);\n        if (count < 0)\n            throw new ArgumentOutOfRangeException(nameof(count), count, message: null);\n        if (offset > buffer.Length || count > buffer.Length - offset)\n            throw new ArgumentException(Properties.Resources.InvalidOffsetAndCount);\n    }\n\n    private static string QuoteIdentifier(string identifier)\n        => \"\\\"\" + identifier.Replace(\"\\\"\", \"\\\"\\\"\", StringComparison.Ordinal) + \"\\\"\";\n}\n","sourceCodeStart":140,"sourceCodeEnd":164,"githubUrl":"https://github.com/tursodatabase/turso/blob/244cde92a7df7f9b8b8b7a4075c35a12977e303e/bindings/dotnet/src/Turso.Data.Sqlite/SqliteBlob.cs#L140-L164","documentation":"Every Read/Write first calls ValidateBuffer, which enforces the standard bounds contract: buffer non-null, offset/count non-negative, and offset <= buffer.Length && count <= buffer.Length - offset. Any violation throws ArgumentException (Properties.Resources.InvalidOffsetAndCount) before any I/O happens, matching System.IO's span rules.","triggerScenarios":"Passing a count larger than the space remaining after offset (the classic off-by-one: count = buffer.Length while offset > 0); negative offset/count from unsigned underflow or parsed input; an offset past the end of the buffer.","commonSituations":"Looping reads that keep an offset cursor but pass the full length as count; (buffer, 0, int.MaxValue) 'read everything' idioms; pointer-arithmetic code translated from C/C++; header-size math off by one.","solutions":["Derive count from the remaining space: count = Math.Min(requested, buffer.Length - offset).","Prefer modern APIs (stream.ReadExactly, spans/ArraySegment) that remove manual bounds math.","When it throws, log buffer.Length/offset/count at the call site - the values are always the fastest clue."],"exampleFix":"// before\nint read = blob.Read(buf, offset: 4, count: buf.Length); // 4 + buf.Length > buf.Length -> throws\n\n// after\nint read = blob.Read(buf, 4, buf.Length - 4);","handlingStrategy":"validation","validationCode":"static void CheckBounds(byte[] buffer, int offset, int count) {\n    ArgumentNullException.ThrowIfNull(buffer);\n    if (offset < 0 || count < 0 || offset > buffer.Length || count > buffer.Length - offset)\n        throw new ArgumentException(\"offset/count out of bounds\");\n}\n\nCheckBounds(buf, off, cnt);\nblob.Read(buf, off, cnt);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always derive count from buffer.Length - offset.","Use ReadExactly/span-based APIs that eliminate manual bounds math.","Validate parsed sizes before they reach stream calls."],"tags":["dotnet","stream","buffer-bounds","argument-validation"],"backgroundTag":"buffer-bounds-validation","analyzedSha":"244cde92a7df7f9b8b8b7a4075c35a12977e303e","analyzedAt":"2026-08-20T07:02:18.389Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}