XINCGer/Unity3DTraining · error · ArgumentOutOfRangeException

Length must be non-negative and within the buffer

Error message

Length must be non-negative and within the buffer

What it means

The same constructor validates that the requested length is non-negative and that offset+length does not run past the end of the buffer. If length < 0 or offset + length > buffer.Length, ArgumentOutOfRangeException('Length must be non-negative and within the buffer') is thrown. This prevents the parser from ever reading beyond the supplied data.

Solutions

  1. Compute length as buffer.Length - offset and validate it is >= 0 before constructing the reader.
  2. Validate any length-prefix from the wire against the actual bytes available before honoring it.
  3. Log the buffer length, offset, and computed length at the failure site to find the bad arithmetic.
  4. If truncation is expected, handle it at the framing layer (buffer more data) instead of passing an over-large length.

Example fix

// before
var stream = new CodedInputStream(buf, pos, declaredLen);
// after
int available = buf.Length - pos;
int len = Math.Min(declaredLen, available);
if (len < 0) throw new InvalidDataException("Truncated message");
var stream = new CodedInputStream(buf, pos, len);
Defensive patterns

Strategy: validation

Validate before calling

int avail = buffer.Length - offset;
if (length < 0 || length > avail) throw new ArgumentException($"length {length} invalid; only {avail} bytes available at offset {offset}");

Type guard

bool IsValidWindow(byte[] buffer, int offset, int length) => offset >= 0 && length >= 0 && offset + length <= buffer.Length;

Try / catch

try { var s = new CodedInputStream(buffer, offset, length); ... } catch (ArgumentOutOfRangeException ex) { logger.LogError(ex, "Bad buffer window"); bufferMoreDataFromSocket(); }

Prevention

When it happens

Trigger: new CodedInputStream(buffer, offset, length) with a negative length (e.g. computing length = end - start where end < start), or length so large that offset + length exceeds buffer.Length (e.g. assuming a length prefix that exceeds the actual payload).

Common situations: Framing messages from a stream where the declared message length is trusted but the packet was truncated; off-by-one in start/end index arithmetic; reading a length header in the wrong endianness producing a huge length.

Related errors


AI-assisted analysis of XINCGer/Unity3DTraining@016f98412e (2026-09-12). Data as JSON: /api/errors/a6cd234e185df493. Report an issue: GitHub.

Appendix: source

Thrown at NetWorkAndResources/Socket_Protobuff/Assets/Plugins/Google.Protobuf/CodedInputStream.cs:140

        /// Creates a new CodedInputStream reading data from the given byte array.
        /// </summary>
        public CodedInputStream(byte[] buffer) : this(null, ProtoPreconditions.CheckNotNull(buffer, "buffer"), 0, buffer.Length)
        {
        }

        /// <summary>
        /// Creates a new <see cref="CodedInputStream"/> that reads from the given byte array slice.
        /// </summary>
        public CodedInputStream(byte[] buffer, int offset, int length)
            : this(null, ProtoPreconditions.CheckNotNull(buffer, "buffer"), offset, offset + length)
        {
            if (offset < 0 || offset > buffer.Length)
            {
                throw new ArgumentOutOfRangeException("offset", "Offset must be within the buffer");
            }
            if (length < 0 || offset + length > buffer.Length)
            {
                throw new ArgumentOutOfRangeException("length", "Length must be non-negative and within the buffer");
            }
        }

        /// <summary>
        /// Creates a new <see cref="CodedInputStream"/> reading data from the given stream, which will be disposed
        /// when the returned object is disposed.
        /// </summary>
        /// <param name="input">The stream to read from.</param>
        public CodedInputStream(Stream input) : this(input, false)
        {
        }

        /// <summary>
        /// Creates a new <see cref="CodedInputStream"/> reading data from the given stream.
        /// </summary>
        /// <param name="input">The stream to read from.</param>
        /// <param name="leaveOpen"><c>true</c> to leave <paramref name="input"/> open when the returned
        /// <c cref="CodedInputStream"/> is disposed; <c>false</c> to dispose of the given stream when the

View on GitHub (pinned to 016f98412e)