{"record":{"id":"9b4c51ae55c1d357","repo":"golang/go","slug":"crypto-sha512-invalid-hash-state-size-9b4c51","errorCode":null,"errorMessage":"crypto/sha512: invalid hash state size","messagePattern":"crypto/sha512: invalid hash state size","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/internal/fips140/sha512/sha512.go","lineNumber":177,"sourceCode":"\tb = append(b, make([]byte, len(d.x)-d.nx)...)\n\tb = byteorder.BEAppendUint64(b, d.len)\n\treturn b, nil\n}\n\nfunc (d *Digest) UnmarshalBinary(b []byte) error {\n\tif len(b) < len(magic512) {\n\t\treturn errors.New(\"crypto/sha512: invalid hash state identifier\")\n\t}\n\tswitch {\n\tcase d.size == size384 && string(b[:len(magic384)]) == magic384:\n\tcase d.size == size224 && string(b[:len(magic512_224)]) == magic512_224:\n\tcase d.size == size256 && string(b[:len(magic512_256)]) == magic512_256:\n\tcase d.size == size512 && string(b[:len(magic512)]) == magic512:\n\tdefault:\n\t\treturn errors.New(\"crypto/sha512: invalid hash state identifier\")\n\t}\n\tif len(b) != marshaledSize {\n\t\treturn errors.New(\"crypto/sha512: invalid hash state size\")\n\t}\n\tb = b[len(magic512):]\n\tb, d.h[0] = consumeUint64(b)\n\tb, d.h[1] = consumeUint64(b)\n\tb, d.h[2] = consumeUint64(b)\n\tb, d.h[3] = consumeUint64(b)\n\tb, d.h[4] = consumeUint64(b)\n\tb, d.h[5] = consumeUint64(b)\n\tb, d.h[6] = consumeUint64(b)\n\tb, d.h[7] = consumeUint64(b)\n\tb = b[copy(d.x[:], b):]\n\tb, d.len = consumeUint64(b)\n\td.nx = int(d.len % chunk)\n\treturn nil\n}\n\nfunc consumeUint64(b []byte) ([]byte, uint64) {\n\treturn b[8:], byteorder.BEUint64(b)","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/internal/fips140/sha512/sha512.go#L159-L195","documentation":"Returned by sha512 Digest.UnmarshalBinary when the magic prefix is valid (variant matched) but the total byte length is not marshaledSize. The sha512 layout is fixed-length (magic + 8 x uint64 state + 128-byte block buffer + uint64 length counter); truncation or extra bytes fail this check.","triggerScenarios":"Passing bytes whose variant magic is correct but whose length differs from the fixed marshaledSize: a buffer truncated by storage, an extra trailing byte appended by a buggy serializer, or bytes from a build with a different marshaled layout.","commonSituations":"Database BLOB column sized too small and silently truncating; transport framing that drops or duplicates bytes; copy/paste of a hex string that lost or added characters; version skew between producer and consumer Go builds.","solutions":["Store and retrieve the full marshaledSize bytes unchanged; verify byte-for-byte length.","If data transits a length-prefixed protocol, check the length prefix matches marshaledSize before forwarding.","Re-hash from the original input if the state is unrecoverable.","Pin producer and consumer Go major versions when persisting hash state long-term."],"exampleFix":"// before\nd.UnmarshalBinary(b[:len(b)-1]) // missing last byte -> error\n// after\nd.UnmarshalBinary(b) // exact marshaledSize","handlingStrategy":"validation","validationCode":"if len(b) != marshaledSize {\n    return fmt.Errorf(\"sha512 state size mismatch: got %d want %d\", len(b), marshaledSize)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Verify byte-for-byte length of persisted state on read and write.","Check length prefixes in transit protocols against marshaledSize.","Pin producer and consumer Go major versions for long-lived persisted state."],"tags":["crypto","hash","sha512","serialization","go-stdlib"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}