jstedfast/MailKit · error · ArgumentOutOfRangeException

Specified argument was out of the range of valid values.

Error message

Specified argument was out of the range of valid values.

What it means

NtlmSingleHostData.Decode throws ArgumentOutOfRangeException when startIndex is negative or points past the end of the buffer. Since the structure is fixed at 48 bytes, the decoder must have a valid starting position within the supplied blob. Validation happens before any field is read.

Solutions

  1. Validate startIndex is within [0, buffer.Length] before decoding
  2. Recompute the offset from the AV-pair walk, bounding it by buffer.Length
  3. Slice the exact 48-byte region first and decode it at index 0

Example fix

// before
var singleHost = new NtlmSingleHostData(buffer, offset, 48); // offset can exceed buffer
// after
offset = Math.Min(offset, buffer.Length - 48);
if (offset >= 0)
    var singleHost = new NtlmSingleHostData(buffer, offset, 48);
Defensive patterns

Strategy: validation

Validate before calling

if (buffer == null || startIndex < 0 || startIndex + 48 > buffer.Length)
    throw new ArgumentOutOfRangeException(nameof(startIndex));

Type guard

static bool CanDecodeAt(byte[] b, int start) => b != null && start >= 0 && start + 48 <= b.Length;

Try / catch

try { var d = new NtlmSingleHostData(buffer, offset, 48); }
catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "startIndex") { /* recompute AV-pair offset */ }

Prevention

When it happens

Trigger: Calling the blob constructor / Decode with startIndex < 0 or startIndex > buffer.Length, e.g. an offset past the end of the target-info AV-pair buffer.

Common situations: Computing the Single_Host_Data offset from AV-pair walking that overran the buffer; passing the length as the offset; off-by-one after skipping a 4-byte AV header.

Related errors


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

Appendix: source

Thrown at MailKit/Security/Ntlm/NtlmSingleHostData.cs:131

		/// <summary>
		/// Get the size of the SingleHostData structure.
		/// </summary>
		/// <remarks>
		/// Gets the size of the SingleHostData structure.
		/// </remarks>
		/// <value>The size of the SingleHostData structure.</value>
		public int Size {
			get; private set;
		}

		[MemberNotNull (nameof (CustomData), nameof (MachineId))]
		void Decode (byte[] buffer, int startIndex, int length)
		{
			if (buffer == null)
				throw new ArgumentNullException (nameof (buffer));

			if (startIndex < 0 || startIndex > buffer.Length)
				throw new ArgumentOutOfRangeException (nameof (startIndex));

			if (length < 48 || length > (buffer.Length - startIndex))
				throw new ArgumentOutOfRangeException (nameof (length));

			int index = startIndex;

			// Size (4 bytes): A 32-bit unsigned integer that defines the length, in bytes, of the Value field in the AV_PAIR (section 2.2.2.1) structure.
			Size = BitConverterLE.ToInt32 (buffer, index);
			index += 4;

			// Z4 (4 bytes): A 32-bit integer value containing 0x00000000.
			index += 4;

			// CustomData (8 bytes): An 8-byte platform-specific blob containing info only relevant when the client and the server are on the same host.
			CustomData = new byte[8];
			Buffer.BlockCopy (buffer, index, CustomData, 0, 8);
			index += 8;

View on GitHub (pinned to 9d3859a785)