Skip to content

Commit

Permalink
Implement glob-like pattern matching
Browse files Browse the repository at this point in the history
According to the recently updated version of the specification the shell
style wildcard matching is glob-like (see theupdateframework/specification#174),
and therefore a path separator in a path should not be matched by a
wildcard in the PATHPATTERN.

That's not what happens with fnmatch.fnmatch() which doesn't
see "/" separator as special symbol.

Signed-off-by: Martin Vrachev <[email protected]>
  • Loading branch information
MVrachev committed Jul 29, 2021
1 parent 01e2308 commit e79ff53
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 2 deletions.
24 changes: 24 additions & 0 deletions tests/test_updater_ng.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

from tests import utils
from tuf import ngclient
from tuf.ngclient.updater import _is_target_in_pathpattern

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -148,6 +149,29 @@ def test_refresh_with_only_local_root(self):
# Get targetinfo for 'file3.txt' listed in the delegated role1
targetinfo3= self.repository_updater.get_one_valid_targetinfo('file3.txt')


def test_is_target_in_pathpattern(self):
supported_use_cases = [
("foo.tgz", "foo.tgz"),
("foo.tgz", "*"),
("targets/foo.tgz", "*"),
("foo.tgz", "*.tgz"),
("foo-version-2.tgz", "foo-version-?.tgz"),
("foo-version-a.tgz", "foo-version-?.tgz"),
("targets/foo.tgz", "targets/*.tgz"),
("targets/bar.tgz", "targets/*.tgz")
]
for targetname, pathpattern in supported_use_cases:
self.assertTrue(_is_target_in_pathpattern(targetname, pathpattern))

invalid_use_cases = [
("targets/foo.tgz", "*.tgz"),
("*.tgz", "/foo.tgz"),
("foo-version-?.tgz", "foo-version-alpha.tgz")
]
for pathpattern, targetname in invalid_use_cases:
self.assertFalse(_is_target_in_pathpattern(pathpattern, targetname))

if __name__ == '__main__':
utils.configure_test_logging(sys.argv)
unittest.main()
15 changes: 13 additions & 2 deletions tuf/ngclient/updater.py
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,17 @@ def _preorder_depth_first_walk(self, target_filepath) -> Dict:
return {"filepath": target_filepath, "fileinfo": target}


def _is_target_in_pathpattern(targetname, pathpattern):
pathpattern_dir = os.path.dirname(pathpattern)
target_dir = os.path.dirname(targetname)
if pathpattern_dir == target_dir:
return fnmatch.fnmatch(targetname, pathpattern)
elif pathpattern == "*":
return True
# pathpattern dir != targetname dir means target is not in pathpattern
return False


def _visit_child_role(child_role: Dict, target_filepath: str) -> str:
"""
<Purpose>
Expand Down Expand Up @@ -527,8 +538,8 @@ def _visit_child_role(child_role: Dict, target_filepath: str) -> str:
# target without a leading path separator - make sure to strip any
# leading path separators so that a match is made.
# Example: "foo.tgz" should match with "/*.tgz".
if fnmatch.fnmatch(
target_filepath.lstrip(os.sep), child_role_path.lstrip(os.sep)
if _is_target_in_pathpattern(
child_role_path.lstrip(os.sep), target_filepath.lstrip(os.sep),
):
logger.debug(
"Child role %s is allowed to sign for %s",
Expand Down

0 comments on commit e79ff53

Please sign in to comment.