jstedfast/MailKit · error · ArgumentOutOfRangeException

outputOffset

Error message

outputOffset

What it means

DES.TransformBlock validates outputOffset with ArgumentOutOfRangeException: it must be >= 0 and allow 8 bytes to be written, i.e. outputOffset <= outputBuffer.Length - 8. This guarantees the cipher never writes past the end of the destination buffer.

Solutions

  1. Size the output buffer as a multiple of 8 bytes (or input length rounded up) and advance outputOffset by 8 per block.
  2. Before each call, assert outputOffset + 8 <= outputBuffer.Length.
  3. Fix loop bounds so the last iteration's offset still leaves room for a full block.

Example fix

// before
des.TransformBlock(input, i, 8, output, i); // output too small near end

// after
if (i + 8 <= output.Length)
    des.TransformBlock(input, i, 8, output, i);
Defensive patterns

Strategy: validation

Validate before calling

if (outputOffset >= 0 && outputOffset + 8 <= outputBuffer.Length)
    des.TransformBlock(input, 0, 8, outputBuffer, outputOffset);

Type guard

static bool OutputFits(byte[] buf, int off) => off >= 0 && off + 8 <= buf.Length;

Try / catch

try {
    des.TransformBlock(input, 0, 8, output, outOff);
} catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "outputOffset") {
    // grow the output buffer or fix the offset before retrying
}

Prevention

When it happens

Trigger: Calling TransformBlock with outputOffset < 0 or outputOffset > outputBuffer.Length - 8, e.g. writing to the tail of an output buffer that is too small for one more block.

Common situations: Output buffer allocated exactly for the message but loop writes one block too many; offset math off by 8 after the last chunk; buffer downsized between iterations.

Related errors


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

Appendix: source

Thrown at MailKit/Security/Ntlm/DES.cs:123

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

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

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

				if (inputCount != 8)
					throw new ArgumentOutOfRangeException ("inputCount", "Can only transform 8 bytes at a time.");

				if (outputBuffer == null)
					throw new ArgumentNullException ("outputBuffer");

				if (outputOffset < 0 || outputOffset > outputBuffer.Length - 8)
					throw new ArgumentOutOfRangeException ("outputOffset");

				return engine.ProcessBlock (inputBuffer, inputOffset, outputBuffer, outputOffset);
			}

			public byte[] TransformFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount)
			{
				if (inputBuffer == null)
					throw new ArgumentNullException ("inputBuffer");

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

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

				var output = new byte[8];

				engine.ProcessBlock (inputBuffer, inputOffset, output, 0);

View on GitHub (pinned to 9d3859a785)