Remove a TOCTOU read in build (#860)

We should just read and handle the not-found case, rather than checking
if the file doesn't exist first.
This commit is contained in:
Charlie Marsh
2024-01-09 15:33:08 -05:00
committed by GitHub
parent 31139aa88d
commit 33982efb25
2 changed files with 37 additions and 34 deletions
+4 -2
View File
@@ -1,5 +1,5 @@
use std::collections::HashMap;
use std::ffi::OsString;
use std::io::{BufRead, BufReader, BufWriter, Cursor, Read, Seek, Write};
use std::path::{Path, PathBuf};
use std::process::{Command, ExitStatus, Stdio};
@@ -446,7 +446,9 @@ fn bytecode_compile(
let py_source_paths: Vec<_> = unpacked_paths
.into_iter()
.filter(|path| {
site_packages.join(path).is_file() && path.extension() == Some(&OsString::from("py"))
path.extension()
.is_some_and(|ext| ext.eq_ignore_ascii_case("py"))
&& site_packages.join(path).is_file()
})
.collect();
+33 -32
View File
@@ -284,39 +284,40 @@ impl SourceBuild {
};
// Check if we have a PEP 517 build backend.
let pep517_backend = if source_tree.join("pyproject.toml").is_file() {
let pyproject_toml: PyProjectToml =
toml::from_str(&fs::read_to_string(source_tree.join("pyproject.toml"))?)
.map_err(Error::InvalidPyprojectToml)?;
if let Some(build_system) = pyproject_toml.build_system {
Some(Pep517Backend {
// If `build-backend` is missing, inject the legacy setuptools backend, but
// retain the `requires`, to match `pip` and `build`. Note that while PEP 517
// says that in this case we "should revert to the legacy behaviour of running
// `setup.py` (either directly, or by implicitly invoking the
// `setuptools.build_meta:__legacy__` backend)", we found that in practice, only
// the legacy setuptools backend is allowed. See also:
// https://github.com/pypa/build/blob/de5b44b0c28c598524832dff685a98d5a5148c44/src/build/__init__.py#L114-L118
backend: build_system
.build_backend
.unwrap_or_else(|| "setuptools.build_meta:__legacy__".to_string()),
backend_path: build_system.backend_path,
requirements: build_system.requires,
})
} else {
// If a `pyproject.toml` is present, but `[build-system]` is missing, proceed with
// a PEP 517 build using the default backend, to match `pip` and `build`.
Some(Pep517Backend {
backend: "setuptools.build_meta:__legacy__".to_string(),
backend_path: None,
requirements: vec![
Requirement::from_str("wheel").unwrap(),
Requirement::from_str("setuptools >= 40.8.0").unwrap(),
],
})
let pep517_backend = match fs::read_to_string(source_tree.join("pyproject.toml")) {
Ok(toml) => {
let pyproject_toml: PyProjectToml =
toml::from_str(&toml).map_err(Error::InvalidPyprojectToml)?;
if let Some(build_system) = pyproject_toml.build_system {
Some(Pep517Backend {
// If `build-backend` is missing, inject the legacy setuptools backend, but
// retain the `requires`, to match `pip` and `build`. Note that while PEP 517
// says that in this case we "should revert to the legacy behaviour of running
// `setup.py` (either directly, or by implicitly invoking the
// `setuptools.build_meta:__legacy__` backend)", we found that in practice, only
// the legacy setuptools backend is allowed. See also:
// https://github.com/pypa/build/blob/de5b44b0c28c598524832dff685a98d5a5148c44/src/build/__init__.py#L114-L118
backend: build_system
.build_backend
.unwrap_or_else(|| "setuptools.build_meta:__legacy__".to_string()),
backend_path: build_system.backend_path,
requirements: build_system.requires,
})
} else {
// If a `pyproject.toml` is present, but `[build-system]` is missing, proceed with
// a PEP 517 build using the default backend, to match `pip` and `build`.
Some(Pep517Backend {
backend: "setuptools.build_meta:__legacy__".to_string(),
backend_path: None,
requirements: vec![
Requirement::from_str("wheel").unwrap(),
Requirement::from_str("setuptools >= 40.8.0").unwrap(),
],
})
}
}
} else {
None
Err(err) if err.kind() == io::ErrorKind::NotFound => None,
Err(err) => return Err(err.into()),
};
let venv = gourgeist::create_venv(&temp_dir.path().join(".venv"), interpreter.clone())?;