diff --git a/libexec/pyenv-global b/libexec/pyenv-global index dd9dae97..de6007f7 100755 --- a/libexec/pyenv-global +++ b/libexec/pyenv-global @@ -36,12 +36,16 @@ if [ -n "$versions" ]; then pyenv-version-file-write "$PYENV_VERSION_FILE" "${versions[@]}" else OLDIFS="$IFS" + # VAR=() of unquoted value does glob expansion (against the current dir's contents) after IFS-splitting + # which is undesired + set -f IFS=: versions=($( pyenv-version-file-read "$PYENV_VERSION_FILE" || pyenv-version-file-read "${PYENV_ROOT}/global" || pyenv-version-file-read "${PYENV_ROOT}/default" || echo system )) + set +f IFS="$OLDIFS" for version in "${versions[@]}"; do echo "$version" diff --git a/libexec/pyenv-local b/libexec/pyenv-local index a44576a6..4c4e37c1 100755 --- a/libexec/pyenv-local +++ b/libexec/pyenv-local @@ -59,7 +59,11 @@ elif [ -n "$versions" ]; then pyenv-version-file-write ${FORCE:+-f }.python-version "${versions[@]}" else if version_file="$(pyenv-version-file "$PWD")"; then + # VAR=() of unquoted value does glob expansion (against the current dir's contents) after IFS-splitting + # which is undesired + set -f IFS=: versions=($(pyenv-version-file-read "$version_file")) + set +f for version in "${versions[@]}"; do echo "$version" done diff --git a/libexec/pyenv-prefix b/libexec/pyenv-prefix index 65bc5425..f42bd660 100755 --- a/libexec/pyenv-prefix +++ b/libexec/pyenv-prefix @@ -28,6 +28,9 @@ fi PYENV_PREFIX_PATHS=() OLDIFS="$IFS" { IFS=: + # Unquoted $VAR does glob expansion (against the current dir's contents) after IFS-splitting + # which is undesired + set -f for version in ${PYENV_VERSION}; do if [ "$version" = "system" ]; then if PYTHON_PATH="$(PYENV_VERSION="${version}" pyenv-which python --skip-advice 2>/dev/null)" || \ @@ -52,6 +55,7 @@ OLDIFS="$IFS" exit 1 fi done + set +f } IFS="$OLDIFS" diff --git a/libexec/pyenv-version b/libexec/pyenv-version index 75e2287c..a2ad8e7e 100755 --- a/libexec/pyenv-version +++ b/libexec/pyenv-version @@ -9,7 +9,11 @@ set -e exitcode=0 OLDIFS="$IFS" +# VAR=() of unquoted value does glob expansion (against the current dir's contents) after IFS-splitting +# which is undesired +set -f IFS=: PYENV_VERSION_NAMES=($(pyenv-version-name)) || exitcode=$? +set +f IFS="$OLDIFS" unset bare diff --git a/libexec/pyenv-version-name b/libexec/pyenv-version-name index f7c57efb..4430f8ed 100755 --- a/libexec/pyenv-version-name +++ b/libexec/pyenv-version-name @@ -46,6 +46,9 @@ versions=() OLDIFS="$IFS" { IFS=: any_not_installed=0 + # Unquoted $VAR does glob expansion (against the current dir's contents) after IFS-splitting + # which is undesired + set -f for version in ${PYENV_VERSION}; do # Remove the explicit 'python-' prefix from versions like 'python-3.12'. normalised_version="${version#python-}" @@ -66,6 +69,7 @@ OLDIFS="$IFS" fi fi done + set +f } IFS="$OLDIFS" diff --git a/libexec/pyenv-versions b/libexec/pyenv-versions index bfd67c70..91cb56d4 100755 --- a/libexec/pyenv-versions +++ b/libexec/pyenv-versions @@ -99,6 +99,9 @@ else miss_prefix=" " OLDIFS="$IFS" IFS=: + # VAR=() of unquoted value does glob expansion (against the current dir's contents) after IFS-splitting + # which is undesired + set -f if ((${BASH_VERSINFO[0]} > 3)); then for i in $(pyenv-version-name || true); do current_versions["$i"]="1" @@ -106,6 +109,7 @@ else else current_versions=($(pyenv-version-name || true)) fi + set +f IFS="$OLDIFS" include_system="1" fi @@ -161,11 +165,15 @@ versions_dir_entries=("$versions_dir"/*) if sort --version-sort /dev/null 2>&1; then # system sort supports version sorting OLDIFS="$IFS" + # VAR=() of unquoted value does glob expansion (against the current dir's contents) after IFS-splitting + # which is undesired + set -f IFS=$'\n' versions_dir_entries=($( printf "%s\n" "${versions_dir_entries[@]}" | sort --version-sort )) + set +f IFS="$OLDIFS" fi diff --git a/libexec/pyenv-which b/libexec/pyenv-which index 4cdcfeb0..1bc6ed0e 100755 --- a/libexec/pyenv-which +++ b/libexec/pyenv-which @@ -63,7 +63,11 @@ if [ -z "$PYENV_COMMAND" ]; then fi OLDIFS="$IFS" +# Unquoted $VAR or VAR=() of unquoted value does glob expansion (against the current dir's contents) +# after IFS-splitting which is undesired +set -f IFS=: versions=(${PYENV_VERSION:-$(pyenv-version-name -f)}) +set +f IFS="$OLDIFS" declare -a nonexistent_versions diff --git a/test/global.bats b/test/global.bats index 62870b3e..be67987d 100644 --- a/test/global.bats +++ b/test/global.bats @@ -16,6 +16,14 @@ load test_helper assert_output "1.2.3" } +@test "version with glob characters is handled correctly" { + touch 1.1 + mkdir -p "$PYENV_ROOT" + echo "[1-9].?*" > "$PYENV_ROOT/version" + run pyenv-global + assert_success "[1-9].?*" +} + @test "set PYENV_ROOT/version" { mkdir -p "$PYENV_ROOT/versions/1.2.3" run pyenv-global "1.2.3" diff --git a/test/local.bats b/test/local.bats index 98639673..74d02e8a 100644 --- a/test/local.bats +++ b/test/local.bats @@ -19,6 +19,13 @@ _setup() { assert_success "1.2.3" } +@test "version with glob characters is handled correctly" { + touch 1.1 + echo "[1-9].?*" > .python-version + run pyenv-local + assert_success "[1-9].?*" +} + @test "discovers version file in parent directory" { echo "1.2.3" > .python-version mkdir -p "subdir" && cd "subdir" diff --git a/test/prefix.bats b/test/prefix.bats index f52e520d..3a6bfb6a 100644 --- a/test/prefix.bats +++ b/test/prefix.bats @@ -16,6 +16,12 @@ load test_helper assert_failure "pyenv: version \`1.2.3' not installed" } +@test "version with glob characters is handled correctly" { + touch 1.1 + PYENV_VERSION="[1-9].?*" run pyenv-prefix + assert_failure "pyenv: version \`[1-9].?*' not installed" +} + @test "prefix for system" { mkdir -p "${PYENV_TEST_DIR}/bin" touch "${PYENV_TEST_DIR}/bin/python" diff --git a/test/version-name.bats b/test/version-name.bats index cc179b97..95afded8 100644 --- a/test/version-name.bats +++ b/test/version-name.bats @@ -22,6 +22,14 @@ _setup() { assert_success "system" } +@test "version with glob characters is handled correctly" { + touch 1.1 + PYENV_VERSION="[1-9].?*" run pyenv-version-name + assert_failure <<'!' +pyenv: version `[1-9].?*' is not installed (set by PYENV_VERSION environment variable) +! +} + @test "PYENV_VERSION can be overridden by hook" { create_version "2.7.11" create_version "3.5.1" diff --git a/test/version.bats b/test/version.bats index a311b62f..25623413 100644 --- a/test/version.bats +++ b/test/version.bats @@ -79,3 +79,12 @@ OUT 3.3.3 OUT } + +@test "version with glob characters is handled correctly" { + touch 1.1 + PYENV_VERSION="[1-9].?*" run pyenv-version + assert_failure + assert_output <