1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 17:38:00 +00:00

wincliloop: cope with winselcli_event not existing.

I found recently that if I ran Windows PSCP as a connection-sharing
downstream, it would send the SSH greeting down the named pipe, but
never receive anything back, though the upstream PuTTY was sending it.
PuTTY and Plink from the same build of the code would act happily as
downstreams.

It turned out that this was because the WaitForMultipleObjects call in
cli_main_loop() in wincliloop.c was failing with ERROR_ACCESS_DENIED.
That happened because it had an INVALID_HANDLE_VALUE in its list of
objects to wait for. That in turn happened because winselcli_event was
set to INVALID_HANDLE_VALUE.

Why was winselcli_event not set up? Because it's set up lazily by
do_select(), so if the program isn't handling any network sockets at
all (which is the case when PSCP is speaking over a named pipe
instead), then it never gets made into a valid event object.

So the problem wasn't that winselcli_event was in a bad state; it was
quite legitimately invalid. The problem was that wincliloop ought to
have _coped_ with it being invalid, by not inserting it in its list of
objects to wait for.

So now we check that case, and only insert winselcli_event in the list
if it's valid. And PSCP works again over connection sharing.
This commit is contained in:
Simon Tatham 2021-01-19 20:26:04 +00:00
parent 20d1c47484
commit c6ff548ae0

View File

@ -10,7 +10,7 @@ void cli_main_loop(cliloop_pre_t pre, cliloop_post_t post, void *ctx)
while (true) {
int nhandles;
HANDLE *handles;
int n;
DWORD n;
DWORD ticks;
const HANDLE *extra_handles = NULL;
@ -35,11 +35,14 @@ void cli_main_loop(cliloop_pre_t pre, cliloop_post_t post, void *ctx)
}
handles = handle_get_events(&nhandles);
size_t winselcli_index = nhandles;
size_t extra_base = winselcli_index + 1;
size_t winselcli_index = -(size_t)1;
size_t extra_base = nhandles;
if (winselcli_event != INVALID_HANDLE_VALUE) {
winselcli_index = extra_base++;
handles[winselcli_index] = winselcli_event;
}
size_t total_handles = extra_base + n_extra_handles;
handles = sresize(handles, total_handles, HANDLE);
handles[winselcli_index] = winselcli_event;
for (size_t i = 0; i < n_extra_handles; i++)
handles[extra_base + i] = extra_handles[i];
@ -49,7 +52,8 @@ void cli_main_loop(cliloop_pre_t pre, cliloop_post_t post, void *ctx)
if ((unsigned)(n - WAIT_OBJECT_0) < (unsigned)nhandles) {
handle_got_event(handles[n - WAIT_OBJECT_0]);
} else if (n == WAIT_OBJECT_0 + nhandles) {
} else if (winselcli_event != INVALID_HANDLE_VALUE &&
n == WAIT_OBJECT_0 + winselcli_index) {
WSANETWORKEVENTS things;
SOCKET socket;
int i, socketstate;