Skip to content

v5: plumbing: format decoder input bounds and contracts#2125

Merged
pjbgf merged 3 commits into
go-git:releases/v5.xfrom
hiddeco:v5/format-input-bounds
May 14, 2026
Merged

v5: plumbing: format decoder input bounds and contracts#2125
pjbgf merged 3 commits into
go-git:releases/v5.xfrom
hiddeco:v5/format-input-bounds

Conversation

@hiddeco

@hiddeco hiddeco commented May 14, 2026

Copy link
Copy Markdown
Member

Backport of #2119

Apply the size formula canonical Git uses in `packfile.c:load_idx`
[1]: for an idx v2 file with `nr` objects and hash size `hashsz`,
the on-disk length must lie within `[minSize, maxSize]` where

    minSize = 8 + 4*256 + nr*(hashsz+8) + 2*hashsz
    maxSize = minSize + (nr-1)*8     when nr > 0

Overflow-checked multiplication rejects inputs whose claimed object
count overflows the formula rather than wrapping into a smaller
value.

To keep the public `NewDecoder(io.Reader)` signature compatible on
v5, the decoder probes for an unexported `statInput` interface
(`Stat() (fs.FileInfo, error)`) at the top of `Decode`. Inputs that
satisfy it have the size formula applied; arbitrary readers retain
the pre-existing behaviour of erroring out at the truncated-payload
boundary. The two production call sites in `storage/filesystem`
pass a `billy.File`; on `osfs` that wraps `*os.File`, so the
formula does run there.

[1]: https://github.com/git/git/blob/v2.54.0/packfile.c#L232-L258

Backport of go-git#2119.

Assisted-by: Claude Opus 4.7
Signed-off-by: Hidde Beydals <[email protected]>
Comment thread plumbing/format/packfile/scanner.go Outdated
Comment thread plumbing/format/packfile/scanner.go Outdated
hiddeco added 2 commits May 14, 2026 23:45
A packfile object header carries the object's uncompressed size, and
a well-formed packfile never produces more inflated bytes than that
value. Enforce this structural invariant at every site that consumes
the inflated stream and surface mismatches as
`ErrInflatedSizeMismatch`.

Both `Scanner.NextObject` and `Scanner.ReadObject` capture the
declared length from the most recent `pendingObject` before clearing
it, then thread that bound into `copyObject`. The shared
`copyObject(w, declaredSize)` wraps its writer in a new
`boundedWriter` when a positive size is supplied, so an overrun
returns the legal prefix alongside `ErrInflatedSizeMismatch` rather
than being silently appended. Callers in `parser.go` and
`packfile.go` go through `NextObject`, so they pick up the bound
without further changes; for delta entries the declared length is
the size of the delta instruction stream, not the resolved result,
which matches what these call sites already pass through.

The lazy `FSObject.Reader` big-object path returns a new
`boundedReadCloser` that wraps the underlying zlib-backed reader.
It builds on `io.LimitedReader` with the standard overrun-detection
trick — request `limit + 1` bytes and treat the sentinel byte as an
explicit signal — so an `io.ReadAll` on an opened object cannot
stream past the declared size. The bound is `o.size`, the resolved
object size, which matches what the caller is reading regardless of
whether the underlying entry is a non-delta or delta-resolved
object. The type and its constructor are unexported for now; they
can be promoted once a stable use case outside the package emerges.

These changes do not reject any conforming pack.

Backport of go-git#2119.

Assisted-by: Claude Opus 4.7
Signed-off-by: Hidde Beydals <[email protected]>
`Reader` defines a two-phase contract: callers must invoke `Header`
to consume the loose-object type and size fields, after which the
internal `multi` reader and `hasher` are initialised. Calling `Read`
or `Hash` before a successful `Header` accessed uninitialised
fields and would panic on `r.multi.Read` / `r.hasher.Sum`.

Make the contract explicit: `Read` returns the new `ErrHeaderNotRead`
sentinel when `Header` has not been called successfully. `Hash`
returns `plumbing.ZeroHash` in the same situation. Both methods
guard on `r.multi == nil`, which `prepareForRead` sets on the first
successful `Header` call.

Two unit tests pin the behaviour: `TestReaderReadBeforeHeader`
asserts that `Read` returns `ErrHeaderNotRead` and `Hash` returns
`ZeroHash`; `TestReaderReadAfterHeaderError` calls `Read` after
`Header` has returned an error.

Backport of go-git#2119.

Assisted-by: Claude Opus 4.7
Signed-off-by: Hidde Beydals <[email protected]>
@hiddeco hiddeco force-pushed the v5/format-input-bounds branch from fdf4dd2 to aeaa125 Compare May 14, 2026 21:46

@pjbgf pjbgf left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hiddeco Thanks for working on this. 🙇

@pjbgf pjbgf merged commit a97d660 into go-git:releases/v5.x May 14, 2026
9 checks passed
@hiddeco hiddeco deleted the v5/format-input-bounds branch May 14, 2026 22:12
chhe pushed a commit to chhe/act_runner that referenced this pull request May 19, 2026
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [github.com/go-git/go-git/v5](https://github.com/go-git/go-git) | `v5.19.0` → `v5.19.1` | ![age](https://developer.mend.io/api/mc/badges/age/go/github.com%2fgo-git%2fgo-git%2fv5/v5.19.1?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/github.com%2fgo-git%2fgo-git%2fv5/v5.19.0/v5.19.1?slim=true) |

---

### Release Notes

<details>
<summary>go-git/go-git (github.com/go-git/go-git/v5)</summary>

### [`v5.19.1`](https://github.com/go-git/go-git/releases/tag/v5.19.1)

[Compare Source](go-git/go-git@v5.19.0...v5.19.1)

#### What's Changed

- v5: plumbing: transport/ssh, Shell-quote path by [@&#8203;hiddeco](https://github.com/hiddeco) in [#&#8203;2068](go-git/go-git#2068)
- v5: git: submodule, Fix relative URL resolution by [@&#8203;hiddeco](https://github.com/hiddeco) in [#&#8203;2070](go-git/go-git#2070)
- v5: git: submodule, canonical remote for relative URLs by [@&#8203;hiddeco](https://github.com/hiddeco) in [#&#8203;2074](go-git/go-git#2074)
- v5: git: submodule, error on remote without URLs by [@&#8203;hiddeco](https://github.com/hiddeco) in [#&#8203;2078](go-git/go-git#2078)
- v5: plumbing: format/idxfile, Validate offset64 indices by [@&#8203;hiddeco](https://github.com/hiddeco) in [#&#8203;2084](go-git/go-git#2084)
- v5: \*: Reject malformed variable-length integers by [@&#8203;hiddeco](https://github.com/hiddeco) in [#&#8203;2092](go-git/go-git#2092)
- v5: plumbing: format/packfile, Tighten delta validation by [@&#8203;hiddeco](https://github.com/hiddeco) in [#&#8203;2091](go-git/go-git#2091)
- v5: Add `worktreeFilesystem` wrapper for worktree and hardening by [@&#8203;hiddeco](https://github.com/hiddeco) in [#&#8203;2100](go-git/go-git#2100)
- v5: config: validate submodule names by [@&#8203;hiddeco](https://github.com/hiddeco) in [#&#8203;2082](go-git/go-git#2082)
- build: Update module github.com/go-git/go-git/v5 to v5.19.0 \[SECURITY] (releases/v5.x) by [@&#8203;go-git-renovate](https://github.com/go-git-renovate)\[bot] in [#&#8203;2111](go-git/go-git#2111)
- v5: git: Allow MkdirAll on worktree-root paths by [@&#8203;hiddeco](https://github.com/hiddeco) in [#&#8203;2117](go-git/go-git#2117)
- v5: git: Stop validating symlink target paths by [@&#8203;pjbgf](https://github.com/pjbgf) in [#&#8203;2116](go-git/go-git#2116)
- v5: plumbing: format decoder input bounds and contracts by [@&#8203;hiddeco](https://github.com/hiddeco) in [#&#8203;2125](go-git/go-git#2125)
- plumbing: format/packfile, cap delta chain depth in parser by [@&#8203;pjbgf](https://github.com/pjbgf) in [#&#8203;2137](go-git/go-git#2137)

**Full Changelog**: <go-git/go-git@v5.19.0...v5.19.1>

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xODIuMSIsInVwZGF0ZWRJblZlciI6IjQzLjE4Mi4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Reviewed-on: https://gitea.com/gitea/runner/pulls/980
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: Renovate Bot <[email protected]>
Co-committed-by: Renovate Bot <[email protected]>
Maks1mS pushed a commit to stplr-dev/stplr that referenced this pull request May 20, 2026
This PR contains the following updates:

| Package | Type | Update | Change | OpenSSF |
|---|---|---|---|---|
| [github.com/go-git/go-git/v5](https://github.com/go-git/go-git) | require | patch | `v5.19.0` → `v5.19.1` | [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/go-git/go-git/badge)](https://securityscorecards.dev/viewer/?uri=github.com/go-git/go-git) |

---

> ⚠️ **Warning**
>
> Some dependencies could not be looked up. Check the [Dependency Dashboard](issues/23) for more information.

---

### Release Notes

<details>
<summary>go-git/go-git (github.com/go-git/go-git/v5)</summary>

### [`v5.19.1`](https://github.com/go-git/go-git/releases/tag/v5.19.1)

[Compare Source](go-git/go-git@v5.19.0...v5.19.1)

#### What's Changed

- v5: plumbing: transport/ssh, Shell-quote path by [@&#8203;hiddeco](https://github.com/hiddeco) in [#&#8203;2068](go-git/go-git#2068)
- v5: git: submodule, Fix relative URL resolution by [@&#8203;hiddeco](https://github.com/hiddeco) in [#&#8203;2070](go-git/go-git#2070)
- v5: git: submodule, canonical remote for relative URLs by [@&#8203;hiddeco](https://github.com/hiddeco) in [#&#8203;2074](go-git/go-git#2074)
- v5: git: submodule, error on remote without URLs by [@&#8203;hiddeco](https://github.com/hiddeco) in [#&#8203;2078](go-git/go-git#2078)
- v5: plumbing: format/idxfile, Validate offset64 indices by [@&#8203;hiddeco](https://github.com/hiddeco) in [#&#8203;2084](go-git/go-git#2084)
- v5: \*: Reject malformed variable-length integers by [@&#8203;hiddeco](https://github.com/hiddeco) in [#&#8203;2092](go-git/go-git#2092)
- v5: plumbing: format/packfile, Tighten delta validation by [@&#8203;hiddeco](https://github.com/hiddeco) in [#&#8203;2091](go-git/go-git#2091)
- v5: Add `worktreeFilesystem` wrapper for worktree and hardening by [@&#8203;hiddeco](https://github.com/hiddeco) in [#&#8203;2100](go-git/go-git#2100)
- v5: config: validate submodule names by [@&#8203;hiddeco](https://github.com/hiddeco) in [#&#8203;2082](go-git/go-git#2082)
- build: Update module github.com/go-git/go-git/v5 to v5.19.0 \[SECURITY] (releases/v5.x) by [@&#8203;go-git-renovate](https://github.com/go-git-renovate)\[bot] in [#&#8203;2111](go-git/go-git#2111)
- v5: git: Allow MkdirAll on worktree-root paths by [@&#8203;hiddeco](https://github.com/hiddeco) in [#&#8203;2117](go-git/go-git#2117)
- v5: git: Stop validating symlink target paths by [@&#8203;pjbgf](https://github.com/pjbgf) in [#&#8203;2116](go-git/go-git#2116)
- v5: plumbing: format decoder input bounds and contracts by [@&#8203;hiddeco](https://github.com/hiddeco) in [#&#8203;2125](go-git/go-git#2125)
- plumbing: format/packfile, cap delta chain depth in parser by [@&#8203;pjbgf](https://github.com/pjbgf) in [#&#8203;2137](go-git/go-git#2137)

**Full Changelog**: <go-git/go-git@v5.19.0...v5.19.1>

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At 12:00 AM through 04:59 AM and 10:00 PM through 11:59 PM, Monday through Friday (`* 0-4,22-23 * * 1-5`)
  - Only on Sunday and Saturday (`* * * * 0,6`)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNzAuMjIiLCJ1cGRhdGVkSW5WZXIiOiI0My4xNzAuMjIiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbIktpbmQvRGVwZW5kZW5jaWVzIl19-->

Reviewed-on: https://altlinux.space/stapler/stplr/pulls/435
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants