summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mesonbuild/interpreter/interpreter.py51
1 files changed, 31 insertions, 20 deletions
diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py
index a118b3c59..dd91474eb 100644
--- a/mesonbuild/interpreter/interpreter.py
+++ b/mesonbuild/interpreter/interpreter.py
@@ -292,6 +292,7 @@ class Interpreter(InterpreterBase, HoldableObject):
self.sanity_check_ast()
self.builtin.update({'meson': MesonMain(self.build, self)})
self.processed_buildfiles: T.Set[str] = set()
+ self.validated_cache: T.Set[str] = set()
self.project_args_frozen = False
self.global_args_frozen = False # implies self.project_args_frozen
self.subprojects: T.Dict[str, SubprojectHolder] = {}
@@ -3129,27 +3130,37 @@ class Interpreter(InterpreterBase, HoldableObject):
# subproject files, as long as they are scheduled to be installed.
if validate_installable_file(norm):
return
- norm = Path(os.path.abspath(Path(srcdir, subdir, fname)))
- 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:
- return
- if srcdir not in norm.parents:
- # 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:
+
+ def do_validate_within_subproject(norm: Path) -> 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:
+ return
+ if srcdir not in norm.parents:
+ # 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.')
+
+ fname = os.path.join(subdir, fname)
+ if fname in self.validated_cache:
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.')
+
+ # Use os.path.abspath() to eliminate .. segments, but do not resolve symlinks
+ norm = Path(os.path.abspath(Path(srcdir, fname)))
+ do_validate_within_subproject(norm)
+ self.validated_cache.add(fname)
@T.overload
def source_strings_to_files(self, sources: T.List['mesonlib.FileOrString'], strict: bool = True) -> T.List['mesonlib.File']: ...