{"record":{"id":"a5b2f739e206670c","repo":"peass-ng/PEASS-ng","slug":"attempt-to-absorb-with-odd-length-queue","errorCode":null,"errorMessage":"attempt to absorb with odd length queue","messagePattern":"attempt to absorb with odd length queue","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"winPEAS/winPEASexe/winPEAS/3rdParty/BouncyCastle/crypto/digests/KeccakDigest.cs","lineNumber":152,"sourceCode":"        }\n\n        private void InitSponge(int rate)\n        {\n            if (rate <= 0 || rate >= 1600 || (rate & 63) != 0)\n                throw new InvalidOperationException(\"invalid rate value\");\n\n            this.rate = rate;\n            Array.Clear(state, 0, state.Length);\n            Arrays.Fill(this.dataQueue, (byte)0);\n            this.bitsInQueue = 0;\n            this.squeezing = false;\n            this.fixedOutputLength = (1600 - rate) >> 1;\n        }\n\n        protected void Absorb(byte data)\n        {\n            if ((bitsInQueue & 7) != 0)\n                throw new InvalidOperationException(\"attempt to absorb with odd length queue\");\n            if (squeezing)\n                throw new InvalidOperationException(\"attempt to absorb while squeezing\");\n\n            dataQueue[bitsInQueue >> 3] = data;\n            if ((bitsInQueue += 8) == rate)\n            {\n                KeccakAbsorb(dataQueue, 0);\n                bitsInQueue = 0;\n            }\n        }\n\n        protected void Absorb(byte[] data, int off, int len)\n        {\n            if ((bitsInQueue & 7) != 0)\n                throw new InvalidOperationException(\"attempt to absorb with odd length queue\");\n            if (squeezing)\n                throw new InvalidOperationException(\"attempt to absorb while squeezing\");\n","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/peass-ng/PEASS-ng/blob/53fb989abc2219826385683a6fee826bd6cd38d6/winPEAS/winPEASexe/winPEAS/3rdParty/BouncyCastle/crypto/digests/KeccakDigest.cs#L134-L170","documentation":"During absorbing, the Keccak implementation buffers bits and must always append 8 bits at a byte boundary. Absorb(byte) checks bitsInQueue % 8 == 0 before writing; if a partial byte is queued it throws InvalidOperationException. This is an internal invariant — the public Update always feeds whole bytes, so it indicates misuse of an instance mid-update or corrupt state.","triggerScenarios":"Absorb() reached while bitsInQueue is not a multiple of 8 — e.g. after a failed/partial Update left the queue misaligned, concurrent BlockUpdate calls on a shared digest instance, or calling the protected Absorb directly from a subclass after manipulating the queue.","commonSituations":"Sharing one IDigest across threads without synchronization; resuming a hash from a deserialized half-used instance; custom sponge subclasses that call Absorb byte-wise after a bit-level squeeze.","solutions":["Create a new digest instance (or call Reset()) instead of reusing an instance whose update failed halfway.","Use one IDigest instance per thread; synchronize access if sharing is unavoidable.","Feed data only via BlockUpdate()/Update() with whole bytes; never call Absorb directly after custom bit manipulation."],"exampleFix":"// before\nvar d = new KeccakDigest(256);\nParallel.For(0, 10, i => d.BlockUpdate(data, 0, data.Length)); // races corrupt queue\n// after\nvar d = new KeccakDigest(256);\nd.BlockUpdate(data, 0, data.Length); // single-threaded, or lock around updates","handlingStrategy":"try-catch","validationCode":"// ensure single-threaded, whole-byte updates\nlock (digestLock) { digest.BlockUpdate(data, 0, data.Length); }","typeGuard":null,"tryCatchPattern":"try { digest.BlockUpdate(data, 0, data.Length); }\ncatch (InvalidOperationException ex) {\n    digest.Reset(); // discard misaligned state and restart the hash\n}","preventionTips":["Never share an IDigest across threads without locking","Reset() or recreate a digest after any failed update","Feed data only via BlockUpdate/Update with whole bytes","Avoid custom bit-level manipulation of the sponge queue"],"tags":["csharp","cryptography","invalid-operation","keccak","thread-safety"],"backgroundTag":"invalid-absorb-state","analyzedSha":"53fb989abc2219826385683a6fee826bd6cd38d6","analyzedAt":"2026-09-02T04:25:09.259Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T11:17:12.671Z"}