Skip to content

Commit 0cc154c

Browse files
Avoid TOCTOU errors in cache initialization (#10884)
## Summary I believe this should close #10880? The `.gitignore` creation seems ok, since it truncates, but using `cachedir::is_tagged` followed by `cachedir::add_tag` is not safe, as `cachedir::add_tag` _fails_ if the file already exists. This also matches the structure of the code in `uv`. Closes #10880.
1 parent 4e8a846 commit 0cc154c

File tree

1 file changed

+9
-7
lines changed

1 file changed

+9
-7
lines changed

crates/ruff/src/cache.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -375,15 +375,17 @@ pub(crate) fn init(path: &Path) -> Result<()> {
375375
fs::create_dir_all(path.join(VERSION))?;
376376

377377
// Add the CACHEDIR.TAG.
378-
if !cachedir::is_tagged(path)? {
379-
cachedir::add_tag(path)?;
380-
}
378+
cachedir::ensure_tag(path)?;
381379

382380
// Add the .gitignore.
383-
let gitignore_path = path.join(".gitignore");
384-
if !gitignore_path.exists() {
385-
let mut file = fs::File::create(gitignore_path)?;
386-
file.write_all(b"# Automatically created by ruff.\n*\n")?;
381+
match fs::OpenOptions::new()
382+
.write(true)
383+
.create_new(true)
384+
.open(path.join(".gitignore"))
385+
{
386+
Ok(mut file) => file.write_all(b"# Automatically created by ruff.\n*\n")?,
387+
Err(err) if err.kind() == io::ErrorKind::AlreadyExists => (),
388+
Err(err) => return Err(err.into()),
387389
}
388390

389391
Ok(())

0 commit comments

Comments
 (0)