Skip to content

Resolve prefix injection #11666

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

Merged
merged 8 commits into from
Aug 10, 2022
Merged

Resolve prefix injection #11666

merged 8 commits into from
Aug 10, 2022

Conversation

kenodegard
Copy link
Contributor

@kenodegard kenodegard commented Jul 28, 2022

Description

Depends on #11649
Resolves #11174

When running conda run, users discovered that the wrong executable is invoked. This was especially noticeable on Windows. We first attempted to address this issue in #11257 but found that the source of the prefix injection occurred at the shell integration level so trying to do the path deduplication in the Python code would've been ripe for buggy behavior.

We narrowed it down to being the prefix injection that occurred in the following locations:

__add_sys_prefix_to_path() {
# In dev-mode CONDA_EXE is python.exe and on Windows
# it is in a different relative location to condabin.
if [ -n "${_CE_CONDA}" ] && [ -n "${WINDIR+x}" ]; then
SYSP=$(\dirname "${CONDA_EXE}")
else
SYSP=$(\dirname "${CONDA_EXE}")
SYSP=$(\dirname "${SYSP}")
fi
if [ -n "${WINDIR+x}" ]; then
PATH="${SYSP}/bin:${PATH}"
PATH="${SYSP}/Scripts:${PATH}"
PATH="${SYSP}/Library/bin:${PATH}"
PATH="${SYSP}/Library/usr/bin:${PATH}"
PATH="${SYSP}/Library/mingw-w64/bin:${PATH}"
PATH="${SYSP}:${PATH}"
else
PATH="${SYSP}/bin:${PATH}"
fi
\export PATH
}
__conda_exe() (
__add_sys_prefix_to_path
"$CONDA_EXE" $_CE_M $_CE_CONDA "$@"
)

set conda_tmp_path="$PATH"
setenv PATH "`dirname ${_CONDA_EXE}`:$PATH"

@SET PATH=!_sysp!;!_sysp!\Library\mingw-w64\bin;!_sysp!\Library\usr\bin;!_sysp!\Library\bin;!_sysp!\Scripts;!_sysp!\bin;%PATH%

@SET PATH=!_sysp!;!_sysp!\Library\mingw-w64\bin;!_sysp!\Library\usr\bin;!_sysp!\Library\bin;!_sysp!\Scripts;!_sysp!\bin;%PATH%

<#
.SYNOPSIS
Adds the entries of sys.prefix to PATH and returns the old PATH.
.EXAMPLE
$OldPath = Add-Sys-Prefix-To-Path
#>
function Add-Sys-Prefix-To-Path() {
$OldPath = $Env:PATH;
if ($Env:_CE_CONDA -eq '' -And $Env:OS -eq 'Windows_NT') {
# Windows has a different layout for the python exe than other platforms.
$sysp = Split-Path $Env:CONDA_EXE -Parent;
} else {
$sysp = Split-Path $Env:CONDA_EXE -Parent;
$sysp = Split-Path $sysp -Parent;
}
if ($Env:OS -eq 'Windows_NT') {
$Env:PATH = $sysp + ';' +
$sysp + '\Library\mingw-w64\bin;' +
$sysp + '\Library\usr\bin;' +
$sysp + '\Library\bin;' +
$sysp + '\Scripts;' +
$sysp + '\bin;' + $Env:PATH;
} else {
$Env:PATH = $sysp + '/bin:' + $Env:PATH;
}
return $OldPath;
}

After digging through conda.activate and the git history, it appears that the prefix injection code was first introduced in conda 4.4 (April 2017), @kalefranz sums it up well in comments that have unfortunately not withstood the test of time:

conda/conda/activate.py

Lines 219 to 225 in c6e8d6a

def _get_starting_path_list(self):
path = os.environ['PATH']
if on_win:
# on Windows, the python interpreter prepends sys.prefix\Library\bin on startup WTF
return path.split(os.pathsep)[1:]
else:
return path.split(os.pathsep)

Subsequent changes indicate that this injection on Python startup was actually a Python 3.6 feedstock patch which appears to have been long since removed (AnacondaRecipes/python-feedstock@ef17e17).

In conda 4.6.9 (March 2019) the Python package patching was instead replaced (ca77c9c) with the shell interface prefix injection that we see today.

Originally all of this prefix injection was unique to Windows but eventually in conda 4.6.13 (April 2019) it was mirrored over to *nix systems (8ec72dd) which is where we find ourselves now, still wondering WTF.

Checklist - did you ...

  • Add a file to the news directory (using the template) for the next release's release notes?
  • Add / update necessary tests?
  • Add / update outdated documentation?

@kenodegard kenodegard requested a review from a team as a code owner July 28, 2022 03:02
@conda-bot conda-bot added the cla-signed [bot] added once the contributor has signed the CLA label Jul 28, 2022
@travishathaway travishathaway added the source::anaconda created by members of Anaconda, Inc. label Jul 28, 2022
@jaimergp
Copy link
Contributor

jaimergp commented Aug 1, 2022

I think it has to do with how DLL loading works on Windows. DLLs have to be on PATH, and the Library path is a conda artifact that is not usually part of the standard Python path. I think all of this helps Windows users running Python without having to activate the environment, but at this point I am just guessing.

@kenodegard
Copy link
Contributor Author

@jaimergp probably but I assume something has improved in this regard since the patch has been removed and since other versions of the Python package don't appear to have this patch

@jaimergp
Copy link
Contributor

jaimergp commented Aug 1, 2022

I think it was removed in 3.9.something and 3.10 (at least in conda-forge).

@kenodegard
Copy link
Contributor Author

I see that CF's Python 3.6 still has the patch, the other versions do not

@kenodegard kenodegard force-pushed the prefix-injection branch 5 times, most recently from 227ec1d to a6d66e3 Compare August 4, 2022 19:57
jezdez
jezdez previously approved these changes Aug 8, 2022
Copy link
Member

@jezdez jezdez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments not withstanding, let's merge this as-is and create a follow-up issue to fix the Windows CI setup and/or add support for the tests that are currently not working in the CI setup. It's not ideal, but as long as the manual tests worked, that's better than nothing.

I'd be interested to hear what the VS Code people think abut this, maybe they could try the Canary build of this?

Nice sleuthing @kenodegard!! 🥳

@kenodegard kenodegard merged commit c6ead1b into conda:main Aug 10, 2022
@kenodegard kenodegard deleted the prefix-injection branch August 10, 2022 19:02
@kenodegard kenodegard mentioned this pull request Aug 11, 2022
3 tasks
if( $conda_tmp_status != 0 ) exit ${conda_tmp_status}
eval "${ask_conda}"
rehash
breaksw
default:
$_CONDA_EXE $argv[1-]
setenv PATH "$conda_tmp_path"
# setenv PATH "$conda_tmp_path"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kenodegard Didn't you want to clean these things up before merge?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops missed this one

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kenodegard kenodegard mentioned this pull request Aug 12, 2022
3 tasks
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
cla-signed [bot] added once the contributor has signed the CLA locked [bot] locked due to inactivity source::anaconda created by members of Anaconda, Inc.
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

conda shell function injects $CONDA_PREFIX into $PATH causing incorrect behavior in conda run
5 participants