Skip to content

Commit 71f9b8a

Browse files
committed
Fix an issue introduced back in 2.18.0 around more flexible env types
This commit fixes an issue when passing in a mapping which is not an actual dict as an environment argument. Internally, AsyncSSH uses a read-only MappingProxyType in places which can trigger this problem if an env from one session is used when starting another. Thanks go to Boris Pavlovic for reporting this issue!
1 parent bf9e1f7 commit 71f9b8a

File tree

2 files changed

+10
-8
lines changed

2 files changed

+10
-8
lines changed

asyncssh/connection.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4169,7 +4169,7 @@ def detach_x11_listener(self, chan: SSHChannel[AnyStr]) -> None:
41694169
async def create_session(self, session_factory: SSHClientSessionFactory,
41704170
command: DefTuple[Optional[str]] = (), *,
41714171
subsystem: DefTuple[Optional[str]]= (),
4172-
env: DefTuple[Env] = (),
4172+
env: DefTuple[Optional[Env]] = (),
41734173
send_env: DefTuple[Optional[EnvSeq]] = (),
41744174
request_pty: DefTuple[Union[bool, str]] = (),
41754175
term_type: DefTuple[Optional[str]] = (),
@@ -5687,7 +5687,7 @@ def session_factory() -> SSHTunTapSession:
56875687
return cast(SSHForwarder, peer)
56885688

56895689
@async_context_manager
5690-
async def start_sftp_client(self, env: DefTuple[Env] = (),
5690+
async def start_sftp_client(self, env: DefTuple[Optional[Env]] = (),
56915691
send_env: DefTuple[Optional[EnvSeq]] = (),
56925692
path_encoding: Optional[str] = 'utf-8',
56935693
path_errors = 'strict',
@@ -8042,7 +8042,7 @@ class SSHClientConnectionOptions(SSHConnectionOptions):
80428042
pkcs11_pin: Optional[str]
80438043
command: Optional[str]
80448044
subsystem: Optional[str]
8045-
env: Env
8045+
env: Optional[Env]
80468046
send_env: Optional[EnvSeq]
80478047
request_pty: _RequestPTY
80488048
term_type: Optional[str]
@@ -8115,7 +8115,8 @@ def prepare(self, # type: ignore
81158115
pkcs11_provider: DefTuple[Optional[str]] = (),
81168116
pkcs11_pin: Optional[str] = None,
81178117
command: DefTuple[Optional[str]] = (),
8118-
subsystem: Optional[str] = None, env: DefTuple[Env] = (),
8118+
subsystem: Optional[str] = None,
8119+
env: DefTuple[Optional[Env]] = (),
81198120
send_env: DefTuple[Optional[EnvSeq]] = (),
81208121
request_pty: DefTuple[_RequestPTY] = (),
81218122
term_type: Optional[str] = None,
@@ -8354,7 +8355,8 @@ def prepare(self, # type: ignore
83548355

83558356
self.subsystem = subsystem
83568357

8357-
self.env = cast(Env, env if env != () else config.get('SetEnv'))
8358+
self.env = cast(Optional[Env], env if env != () else
8359+
config.get('SetEnv'))
83588360

83598361
self.send_env = cast(Optional[EnvSeq], send_env if send_env != () else
83608362
config.get('SendEnv'))

asyncssh/misc.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ async def wait_closed(self) -> None:
125125
EnvMap = Mapping[BytesOrStr, BytesOrStr]
126126
EnvItems = Sequence[Tuple[BytesOrStr, BytesOrStr]]
127127
EnvSeq = Sequence[BytesOrStr]
128-
Env = Optional[Union[EnvMap, EnvItems, EnvSeq]]
128+
Env = Union[EnvMap, EnvItems, EnvSeq]
129129

130130
# Define a version of randrange which is based on SystemRandom(), so that
131131
# we get back numbers suitable for cryptographic use.
@@ -141,8 +141,8 @@ async def wait_closed(self) -> None:
141141
def encode_env(env: Env) -> Iterator[Tuple[bytes, bytes]]:
142142
"""Convert environemnt dict or list to bytes-based dictionary"""
143143

144-
env = cast(Sequence[Tuple[BytesOrStr, BytesOrStr]],
145-
env.items() if isinstance(env, dict) else env)
144+
if hasattr(env, 'items'):
145+
env = cast(Env, env.items())
146146

147147
try:
148148
for item in env:

0 commit comments

Comments
 (0)