mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-26 01:32:25 +00:00
pscp, psftp: use a bufchain in ssh_scp_recv.
The ad-hoc code that received data from the SCP or SFTP server predated even not-very-modern conveniences such as bufchain, and was quite horrible and cumbersome. Particularly nasty was the part where ssh_scp_recv set a _global_ pointer variable to the buffer it was in the middle of writing to, and then recursed and expected a callback to use that pointer. That caused clang-analyzer to grumble at me, in a particular case where the output buffer was in the ultimate caller's stack frame; even though I'm confident the code _worked_, I can't blame clang for being unhappy! So now we do things the modern and much simpler way: the callback when data comes in just puts it on a bufchain, and the top-level ssh_scp_recv repeatedly waits until data arrives in the bufchain and then copies it to the output buffer.
This commit is contained in:
parent
dbb2c0030a
commit
144b738f31
9
misc.c
9
misc.c
@ -813,6 +813,15 @@ bool bufchain_try_fetch_consume(bufchain *ch, void *data, int len)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int bufchain_fetch_consume_up_to(bufchain *ch, void *data, int len)
|
||||||
|
{
|
||||||
|
if (len > ch->buffersize)
|
||||||
|
len = ch->buffersize;
|
||||||
|
if (len)
|
||||||
|
bufchain_fetch_consume(ch, data, len);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
* Sanitise terminal output that we have reason not to trust, e.g.
|
* Sanitise terminal output that we have reason not to trust, e.g.
|
||||||
* because it appears in the login banner or password prompt from a
|
* because it appears in the login banner or password prompt from a
|
||||||
|
1
misc.h
1
misc.h
@ -106,6 +106,7 @@ void bufchain_consume(bufchain *ch, int len);
|
|||||||
void bufchain_fetch(bufchain *ch, void *data, int len);
|
void bufchain_fetch(bufchain *ch, void *data, int len);
|
||||||
void bufchain_fetch_consume(bufchain *ch, void *data, int len);
|
void bufchain_fetch_consume(bufchain *ch, void *data, int len);
|
||||||
bool bufchain_try_fetch_consume(bufchain *ch, void *data, int len);
|
bool bufchain_try_fetch_consume(bufchain *ch, void *data, int len);
|
||||||
|
int bufchain_fetch_consume_up_to(bufchain *ch, void *data, int len);
|
||||||
|
|
||||||
void sanitise_term_data(bufchain *out, const void *vdata, int len);
|
void sanitise_term_data(bufchain *out, const void *vdata, int len);
|
||||||
|
|
||||||
|
71
pscp.c
71
pscp.c
@ -144,16 +144,9 @@ void agent_schedule_callback(void (*callback)(void *, void *, int),
|
|||||||
* this until we have enough data.
|
* this until we have enough data.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static unsigned char *outptr; /* where to put the data */
|
static bufchain received_data;
|
||||||
static unsigned outlen; /* how much data required */
|
static int pscp_output(Seat *seat, bool is_stderr, const void *data, int len)
|
||||||
static unsigned char *pending = NULL; /* any spare data */
|
|
||||||
static unsigned pendlen = 0, pendsize = 0; /* length and phys. size of buffer */
|
|
||||||
static int pscp_output(Seat *seat, bool is_stderr,
|
|
||||||
const void *data, int datalen)
|
|
||||||
{
|
{
|
||||||
unsigned char *p = (unsigned char *) data;
|
|
||||||
unsigned len = (unsigned) datalen;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* stderr data is just spouted to local stderr and otherwise
|
* stderr data is just spouted to local stderr and otherwise
|
||||||
* ignored.
|
* ignored.
|
||||||
@ -165,26 +158,7 @@ static int pscp_output(Seat *seat, bool is_stderr,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((outlen > 0) && (len > 0)) {
|
bufchain_add(&received_data, data, len);
|
||||||
unsigned used = outlen;
|
|
||||||
if (used > len)
|
|
||||||
used = len;
|
|
||||||
memcpy(outptr, p, used);
|
|
||||||
outptr += used;
|
|
||||||
outlen -= used;
|
|
||||||
p += used;
|
|
||||||
len -= used;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len > 0) {
|
|
||||||
if (pendsize < pendlen + len) {
|
|
||||||
pendsize = pendlen + len + 4096;
|
|
||||||
pending = sresize(pending, pendsize, unsigned char);
|
|
||||||
}
|
|
||||||
memcpy(pending + pendlen, p, len);
|
|
||||||
pendlen += len;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
static bool pscp_eof(Seat *seat)
|
static bool pscp_eof(Seat *seat)
|
||||||
@ -201,38 +175,21 @@ static bool pscp_eof(Seat *seat)
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
static bool ssh_scp_recv(void *buf, int len)
|
static bool ssh_scp_recv(void *vbuf, int len)
|
||||||
{
|
{
|
||||||
outptr = buf;
|
char *buf = (char *)vbuf;
|
||||||
outlen = len;
|
while (len > 0) {
|
||||||
|
while (bufchain_size(&received_data) == 0) {
|
||||||
/*
|
if (backend_exitcode(backend) >= 0 ||
|
||||||
* See if the pending-input block contains some of what we
|
ssh_sftp_loop_iteration() < 0)
|
||||||
* need.
|
|
||||||
*/
|
|
||||||
if (pendlen > 0) {
|
|
||||||
unsigned pendused = pendlen;
|
|
||||||
if (pendused > outlen)
|
|
||||||
pendused = outlen;
|
|
||||||
memcpy(outptr, pending, pendused);
|
|
||||||
memmove(pending, pending + pendused, pendlen - pendused);
|
|
||||||
outptr += pendused;
|
|
||||||
outlen -= pendused;
|
|
||||||
pendlen -= pendused;
|
|
||||||
if (pendlen == 0) {
|
|
||||||
pendsize = 0;
|
|
||||||
sfree(pending);
|
|
||||||
pending = NULL;
|
|
||||||
}
|
|
||||||
if (outlen == 0)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (outlen > 0) {
|
|
||||||
if (backend_exitcode(backend) >= 0 || ssh_sftp_loop_iteration() < 0)
|
|
||||||
return false; /* doom */
|
return false; /* doom */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int got = bufchain_fetch_consume_up_to(&received_data, buf, len);
|
||||||
|
buf += got;
|
||||||
|
len -= got;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
74
psftp.c
74
psftp.c
@ -2490,16 +2490,9 @@ void agent_schedule_callback(void (*callback)(void *, void *, int),
|
|||||||
* do this until we have enough data.
|
* do this until we have enough data.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static unsigned char *outptr; /* where to put the data */
|
static bufchain received_data;
|
||||||
static unsigned outlen; /* how much data required */
|
static int psftp_output(Seat *seat, bool is_stderr, const void *data, int len)
|
||||||
static unsigned char *pending = NULL; /* any spare data */
|
|
||||||
static unsigned pendlen = 0, pendsize = 0; /* length and phys. size of buffer */
|
|
||||||
static int psftp_output(Seat *seat, bool is_stderr,
|
|
||||||
const void *data, int datalen)
|
|
||||||
{
|
{
|
||||||
unsigned char *p = (unsigned char *) data;
|
|
||||||
unsigned len = (unsigned) datalen;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* stderr data is just spouted to local stderr and otherwise
|
* stderr data is just spouted to local stderr and otherwise
|
||||||
* ignored.
|
* ignored.
|
||||||
@ -2511,32 +2504,7 @@ static int psftp_output(Seat *seat, bool is_stderr,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
bufchain_add(&received_data, data, len);
|
||||||
* If this is before the real session begins, just return.
|
|
||||||
*/
|
|
||||||
if (!outptr)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if ((outlen > 0) && (len > 0)) {
|
|
||||||
unsigned used = outlen;
|
|
||||||
if (used > len)
|
|
||||||
used = len;
|
|
||||||
memcpy(outptr, p, used);
|
|
||||||
outptr += used;
|
|
||||||
outlen -= used;
|
|
||||||
p += used;
|
|
||||||
len -= used;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len > 0) {
|
|
||||||
if (pendsize < pendlen + len) {
|
|
||||||
pendsize = pendlen + len + 4096;
|
|
||||||
pending = sresize(pending, pendsize, unsigned char);
|
|
||||||
}
|
|
||||||
memcpy(pending + pendlen, p, len);
|
|
||||||
pendlen += len;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2556,36 +2524,18 @@ static bool psftp_eof(Seat *seat)
|
|||||||
|
|
||||||
bool sftp_recvdata(char *buf, int len)
|
bool sftp_recvdata(char *buf, int len)
|
||||||
{
|
{
|
||||||
outptr = (unsigned char *) buf;
|
while (len > 0) {
|
||||||
outlen = len;
|
while (bufchain_size(&received_data) == 0) {
|
||||||
|
if (backend_exitcode(backend) >= 0 ||
|
||||||
/*
|
ssh_sftp_loop_iteration() < 0)
|
||||||
* See if the pending-input block contains some of what we
|
|
||||||
* need.
|
|
||||||
*/
|
|
||||||
if (pendlen > 0) {
|
|
||||||
unsigned pendused = pendlen;
|
|
||||||
if (pendused > outlen)
|
|
||||||
pendused = outlen;
|
|
||||||
memcpy(outptr, pending, pendused);
|
|
||||||
memmove(pending, pending + pendused, pendlen - pendused);
|
|
||||||
outptr += pendused;
|
|
||||||
outlen -= pendused;
|
|
||||||
pendlen -= pendused;
|
|
||||||
if (pendlen == 0) {
|
|
||||||
pendsize = 0;
|
|
||||||
sfree(pending);
|
|
||||||
pending = NULL;
|
|
||||||
}
|
|
||||||
if (outlen == 0)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (outlen > 0) {
|
|
||||||
if (backend_exitcode(backend) >= 0 || ssh_sftp_loop_iteration() < 0)
|
|
||||||
return false; /* doom */
|
return false; /* doom */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int got = bufchain_fetch_consume_up_to(&received_data, buf, len);
|
||||||
|
buf += got;
|
||||||
|
len -= got;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool sftp_senddata(char *buf, int len)
|
bool sftp_senddata(char *buf, int len)
|
||||||
|
Loading…
Reference in New Issue
Block a user