{"record":{"id":"a90a590996229d12","repo":"golang/go","slug":"crypto-sha1-invalid-hash-state-size-a90a59","errorCode":null,"errorMessage":"crypto/sha1: invalid hash state size","messagePattern":"crypto/sha1: invalid hash state size","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/sha1/sha1.go","lineNumber":74,"sourceCode":"func (d *digest) AppendBinary(b []byte) ([]byte, error) {\n\tb = append(b, magic...)\n\tb = byteorder.BEAppendUint32(b, d.h[0])\n\tb = byteorder.BEAppendUint32(b, d.h[1])\n\tb = byteorder.BEAppendUint32(b, d.h[2])\n\tb = byteorder.BEAppendUint32(b, d.h[3])\n\tb = byteorder.BEAppendUint32(b, d.h[4])\n\tb = append(b, d.x[:d.nx]...)\n\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(magic) || string(b[:len(magic)]) != magic {\n\t\treturn errors.New(\"crypto/sha1: invalid hash state identifier\")\n\t}\n\tif len(b) != marshaledSize {\n\t\treturn errors.New(\"crypto/sha1: invalid hash state size\")\n\t}\n\tb = b[len(magic):]\n\tb, d.h[0] = consumeUint32(b)\n\tb, d.h[1] = consumeUint32(b)\n\tb, d.h[2] = consumeUint32(b)\n\tb, d.h[3] = consumeUint32(b)\n\tb, d.h[4] = consumeUint32(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)\n}\n\nfunc consumeUint32(b []byte) ([]byte, uint32) {","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/sha1/sha1.go#L56-L92","documentation":"Thrown by sha1.digest.UnmarshalBinary when the input length does not equal marshaledSize. SHA-1's marshaled state is a fixed size (magic + 5x uint32 state + 64-byte block + uint64 length); a length mismatch means the blob is truncated, extended, or from an incompatible version.","triggerScenarios":"Calling UnmarshalBinary on a byte slice whose length != sha1.marshaledSize. The magic check has already passed, so this is the right algorithm but wrong size.","commonSituations":"Truncated transfer of a marshaled state; blob from a different Go/version with a different marshaled layout; appended trailing bytes; gob/json round-trip that altered length.","solutions":["Validate len(b) == sha1 marshaledSize (currently magic + 20 + 64 + 8 bytes) before unmarshaling.","Re-marshal the state on the same Go version that will unmarshal it.","If persisting hash states, version-stamp the format and migrate on load.","Treat length mismatches as corruption and restart hashing rather than guessing."],"exampleFix":"// before\nerr := d.UnmarshalBinary(truncatedBlob)\n\n// after\nconst sha1MarshaledSize = len(\"sha\\x01\") + 20 + 64 + 8\nif len(b) != sha1MarshaledSize {\n    return fmt.Errorf(\"bad sha1 state size: %d\", len(b))\n}\nerr := d.UnmarshalBinary(b)","handlingStrategy":"validation","validationCode":"// Validate the exact marshaled size before calling UnmarshalBinary.\n// sha1.marshaledSize = len(magic) + 5*4 + 64 + 8 bytes.\nfunc safeUnmarshalSized(d *sha1.Digest, b []byte) error {\n    const marshaledSize = 4 + 20 + 64 + 8 // adjust magic len to match source\n    if len(b) != marshaledSize {\n        return fmt.Errorf(\"sha1 state size mismatch: %d\", len(b))\n    }\n    return d.UnmarshalBinary(b)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pin the Go version used to marshal/unmarshal hash states, or migrate formats explicitly.","Persist the marshaled size alongside the blob and compare on load.","Do not append or truncate a marshaled state blob in transit.","Restart hashing from scratch if a state fails to load, rather than guessing."],"tags":["crypto","sha1","serialization","go"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}