Bug 575385 - FS_POSIX.discoverGitExe violates POSIX by using FS.searchPath
Summary: FS_POSIX.discoverGitExe violates POSIX by using FS.searchPath
Status: RESOLVED FIXED
Alias: None
Product: JGit
Classification: Technology
Component: JGit (show other bugs)
Version: 5.13   Edit
Hardware: All All
: P3 normal (vote)
Target Milestone: 5.13   Edit
Assignee: Project Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-08-12 18:56 EDT by Josh Soref CLA
Modified: 2021-08-17 11:58 EDT (History)
2 users (show)

See Also:


Attachments
Maybe? (1.85 KB, patch)
2021-08-12 19:44 EDT, Josh Soref CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Josh Soref CLA 2021-08-12 18:56:31 EDT
I tried using a Gradle task in VSCode on macOS (Big Sur) and got this output:

> Task :addOns:spotlessKotlinGradle
Cannot run program "/Users/jsoref/bin/git" (in directory "/Users/jsoref/bin"): error=13, Permission denied

In my path, I have ~/bin and /usr/local/bin

~/bin/git is a non executable file
/usr/local/bin/git is an executable file

https://itectec.com/superuser/does-path-search-include-symlinks/
> The list shall be searched from beginning to end, applying the filename to each prefix, until an executable file with the specified name and appropriate execution permissions is found.

https://git.eclipse.org/c/jgit/jgit.git/tree/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_POSIX.java#n141
	protected File discoverGitExe() {
		String path = SystemReader.getInstance().getenv("PATH"); //$NON-NLS-1$
		File gitExe = searchPath(path, "git"); //$NON-NLS-1$


https://git.eclipse.org/c/jgit/jgit.git/tree/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java#n1269
	 * Searches the given path to see if it contains one of the given files.
	 * Returns the first it finds. Returns null if not found or if path is null.
	 *
	 * @param path
	 *            List of paths to search separated by File.pathSeparator
	 * @param lookFor
	 *            Files to search for in the given path
	 * @return the first match found, or null
	 * @since 3.0
	 */
	protected static File searchPath(String path, String... lookFor) {
		if (path == null)
			return null;

		for (String p : path.split(File.pathSeparator)) {
			for (String command : lookFor) {
				final File file = new File(p, command);
				try {
					if (file.isFile()) {
						return file.getAbsoluteFile();


Expected results:
Honor posix and only consider files that are executable.
Comment 1 Josh Soref CLA 2021-08-12 19:44:53 EDT
Created attachment 286929 [details]
Maybe?
Comment 2 Thomas Wolf CLA 2021-08-13 03:14:11 EDT
Funny. That code is like that since its inception, i.e., 2010 and before, and you're the first person to report this? At least I found no previous bug report about this.

Anyway; I think just adding "&& f.canExecute()" in FS.searchPath() should be fine. On Windows, File.canExecute() is always true.
Comment 3 Josh Soref CLA 2021-08-13 08:07:30 EDT
I didn't feel like looking at (/searching for) the Windows implementation of canExecute. In practice, it shouldn't matter, since the Windows caller would ask about git.exe.

The Windows caller probably doesn't properly check PATHEXT, but that's another bug for another time.

Technically NTFS does have an execute bit, FAT does not (and thus implementations tend to return true for all files), which is why I didn't spend the time trying to find the details.

I have been known to take advantage of all of these features. However I don't usually interact with jgit (other than via Jenkins, which, while I also built for a while).

This kind of thing would generally only happen if someone like me was temporarily shimming something and decided to keep the shim around for the future and chose to use `-x` instead of renaming it.

Fwiw, I think I still have a couple of other shims in my path. Typically some for `hg` and `gcloud`/`gsutil`. I probably should add one for `kubectl` since `brew` keeps on swapping implementations whenever it upgrades docker.app.
Comment 4 Josh Soref CLA 2021-08-13 12:38:54 EDT
Thomas Wolf: can I leave this bug to you to resolve? I'm really not attached to the particulars of how it's fixed. I'm happy to provide an empty non executable text file named `git` if that would help, but...

(This was just a random bump I hit while trying to fix something else.)

For the win32 thing I flagged:

https://git.eclipse.org/c/jgit/jgit.git/tree/org.eclipse.jgit/src/org/eclipse/jgit/util/FS_Win32.java#n144

> 		File gitExe = searchPath(path, "git.exe", "git.cmd"); //$NON-NLS-1$ //$NON-NLS-2$

It is wrong as noted.

https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/where#remarks
https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/cc770297(v=ws.11)#remarks

Roughly, the code should get the PathExt system environment variable, split it by `;` and then append each to `git` and then call `searchPath(path, array_of_possible_git_file_names)`.

(Technically it probably should have a default fallback value in case PathExt is not set, you're welcome to use `.exe;.cmd` to match the current behavior, or `.com;.exe;.bat;.cmd` to match NT. I wouldn't suggest not having a fallback, since it wouldn't shock me if someone (like me) randomly deleted that environment variable (from memory, from >20 years ago, it doesn't break most things).
Comment 5 Eclipse Genie CLA 2021-08-15 17:35:28 EDT
New Gerrit change created: https://git.eclipse.org/r/c/jgit/jgit/+/184048