{"record":{"id":"9bcc391c94e7ba0e","repo":"jstedfast/MailKit","slug":"hashalgorithm","errorCode":null,"errorMessage":"HashAlgorithm","messagePattern":"HashAlgorithm","errorType":"validation","errorClass":"ObjectDisposedException","httpStatus":null,"severity":"error","filePath":"MailKit/Security/Ntlm/HMACMD5.cs","lineNumber":112,"sourceCode":"\n\t\tpublic void Clear ()\n\t\t{\n\t\t\tDispose (false);\n\t\t}\n\n\t\tpublic byte[] ComputeHash (byte[] buffer, int offset, int count)\n\t\t{\n\t\t\tif (buffer == null)\n\t\t\t\tthrow new ArgumentNullException (nameof (buffer));\n\n\t\t\tif (offset < 0 || offset > buffer.Length)\n\t\t\t\tthrow new ArgumentOutOfRangeException (nameof (offset));\n\n\t\t\tif (count < 0 || offset > buffer.Length - count)\n\t\t\t\tthrow new ArgumentOutOfRangeException (nameof (count));\n\n\t\t\tif (disposed)\n\t\t\t\tthrow new ObjectDisposedException (\"HashAlgorithm\");\n\n\t\t\tHashCore (buffer, offset, count);\n\t\t\thashValue = HashFinal ();\n\n\t\t\treturn hashValue;\n\t\t}\n\n\t\tpublic byte[] ComputeHash (byte[] buffer)\n\t\t{\n\t\t\tif (buffer == null)\n\t\t\t\tthrow new ArgumentNullException (nameof (buffer));\n\n\t\t\treturn ComputeHash (buffer, 0, buffer.Length);\n\t\t}\n\n\t\tpublic byte[] ComputeHash (Stream inputStream)\n\t\t{\n\t\t\t// don't read stream unless object is ready to use","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/jstedfast/MailKit/blob/9d3859a7855e3e17582c07fd01972b8e262bf176/MailKit/Security/Ntlm/HMACMD5.cs#L94-L130","documentation":"HMACMD5.ComputeHash(buffer, offset, count) throws an ArgumentOutOfRange with the name 'HashAlgorithm' when the instance has already been disposed. MailKit's NTLM HMACMD5 mimics System.Security.Cryptography.HashAlgorithm, which signals a used-up object via ObjectDisposedException('HashAlgorithm'). Once Dispose() runs, the internal MD5 state is gone and hashing can no longer proceed.","triggerScenarios":"Calling ComputeHash after HMACMD5.Dispose() was invoked (explicitly or via using block); reusing a single instance across two authentication attempts where the first attempt disposed it.","commonSituations":"Reusing one HMACMD5 instance for multiple NTLM auth rounds in a connection pool; wrapping the hash in 'using' then calling ComputeHash afterwards; disposal triggered by an outer authenticate() finally block.","solutions":["Create a new HMACMD5 instance for each ComputeHash call instead of reusing a disposed one","Move ComputeHash calls inside the using/undisposed scope","Verify no double-dispose via IDisposable cascades (e.g., SaslMechanism disposing the HMAC early)"],"exampleFix":"// before\nusing (var hmac = new HMACMD5 (key)) { }\nbyte[] hash = hmac.ComputeHash (data); // ObjectDisposedException\n// after\nusing (var hmac = new HMACMD5 (key)) {\n    byte[] hash = hmac.ComputeHash (data);\n}","handlingStrategy":"try-catch","validationCode":"if (hmac == null) throw new InvalidOperationException (\"HMACMD5 not created\");\n// MailKit's HMACMD5 exposes no public IsDisposed; track it yourself:\nbool disposed = false;\nif (disposed) throw new InvalidOperationException (\"HMAC instance already disposed\");","typeGuard":"static bool IsUsable (HMACMD5? hmac) => hmac != null && !ReferenceEquals (hmac, null);","tryCatchPattern":"try {\n    byte[] hash = hmac.ComputeHash (data);\n} catch (ObjectDisposedException) {\n    hmac = new HMACMD5 (key);\n    byte[] hash = hmac.ComputeHash (data);\n}","preventionTips":["Create a new HMACMD5 per hashing operation; instances are cheap","Scope instance and usage inside the same using block","Never cache hash instances across authentication attempts"],"tags":["csharp","disposed-object","hashing","ntlm"],"backgroundTag":"invalid-state-transition","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"}