Avoid TOCTOU errors in cache initialization (#10884)

## Summary

I believe this should close
https://github.com/astral-sh/ruff/issues/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 https://github.com/astral-sh/ruff/issues/10880.
This commit is contained in:
Charlie Marsh 2024-04-11 12:09:07 -04:00 committed by GitHub
parent 4e8a84617c
commit 0cc154c2a9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 9 additions and 7 deletions

View File

@ -375,15 +375,17 @@ pub(crate) fn init(path: &Path) -> Result<()> {
fs::create_dir_all(path.join(VERSION))?; fs::create_dir_all(path.join(VERSION))?;
// Add the CACHEDIR.TAG. // Add the CACHEDIR.TAG.
if !cachedir::is_tagged(path)? { cachedir::ensure_tag(path)?;
cachedir::add_tag(path)?;
}
// Add the .gitignore. // Add the .gitignore.
let gitignore_path = path.join(".gitignore"); match fs::OpenOptions::new()
if !gitignore_path.exists() { .write(true)
let mut file = fs::File::create(gitignore_path)?; .create_new(true)
file.write_all(b"# Automatically created by ruff.\n*\n")?; .open(path.join(".gitignore"))
{
Ok(mut file) => file.write_all(b"# Automatically created by ruff.\n*\n")?,
Err(err) if err.kind() == io::ErrorKind::AlreadyExists => (),
Err(err) => return Err(err.into()),
} }
Ok(()) Ok(())