build-a-png-codec / lesson-12.md
Lesson 12 · Integrity with CRC32

Verifying every chunk

With per-chunk validation in hand, you can vet a whole file. Today you extend the chunk walk to check every CRC and fail fast on the first corrupt chunk, so nothing downstream ever sees bad data.

The goal

Walk a PNG and confirm every chunk's CRC, returning an error that names the first chunk whose CRC does not match.

Start here - the target
TO DO
Scenario: Validating a full file
Givena PNG whose IHDR, IDAT, and IEND chunks all carry correct CRCs
Whenthe file is verified
Thenit reports all chunks valid
Andif one byte inside the IDAT data is flipped, verification fails with an error naming the IDAT chunk
Background

This closes the integrity chapter with a single guarantee: run Verify and either every chunk is sound or you learn exactly which one is not. It reuses the chunk walk from chapter one and the per-chunk Valid check, and the naming matters - “bad CRC in IDAT chunk” tells a caller precisely where the damage is, which is far more useful than a bare failure. A corrupt byte in the compressed image data is caught here, before the inflater ever tries to make sense of it.

You now have a container you can fully trust: recognized by signature, split into chunks, and every chunk proven intact. That trust is the foundation the hard part stands on. The next chapter opens the IDAT payload and begins the real work - turning that compressed zlib stream back into raw bytes.

Make it work
func Verify(b []byte) error {
chunks, err := Chunks(b)
if err != nil { return err }
for _, c := range chunks {
if !c.Valid() { return fmt.Errorf("bad CRC in %s chunk", c.Type) }
}
return nil
}
CheckpointDONE
The decoder verifies an entire PNG and pinpoints the first corrupt chunk. Commit and stop here.