Fix recursive definitions in env vars not expanded

This commit is contained in:
Kovid Goyal 2022-03-07 11:07:26 +05:30
parent 6ff69c88df
commit 68df13d3fe
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 21 additions and 5 deletions

View File

@ -33,11 +33,21 @@ from .options.types import Options as SSHOptions
from .options.utils import DELETE_ENV_VAR from .options.utils import DELETE_ENV_VAR
# See https://www.gnu.org/software/bash/manual/html_node/Double-Quotes.html
quote_pat = re.compile('([\\`"\n])')
def quote_env_val(x: str) -> str:
x = quote_pat.sub(r'\\\1', x)
x = x.replace('$(', r'\$(') # prevent execution with $()
return f'"{x}"'
def serialize_env(env: Dict[str, str], base_env: Dict[str, str]) -> bytes: def serialize_env(env: Dict[str, str], base_env: Dict[str, str]) -> bytes:
lines = [] lines = []
def a(k: str, val: str) -> None: def a(k: str, val: str) -> None:
lines.append(f'export {k}={shlex.quote(val)}') lines.append(f'export {shlex.quote(k)}={quote_env_val(val)}')
for k in sorted(env): for k in sorted(env):
v = env[k] v = env[k]

View File

@ -139,16 +139,18 @@ copy --exclude */w.* d1
self.ae(len(glob.glob(f'{remote_home}/{tname}/*/xterm-kitty')), 2) self.ae(len(glob.glob(f'{remote_home}/{tname}/*/xterm-kitty')), 2)
def test_ssh_env_vars(self): def test_ssh_env_vars(self):
tset = '$A-$(echo no)-`echo no2` "something"'
for sh in self.all_possible_sh: for sh in self.all_possible_sh:
with self.subTest(sh=sh), tempfile.TemporaryDirectory() as tdir: with self.subTest(sh=sh), tempfile.TemporaryDirectory() as tdir:
pty = self.check_bootstrap( pty = self.check_bootstrap(
sh, tdir, test_script='env; exit 0', SHELL_INTEGRATION_VALUE='', sh, tdir, test_script='env; exit 0', SHELL_INTEGRATION_VALUE='',
ssh_opts={'env': { ssh_opts={'env': {
'TSET': 'set-works', 'A': 'AAA',
'TSET': tset,
'COLORTERM': DELETE_ENV_VAR, 'COLORTERM': DELETE_ENV_VAR,
}} }}
) )
pty.wait_till(lambda: 'TSET=set-works' in pty.screen_contents()) pty.wait_till(lambda: 'TSET={}'.format(tset.replace('$A', 'AAA')) in pty.screen_contents())
self.assertNotIn('COLORTERM', pty.screen_contents()) self.assertNotIn('COLORTERM', pty.screen_contents())
def test_ssh_leading_data(self): def test_ssh_leading_data(self):

View File

@ -8,8 +8,8 @@ import getpass
import io import io
import os import os
import pwd import pwd
import re
import select import select
import shlex
import shutil import shutil
import subprocess import subprocess
import sys import sys
@ -72,6 +72,10 @@ def debug(msg):
write_all(tty_fd, data) write_all(tty_fd, data)
def unquote_env_val(x):
return re.sub('\\\\([\\$`"\n])', r'\1', x[1:-1])
def apply_env_vars(raw): def apply_env_vars(raw):
global login_shell global login_shell
@ -81,7 +85,7 @@ def apply_env_vars(raw):
key, val = parts[0], '' key, val = parts[0], ''
else: else:
key, val = parts key, val = parts
val = shlex.split(val)[0] val = os.path.expandvars(unquote_env_val(val))
os.environ[key] = val os.environ[key] = val
for line in raw.splitlines(): for line in raw.splitlines():