go-zucchini is a pure Go port of Chromium's Zucchini binary diff algorithm.
It provides a command-line tool and a Go package for generating and applying
Zucchini patches without Chromium, C++, cgo, or external Go modules.
- Generates and applies Chromium-compatible Zucchini patches.
- Uses executable-aware matching for supported PE and ELF images.
- Falls back to raw binary matching for unrecognized data.
- Memory-maps files on Unix. Default Windows builds use ordinary file I/O and
exclude the project's
unsafewritable-mapping backend. - Supports in-memory and caller-provided output buffers.
- Builds with the Go standard library only.
- Go 1.26.5 or later.
- Windows, Linux, macOS, or another Unix platform covered by the file-mapping implementation.
Install the command-line tool:
go install github.com/404Setup/go-zucchini/cmd/zucchini@latestOr build it from a checkout:
go build -o zucchini ./cmd/zucchiniFor a standard Windows release build, use:
.\scripts\build-windows.ps1The script disables inherited experiments and linker stripping, targets the baseline amd64 instruction set, preserves Go/VCS build metadata, and writes a SHA-256 checksum next to the executable.
For a high-performance, position-independent Windows build:
.\scripts\build-windows.ps1 -GoAmd64 v3 -GoExperiment arenas -HardenedThis retains the selected CPU and Go runtime features, normal build ID, debug information, and Go/VCS metadata. Hardened mode removes host paths and emits a position-independent executable.
Tagged and manually dispatched GitHub builds also attach signed build provenance to the Windows executable. Verify a downloaded release artifact:
Get-FileHash .\zucchini.exe -Algorithm SHA256
gh attestation verify .\zucchini.exe --repo 404Setup/go-zucchini
go version -m .\zucchini.exeGenerate and apply a patch:
zucchini gen old.bin new.bin update.patch
zucchini apply old.bin update.patch reconstructed.bin
zucchini apply old.bin update.patch reconstructed.bin --sha256 <trusted-output-sha256>Available commands:
gen Generate a patch
apply Apply a patch
verify Validate a patch
read Inspect executable references
detect Detect embedded executables
match Match executable elements
crc32 Calculate CRC32
suffix-array Build a suffix array
Run zucchini help or zucchini <command> --help for command syntax. The
legacy -gen and -apply command forms are also accepted.
Generation options:
--rawdisables executable-aware matching.--impose <matches>supplies explicit element matches inold_offset+old_size=new_offset+new_sizeform.--keepretains a partial output file after an error.
Add the module:
go get github.com/404Setup/go-zucchiniUse the file-oriented API for large inputs:
package main
import (
"log"
zucchini "github.com/404Setup/go-zucchini"
)
func main() {
if err := zucchini.GenerateFile("old.bin", "new.bin", "update.patch"); err != nil {
log.Fatal(err)
}
if err := zucchini.ApplyFile("old.bin", "update.patch", "reconstructed.bin"); err != nil {
log.Fatal(err)
}
}For data already in memory:
patch, err := zucchini.GenerateBuffer(oldImage, newImage)
if err != nil {
return err
}
reconstructed, err := zucchini.Apply(oldImage, patch)ApplyTo writes into a caller-provided buffer. GenerateFileWithOptions and
ApplyFileWithOptions expose raw matching, imposed matches, and partial-output
retention. File-backed apply writes to a same-directory temporary file and only
installs it after CRC and optional trusted SHA-256 verification succeed.
GenerateFile streams patch serialization to a temporary file in
the destination directory, flushes and verifies its size, then atomically
replaces the destination. Failed generation leaves an existing destination
untouched unless partial-output retention is explicitly requested.
Executable-aware matching currently supports:
- Windows PE: x86 and x86-64.
- ELF: x86, x86-64, ARM, and AArch64.
The PE parser validates both the optional-header format and COFF machine type. Other architectures are handled as raw data instead of being interpreted as x86-64. DEX and Zucchini Text Format are not implemented.
BenchmarkGenerateFile is the representative profile entry point for patch
generation. Collect profiles from production-like inputs:
ZUCCHINI_BENCH_OLD=old.bin ZUCCHINI_BENCH_NEW=new.bin \
go test -run '^$' -bench '^BenchmarkGenerateFile$' -benchtime=1x \
-cpuprofile=cpu.pprof
go build -pgo=off -o zucchini-baseline ./cmd/zucchini
go build -pgo=cpu.pprof -o zucchini-pgo ./cmd/zucchiniCompare end-to-end generation on several representative files before adopting
a profile. Promote it to cmd/zucchini/default.pgo only when the improvement is
stable across the intended workload.
Run the test suite and static checks:
go test ./...
go vet ./...On Windows, use the hardened test entry point. It removes host paths and uses position-independent transient test executables while preserving the active CPU and Go feature configuration and full Go build metadata:
.\scripts\test-windows.ps1
.\scripts\test-windows.ps1 -GoAmd64 v1 -GoExperiment none
.\scripts\test-windows.ps1 -GoAmd64 v3 -GoExperiment arenas
go vet ./...The first command follows the active Go configuration. The second pins the portable amd64 baseline, and the third exercises the high-performance profile.
The large memory and assembly corpus probes are intentionally absent from the
default test executable. Enable them only for their dedicated measurement
workflows with -tags zucchini_memprobe or -tags zucchini_asmcorpus.
The implementation includes randomized SA-IS tests, patch validation tests, generate/apply symmetry tests, and file-mapping tests. Large local PE fixtures enable additional memory and compatibility probes when present.
Applying a patch never starts the reconstructed file, invokes a shell, or uses
the network. However, the Zucchini format's CRC32 fields only detect accidental
corruption; they do not authenticate a patch or its output. An attacker who can
replace a patch can construct a patch for attacker-chosen output when the old
file is known. Authenticate patches with a signature, or pass a SHA-256 digest
obtained through a trusted channel via apply --sha256 or
ApplyFileOptions.ExpectedNewSHA256, before executing or distributing output.
This project is derived from Chromium's Zucchini implementation and is distributed under the BSD 3-Clause license in LICENSE. See THIRD_PARTY_NOTICES.md for upstream attribution.