aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2025-01-09 13:53:06 +0100
committerEli Schwartz <eschwartz93@gmail.com>2025-03-09 13:05:08 -0400
commita25e3e58aae434ce0788b947fcbe7ddbbff9f0e2 (patch)
tree67edebec8687ccedafdf0b69dddc2abefb81b79d
parente3dfcf6cba97f00a51d34f0feb67fe88d098fff5 (diff)
downloadmeson-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.py34
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)