Files
nvm/test/fast/Unit tests/nvm_ls matches patterns literally
T
Jordan Harband 66228bd1fa [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.
2026-10-22 20:10:42 -07:00

58 lines
1.6 KiB
Bash
Executable File

#!/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