Interpreter: Fix nested subsubproject detection

A sub-subproject can be configured directly from
`subprojects/foo/subprojects/bar/` in the case `bar` is in the same git
repository as `foo` and not downloaded separately into the main
project's `subprojects/`. In that case the nested subproject violation
code was wrong because it is allowed to have more than one "subprojects"
in path (was not possible before Meson 0.56.0).

Example:
- self.environment.source_dir = '/home/user/myproject'
- self.root_subdir = 'subprojects/foo/subprojects/bar'
- project_root = '/home/user/myproject/subprojects/foo/subprojects/bar'
- norm = '/home/user/myproject/subprojects/foo/subprojects/bar/file.c'

We want `norm` path to have `project_root` in its parents and not have
`project_root / 'subprojects'` in its parents. In that case we are sure
`file.c` is within `bar` subproject.
pull/8166/head
Xavier Claessens 4 years ago committed by Jussi Pakkanen
parent 4ff020759a
commit c659be6928
  1. 48
      mesonbuild/interpreter.py
  2. 1
      test cases/common/99 subproject subdir/subprojects/sub_implicit/subprojects/subsub/foo.h
  3. 4
      test cases/common/99 subproject subdir/subprojects/sub_implicit/subprojects/subsub/meson.build
  4. 5
      test cases/common/99 subproject subdir/test.json
  5. 2
      test cases/failing/62 subproj filegrab/test.json
  6. 2
      test cases/failing/63 grab subproj/test.json
  7. 2
      test cases/failing/64 grab sibling/test.json

@ -4786,21 +4786,6 @@ This will probably not work.
Try setting b_lundef to false instead.'''.format(self.coredata.options[OptionKey('b_sanitize')].value),
location=self.current_node)
def evaluate_subproject_info(self, path_from_source_root, subproject_dir):
depth = 0
subproj_name = ''
segs = PurePath(path_from_source_root).parts
segs_spd = PurePath(subproject_dir).parts
while segs and segs[0] == segs_spd[0]:
if len(segs_spd) == 1:
subproj_name = segs[1]
segs = segs[2:]
depth += 1
else:
segs_spd = segs_spd[1:]
segs = segs[1:]
return (depth, subproj_name)
# Check that the indicated file is within the same subproject
# as we currently are. This is to stop people doing
# nasty things like:
@ -4812,26 +4797,19 @@ Try setting b_lundef to false instead.'''.format(self.coredata.options[OptionKey
# subproject than it is defined in (due to e.g. a
# declare_dependency).
def validate_within_subproject(self, subdir, fname):
norm = os.path.normpath(os.path.join(subdir, fname))
if os.path.isabs(norm):
if not norm.startswith(self.environment.source_dir):
# Grabbing files outside the source tree is ok.
# This is for vendor stuff like:
#
# /opt/vendorsdk/src/file_with_license_restrictions.c
return
norm = os.path.relpath(norm, self.environment.source_dir)
assert(not os.path.isabs(norm))
(num_sps, sproj_name) = self.evaluate_subproject_info(norm, self.subproject_dir)
plain_filename = os.path.basename(norm)
if num_sps == 0:
if not self.is_subproject():
return
raise InterpreterException('Sandbox violation: Tried to grab file %s from a different subproject.' % plain_filename)
if num_sps > 1:
raise InterpreterException('Sandbox violation: Tried to grab file %s from a nested subproject.' % plain_filename)
if sproj_name != self.subproject_directory_name:
raise InterpreterException('Sandbox violation: Tried to grab file %s from a different subproject.' % plain_filename)
srcdir = Path(self.environment.source_dir)
norm = Path(srcdir, subdir, fname).resolve()
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)
if project_root not in norm.parents:
raise InterpreterException('Sandbox violation: Tried to grab file {} outside current (sub)project.'.format(norm.name))
if project_root / self.subproject_dir in norm.parents:
raise InterpreterException('Sandbox violation: Tried to grab file {} from a nested subproject.'.format(norm.name))
def source_strings_to_files(self, sources: T.List[str]) -> T.List[mesonlib.File]:
mesonlib.check_direntry_issues(sources)

@ -1,3 +1,7 @@
project('subsub')
meson.override_dependency('subsub', declare_dependency())
# Regression test: Installing a header from nested sub-subproject used to raise:
# ERROR: Sandbox violation: Tried to grab file foo.h from a nested subproject.
install_headers('foo.h')

@ -0,0 +1,5 @@
{
"installed": [
{ "type": "file", "file": "usr/include/foo.h" }
]
}

@ -1,7 +1,7 @@
{
"stdout": [
{
"line": "test cases/failing/62 subproj filegrab/subprojects/a/meson.build:3:0: ERROR: Sandbox violation: Tried to grab file prog.c from a different subproject."
"line": "test cases/failing/62 subproj filegrab/subprojects/a/meson.build:3:0: ERROR: Sandbox violation: Tried to grab file prog.c outside current (sub)project."
}
]
}

@ -1,7 +1,7 @@
{
"stdout": [
{
"line": "test cases/failing/63 grab subproj/meson.build:7:0: ERROR: Sandbox violation: Tried to grab file sub.c from a different subproject."
"line": "test cases/failing/63 grab subproj/meson.build:7:0: ERROR: Sandbox violation: Tried to grab file sub.c from a nested subproject."
}
]
}

@ -1,7 +1,7 @@
{
"stdout": [
{
"line": "test cases/failing/64 grab sibling/subprojects/a/meson.build:3:0: ERROR: Sandbox violation: Tried to grab file sneaky.c from a different subproject."
"line": "test cases/failing/64 grab sibling/subprojects/a/meson.build:3:0: ERROR: Sandbox violation: Tried to grab file sneaky.c outside current (sub)project."
}
]
}

Loading…
Cancel
Save