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

ssh2_try_send: don't try sending if a channel is half-open.

When ssh2_connection_filter_queue is _receiving_ messages about a
channel from the other end, it carefully checks if the channel
referred to is half-open. But we weren't exercising the same caution
before beginning to _send_ channel data, and we should, because in
that situation important fields like c->remwinsize aren't even
initialised yet.

This can come up, for example, due to typeahead in the main session
window before the server has sent OPEN_CONFIRMATION.
This commit is contained in:
Simon Tatham 2019-03-03 07:09:26 +00:00
parent 8c366766ae
commit deafaa811e

View File

@ -1060,30 +1060,32 @@ static size_t ssh2_try_send(struct ssh2_channel *c)
PktOut *pktout;
size_t bufsize;
while (c->remwindow > 0 &&
(bufchain_size(&c->outbuffer) > 0 ||
bufchain_size(&c->errbuffer) > 0)) {
bufchain *buf = (bufchain_size(&c->errbuffer) > 0 ?
&c->errbuffer : &c->outbuffer);
if (!c->halfopen) {
while (c->remwindow > 0 &&
(bufchain_size(&c->outbuffer) > 0 ||
bufchain_size(&c->errbuffer) > 0)) {
bufchain *buf = (bufchain_size(&c->errbuffer) > 0 ?
&c->errbuffer : &c->outbuffer);
ptrlen data = bufchain_prefix(buf);
if (data.len > c->remwindow)
data.len = c->remwindow;
if (data.len > c->remmaxpkt)
data.len = c->remmaxpkt;
if (buf == &c->errbuffer) {
pktout = ssh_bpp_new_pktout(
s->ppl.bpp, SSH2_MSG_CHANNEL_EXTENDED_DATA);
put_uint32(pktout, c->remoteid);
put_uint32(pktout, SSH2_EXTENDED_DATA_STDERR);
} else {
pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH2_MSG_CHANNEL_DATA);
put_uint32(pktout, c->remoteid);
ptrlen data = bufchain_prefix(buf);
if (data.len > c->remwindow)
data.len = c->remwindow;
if (data.len > c->remmaxpkt)
data.len = c->remmaxpkt;
if (buf == &c->errbuffer) {
pktout = ssh_bpp_new_pktout(
s->ppl.bpp, SSH2_MSG_CHANNEL_EXTENDED_DATA);
put_uint32(pktout, c->remoteid);
put_uint32(pktout, SSH2_EXTENDED_DATA_STDERR);
} else {
pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH2_MSG_CHANNEL_DATA);
put_uint32(pktout, c->remoteid);
}
put_stringpl(pktout, data);
pq_push(s->ppl.out_pq, pktout);
bufchain_consume(buf, data.len);
c->remwindow -= data.len;
}
put_stringpl(pktout, data);
pq_push(s->ppl.out_pq, pktout);
bufchain_consume(buf, data.len);
c->remwindow -= data.len;
}
/*