Skip to content

Commit 3af9b4a

Browse files
authored
Merge pull request #2559 from GitoxideLabs/fix/symlink-prefix-reuse-worktree-escape-GHSA-f89h-2fjh-2r9q
Revalidate cached stack leaves before directory reuse
2 parents 23af41a + d3e4c17 commit 3af9b4a

29 files changed

Lines changed: 832 additions & 76 deletions

File tree

Cargo.lock

Lines changed: 3 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

etc/plan/performance.md

Lines changed: 282 additions & 0 deletions
Large diffs are not rendered by default.

gix-diff/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ gix-filter = { version = "^0.30.0", path = "../gix-filter", optional = true }
5454
gix-worktree = { version = "^0.52.0", path = "../gix-worktree", default-features = false, features = ["attributes"], optional = true }
5555
gix-command = { version = "^0.9.0", path = "../gix-command", optional = true }
5656
gix-path = { version = "^0.12.0", path = "../gix-path", optional = true }
57-
gix-fs = { version = "^0.21.0", path = "../gix-fs", optional = true }
57+
gix-fs = { version = "^0.21.1", path = "../gix-fs", optional = true }
5858
gix-tempfile = { version = "^23.0.0", path = "../gix-tempfile", optional = true }
5959
gix-trace = { version = "^0.1.19", path = "../gix-trace", optional = true }
6060
gix-traverse = { version = "^0.57.0", path = "../gix-traverse", optional = true }

gix-dir/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ sha1 = ["gix-discover/sha1", "gix-index/sha1", "gix-object/sha1", "gix-worktree/
2323
gix-trace = { version = "^0.1.19", path = "../gix-trace" }
2424
gix-index = { version = "^0.51.0", path = "../gix-index" }
2525
gix-discover = { version = "^0.51.0", path = "../gix-discover" }
26-
gix-fs = { version = "^0.21.0", path = "../gix-fs" }
26+
gix-fs = { version = "^0.21.1", path = "../gix-fs" }
2727
gix-path = { version = "^0.12.0", path = "../gix-path" }
2828
gix-pathspec = { version = "^0.18.0", path = "../gix-pathspec" }
2929
gix-worktree = { version = "^0.52.0", path = "../gix-worktree", default-features = false }

gix-discover/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ sha1 = ["gix-ref/sha1"]
2222
gix-sec = { version = "^0.14.0", path = "../gix-sec" }
2323
gix-path = { version = "^0.12.0", path = "../gix-path" }
2424
gix-ref = { version = "^0.63.0", path = "../gix-ref" }
25-
gix-fs = { version = "^0.21.0", path = "../gix-fs" }
25+
gix-fs = { version = "^0.21.1", path = "../gix-fs" }
2626

2727
bstr = { version = "1.12.0", default-features = false, features = ["std", "unicode"] }
2828
thiserror = "2.0.18"

gix-fs/CHANGELOG.md

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,39 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## 0.21.1 (2026-04-30)
9+
10+
A security fix for https://github.com/GitoxideLabs/gitoxide/security/advisories/GHSA-f89h-2fjh-2r9q,
11+
which could allow attackers to trick `gix clone` into writing outside of the repository.
12+
13+
### Commit Statistics
14+
15+
<csr-read-only-do-not-edit/>
16+
17+
- 3 commits contributed to the release over the course of 2 calendar days.
18+
- 2 days passed between releases.
19+
- 0 commits were understood as [conventional](https://www.conventionalcommits.org).
20+
- 0 issues like '(#ID)' were seen in commit messages
21+
22+
### Commit Details
23+
24+
<csr-read-only-do-not-edit/>
25+
26+
<details><summary>view details</summary>
27+
28+
* **Uncategorized**
29+
- Update changelog of gix-fs prior to release ([`e26d378`](https://github.com/GitoxideLabs/gitoxide/commit/e26d37819e59556e018700cba9c414648d6939be))
30+
- Revalidate cached stack leaves before directory reuse ([`93d0ff6`](https://github.com/GitoxideLabs/gitoxide/commit/93d0ff6342f9fba5e30a6a893ad11347cf6cfcbc))
31+
- Merge pull request #2546 from GitoxideLabs/fix-2545 ([`adb8328`](https://github.com/GitoxideLabs/gitoxide/commit/adb8328952478c443ead5f5a8c6851928b377b37))
32+
</details>
33+
834
## 0.21.0 (2026-04-28)
935

1036
### Commit Statistics
1137

1238
<csr-read-only-do-not-edit/>
1339

14-
- 1 commit contributed to the release over the course of 2 calendar days.
40+
- 2 commits contributed to the release over the course of 2 calendar days.
1541
- 3 days passed between releases.
1642
- 0 commits were understood as [conventional](https://www.conventionalcommits.org).
1743
- 0 issues like '(#ID)' were seen in commit messages
@@ -23,6 +49,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2349
<details><summary>view details</summary>
2450

2551
* **Uncategorized**
52+
- Release gix-error v0.2.3, gix-date v0.15.3, gix-actor v0.41.0, gix-path v0.12.0, gix-features v0.48.0, gix-hash v0.25.0, gix-hashtable v0.15.0, gix-object v0.60.0, gix-glob v0.26.0, gix-attributes v0.33.0, gix-command v0.9.0, gix-filter v0.30.0, gix-fs v0.21.0, gix-commitgraph v0.37.0, gix-revwalk v0.31.0, gix-traverse v0.57.0, gix-worktree-stream v0.32.0, gix-archive v0.32.0, gix-tempfile v23.0.0, gix-lock v23.0.0, gix-index v0.51.0, gix-config-value v0.18.0, gix-pathspec v0.18.0, gix-ignore v0.21.0, gix-worktree v0.52.0, gix-imara-diff v0.2.1, gix-diff v0.63.0, gix-blame v0.13.0, gix-ref v0.63.0, gix-sec v0.14.0, gix-config v0.56.0, gix-prompt v0.15.0, gix-url v0.36.0, gix-credentials v0.38.0, gix-discover v0.51.0, gix-dir v0.25.0, gix-mailmap v0.33.0, gix-revision v0.45.0, gix-merge v0.16.0, gix-negotiate v0.31.0, gix-pack v0.70.0, gix-odb v0.80.0, gix-refspec v0.41.0, gix-shallow v0.12.0, gix-transport v0.57.0, gix-protocol v0.61.0, gix-status v0.30.0, gix-submodule v0.30.0, gix-worktree-state v0.30.0, gix v0.83.0, gix-fsck v0.21.0, gitoxide-core v0.57.0, gitoxide v0.53.0, safety bump 48 crates ([`53f880c`](https://github.com/GitoxideLabs/gitoxide/commit/53f880c7604232c367870088176e42efd8a5b783))
2653
- Merge pull request #2540 from GitoxideLabs/reporting ([`4d5ba23`](https://github.com/GitoxideLabs/gitoxide/commit/4d5ba231685e8ff36195603c57193aa1cd21fa8e))
2754
</details>
2855

gix-fs/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ lints.workspace = true
22

33
[package]
44
name = "gix-fs"
5-
version = "0.21.0"
5+
version = "0.21.1"
66
repository = "https://github.com/GitoxideLabs/gitoxide"
77
license = "MIT OR Apache-2.0"
88
description = "A crate providing file system specific utilities to `gitoxide`"

gix-fs/src/stack.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -193,27 +193,40 @@ impl Stack {
193193
self.valid_components = matching_components;
194194

195195
if !self.current_is_directory && components.peek().is_some() {
196-
delegate.push_directory(self)?;
196+
delegate.push(false, self)?;
197+
// Make sure we don't consider this a directory if the `push` above fails.
198+
self.current_is_directory = true;
199+
if let Err(err) = delegate.push_directory(self) {
200+
self.current_is_directory = false;
201+
return Err(err);
202+
}
197203
}
198204

199205
while let Some(comp) = components.next() {
200206
let comp = comp.map_err(std::io::Error::other)?;
201207
let is_last_component = components.peek().is_none();
208+
let parent_is_directory = self.current_is_directory;
202209
self.current_is_directory = !is_last_component;
203210
self.current.push(comp);
204211
self.current_relative.push(comp);
205212
self.valid_components += 1;
206213
let res = delegate.push(is_last_component, self);
207-
if self.current_is_directory {
208-
delegate.push_directory(self)?;
209-
}
210-
211214
if let Err(err) = res {
212215
self.current.pop();
213216
self.current_relative.pop();
214217
self.valid_components -= 1;
218+
self.current_is_directory = parent_is_directory;
215219
return Err(err);
216220
}
221+
if self.current_is_directory {
222+
if let Err(err) = delegate.push_directory(self) {
223+
self.current.pop();
224+
self.current_relative.pop();
225+
self.valid_components -= 1;
226+
self.current_is_directory = parent_is_directory;
227+
return Err(err);
228+
}
229+
}
217230
}
218231
Ok(())
219232
}

0 commit comments

Comments
 (0)