diff --git a/Cargo.lock b/Cargo.lock index cf86548edc..e00aeaae0e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -224,6 +224,12 @@ dependencies = [ "syn", ] +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + [[package]] name = "errno" version = "0.3.13" @@ -322,6 +328,7 @@ dependencies = [ "openssl-sys", "tempfile", "time", + "trybuild", "url", ] @@ -336,6 +343,18 @@ dependencies = [ "url", ] +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + [[package]] name = "heck" version = "0.5.0" @@ -449,6 +468,16 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown", +] + [[package]] name = "is_terminal_polyfill" version = "1.70.1" @@ -743,6 +772,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" +dependencies = [ + "serde_core", +] + [[package]] name = "shlex" version = "1.3.0" @@ -808,6 +846,12 @@ dependencies = [ "libgit2-sys", ] +[[package]] +name = "target-triple" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "591ef38edfb78ca4771ee32cf494cb8771944bee237a9b91fc9c1424ac4b777b" + [[package]] name = "tempfile" version = "3.20.0" @@ -831,6 +875,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + [[package]] name = "thiserror" version = "1.0.69" @@ -892,6 +945,60 @@ dependencies = [ "zerovec", ] +[[package]] +name = "toml" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned", + "toml_datetime", + "toml_parser", + "toml_writer", + "winnow", +] + +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_parser" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +dependencies = [ + "winnow", +] + +[[package]] +name = "toml_writer" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" + +[[package]] +name = "trybuild" +version = "1.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0710d4dfbeae4f9c390baa784c49858a7468fa433f3fe5d0ec5ebef651cf59f9" +dependencies = [ + "glob", + "serde", + "serde_derive", + "serde_json", + "target-triple", + "termcolor", + "toml", +] + [[package]] name = "unicode-ident" version = "1.0.18" @@ -964,6 +1071,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.60.2", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -1125,6 +1241,12 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" +[[package]] +name = "winnow" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" + [[package]] name = "wit-bindgen-rt" version = "0.39.0" diff --git a/Cargo.toml b/Cargo.toml index d92caf60b1..98d839b958 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,6 +31,7 @@ openssl-probe = { version = "0.1", optional = true } clap = { version = "4.4.13", features = ["derive"] } time = { version = "0.3.45", features = ["formatting"] } tempfile = "3.1.0" +trybuild = "1.0.117" url = "2.5.4" [features] diff --git a/src/remote.rs b/src/remote.rs index 290b5517da..4484c6ddd5 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -298,7 +298,7 @@ impl<'repo> Remote<'repo> { /// Get the `nth` refspec from this remote. /// /// The `refspecs` iterator can be used to iterate over all refspecs. - pub fn get_refspec(&self, i: usize) -> Option> { + pub fn get_refspec(&self, i: usize) -> Option> { unsafe { let ptr = raw::git_remote_get_refspec(&*self.raw, i as libc::size_t); Binding::from_raw_opt(ptr) diff --git a/tests/compile_fail.rs b/tests/compile_fail.rs new file mode 100644 index 0000000000..fc7018106d --- /dev/null +++ b/tests/compile_fail.rs @@ -0,0 +1,7 @@ +//! Regression tests for things that should not compile but used to + +#[test] +fn test_compile_fail() { + let t = trybuild::TestCases::new(); + t.compile_fail("tests/compile_fail/remote_refspec.rs"); +} diff --git a/tests/compile_fail/remote_refspec.rs b/tests/compile_fail/remote_refspec.rs new file mode 100644 index 0000000000..e2ab25c5fa --- /dev/null +++ b/tests/compile_fail/remote_refspec.rs @@ -0,0 +1,23 @@ +// Regression tests for https://github.com/rust-lang/git2-rs/issues/1286 + +#[forbid(unsafe_code)] + +use git2::Repository; + +fn main() { + let repo = Repository::init("temp_dir").unwrap(); + repo.remote("origin", "https://aaa.com/bbb.git").unwrap(); + + let refspec = { + let remote = repo.find_remote("origin").unwrap(); + remote.get_refspec(0) + }; + // remote goes out of scope + // but refspec's lifetime is not bounded to remote + + // removing temp_dir, not necessary to trigger UAF + let _ = std::fs::remove_dir_all("temp_dir"); + + // triggers UAF + let _ = refspec.unwrap().str(); +} diff --git a/tests/compile_fail/remote_refspec.stderr b/tests/compile_fail/remote_refspec.stderr new file mode 100644 index 0000000000..7d455f4f5c --- /dev/null +++ b/tests/compile_fail/remote_refspec.stderr @@ -0,0 +1,11 @@ +error[E0597]: `remote` does not live long enough + --> tests/compile_fail/remote_refspec.rs:13:9 + | +11 | let refspec = { + | ------- borrow later stored here +12 | let remote = repo.find_remote("origin").unwrap(); + | ------ binding `remote` declared here +13 | remote.get_refspec(0) + | ^^^^^^ borrowed value does not live long enough +14 | }; + | - `remote` dropped here while still borrowed