diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2025-01-09 13:53:06 +0100 |
---|---|---|
committer | Eli Schwartz <eschwartz93@gmail.com> | 2025-03-09 13:05:08 -0400 |
commit | a25e3e58aae434ce0788b947fcbe7ddbbff9f0e2 (patch) | |
tree | 67edebec8687ccedafdf0b69dddc2abefb81b79d | |
parent | e3dfcf6cba97f00a51d34f0feb67fe88d098fff5 (diff) | |
download | meson-a25e3e58aae434ce0788b947fcbe7ddbbff9f0e2.zip meson-a25e3e58aae434ce0788b947fcbe7ddbbff9f0e2.tar.gz meson-a25e3e58aae434ce0788b947fcbe7ddbbff9f0e2.tar.bz2 |
interpreter: do not use pathlib in validate_within_subproject
pathlib's implementation of Path iteration is expensive;
"foo.parents" has quadratic complexity when building it:
return self._path._from_parsed_parts(self._drv, self._root,
self._tail[:-idx - 1])
and comparisons performed by "path in file.parents" potentially
have the same issue. Use the newly introduced "is_parent_path"
function to check whether a file is under a path in the same way.
This removes Path from its hottest use.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r-- | mesonbuild/interpreter/interpreter.py | 34 |
1 files changed, 18 insertions, 16 deletions
diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index dd91474..ff93ac6 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -19,7 +19,7 @@ from .. import envconfig from ..wrap import wrap, WrapMode from .. import mesonlib from ..mesonlib import (EnvironmentVariables, ExecutableSerialisation, MesonBugException, MesonException, HoldableObject, - FileMode, MachineChoice, listify, + FileMode, MachineChoice, is_parent_path, listify, extract_as_list, has_path_sep, path_is_in_root, PerMachine) from ..options import OptionKey from ..programs import ExternalProgram, NonExistingExternalProgram @@ -3109,8 +3109,8 @@ class Interpreter(InterpreterBase, HoldableObject): # subproject than it is defined in (due to e.g. a # declare_dependency). def validate_within_subproject(self, subdir, fname): - srcdir = Path(self.environment.source_dir) - builddir = Path(self.environment.build_dir) + srcdir = self.environment.source_dir + builddir = self.environment.build_dir if isinstance(fname, P_OBJ.DependencyVariableString): def validate_installable_file(fpath: Path) -> bool: installablefiles: T.Set[Path] = set() @@ -3131,34 +3131,36 @@ class Interpreter(InterpreterBase, HoldableObject): if validate_installable_file(norm): return - def do_validate_within_subproject(norm: Path) -> None: + def do_validate_within_subproject(norm: str) -> None: if os.path.isdir(norm): inputtype = 'directory' else: inputtype = 'file' - if InterpreterRuleRelaxation.ALLOW_BUILD_DIR_FILE_REFERENCES in self.relaxations and builddir in norm.parents: + if InterpreterRuleRelaxation.ALLOW_BUILD_DIR_FILE_REFERENCES in self.relaxations and is_parent_path(builddir, norm): return - if srcdir not in norm.parents: + + if not is_parent_path(srcdir, norm): # Grabbing files outside the source tree is ok. # This is for vendor stuff like: # # /opt/vendorsdk/src/file_with_license_restrictions.c return - project_root = Path(srcdir, self.root_subdir) - subproject_dir = project_root / self.subproject_dir - if norm == project_root: - return - if project_root not in norm.parents: - raise InterpreterException(f'Sandbox violation: Tried to grab {inputtype} {norm.name} outside current (sub)project.') - if subproject_dir == norm or subproject_dir in norm.parents: - raise InterpreterException(f'Sandbox violation: Tried to grab {inputtype} {norm.name} from a nested subproject.') + + project_root = os.path.join(srcdir, self.root_subdir) + if not is_parent_path(project_root, norm): + name = os.path.basename(norm) + raise InterpreterException(f'Sandbox violation: Tried to grab {inputtype} {name} outside current (sub)project.') + + subproject_dir = os.path.join(project_root, self.subproject_dir) + if is_parent_path(subproject_dir, norm): + name = os.path.basename(norm) + raise InterpreterException(f'Sandbox violation: Tried to grab {inputtype} {name} from a nested subproject.') fname = os.path.join(subdir, fname) if fname in self.validated_cache: return - # Use os.path.abspath() to eliminate .. segments, but do not resolve symlinks - norm = Path(os.path.abspath(Path(srcdir, fname))) + norm = os.path.abspath(os.path.join(srcdir, fname)) do_validate_within_subproject(norm) self.validated_cache.add(fname) |