mirror of
https://github.com/nvm-sh/nvm.git
synced 2026-10-26 08:24:40 +08:00
[Fix] nvm_ls: match the version pattern literally
nvm_ls escaped only `.` and `#` before using the pattern
(which may come from a `.nvmrc`)
as a sed address,
so any other regex characters in it were interpreted:
`v2[0-9]` matched installed versions,
`[` made sed fail with an error,
and nested bounded repetitions like `\(v\{1,300\}\)\{1,300\}`
made sed take a very long time and a lot of memory to compile,
stalling `nvm use` and shell startup.
Escape every BRE metacharacter,
including the backslash,
so the pattern is always matched as literal text
Discovered by Anthropic's OSS Scanner, as bug ANT-2026-HZAFTTUK; the scanner correctly classified it as not a vulnerability.
This commit is contained in:
2
nvm.sh
2
nvm.sh
@@ -1942,7 +1942,7 @@ nvm_ls() {
|
||||
PATTERN='v'
|
||||
SEARCH_PATTERN='.*'
|
||||
else
|
||||
SEARCH_PATTERN="$(nvm_echo "${PATTERN}" | command sed 's#\.#\\\.#g; s|#|\\#|g')"
|
||||
SEARCH_PATTERN="$(nvm_echo "${PATTERN}" | command sed 's/[[\.*^$#]/\\&/g')"
|
||||
fi
|
||||
if [ -n "${NVM_DIRS_TO_SEARCH1}${NVM_DIRS_TO_SEARCH2}${NVM_DIRS_TO_SEARCH3}" ]; then
|
||||
VERSIONS="$(command find "${NVM_DIRS_TO_SEARCH1}"/* "${NVM_DIRS_TO_SEARCH2}"/* "${NVM_DIRS_TO_SEARCH3}"/* -name . -o -type d -prune -o -path "${PATTERN}*" \
|
||||
|
||||
57
test/fast/Unit tests/nvm_ls matches patterns literally
Executable file
57
test/fast/Unit tests/nvm_ls matches patterns literally
Executable file
@@ -0,0 +1,57 @@
|
||||
#!/bin/sh
|
||||
|
||||
die () { echo "$@" ; cleanup ; exit 1; }
|
||||
|
||||
cleanup() {
|
||||
rm -rf "${TEST_DIR-}"
|
||||
unset -f assert_ls assert_no_match
|
||||
unset TEST_DIR NVM_DIR PATTERN
|
||||
}
|
||||
|
||||
: nvm.sh
|
||||
\. ../../../nvm.sh
|
||||
|
||||
\. ../../common.sh
|
||||
|
||||
# an isolated NVM_DIR with known versions, so that ambient versions
|
||||
# and aliases can not affect any assertions
|
||||
TEST_DIR="${PWD}/nvm_ls_literal_pattern_tmp"
|
||||
for VERSION in v20.0.0 v22.1.0 v24.13.0; do
|
||||
mkdir -p "${TEST_DIR}/versions/node/${VERSION}/bin" || die "failed to create ${VERSION} dir"
|
||||
make_echo "${TEST_DIR}/versions/node/${VERSION}/bin/node" "${VERSION}" || die "failed to create ${VERSION} node binary"
|
||||
done
|
||||
unset VERSION
|
||||
NVM_DIR="${TEST_DIR}"
|
||||
|
||||
assert_ls() {
|
||||
try nvm_ls "$1"
|
||||
[ "_${CAPTURED_STDOUT}" = "_$2" ] || die "\`nvm_ls '$1'\` should output >$2<; got >${CAPTURED_STDOUT}<"
|
||||
}
|
||||
|
||||
# a pattern (which may come from a `.nvmrc`) is literal text, not a sed regex:
|
||||
# each of these matched installed versions, failed to compile, or made sed slow
|
||||
assert_no_match() {
|
||||
try_err nvm_ls "$1"
|
||||
[ -z "${CAPTURED_STDERR}" ] || die "\`nvm_ls '$1'\` should not print to stderr; got >${CAPTURED_STDERR}<"
|
||||
try nvm_ls "$1"
|
||||
[ "_${CAPTURED_STDOUT}" = '_N/A' ] || die "\`nvm_ls '$1'\` should output N/A; got >${CAPTURED_STDOUT}<"
|
||||
[ "_${CAPTURED_EXIT_CODE}" = '_3' ] || die "\`nvm_ls '$1'\` should exit with code 3; got ${CAPTURED_EXIT_CODE}"
|
||||
}
|
||||
|
||||
assert_ls 24 'v24.13.0'
|
||||
assert_ls v22 'v22.1.0'
|
||||
assert_ls 24.13 'v24.13.0'
|
||||
assert_ls v20.0.0 'v20.0.0'
|
||||
|
||||
for PATTERN in \
|
||||
'v2[0-9]' \
|
||||
'v2*4' \
|
||||
'\(v24\)' \
|
||||
'v24\|x' \
|
||||
'\(v\{1,9\}\)\{1,9\}' \
|
||||
'[' \
|
||||
'\'; do
|
||||
assert_no_match "${PATTERN}"
|
||||
done
|
||||
|
||||
cleanup
|
||||
Reference in New Issue
Block a user