You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix: Extend ALTERNATIVE_LOCATIONS for ARM64 Windows
`gix-path` looks for and runs an installed `git` executable, when
present, to discover information about how Git is set up. This
is used in several functions in `gix_path::env`, especially on
Windows, where if `git` is not found in a `PATH` search, then
common installation locations for Git for Windows are checked.
These locations on Windows are resolved based on information from
the current environment, since different systems have different
program files directories. This was implemented in GitoxideLabs#1456 (which
built on GitoxideLabs#1419). Although this was sufficient to find the most
common Git for Windows installation locations, it did not find
ARM64 builds of Git for Windows. Such builds place the non-shim
`git.exe` program in `(git root)\clangarm64\bin`, rather than in
`(git root)\mingw64\bin` or `(git root)\mingw32\bin`. At the time
of GitoxideLabs#1416 and GitoxideLabs#1419, no stable ARM64 builds of Git for Windows were
available. Since then, Git for Windows began releasing such builds.
This modifies the alternative locations examined if `git.exe` is
not found in a `PATH` search on Windows so that, where `(git root)`
is in a 64-bit program files directory, we check for a
`(git root)\clangarm64\bin` directory, in addition to checking for
a `(git root)\mingw64\bin` directory as was already done.
Although 64-bit and 32-bit program files directories are separate,
on ARM64 systems the 64-bit program files directory is used for
both ARM64 programs that the system can run directly and x86_64
programs that the system must run through emulation.
This checks both `clangarm64` and `mingw64`, where `mingw64` was
checked before. It does so in that order, because if both are
available, then we are probably on an ARM64 system, and the ARM64
build of Git for Windows should be preferred, both because it will
tend to perform better and because the user is likely to expect
that to be used. (An x86_64 build, especially if present directly
alongside an ARM64 build, may be left over from a previous version
of Git for Windows that didn't have ARM64 builds and that was only
incompletely uninstalled.)
This checks both, in that order, on all systems where we had
checked `mingw64` before, even on x86_64 systems. This is because:
- To limit production dependencies and code complexity, we have
been examining only environment variables to ascertain which
program files directories exist and whether they are 64-bit or
32-bit program files directories. At least for now, this
preserves that general approach.
- But determining whether the system is ARM64 or x86_64 is less
straightforward to ascertain from environment variables, if we
are to accommodate all reasonable edge cases.
The reason it's less straightforward is that, if our parent process
(or other ancestor) passes down a sanitized environment while still
attempting to let the program files directories be found, then:
- That process should make available all of the `ProgramFiles`,
`ProgramW6432`, `ProgramFiles(x86)`, and `ProgramFiles(ARM)`
variables that exist in its own environment.
(This is because, on 64-bit Windows, the child `ProgramFiles` is
populated from the parent `ProgramW6432`, `ProgramFiles(x86)`, or
`ProgramFiles(ARM)`, depending on the architectures of the parent
and child, if the parent passes down the relevant variable.)
- Even if the parent/ancestor is not designed with the WoW64 rules
in mind, it will likely pass down at least `ProgramFiles`.
This will then be used as the child `ProgramFiles`, if whichever
of `ProgramFilesW6432`, `ProgramFiles(x86)`, or
`ProgramFiles(ARM)` is relevant is not passed down by the parent.
- In contrast, the parent/ancestor may omit the variables
`PROCESSOR_ARCHITECTURE` and `PROCESSOR_ARCHITEW6432`, which are
not obviously needed for locating programs.
- Even if `PROCESSOR_ARCHITE*` variables are preserved, there are
common cases where they are not sufficient, such as when we are
an x86_64 build but the system is ARM64 and Git for Windows is
ARM64. `gix-path` is a library crate, and it is likely sometimes
to be used in an x86_64 program on such a system.
Also, if `gix-path` is used in an Arm64EC program, then even
though its code may be ARM64 with the `arm64ec-pc-windows-msvc`
Rust target, the program would still be treated as an x86_64
program in its interactions with the system and other programs,
including in how its environment variables' values are populated
and how their values are affected by WoW64.
(`gix-path` may also be x86_64 code where the program is Arm64EC.
One way this happens is if `gix-path` is used in an x86_64 DLL,
and an Arm64EC program loads the DLL. Using x86_64 DLLs from
ARM64 code is one of the reasons a program may use an Arm64EC
target. In this case, the Rust target will be for x86_64, not
ARM64 or Arm64EC. So checking our own build target can't fully
check if the program is Arm64EC.)
- Although the `PROCESSOR_IDENTIFIER` variable is more reliable if
present--see actions/partner-runner-images#117 for an example of
where this is more reliable than `PROCESSOR_ARCHITECTURE`--it is
more complex to parse. More importantly, it may be omitted even
if a parent/ancestor lets `PROCESSOR_ARCHITE*` through.
- It would sometimes work to look for `ProgramFiles(ARM)`. This
environment variable, if present, gives the 32-bit ARM program
files directory location. If set, then the Windows system could
be treated as ARM64. However, a parent/ancestor process may omit
this even when passing down program files related environment
variables, including `ProgramFiles(x86)`. It may do so because
the `ProgramFiles(ARM)` environment variable is less well known.
It may also do so intentionally, if the parent process is only
passing down variables needed to find Git for Windows, for which
one shouldn't need to know the 32-bit ARM program files directory
location, since Git for Windows has never had 32-bit ARM builds.
Relatedly, augmenting the search by checking the filesystem for a
sibling directory named `Program Files (ARM)` should not be done,
because this directory has no special meaning outside of ARM64
Windows. It may therefore be left over from a previous
installation or migration, or even created by a local user as in
the CVE-2024-40644 scenario patched in GitoxideLabs#1456.
(Complexities related to deciding whether and in what order to
search `bin` subdirectories of `clangarm64`, `mingw64`, and
`mingw32` would go away if we looked for the shim rather than the
non-shim executable. This is because the path from `(git root)` to
the shim does not contain a directory component named after a build
target. That simplification would carry its own tradeoffs, and it
is unclear if it ought to be done; it is not done here.)
0 commit comments