jstedfast/MailKit · error · ArgumentOutOfRangeException

inputOffset

Error message

inputOffset

What it means

TransformBlock throws ArgumentOutOfRangeException named "inputOffset" when inputOffset is negative or greater than inputBuffer.Length. This keeps the transform's read window within the input array, mirroring ICryptoTransform argument contracts. It is thrown before HashCore mutates state, so incremental hashing remains consistent.

Solutions

  1. Recompute/validate inputOffset per call: it must satisfy 0 <= inputOffset <= inputBuffer.Length.
  2. Track the running offset from the same buffer being transformed; reset it when switching buffers.
  3. Use safe chunking (offset advances by chunk.Length from 0) instead of manual arithmetic.
  4. Validate externally supplied offsets before the call and reject with a clear message.

Example fix

// before
transform.TransformBlock(buf, pos, buf.Length - pos, null, 0); // pos may exceed buf.Length
// after
int pos = 0;
while (pos < buf.Length) {
    int n = Math.Min(4096, buf.Length - pos);
    transform.TransformBlock(buf, pos, n, null, 0);
    pos += n;
}
Defensive patterns

Strategy: validation

Validate before calling

if (inputOffset < 0 || inputOffset > inputBuffer.Length)
    throw new ArgumentOutOfRangeException(nameof(inputOffset));

Type guard

static bool IsValidOffset(byte[] buf, int offset) => offset >= 0 && offset <= buf.Length;

Try / catch

try { transform.TransformBlock(buf, offset, count, null, 0); }
catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "inputOffset") { log.LogError(ex, "inputOffset {Offset} invalid for len {Len}", offset, buf.Length); throw; }

Prevention

When it happens

Trigger: Calling TransformBlock(buf, -1, len, null, 0) or TransformBlock(buf, buf.Length + 1, 0, null, 0); incremental loops where a running offset accumulates past the buffer end due to a wrong increment or stale offset variable.

Common situations: Chunked hashing where chunk offsets are computed from previous chunk sizes with an off-by-one; NTLM message assembly code reusing an offset across differently sized buffers.

Related errors


AI-assisted analysis of jstedfast/MailKit@9d3859a785 (2026-09-15). Data as JSON: /api/errors/20fc3a7496aa903e. Report an issue: GitHub.

Appendix: source

Thrown at MailKit/Security/Ntlm/MD4.cs:345

			do {
				if ((nread = inputStream.Read (buffer, 0, buffer.Length)) > 0)
					HashCore (buffer, 0, nread);
			} while (nread > 0);

			hashValue = HashFinal ();
			Initialize ();

			return hashValue;
		}

		public int TransformBlock (byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
		{
			if (inputBuffer == null)
				throw new ArgumentNullException (nameof (inputBuffer));

			if (inputOffset < 0 || inputOffset > inputBuffer.Length)
				throw new ArgumentOutOfRangeException (nameof (inputOffset));

			if (inputCount < 0 || inputOffset > inputBuffer.Length - inputCount)
				throw new ArgumentOutOfRangeException (nameof (inputCount));

			if (outputBuffer != null) {
				if (outputOffset < 0 || outputOffset > outputBuffer.Length - inputCount)
					throw new ArgumentOutOfRangeException (nameof (outputOffset));
			}

			HashCore (inputBuffer, inputOffset, inputCount);

			if (outputBuffer != null)
				Buffer.BlockCopy (inputBuffer, inputOffset, outputBuffer, outputOffset, inputCount);

			return inputCount;
		}

		public byte[] TransformFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount)

View on GitHub (pinned to 9d3859a785)