mirror of
https://github.com/ohmyzsh/ohmyzsh.git
synced 2026-06-05 05:03:16 +02:00
fix(dotenv): FIFO shouldn't be read twice
This commit is contained in:
parent
3f36e70822
commit
cb31ff6fd7
2 changed files with 92 additions and 24 deletions
|
|
@ -9,10 +9,10 @@
|
||||||
|
|
||||||
## Functions
|
## Functions
|
||||||
|
|
||||||
parse_dotenv() {
|
_parse_dotenv_content() {
|
||||||
setopt localoptions extendedglob
|
setopt localoptions extendedglob
|
||||||
|
|
||||||
local filename="$1"
|
local content="$1"
|
||||||
local mode="${2:-export}"
|
local mode="${2:-export}"
|
||||||
|
|
||||||
# Validate mode argument
|
# Validate mode argument
|
||||||
|
|
@ -24,26 +24,10 @@ parse_dotenv() {
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# Fail if file is too large to avoid DoS
|
local node line key value
|
||||||
zmodload -F zsh/stat b:zstat
|
|
||||||
local -i file_size max_size=10485760 # 10MiB
|
|
||||||
if ! file_size=$(zstat -L +size "$filename" 2>/dev/null); then
|
|
||||||
echo "dotenv: unable to determine size of file '$filename'" >&2
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if (( file_size > max_size )); then
|
|
||||||
echo "dotenv: file '$filename' is too large to parse (size: $file_size bytes)" >&2
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
local content node line key value
|
|
||||||
local -A parsed_vars
|
local -A parsed_vars
|
||||||
local -a nodes lines
|
local -a nodes lines
|
||||||
|
|
||||||
# Read entire file
|
|
||||||
content="$(<$filename)" || return 1
|
|
||||||
|
|
||||||
# Parse into command lines separated by `;`, with built-in support for multi-line commands.
|
# Parse into command lines separated by `;`, with built-in support for multi-line commands.
|
||||||
# (Z:C:) ignores comments and preserves quotes and escapes.
|
# (Z:C:) ignores comments and preserves quotes and escapes.
|
||||||
#
|
#
|
||||||
|
|
@ -184,6 +168,41 @@ parse_dotenv() {
|
||||||
DOTENV_TEST_VARS=("${(@kv)parsed_vars}")
|
DOTENV_TEST_VARS=("${(@kv)parsed_vars}")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parse_dotenv() {
|
||||||
|
local filename="$1"
|
||||||
|
local mode="${2:-export}"
|
||||||
|
local content
|
||||||
|
|
||||||
|
# Fail if file is too large to avoid DoS
|
||||||
|
zmodload -F zsh/stat b:zstat
|
||||||
|
local -i file_size max_size=10485760 # 10MiB
|
||||||
|
if ! file_size=$(zstat -L +size "$filename" 2>/dev/null); then
|
||||||
|
echo "dotenv: unable to determine size of file '$filename'" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if (( file_size > max_size )); then
|
||||||
|
echo "dotenv: file '$filename' is too large to parse (size: $file_size bytes)" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
content="$(<"$filename")" || return 1
|
||||||
|
_parse_dotenv_content "$content" "$mode"
|
||||||
|
}
|
||||||
|
|
||||||
|
_dotenv_check_syntax() {
|
||||||
|
local filename="$1"
|
||||||
|
|
||||||
|
if (( $# == 2 )); then
|
||||||
|
printf '%s' "$2" | zsh -fn /dev/stdin
|
||||||
|
else
|
||||||
|
zsh -fn -- "$filename"
|
||||||
|
fi || {
|
||||||
|
echo "dotenv: error when sourcing '$filename' file" >&2
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
source_env() {
|
source_env() {
|
||||||
if [[ ! -f "$ZSH_DOTENV_FILE" ]] && [[ ! -p "$ZSH_DOTENV_FILE" ]]; then
|
if [[ ! -f "$ZSH_DOTENV_FILE" ]] && [[ ! -p "$ZSH_DOTENV_FILE" ]]; then
|
||||||
return
|
return
|
||||||
|
|
@ -225,11 +244,17 @@ source_env() {
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# test .env syntax
|
local content
|
||||||
zsh -fn $ZSH_DOTENV_FILE || {
|
if [[ -p "$ZSH_DOTENV_FILE" ]]; then
|
||||||
echo "dotenv: error when sourcing '$ZSH_DOTENV_FILE' file" >&2
|
content="$(<"$ZSH_DOTENV_FILE")" || return 1
|
||||||
return 1
|
_dotenv_check_syntax "$ZSH_DOTENV_FILE" "$content" || return 1
|
||||||
}
|
|
||||||
|
setopt localoptions allexport
|
||||||
|
_parse_dotenv_content "$content"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
_dotenv_check_syntax "$ZSH_DOTENV_FILE" || return 1
|
||||||
|
|
||||||
setopt localoptions allexport
|
setopt localoptions allexport
|
||||||
parse_dotenv "$ZSH_DOTENV_FILE"
|
parse_dotenv "$ZSH_DOTENV_FILE"
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,49 @@
|
||||||
assert $state equals 1
|
assert $state equals 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test 'source_env loads named pipes without blocking' {
|
||||||
|
local tmpdir fifo output result
|
||||||
|
local child_pid writer_pid killer_pid child_rc
|
||||||
|
|
||||||
|
tmpdir="$(mktemp -d "${TMPDIR:-/tmp}/dotenv.XXXXXX")"
|
||||||
|
fifo="$tmpdir/.env"
|
||||||
|
output="$tmpdir/output"
|
||||||
|
command mkfifo "$fifo"
|
||||||
|
|
||||||
|
(
|
||||||
|
print -r -- 'TOKEN=secret' > "$fifo"
|
||||||
|
) &
|
||||||
|
writer_pid=$!
|
||||||
|
|
||||||
|
(
|
||||||
|
ZSH_DOTENV_PROMPT=false
|
||||||
|
ZSH_DOTENV_FILE="$fifo"
|
||||||
|
source_env
|
||||||
|
print -r -- "${TOKEN-<unset>}" > "$output"
|
||||||
|
) &
|
||||||
|
child_pid=$!
|
||||||
|
|
||||||
|
(
|
||||||
|
sleep 2
|
||||||
|
kill -0 $child_pid 2>/dev/null || exit 0
|
||||||
|
kill $child_pid 2>/dev/null || exit 0
|
||||||
|
) &
|
||||||
|
killer_pid=$!
|
||||||
|
|
||||||
|
wait $child_pid
|
||||||
|
child_rc=$?
|
||||||
|
|
||||||
|
kill $killer_pid 2>/dev/null || true
|
||||||
|
kill $writer_pid 2>/dev/null || true
|
||||||
|
wait $writer_pid 2>/dev/null || true
|
||||||
|
|
||||||
|
[[ -f "$output" ]] && result="$(<"$output")"
|
||||||
|
command rm -rf "$tmpdir"
|
||||||
|
|
||||||
|
assert $child_rc equals 0
|
||||||
|
assert "$result" equals 'secret'
|
||||||
|
}
|
||||||
|
|
||||||
@test 'parse basic variable assignment' {
|
@test 'parse basic variable assignment' {
|
||||||
> "$fixture" <<'EOF'
|
> "$fixture" <<'EOF'
|
||||||
# Basic assignments
|
# Basic assignments
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue