{"record":{"id":"3ed1df94c1396a23","repo":"kovidgoyal/kitty","slug":"rsync-signature-header-has-zero-block-size","errorCode":null,"errorMessage":"rsync signature header has zero block size","messagePattern":"rsync signature header has zero block size","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tools/rsync/api.go","lineNumber":101,"sourceCode":"\t\treturn consumed, fmt.Errorf(\"Invalid checksum_type in signature header: %d\", csum)\n\t}\n\tswitch strong_hash := StrongHashType(bin.Uint16(data[4:])); strong_hash {\n\tcase XXH3:\n\t\tself.Strong_hash_type = strong_hash\n\t\tself.rsync.SetHasher(new_xxh3_64)\n\tdefault:\n\t\treturn consumed, fmt.Errorf(\"Invalid strong_hash in signature header: %d\", strong_hash)\n\t}\n\tswitch weak_hash := WeakHashType(bin.Uint16(data[6:])); weak_hash {\n\tcase Rsync:\n\t\tself.Weak_hash_type = weak_hash\n\tdefault:\n\t\treturn consumed, fmt.Errorf(\"Invalid weak_hash in signature header: %d\", weak_hash)\n\t}\n\tblock_size := int(bin.Uint32(data[8:]))\n\tconsumed = 12\n\tif block_size == 0 {\n\t\treturn consumed, fmt.Errorf(\"rsync signature header has zero block size\")\n\t}\n\tif block_size > MaxBlockSize {\n\t\treturn consumed, fmt.Errorf(\"rsync signature header has too large block size %d > %d\", block_size, MaxBlockSize)\n\t}\n\tself.rsync.BlockSize = block_size\n\tself.signature = make([]BlockHash, 0, 1024)\n\treturn\n}\n\nfunc (self *Api) read_signature_blocks(data []byte) (consumed int) {\n\tblock_hash_size := self.rsync.HashSize() + 12\n\tfor ; len(data) >= block_hash_size; data = data[block_hash_size:] {\n\t\tbl := BlockHash{}\n\t\tbl.Unserialize(data[:block_hash_size])\n\t\tself.signature = append(self.signature, bl)\n\t\tconsumed += block_hash_size\n\t}\n\treturn","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/kovidgoyal/kitty/blob/6d5d0c440603ad9bdf6dcd599f73f6dde21acb44/tools/rsync/api.go#L83-L119","documentation":"The rsync signature header's block-size field (bytes 8-11, big-endian uint32) read as zero, which is invalid — blocks must have a positive size.","triggerScenarios":"AddSignatureData receiving a 12+ byte header whose block-size field is 0 — almost always a corrupted, misaligned, or hand-crafted stream rather than a real signature.","commonSituations":"Stream misalignment (reading from the wrong offset), truncation, or feeding random/test bytes into AddSignatureData without a valid header.","solutions":["Confirm the data passed to AddSignatureData begins with a real signature header","Check for off-by-one offsets or extra framing bytes before the signature","Regenerate the signature from the source file"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if len(data) < 12 { return fmt.Errorf(\"header truncated\") }\nif binary.BigEndian.Uint32(data[8:12]) == 0 { return fmt.Errorf(\"zero block size\") }","typeGuard":null,"tryCatchPattern":"if err := differ.AddSignatureData(chunk); err != nil { abort transfer; regenerate signature }","preventionTips":["Use CreateSignatureIterator output verbatim; don't reframe bytes","Checksum transfers to detect corruption early"],"tags":["rsync","protocol","header","corruption"],"backgroundTag":"protocol-header-invalid","analyzedSha":"6d5d0c440603ad9bdf6dcd599f73f6dde21acb44","analyzedAt":"2026-08-27T14:20:20.142Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}