{"record":{"id":"3f3c632d447d37fc","repo":"jstedfast/MailKit","slug":"outputoffset-md4","errorCode":null,"errorMessage":"outputOffset","messagePattern":"outputOffset","errorType":"validation","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"MailKit/Security/Ntlm/MD4.cs","lineNumber":352,"sourceCode":"\t\t\tInitialize ();\n\n\t\t\treturn hashValue;\n\t\t}\n\n\t\tpublic int TransformBlock (byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)\n\t\t{\n\t\t\tif (inputBuffer == null)\n\t\t\t\tthrow new ArgumentNullException (nameof (inputBuffer));\n\n\t\t\tif (inputOffset < 0 || inputOffset > inputBuffer.Length)\n\t\t\t\tthrow new ArgumentOutOfRangeException (nameof (inputOffset));\n\n\t\t\tif (inputCount < 0 || inputOffset > inputBuffer.Length - inputCount)\n\t\t\t\tthrow new ArgumentOutOfRangeException (nameof (inputCount));\n\n\t\t\tif (outputBuffer != null) {\n\t\t\t\tif (outputOffset < 0 || outputOffset > outputBuffer.Length - inputCount)\n\t\t\t\t\tthrow new ArgumentOutOfRangeException (nameof (outputOffset));\n\t\t\t}\n\n\t\t\tHashCore (inputBuffer, inputOffset, inputCount);\n\n\t\t\tif (outputBuffer != null)\n\t\t\t\tBuffer.BlockCopy (inputBuffer, inputOffset, outputBuffer, outputOffset, inputCount);\n\n\t\t\treturn inputCount;\n\t\t}\n\n\t\tpublic byte[] TransformFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount)\n\t\t{\n\t\t\tif (inputCount < 0)\n\t\t\t\tthrow new ArgumentOutOfRangeException (nameof (inputCount));\n\n\t\t\tvar outputBuffer = new byte[inputCount];\n\n\t\t\t// note: other exceptions are handled by Buffer.BlockCopy","sourceCodeStart":334,"sourceCodeEnd":370,"githubUrl":"https://github.com/jstedfast/MailKit/blob/9d3859a7855e3e17582c07fd01972b8e262bf176/MailKit/Security/Ntlm/MD4.cs#L334-L370","documentation":"TransformBlock throws ArgumentOutOfRangeException named \"outputOffset\" when an outputBuffer is supplied and outputOffset is negative or greater than outputBuffer.Length - inputCount. Because TransformBlock copies inputCount bytes into outputBuffer at outputOffset, the destination region must fit entirely inside the output array.","triggerScenarios":"Calling TransformBlock(input, 0, inputCount, output, badOffset) where badOffset + inputCount > output.Length — e.g. reusing an output offset accumulated across blocks without accounting for inputCount, or an output buffer smaller than the input block.","commonSituations":"Using TransformBlock as an echo/copy transform (the ICryptoTransform contract) with a mis-sized scratch buffer; ported code assuming outputOffset is always 0 while passing leftover offsets; output buffer allocated for a different block size.","solutions":["Allocate outputBuffer at least inputCount bytes and pass outputOffset 0 when hashing-only.","Validate: 0 <= outputOffset && outputOffset <= outputBuffer.Length - inputCount before the call.","If no copy-back is needed, pass null for outputBuffer — the check is skipped entirely.","Recompute per-block output offsets (advance by inputCount each iteration)."],"exampleFix":"// before\ntransform.TransformBlock(input, 0, input.Length, output, outPos); // outPos + input.Length > output.Length\n// after\nint outPos = 0;\ntransform.TransformBlock(input, 0, input.Length, output, outPos);\noutPos += input.Length;","handlingStrategy":"validation","validationCode":"if (outputBuffer != null && (outputOffset < 0 || outputOffset > outputBuffer.Length - inputCount))\n    throw new ArgumentOutOfRangeException(nameof(outputOffset));","typeGuard":"static bool IsValidOutput(byte[] output, int outputOffset, int inputCount) =>\n    output == null || (outputOffset >= 0 && outputOffset <= output.Length - inputCount);","tryCatchPattern":"try { transform.TransformBlock(input, 0, inputCount, output, outputOffset); }\ncatch (ArgumentOutOfRangeException ex) when (ex.ParamName == \"outputOffset\") { log.LogError(ex, \"Output window [{Off},{Count}] exceeds len {Len}\", outputOffset, inputCount, output.Length); throw; }","preventionTips":["Pass null outputBuffer when you only need hashing, not copy-back","Size output buffers to at least the block size","Track outputOffset by advancing inputCount per block"],"tags":["argument-exception","crypto","out-of-range","transformblock"],"backgroundTag":"argument-out-of-range","analyzedSha":"9d3859a7855e3e17582c07fd01972b8e262bf176","analyzedAt":"2026-09-15T15:46:11.592Z","contentChangedAt":"2026-09-15T15:46:11.592Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}