Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Targets' add_target(s) methods do not correctly check passed paths #957

Closed
lukpueh opened this issue Nov 12, 2019 · 6 comments
Closed

Targets' add_target(s) methods do not correctly check passed paths #957

lukpueh opened this issue Nov 12, 2019 · 6 comments

Comments

@lukpueh
Copy link
Member

lukpueh commented Nov 12, 2019

Description of issue or feature request:

Judging from the docstrings and comments, add_target and add_targets are expected to update a Targets object with passed target paths, if they are relative to a targets directory base path (i.e. self._targets_directory).

However, they don't seem to take into account that Python's os.path.join ignores all path component arguments prior to a component that looks like an absolute path.

Current behavior:

  • Works as expected (?) if passed target path is relative to a targets directory base path or absolute but falls into the targets directory:
# repo._targets_directory == "/path/to/repo/targets"
repo.targets.add_target("foo.txt")
repo.targets.add_target("/path/to/repo/targets/bar.txt)
# Successfully adds "foo.txt" and "bar.txt" 
  • Fails if the passed target path is not absolute and does not exist relative to targets directory base path "/path/to/repo/targets".
# repo._targets_directory == "/path/to/repo/targets"
repo.targets.add_target("repo/targets/foo.txt")
# Fails with "'/path/to/repo/targets/repo/targets/foo.txt' is not a valid file in the repository's targets directory"
  • Fails if the passed target path is absolute and does not exist
#repo._targets_directory == "/path/to/repo/targets"
repo.targets.add_target("/path/does/not/exist/foo.txt")
# Fails with "'/path/does/not/exist/foo.txt' is not a valid file in the repository's targets directory"
  • Has unexpected behavior if the passed path is absolute and exists!

Expected behavior:
Revise intended behavior, update implementation accordingly.

lukpueh added a commit to lukpueh/tuf that referenced this issue Nov 20, 2019
- Correctly show that repo.get_filepaths_in_directory() returns
  absolute and not relative paths
- Pass absolute path to repo.targets.add_target() to fix exception
- Also see theupdateframework#957

Signed-off-by: Lukas Puehringer <[email protected]>
@lukpueh
Copy link
Member Author

lukpueh commented Nov 29, 2019

IIUC target files don't get hashed right away, i.e. on add_target(). This happens when generating and writing targets metadata to disk, e.g. via writeall(). So why not completely ignore the notion of files on disk until then?

add_target could just add any paths passed to the internal representation of targets metadata, checking that they are relative (and maybe don't contain ".."?). And only later, when the corresponding files are actually needed, i.e. to generate hashes, should it fail gracefully if any of the paths can't be resolved into a file relative to the targets directory base path.

@joshuagl
Copy link
Member

A possible disadvantage of this proposal may be that it's harder to debug if the errors come at a seemingly unrelated call site. Path related failures when you add those paths in add_target() feels a lot more intuitive than path related failures at a later time.

Is it safe to infer from the issue report that all four of the current behaviour examples should succeed? I'd be happy to have a go at implementing a fix for this.

Aside: I've worked on projects in the past where we had to implement an alternative path joining function, due to the / related behaviour of os.path.join(). That might be a way to go here, perhaps a helper in SSL? I'll need to look at the current code some before committing to that, though.

@lukpueh
Copy link
Member Author

lukpueh commented Nov 29, 2019

I agree with your debugging concern, @joshuagl. I am concerned with least surprise. :)

To me, and this should answer your other question, none of above cases seems fully surprise-free. Here are some concerns:

  • Why can I pass an absolute path, if the spec says that targetpaths should be relative?
  • Why should I pass an absolute path, if it must be relative to an "unknown" base path (i.e. self._targets_directory), whose portion in the path gets stripped anyway?
  • Why must a relative path be relative to an "unknown" base path, and not relative to my cwd?

lukpueh added a commit that referenced this issue Dec 16, 2019
- Correctly show that repo.get_filepaths_in_directory() returns
  absolute and not relative paths
- Pass absolute path to repo.targets.add_target() to fix exception
- Also see #957

Signed-off-by: Lukas Puehringer <[email protected]>
@joshuagl
Copy link
Member

joshuagl commented Mar 4, 2020

add_target could just add any paths passed to the internal representation of targets metadata, checking that they are relative (and maybe don't contain ".."?). And only later, when the corresponding files are actually needed, i.e. to generate hashes, should it fail gracefully if any of the paths can't be resolved into a file relative to the targets directory base path.

This feels like a sensible approach, that handles @lukpueh's least-surprise concerns above and we can address my debugability concern with appropriate logging.

@lukpueh
Copy link
Member Author

lukpueh commented Mar 17, 2020

For consistency we should adopt whatever behavior we want for add_target and add_targets to other methods of repository_tool.Targets, that allow adding target files, i.e.:

@lukpueh
Copy link
Member Author

lukpueh commented Apr 8, 2020

Fixed in #1008

@lukpueh lukpueh closed this as completed Apr 8, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants