1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 01:48:00 +00:00

Replace more ad-hoc growing char buffers with strbuf.

I've fixed a handful of these where I found them in passing, but when
I went systematically looking, there were a lot more that I hadn't
found!

A particular highlight of this collection is the code that formats
Windows clipboard data in RTF, which was absolutely crying out for
strbuf_catf, and now it's got it.
This commit is contained in:
Simon Tatham 2019-02-11 06:58:07 +00:00
parent e3e4315033
commit d07d7d66f6
13 changed files with 194 additions and 311 deletions

2
Recipe
View File

@ -395,7 +395,7 @@ testcrypt : [C] testcrypt SSHCRYPTO sshprng sshprime marshal utils
+ memory tree234 winmiscs + memory tree234 winmiscs
testsc : [UT] testsc SSHCRYPTO marshal utils memory tree234 wildcard testsc : [UT] testsc SSHCRYPTO marshal utils memory tree234 wildcard
+ sshmac uxutils + sshmac uxutils
testzlib : [UT] testzlib sshzlib memory testzlib : [UT] testzlib sshzlib utils marshal memory
uppity : [UT] uxserver SSHSERVER UXMISC uxsignal uxnoise uxgss uxnogtk uppity : [UT] uxserver SSHSERVER UXMISC uxsignal uxnoise uxgss uxnogtk
+ uxpty uxsftpserver ux_x11 uxagentsock + uxpty uxsftpserver ux_x11 uxagentsock

View File

@ -563,10 +563,7 @@ int cmdline_process_param(const char *p, char *value,
} }
if (!strcmp(p, "-m")) { if (!strcmp(p, "-m")) {
const char *filename; const char *filename;
char *command;
int cmdlen, cmdsize;
FILE *fp; FILE *fp;
int c, d;
RETURN(2); RETURN(2);
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
@ -574,29 +571,24 @@ int cmdline_process_param(const char *p, char *value,
filename = value; filename = value;
cmdlen = cmdsize = 0;
command = NULL;
fp = fopen(filename, "r"); fp = fopen(filename, "r");
if (!fp) { if (!fp) {
cmdline_error("unable to open command file \"%s\"", filename); cmdline_error("unable to open command file \"%s\"", filename);
return ret; return ret;
} }
do { strbuf *command = strbuf_new();
c = fgetc(fp); char readbuf[4096];
d = c; while (1) {
if (c == EOF) size_t nread = fread(readbuf, 1, sizeof(readbuf), fp);
d = 0; if (nread == 0)
if (cmdlen >= cmdsize) { break;
cmdsize = cmdlen + 512; put_data(command, readbuf, nread);
command = sresize(command, cmdsize, char); }
}
command[cmdlen++] = d;
} while (c != EOF);
fclose(fp); fclose(fp);
conf_set_str(conf, CONF_remote_cmd, command); conf_set_str(conf, CONF_remote_cmd, command->s);
conf_set_str(conf, CONF_remote_cmd2, ""); conf_set_str(conf, CONF_remote_cmd2, "");
conf_set_bool(conf, CONF_nopty, true); /* command => no terminal */ conf_set_bool(conf, CONF_nopty, true); /* command => no terminal */
sfree(command); strbuf_free(command);
} }
if (!strcmp(p, "-P")) { if (!strcmp(p, "-P")) {
RETURN(2); RETURN(2);

View File

@ -1084,8 +1084,7 @@ struct openssh_new_key {
/* This too points to a position within keyblob */ /* This too points to a position within keyblob */
ptrlen private; ptrlen private;
unsigned char *keyblob; strbuf *keyblob;
int keyblob_len, keyblob_size;
}; };
static struct openssh_new_key *load_openssh_new_key(const Filename *filename, static struct openssh_new_key *load_openssh_new_key(const Filename *filename,
@ -1103,8 +1102,7 @@ static struct openssh_new_key *load_openssh_new_key(const Filename *filename,
unsigned key_index; unsigned key_index;
ret = snew(struct openssh_new_key); ret = snew(struct openssh_new_key);
ret->keyblob = NULL; ret->keyblob = strbuf_new();
ret->keyblob_len = ret->keyblob_size = 0;
fp = f_open(filename, "r", false); fp = f_open(filename, "r", false);
if (!fp) { if (!fp) {
@ -1153,14 +1151,7 @@ static struct openssh_new_key *load_openssh_new_key(const Filename *filename,
goto error; goto error;
} }
if (ret->keyblob_len + len > ret->keyblob_size) { put_data(ret->keyblob, out, len);
ret->keyblob_size = ret->keyblob_len + len + 256;
ret->keyblob = sresize(ret->keyblob, ret->keyblob_size,
unsigned char);
}
memcpy(ret->keyblob + ret->keyblob_len, out, len);
ret->keyblob_len += len;
smemclr(out, sizeof(out)); smemclr(out, sizeof(out));
} }
@ -1175,12 +1166,12 @@ static struct openssh_new_key *load_openssh_new_key(const Filename *filename,
fclose(fp); fclose(fp);
fp = NULL; fp = NULL;
if (ret->keyblob_len == 0 || !ret->keyblob) { if (ret->keyblob->len == 0 || !ret->keyblob) {
errmsg = "key body not present"; errmsg = "key body not present";
goto error; goto error;
} }
BinarySource_BARE_INIT(src, ret->keyblob, ret->keyblob_len); BinarySource_BARE_INIT_PL(src, ptrlen_from_strbuf(ret->keyblob));
if (strcmp(get_asciz(src), "openssh-key-v1") != 0) { if (strcmp(get_asciz(src), "openssh-key-v1") != 0) {
errmsg = "new-style OpenSSH magic number missing\n"; errmsg = "new-style OpenSSH magic number missing\n";
@ -1288,10 +1279,7 @@ static struct openssh_new_key *load_openssh_new_key(const Filename *filename,
} }
smemclr(base64_bit, sizeof(base64_bit)); smemclr(base64_bit, sizeof(base64_bit));
if (ret) { if (ret) {
if (ret->keyblob) { strbuf_free(ret->keyblob);
smemclr(ret->keyblob, ret->keyblob_size);
sfree(ret->keyblob);
}
smemclr(ret, sizeof(*ret)); smemclr(ret, sizeof(*ret));
sfree(ret); sfree(ret);
} }
@ -1308,8 +1296,7 @@ static bool openssh_new_encrypted(const Filename *filename)
if (!key) if (!key)
return false; return false;
ret = (key->cipher != ON_E_NONE); ret = (key->cipher != ON_E_NONE);
smemclr(key->keyblob, key->keyblob_size); strbuf_free(key->keyblob);
sfree(key->keyblob);
smemclr(key, sizeof(*key)); smemclr(key, sizeof(*key));
sfree(key); sfree(key);
return ret; return ret;
@ -1483,8 +1470,7 @@ static ssh2_userkey *openssh_new_read(
ssh_key_free(retkey->key); ssh_key_free(retkey->key);
sfree(retkey); sfree(retkey);
} }
smemclr(key->keyblob, key->keyblob_size); strbuf_free(key->keyblob);
sfree(key->keyblob);
smemclr(key, sizeof(*key)); smemclr(key, sizeof(*key));
sfree(key); sfree(key);
if (errmsg_p) *errmsg_p = errmsg; if (errmsg_p) *errmsg_p = errmsg;
@ -1714,8 +1700,7 @@ static bool openssh_auto_write(
struct sshcom_key { struct sshcom_key {
char comment[256]; /* allowing any length is overkill */ char comment[256]; /* allowing any length is overkill */
unsigned char *keyblob; strbuf *keyblob;
int keyblob_len, keyblob_size;
}; };
static struct sshcom_key *load_sshcom_key(const Filename *filename, static struct sshcom_key *load_sshcom_key(const Filename *filename,
@ -1733,8 +1718,7 @@ static struct sshcom_key *load_sshcom_key(const Filename *filename,
ret = snew(struct sshcom_key); ret = snew(struct sshcom_key);
ret->comment[0] = '\0'; ret->comment[0] = '\0';
ret->keyblob = NULL; ret->keyblob = strbuf_new();
ret->keyblob_len = ret->keyblob_size = 0;
fp = f_open(filename, "r", false); fp = f_open(filename, "r", false);
if (!fp) { if (!fp) {
@ -1831,14 +1815,7 @@ static struct sshcom_key *load_sshcom_key(const Filename *filename,
goto error; goto error;
} }
if (ret->keyblob_len + len > ret->keyblob_size) { put_data(ret->keyblob, out, len);
ret->keyblob_size = ret->keyblob_len + len + 256;
ret->keyblob = sresize(ret->keyblob, ret->keyblob_size,
unsigned char);
}
memcpy(ret->keyblob + ret->keyblob_len, out, len);
ret->keyblob_len += len;
} }
p++; p++;
@ -1849,7 +1826,7 @@ static struct sshcom_key *load_sshcom_key(const Filename *filename,
line = NULL; line = NULL;
} }
if (ret->keyblob_len == 0 || !ret->keyblob) { if (ret->keyblob->len == 0) {
errmsg = "key body not present"; errmsg = "key body not present";
goto error; goto error;
} }
@ -1868,10 +1845,7 @@ static struct sshcom_key *load_sshcom_key(const Filename *filename,
line = NULL; line = NULL;
} }
if (ret) { if (ret) {
if (ret->keyblob) { strbuf_free(ret->keyblob);
smemclr(ret->keyblob, ret->keyblob_size);
sfree(ret->keyblob);
}
smemclr(ret, sizeof(*ret)); smemclr(ret, sizeof(*ret));
sfree(ret); sfree(ret);
} }
@ -1890,7 +1864,7 @@ static bool sshcom_encrypted(const Filename *filename, char **comment)
if (!key) if (!key)
goto done; goto done;
BinarySource_BARE_INIT(src, key->keyblob, key->keyblob_len); BinarySource_BARE_INIT_PL(src, ptrlen_from_strbuf(key->keyblob));
if (get_uint32(src) != SSHCOM_MAGIC_NUMBER) if (get_uint32(src) != SSHCOM_MAGIC_NUMBER)
goto done; /* key is invalid */ goto done; /* key is invalid */
@ -1905,8 +1879,7 @@ static bool sshcom_encrypted(const Filename *filename, char **comment)
done: done:
if (key) { if (key) {
*comment = dupstr(key->comment); *comment = dupstr(key->comment);
smemclr(key->keyblob, key->keyblob_size); strbuf_free(key->keyblob);
sfree(key->keyblob);
smemclr(key, sizeof(*key)); smemclr(key, sizeof(*key));
sfree(key); sfree(key);
} else { } else {
@ -1983,7 +1956,7 @@ static ssh2_userkey *sshcom_read(
if (!key) if (!key)
return NULL; return NULL;
BinarySource_BARE_INIT(src, key->keyblob, key->keyblob_len); BinarySource_BARE_INIT_PL(src, ptrlen_from_strbuf(key->keyblob));
if (get_uint32(src) != SSHCOM_MAGIC_NUMBER) { if (get_uint32(src) != SSHCOM_MAGIC_NUMBER) {
errmsg = "key does not begin with magic number"; errmsg = "key does not begin with magic number";
@ -2158,8 +2131,7 @@ static ssh2_userkey *sshcom_read(
if (blob) { if (blob) {
strbuf_free(blob); strbuf_free(blob);
} }
smemclr(key->keyblob, key->keyblob_size); strbuf_free(key->keyblob);
sfree(key->keyblob);
smemclr(key, sizeof(*key)); smemclr(key, sizeof(*key));
sfree(key); sfree(key);
if (errmsg_p) *errmsg_p = errmsg; if (errmsg_p) *errmsg_p = errmsg;

View File

@ -450,14 +450,11 @@ static Filename *xlatlognam(Filename *src, char *hostname, int port,
{ {
char buf[32], *bufp; char buf[32], *bufp;
int size; int size;
char *buffer; strbuf *buffer;
int buflen, bufsize;
const char *s; const char *s;
Filename *ret; Filename *ret;
bufsize = FILENAME_MAX; buffer = strbuf_new();
buffer = snewn(bufsize, char);
buflen = 0;
s = filename_to_str(src); s = filename_to_str(src);
while (*s) { while (*s) {
@ -504,20 +501,15 @@ static Filename *xlatlognam(Filename *src, char *hostname, int port,
buf[0] = *s++; buf[0] = *s++;
size = 1; size = 1;
} }
if (bufsize <= buflen + size) {
bufsize = (buflen + size) * 5 / 4 + 512;
buffer = sresize(buffer, bufsize, char);
}
while (size-- > 0) { while (size-- > 0) {
char c = *bufp++; char c = *bufp++;
if (sanitise) if (sanitise)
c = filename_char_sanitise(c); c = filename_char_sanitise(c);
buffer[buflen++] = c; put_byte(buffer, c);
} }
} }
buffer[buflen] = '\0';
ret = filename_from_str(buffer); ret = filename_from_str(buffer->s);
sfree(buffer); strbuf_free(buffer);
return ret; return ret;
} }

50
pscp.c
View File

@ -1096,7 +1096,7 @@ int scp_sink_init(void)
#define SCP_SINK_RETRY 4 /* not an action; just try again */ #define SCP_SINK_RETRY 4 /* not an action; just try again */
struct scp_sink_action { struct scp_sink_action {
int action; /* FILE, DIR, ENDDIR */ int action; /* FILE, DIR, ENDDIR */
char *buf; /* will need freeing after use */ strbuf *buf; /* will need freeing after use */
char *name; /* filename or dirname (not ENDDIR) */ char *name; /* filename or dirname (not ENDDIR) */
long permissions; /* access permissions (not ENDDIR) */ long permissions; /* access permissions (not ENDDIR) */
uint64_t size; /* file size (not ENDDIR) */ uint64_t size; /* file size (not ENDDIR) */
@ -1327,8 +1327,9 @@ int scp_get_sink_action(struct scp_sink_action *act)
act->action = SCP_SINK_RETRY; act->action = SCP_SINK_RETRY;
} else { } else {
act->action = SCP_SINK_DIR; act->action = SCP_SINK_DIR;
act->buf = dupstr(stripslashes(fname, false)); act->buf->len = 0;
act->name = act->buf; put_asciz(act->buf, stripslashes(fname, false));
act->name = act->buf->s;
act->size = 0; /* duhh, it's a directory */ act->size = 0; /* duhh, it's a directory */
act->permissions = 07777 & attrs.permissions; act->permissions = 07777 & attrs.permissions;
if (scp_sftp_preserve && if (scp_sftp_preserve &&
@ -1346,8 +1347,9 @@ int scp_get_sink_action(struct scp_sink_action *act)
* It's a file. Return SCP_SINK_FILE. * It's a file. Return SCP_SINK_FILE.
*/ */
act->action = SCP_SINK_FILE; act->action = SCP_SINK_FILE;
act->buf = dupstr(stripslashes(fname, false)); act->buf->len = 0;
act->name = act->buf; put_asciz(act->buf, stripslashes(fname, false));
act->name = act->buf->s;
if (attrs.flags & SSH_FILEXFER_ATTR_SIZE) { if (attrs.flags & SSH_FILEXFER_ATTR_SIZE) {
act->size = attrs.size; act->size = attrs.size;
} else } else
@ -1369,46 +1371,38 @@ int scp_get_sink_action(struct scp_sink_action *act)
} else { } else {
bool done = false; bool done = false;
int i, bufsize;
int action; int action;
char ch; char ch;
act->settime = false; act->settime = false;
act->buf = NULL; act->buf->len = 0;
bufsize = 0;
while (!done) { while (!done) {
if (!ssh_scp_recv(&ch, 1)) if (!ssh_scp_recv(&ch, 1))
return 1; return 1;
if (ch == '\n') if (ch == '\n')
bump("Protocol error: Unexpected newline"); bump("Protocol error: Unexpected newline");
i = 0;
action = ch; action = ch;
do { do {
if (!ssh_scp_recv(&ch, 1)) if (!ssh_scp_recv(&ch, 1))
bump("Lost connection"); bump("Lost connection");
if (i >= bufsize) { put_byte(act->buf, ch);
bufsize = i + 128;
act->buf = sresize(act->buf, bufsize, char);
}
act->buf[i++] = ch;
} while (ch != '\n'); } while (ch != '\n');
act->buf[i - 1] = '\0';
switch (action) { switch (action) {
case '\01': /* error */ case '\01': /* error */
with_stripctrl(san, act->buf) with_stripctrl(san, act->buf->s)
tell_user(stderr, "%s", san); tell_user(stderr, "%s", san);
errs++; errs++;
continue; /* go round again */ continue; /* go round again */
case '\02': /* fatal error */ case '\02': /* fatal error */
with_stripctrl(san, act->buf) with_stripctrl(san, act->buf->s)
bump("%s", san); bump("%s", san);
case 'E': case 'E':
backend_send(backend, "", 1); backend_send(backend, "", 1);
act->action = SCP_SINK_ENDDIR; act->action = SCP_SINK_ENDDIR;
return 0; return 0;
case 'T': case 'T':
if (sscanf(act->buf, "%lu %*d %lu %*d", if (sscanf(act->buf->s, "%lu %*d %lu %*d",
&act->mtime, &act->atime) == 2) { &act->mtime, &act->atime) == 2) {
act->settime = true; act->settime = true;
backend_send(backend, "", 1); backend_send(backend, "", 1);
@ -1438,10 +1432,11 @@ int scp_get_sink_action(struct scp_sink_action *act)
* SCP_SINK_DIR. * SCP_SINK_DIR.
*/ */
{ {
if (sscanf(act->buf, "%lo %"SCNu64" %n", &act->permissions, int i;
if (sscanf(act->buf->s, "%lo %"SCNu64" %n", &act->permissions,
&act->size, &i) != 2) &act->size, &i) != 2)
bump("Protocol error: Illegal file descriptor format"); bump("Protocol error: Illegal file descriptor format");
act->name = act->buf + i; act->name = act->buf->s + i;
return 0; return 0;
} }
} }
@ -1758,13 +1753,17 @@ static void sink(const char *targ, const char *src)
bump("%s: Not a directory", targ); bump("%s: Not a directory", targ);
scp_sink_init(); scp_sink_init();
struct scp_sink_action act;
act.buf = strbuf_new();
while (1) { while (1) {
struct scp_sink_action act;
if (scp_get_sink_action(&act)) if (scp_get_sink_action(&act))
return; goto out;
if (act.action == SCP_SINK_ENDDIR) if (act.action == SCP_SINK_ENDDIR)
return; goto out;
if (act.action == SCP_SINK_RETRY) if (act.action == SCP_SINK_RETRY)
continue; continue;
@ -1889,7 +1888,7 @@ static void sink(const char *targ, const char *src)
if (scp_accept_filexfer()) { if (scp_accept_filexfer()) {
sfree(destfname); sfree(destfname);
close_wfile(f); close_wfile(f);
return; goto out;
} }
stat_bytes = 0; stat_bytes = 0;
@ -1947,8 +1946,9 @@ static void sink(const char *targ, const char *src)
(void) scp_finish_filerecv(); (void) scp_finish_filerecv();
sfree(stat_name); sfree(stat_name);
sfree(destfname); sfree(destfname);
sfree(act.buf);
} }
out:
strbuf_free(act.buf);
} }
/* /*

View File

@ -490,32 +490,19 @@ static bool read_header(FILE * fp, char *header)
static char *read_body(FILE * fp) static char *read_body(FILE * fp)
{ {
char *text; strbuf *buf = strbuf_new();
int len;
int size;
int c;
size = 128;
text = snewn(size, char);
len = 0;
text[len] = '\0';
while (1) { while (1) {
c = fgetc(fp); int c = fgetc(fp);
if (c == '\r' || c == '\n' || c == EOF) { if (c == '\r' || c == '\n' || c == EOF) {
if (c != EOF) { if (c != EOF) {
c = fgetc(fp); c = fgetc(fp);
if (c != '\r' && c != '\n') if (c != '\r' && c != '\n')
ungetc(c, fp); ungetc(c, fp);
} }
return text; return strbuf_to_str(buf);
} }
if (len + 1 >= size) { put_byte(buf, c);
size += 128;
text = sresize(text, size, char);
}
text[len++] = c;
text[len] = '\0';
} }
} }
@ -847,8 +834,7 @@ bool rfc4716_loadpub(FILE *fp, char **algorithm,
const char *error; const char *error;
char *line, *colon, *value; char *line, *colon, *value;
char *comment = NULL; char *comment = NULL;
unsigned char *pubblob = NULL; strbuf *pubblob = NULL;
int pubbloblen, pubblobsize;
char base64in[4]; char base64in[4];
unsigned char base64out[3]; unsigned char base64out[3];
int base64bytes; int base64bytes;
@ -909,9 +895,7 @@ bool rfc4716_loadpub(FILE *fp, char **algorithm,
* Now line contains the initial line of base64 data. Loop round * Now line contains the initial line of base64 data. Loop round
* while it still does contain base64. * while it still does contain base64.
*/ */
pubblobsize = 4096; pubblob = strbuf_new();
pubblob = snewn(pubblobsize, unsigned char);
pubbloblen = 0;
base64bytes = 0; base64bytes = 0;
while (line && line[0] != '-') { while (line && line[0] != '-') {
char *p; char *p;
@ -919,12 +903,7 @@ bool rfc4716_loadpub(FILE *fp, char **algorithm,
base64in[base64bytes++] = *p; base64in[base64bytes++] = *p;
if (base64bytes == 4) { if (base64bytes == 4) {
int n = base64_decode_atom(base64in, base64out); int n = base64_decode_atom(base64in, base64out);
if (pubbloblen + n > pubblobsize) { put_data(pubblob, base64out, n);
pubblobsize = (pubbloblen + n) * 5 / 4 + 1024;
pubblob = sresize(pubblob, pubblobsize, unsigned char);
}
memcpy(pubblob + pubbloblen, base64out, n);
pubbloblen += n;
base64bytes = 0; base64bytes = 0;
} }
} }
@ -946,29 +925,30 @@ bool rfc4716_loadpub(FILE *fp, char **algorithm,
* return the key algorithm string too, so look for that at the * return the key algorithm string too, so look for that at the
* start of the public blob. * start of the public blob.
*/ */
if (pubbloblen < 4) { if (pubblob->len < 4) {
error = "not enough data in SSH-2 public key file"; error = "not enough data in SSH-2 public key file";
goto error; goto error;
} }
alglen = toint(GET_32BIT_MSB_FIRST(pubblob)); alglen = toint(GET_32BIT_MSB_FIRST(pubblob->u));
if (alglen < 0 || alglen > pubbloblen-4) { if (alglen < 0 || alglen > pubblob->len-4) {
error = "invalid algorithm prefix in SSH-2 public key file"; error = "invalid algorithm prefix in SSH-2 public key file";
goto error; goto error;
} }
if (algorithm) if (algorithm)
*algorithm = dupprintf("%.*s", alglen, pubblob+4); *algorithm = dupprintf("%.*s", alglen, pubblob->s+4);
if (commentptr) if (commentptr)
*commentptr = comment; *commentptr = comment;
else else
sfree(comment); sfree(comment);
put_data(bs, pubblob, pubbloblen); put_datapl(bs, ptrlen_from_strbuf(pubblob));
sfree(pubblob); strbuf_free(pubblob);
return true; return true;
error: error:
sfree(line); sfree(line);
sfree(comment); sfree(comment);
sfree(pubblob); if (pubblob)
strbuf_free(pubblob);
if (errorstr) if (errorstr)
*errorstr = error; *errorstr = error;
return false; return false;

View File

@ -28,8 +28,7 @@ struct ssh_verstring_state {
int remote_bugs; int remote_bugs;
char prefix[PREFIX_MAXLEN]; char prefix[PREFIX_MAXLEN];
char *impl_name; char *impl_name;
char *vstring; strbuf *vstring;
size_t vslen, vstrsize;
char *protoversion; char *protoversion;
const char *softwareversion; const char *softwareversion;
@ -93,6 +92,7 @@ BinaryPacketProtocol *ssh_verstring_new(
s->our_protoversion = dupstr(protoversion); s->our_protoversion = dupstr(protoversion);
s->receiver = rcv; s->receiver = rcv;
s->impl_name = dupstr(impl_name); s->impl_name = dupstr(impl_name);
s->vstring = strbuf_new();
/* /*
* We send our version string early if we can. But if it includes * We send our version string early if we can. But if it includes
@ -114,7 +114,7 @@ void ssh_verstring_free(BinaryPacketProtocol *bpp)
container_of(bpp, struct ssh_verstring_state, bpp); container_of(bpp, struct ssh_verstring_state, bpp);
conf_free(s->conf); conf_free(s->conf);
sfree(s->impl_name); sfree(s->impl_name);
sfree(s->vstring); strbuf_free(s->vstring);
sfree(s->protoversion); sfree(s->protoversion);
sfree(s->our_vstring); sfree(s->our_vstring);
sfree(s->our_protoversion); sfree(s->our_protoversion);
@ -271,12 +271,9 @@ void ssh_verstring_handle_input(BinaryPacketProtocol *bpp)
s->found_prefix = true; s->found_prefix = true;
/* /*
* Start a buffer to store the full greeting line. * Copy the greeting line so far into vstring.
*/ */
s->vstrsize = s->prefix_wanted.len + 16; put_data(s->vstring, s->prefix_wanted.ptr, s->prefix_wanted.len);
s->vstring = snewn(s->vstrsize, char);
memcpy(s->vstring, s->prefix_wanted.ptr, s->prefix_wanted.len);
s->vslen = s->prefix_wanted.len;
/* /*
* Now read the rest of the greeting line. * Now read the rest of the greeting line.
@ -292,30 +289,23 @@ void ssh_verstring_handle_input(BinaryPacketProtocol *bpp)
data.len = nl - (char *)data.ptr + 1; data.len = nl - (char *)data.ptr + 1;
} }
if (s->vslen >= s->vstrsize - 1 || put_datapl(s->vstring, data);
data.len >= s->vstrsize - 1 - s->vslen) {
s->vstrsize = (s->vslen + data.len) * 5 / 4 + 32;
s->vstring = sresize(s->vstring, s->vstrsize, char);
}
memcpy(s->vstring + s->vslen, data.ptr, data.len);
s->vslen += data.len;
bufchain_consume(s->bpp.in_raw, data.len); bufchain_consume(s->bpp.in_raw, data.len);
ssh_check_frozen(s->bpp.ssh); ssh_check_frozen(s->bpp.ssh);
} while (s->vstring[s->vslen-1] != '\012'); } while (s->vstring->s[s->vstring->len-1] != '\012');
/* /*
* Trim \r and \n from the version string, and replace them with * Trim \r and \n from the version string, and replace them with
* a NUL terminator. * a NUL terminator.
*/ */
while (s->vslen > 0 && while (s->vstring->len > 0 &&
(s->vstring[s->vslen-1] == '\r' || (s->vstring->s[s->vstring->len-1] == '\r' ||
s->vstring[s->vslen-1] == '\n')) s->vstring->s[s->vstring->len-1] == '\n'))
s->vslen--; s->vstring->len--;
s->vstring[s->vslen] = '\0'; s->vstring->s[s->vstring->len] = '\0';
bpp_logevent("Remote version: %s", s->vstring); bpp_logevent("Remote version: %s", s->vstring->s);
/* /*
* Pick out the protocol version and software version. The former * Pick out the protocol version and software version. The former
@ -324,7 +314,7 @@ void ssh_verstring_handle_input(BinaryPacketProtocol *bpp)
* tail of s->vstring, so it doesn't need to be allocated. * tail of s->vstring, so it doesn't need to be allocated.
*/ */
{ {
const char *pv_start = s->vstring + s->prefix_wanted.len; const char *pv_start = s->vstring->s + s->prefix_wanted.len;
int pv_len = strcspn(pv_start, "-"); int pv_len = strcspn(pv_start, "-");
s->protoversion = dupprintf("%.*s", pv_len, pv_start); s->protoversion = dupprintf("%.*s", pv_len, pv_start);
s->softwareversion = pv_start + pv_len; s->softwareversion = pv_start + pv_len;
@ -614,7 +604,7 @@ const char *ssh_verstring_get_remote(BinaryPacketProtocol *bpp)
{ {
struct ssh_verstring_state *s = struct ssh_verstring_state *s =
container_of(bpp, struct ssh_verstring_state, bpp); container_of(bpp, struct ssh_verstring_state, bpp);
return s->vstring; return s->vstring->s;
} }
const char *ssh_verstring_get_local(BinaryPacketProtocol *bpp) const char *ssh_verstring_get_local(BinaryPacketProtocol *bpp)

View File

@ -342,8 +342,7 @@ static void lz77_compress(struct LZ77Context *ctx,
*/ */
struct Outbuf { struct Outbuf {
unsigned char *outbuf; strbuf *outbuf;
int outlen, outsize;
unsigned long outbits; unsigned long outbits;
int noutbits; int noutbits;
bool firstblock; bool firstblock;
@ -355,11 +354,7 @@ static void outbits(struct Outbuf *out, unsigned long bits, int nbits)
out->outbits |= bits << out->noutbits; out->outbits |= bits << out->noutbits;
out->noutbits += nbits; out->noutbits += nbits;
while (out->noutbits >= 8) { while (out->noutbits >= 8) {
if (out->outlen >= out->outsize) { put_byte(out->outbuf, out->outbits & 0xFF);
out->outsize = out->outlen + 64;
out->outbuf = sresize(out->outbuf, out->outsize, unsigned char);
}
out->outbuf[out->outlen++] = (unsigned char) (out->outbits & 0xFF);
out->outbits >>= 8; out->outbits >>= 8;
out->noutbits -= 8; out->noutbits -= 8;
} }
@ -589,6 +584,7 @@ ssh_compressor *zlib_compress_init(void)
comp->ectx.match = zlib_match; comp->ectx.match = zlib_match;
out = snew(struct Outbuf); out = snew(struct Outbuf);
out->outbuf = NULL;
out->outbits = out->noutbits = 0; out->outbits = out->noutbits = 0;
out->firstblock = true; out->firstblock = true;
comp->ectx.userdata = out; comp->ectx.userdata = out;
@ -600,7 +596,10 @@ void zlib_compress_cleanup(ssh_compressor *sc)
{ {
struct ssh_zlib_compressor *comp = struct ssh_zlib_compressor *comp =
container_of(sc, struct ssh_zlib_compressor, sc); container_of(sc, struct ssh_zlib_compressor, sc);
sfree(comp->ectx.userdata); struct Outbuf *out = (struct Outbuf *)comp->ectx.userdata;
if (out->outbuf)
strbuf_free(out->outbuf);
sfree(out);
sfree(comp->ectx.ictx); sfree(comp->ectx.ictx);
sfree(comp); sfree(comp);
} }
@ -615,8 +614,8 @@ void zlib_compress_block(ssh_compressor *sc,
struct Outbuf *out = (struct Outbuf *) comp->ectx.userdata; struct Outbuf *out = (struct Outbuf *) comp->ectx.userdata;
bool in_block; bool in_block;
out->outbuf = NULL; assert(!out->outbuf);
out->outlen = out->outsize = 0; out->outbuf = strbuf_new();
/* /*
* If this is the first block, output the Zlib (RFC1950) header * If this is the first block, output the Zlib (RFC1950) header
@ -678,13 +677,14 @@ void zlib_compress_block(ssh_compressor *sc,
* at least a given length, do so by emitting further empty static * at least a given length, do so by emitting further empty static
* blocks. * blocks.
*/ */
while (out->outlen < minlen) { while (out->outbuf->len < minlen) {
outbits(out, 0, 7); /* close block */ outbits(out, 0, 7); /* close block */
outbits(out, 2, 3); /* open new static block */ outbits(out, 2, 3); /* open new static block */
} }
*outblock = out->outbuf; *outlen = out->outbuf->len;
*outlen = out->outlen; *outblock = (unsigned char *)strbuf_to_str(out->outbuf);
out->outbuf = NULL;
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
@ -855,8 +855,7 @@ struct zlib_decompress_ctx {
int nbits; int nbits;
unsigned char window[WINSIZE]; unsigned char window[WINSIZE];
int winpos; int winpos;
unsigned char *outblk; strbuf *outblk;
int outlen, outsize;
ssh_decompressor dc; ssh_decompressor dc;
}; };
@ -878,6 +877,7 @@ ssh_decompressor *zlib_decompress_init(void)
dctx->bits = 0; dctx->bits = 0;
dctx->nbits = 0; dctx->nbits = 0;
dctx->winpos = 0; dctx->winpos = 0;
dctx->outblk = NULL;
dctx->dc.vt = &ssh_zlib; dctx->dc.vt = &ssh_zlib;
return &dctx->dc; return &dctx->dc;
@ -896,6 +896,8 @@ void zlib_decompress_cleanup(ssh_decompressor *dc)
zlib_freetable(&dctx->lenlentable); zlib_freetable(&dctx->lenlentable);
zlib_freetable(&dctx->staticlentable); zlib_freetable(&dctx->staticlentable);
zlib_freetable(&dctx->staticdisttable); zlib_freetable(&dctx->staticdisttable);
if (dctx->outblk)
strbuf_free(dctx->outblk);
sfree(dctx); sfree(dctx);
} }
@ -935,11 +937,7 @@ static void zlib_emit_char(struct zlib_decompress_ctx *dctx, int c)
{ {
dctx->window[dctx->winpos] = c; dctx->window[dctx->winpos] = c;
dctx->winpos = (dctx->winpos + 1) & (WINSIZE - 1); dctx->winpos = (dctx->winpos + 1) & (WINSIZE - 1);
if (dctx->outlen >= dctx->outsize) { put_byte(dctx->outblk, c);
dctx->outsize = dctx->outlen + 512;
dctx->outblk = sresize(dctx->outblk, dctx->outsize, unsigned char);
}
dctx->outblk[dctx->outlen++] = c;
} }
#define EATBITS(n) ( dctx->nbits -= (n), dctx->bits >>= (n) ) #define EATBITS(n) ( dctx->nbits -= (n), dctx->bits >>= (n) )
@ -956,9 +954,8 @@ bool zlib_decompress_block(ssh_decompressor *dc,
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
}; };
dctx->outblk = snewn(256, unsigned char); assert(!dctx->outblk);
dctx->outsize = 256; dctx->outblk = strbuf_new();
dctx->outlen = 0;
while (len > 0 || dctx->nbits > 0) { while (len > 0 || dctx->nbits > 0) {
while (dctx->nbits < 24 && len > 0) { while (dctx->nbits < 24 && len > 0) {
@ -1185,13 +1182,13 @@ bool zlib_decompress_block(ssh_decompressor *dc,
} }
finished: finished:
*outblock = dctx->outblk; *outlen = dctx->outblk->len;
*outlen = dctx->outlen; *outblock = (unsigned char *)strbuf_to_str(dctx->outblk);
dctx->outblk = NULL;
return true; return true;
decode_error: decode_error:
sfree(dctx->outblk); *outblock = NULL;
*outblock = dctx->outblk = NULL;
*outlen = 0; *outlen = 0;
return false; return false;
} }

View File

@ -184,9 +184,8 @@ struct Telnet {
bool activated; bool activated;
size_t bufsize; size_t bufsize;
bool in_synch; bool in_synch;
int sb_opt, sb_len; int sb_opt;
unsigned char *sb_buf; strbuf *sb_buf;
int sb_size;
bool session_started; bool session_started;
enum { enum {
@ -363,7 +362,7 @@ static void process_subneg(Telnet *telnet)
switch (telnet->sb_opt) { switch (telnet->sb_opt) {
case TELOPT_TSPEED: case TELOPT_TSPEED:
if (telnet->sb_len == 1 && telnet->sb_buf[0] == TELQUAL_SEND) { if (telnet->sb_buf->len == 1 && telnet->sb_buf->u[0] == TELQUAL_SEND) {
char *termspeed = conf_get_str(telnet->conf, CONF_termspeed); char *termspeed = conf_get_str(telnet->conf, CONF_termspeed);
b = snewn(20 + strlen(termspeed), unsigned char); b = snewn(20 + strlen(termspeed), unsigned char);
b[0] = IAC; b[0] = IAC;
@ -382,7 +381,7 @@ static void process_subneg(Telnet *telnet)
logevent(telnet->logctx, "server:\tSB TSPEED <something weird>"); logevent(telnet->logctx, "server:\tSB TSPEED <something weird>");
break; break;
case TELOPT_TTYPE: case TELOPT_TTYPE:
if (telnet->sb_len == 1 && telnet->sb_buf[0] == TELQUAL_SEND) { if (telnet->sb_buf->len == 1 && telnet->sb_buf->u[0] == TELQUAL_SEND) {
char *termtype = conf_get_str(telnet->conf, CONF_termtype); char *termtype = conf_get_str(telnet->conf, CONF_termtype);
b = snewn(20 + strlen(termtype), unsigned char); b = snewn(20 + strlen(termtype), unsigned char);
b[0] = IAC; b[0] = IAC;
@ -405,8 +404,8 @@ static void process_subneg(Telnet *telnet)
break; break;
case TELOPT_OLD_ENVIRON: case TELOPT_OLD_ENVIRON:
case TELOPT_NEW_ENVIRON: case TELOPT_NEW_ENVIRON:
p = telnet->sb_buf; p = telnet->sb_buf->u;
q = p + telnet->sb_len; q = p + telnet->sb_buf->len;
if (p < q && *p == TELQUAL_SEND) { if (p < q && *p == TELQUAL_SEND) {
p++; p++;
logeventf(telnet->logctx, "server:\tSB %s SEND", logeventf(telnet->logctx, "server:\tSB %s SEND",
@ -581,7 +580,7 @@ static void do_telnet_read(Telnet *telnet, const char *buf, size_t len)
break; break;
case SEENSB: case SEENSB:
telnet->sb_opt = c; telnet->sb_opt = c;
telnet->sb_len = 0; telnet->sb_buf->len = 0;
telnet->state = SUBNEGOT; telnet->state = SUBNEGOT;
break; break;
case SUBNEGOT: case SUBNEGOT:
@ -589,12 +588,7 @@ static void do_telnet_read(Telnet *telnet, const char *buf, size_t len)
telnet->state = SUBNEG_IAC; telnet->state = SUBNEG_IAC;
else { else {
subneg_addchar: subneg_addchar:
if (telnet->sb_len >= telnet->sb_size) { put_byte(telnet->sb_buf, c);
telnet->sb_size += SB_DELTA;
telnet->sb_buf = sresize(telnet->sb_buf, telnet->sb_size,
unsigned char);
}
telnet->sb_buf[telnet->sb_len++] = c;
telnet->state = SUBNEGOT; /* in case we came here by goto */ telnet->state = SUBNEGOT; /* in case we came here by goto */
} }
break; break;
@ -704,8 +698,7 @@ static const char *telnet_init(Seat *seat, Backend **backend_handle,
telnet->echoing = true; telnet->echoing = true;
telnet->editing = true; telnet->editing = true;
telnet->activated = false; telnet->activated = false;
telnet->sb_buf = NULL; telnet->sb_buf = strbuf_new();
telnet->sb_size = 0;
telnet->seat = seat; telnet->seat = seat;
telnet->logctx = logctx; telnet->logctx = logctx;
telnet->term_width = conf_get_int(telnet->conf, CONF_width); telnet->term_width = conf_get_int(telnet->conf, CONF_width);
@ -791,7 +784,7 @@ static void telnet_free(Backend *be)
{ {
Telnet *telnet = container_of(be, Telnet, backend); Telnet *telnet = container_of(be, Telnet, backend);
sfree(telnet->sb_buf); strbuf_free(telnet->sb_buf);
if (telnet->s) if (telnet->s)
sk_close(telnet->s); sk_close(telnet->s);
if (telnet->pinger) if (telnet->pinger)

View File

@ -679,32 +679,21 @@ int main(int argc, char **argv)
!strcmp(p, "-no-sanitize-stderr")) { !strcmp(p, "-no-sanitize-stderr")) {
sanitise_stderr = FORCE_OFF; sanitise_stderr = FORCE_OFF;
} else if (*p != '-') { } else if (*p != '-') {
char *command; strbuf *cmdbuf = strbuf_new();
int cmdlen, cmdsize;
cmdlen = cmdsize = 0;
command = NULL;
while (argc) { while (argc > 0) {
while (*p) { if (cmdbuf->len > 0)
if (cmdlen >= cmdsize) { put_byte(cmdbuf, ' '); /* add space separator */
cmdsize = cmdlen + 512; put_datapl(cmdbuf, ptrlen_from_asciz(p));
command = sresize(command, cmdsize, char); if (--argc > 0)
} p = *++argv;
command[cmdlen++]=*p++;
}
if (cmdlen >= cmdsize) {
cmdsize = cmdlen + 512;
command = sresize(command, cmdsize, char);
}
command[cmdlen++]=' '; /* always add trailing space */
if (--argc) p = *++argv;
} }
if (cmdlen) command[--cmdlen]='\0';
/* change trailing blank to NUL */ conf_set_str(conf, CONF_remote_cmd, cmdbuf->s);
conf_set_str(conf, CONF_remote_cmd, command);
conf_set_str(conf, CONF_remote_cmd2, ""); conf_set_str(conf, CONF_remote_cmd2, "");
conf_set_bool(conf, CONF_nopty, true); /* command => no tty */ conf_set_bool(conf, CONF_nopty, true); /* command => no tty */
strbuf_free(cmdbuf);
break; /* done with cmdline */ break; /* done with cmdline */
} else { } else {
fprintf(stderr, "plink: unknown option \"%s\"\n", p); fprintf(stderr, "plink: unknown option \"%s\"\n", p);

View File

@ -548,34 +548,33 @@ bool enum_settings_next(settings_e *handle, strbuf *out)
{ {
struct dirent *de; struct dirent *de;
struct stat st; struct stat st;
char *fullpath; strbuf *fullpath;
int maxlen, thislen, len;
if (!handle->dp) if (!handle->dp)
return NULL; return NULL;
fullpath = make_filename(INDEX_SESSIONDIR, NULL); fullpath = strbuf_new();
maxlen = len = strlen(fullpath);
char *sessiondir = make_filename(INDEX_SESSIONDIR, NULL);
put_datapl(fullpath, ptrlen_from_asciz(sessiondir));
sfree(sessiondir);
put_byte(fullpath, '/');
size_t baselen = fullpath->len;
while ( (de = readdir(handle->dp)) != NULL ) { while ( (de = readdir(handle->dp)) != NULL ) {
thislen = len + 1 + strlen(de->d_name); fullpath->len = baselen;
if (maxlen < thislen) { put_datapl(fullpath, ptrlen_from_asciz(de->d_name));
maxlen = thislen;
fullpath = sresize(fullpath, maxlen+1, char);
}
fullpath[len] = '/';
strncpy(fullpath+len+1, de->d_name, thislen - (len+1));
fullpath[thislen] = '\0';
if (stat(fullpath, &st) < 0 || !S_ISREG(st.st_mode)) if (stat(fullpath->s, &st) < 0 || !S_ISREG(st.st_mode))
continue; /* try another one */ continue; /* try another one */
decode_session_filename(de->d_name, out); decode_session_filename(de->d_name, out);
sfree(fullpath); strbuf_free(fullpath);
return true; return true;
} }
sfree(fullpath); strbuf_free(fullpath);
return false; return false;
} }

View File

@ -4924,11 +4924,10 @@ static void wintw_clip_write(
if (conf_get_bool(conf, CONF_rtf_paste)) { if (conf_get_bool(conf, CONF_rtf_paste)) {
wchar_t unitab[256]; wchar_t unitab[256];
char *rtf = NULL; strbuf *rtf = strbuf_new();
unsigned char *tdata = (unsigned char *)lock2; unsigned char *tdata = (unsigned char *)lock2;
wchar_t *udata = (wchar_t *)lock; wchar_t *udata = (wchar_t *)lock;
int rtflen = 0, uindex = 0, tindex = 0; int uindex = 0, tindex = 0;
int rtfsize = 0;
int multilen, blen, alen, totallen, i; int multilen, blen, alen, totallen, i;
char before[16], after[4]; char before[16], after[4];
int fgcolour, lastfgcolour = -1; int fgcolour, lastfgcolour = -1;
@ -4944,10 +4943,9 @@ static void wintw_clip_write(
get_unitab(CP_ACP, unitab, 0); get_unitab(CP_ACP, unitab, 0);
rtfsize = 100 + strlen(font->name); strbuf_catf(
rtf = snewn(rtfsize, char); rtf, "{\\rtf1\\ansi\\deff0{\\fonttbl\\f0\\fmodern %s;}\\f0\\fs%d",
rtflen = sprintf(rtf, "{\\rtf1\\ansi\\deff0{\\fonttbl\\f0\\fmodern %s;}\\f0\\fs%d", font->name, font->height*2);
font->name, font->height*2);
/* /*
* Add colour palette * Add colour palette
@ -5028,23 +5026,23 @@ static void wintw_clip_write(
/* /*
* Finally - Write the colour table * Finally - Write the colour table
*/ */
rtf = sresize(rtf, rtfsize + (numcolours * 25), char); put_datapl(rtf, PTRLEN_LITERAL("{\\colortbl ;"));
strcat(rtf, "{\\colortbl ;");
rtflen = strlen(rtf);
for (i = 0; i < NALLCOLOURS; i++) { for (i = 0; i < NALLCOLOURS; i++) {
if (palette[i] != 0) { if (palette[i] != 0) {
rtflen += sprintf(&rtf[rtflen], "\\red%d\\green%d\\blue%d;", defpal[i].rgbtRed, defpal[i].rgbtGreen, defpal[i].rgbtBlue); strbuf_catf(rtf, "\\red%d\\green%d\\blue%d;",
defpal[i].rgbtRed, defpal[i].rgbtGreen,
defpal[i].rgbtBlue);
} }
} }
if (rgbtree) { if (rgbtree) {
rgbindex *rgbp; rgbindex *rgbp;
for (i = 0; (rgbp = index234(rgbtree, i)) != NULL; i++) for (i = 0; (rgbp = index234(rgbtree, i)) != NULL; i++)
rtflen += sprintf(&rtf[rtflen], "\\red%d\\green%d\\blue%d;", strbuf_catf(rtf, "\\red%d\\green%d\\blue%d;",
GetRValue(rgbp->ref), GetGValue(rgbp->ref), GetBValue(rgbp->ref)); GetRValue(rgbp->ref), GetGValue(rgbp->ref),
GetBValue(rgbp->ref));
} }
strcpy(&rtf[rtflen], "}"); put_datapl(rtf, PTRLEN_LITERAL("}"));
rtflen ++;
} }
/* /*
@ -5078,11 +5076,6 @@ static void wintw_clip_write(
* Set text attributes * Set text attributes
*/ */
if (attr) { if (attr) {
if (rtfsize < rtflen + 64) {
rtfsize = rtflen + 512;
rtf = sresize(rtf, rtfsize, char);
}
/* /*
* Determine foreground and background colours * Determine foreground and background colours
*/ */
@ -5165,14 +5158,14 @@ static void wintw_clip_write(
if ((lastfgcolour != fgcolour) || (lastfg != fg)) { if ((lastfgcolour != fgcolour) || (lastfg != fg)) {
lastfgcolour = fgcolour; lastfgcolour = fgcolour;
lastfg = fg; lastfg = fg;
if (fg == -1) if (fg == -1) {
rtflen += sprintf(&rtf[rtflen], "\\cf%d ", strbuf_catf(rtf, "\\cf%d ",
(fgcolour >= 0) ? palette[fgcolour] : 0); (fgcolour >= 0) ? palette[fgcolour] : 0);
else { } else {
rgbindex rgb, *rgbp; rgbindex rgb, *rgbp;
rgb.ref = fg; rgb.ref = fg;
if ((rgbp = find234(rgbtree, &rgb, NULL)) != NULL) if ((rgbp = find234(rgbtree, &rgb, NULL)) != NULL)
rtflen += sprintf(&rtf[rtflen], "\\cf%d ", rgbp->index); strbuf_catf(rtf, "\\cf%d ", rgbp->index);
} }
} }
@ -5180,24 +5173,28 @@ static void wintw_clip_write(
lastbgcolour = bgcolour; lastbgcolour = bgcolour;
lastbg = bg; lastbg = bg;
if (bg == -1) if (bg == -1)
rtflen += sprintf(&rtf[rtflen], "\\highlight%d ", strbuf_catf(rtf, "\\highlight%d ",
(bgcolour >= 0) ? palette[bgcolour] : 0); (bgcolour >= 0) ? palette[bgcolour] : 0);
else { else {
rgbindex rgb, *rgbp; rgbindex rgb, *rgbp;
rgb.ref = bg; rgb.ref = bg;
if ((rgbp = find234(rgbtree, &rgb, NULL)) != NULL) if ((rgbp = find234(rgbtree, &rgb, NULL)) != NULL)
rtflen += sprintf(&rtf[rtflen], "\\highlight%d ", rgbp->index); strbuf_catf(rtf, "\\highlight%d ", rgbp->index);
} }
} }
if (lastAttrBold != attrBold) { if (lastAttrBold != attrBold) {
lastAttrBold = attrBold; lastAttrBold = attrBold;
rtflen += sprintf(&rtf[rtflen], "%s", attrBold ? "\\b " : "\\b0 "); put_datapl(rtf, attrBold ?
PTRLEN_LITERAL("\\b ") :
PTRLEN_LITERAL("\\b0 "));
} }
if (lastAttrUnder != attrUnder) { if (lastAttrUnder != attrUnder) {
lastAttrUnder = attrUnder; lastAttrUnder = attrUnder;
rtflen += sprintf(&rtf[rtflen], "%s", attrUnder ? "\\ul " : "\\ulnone "); put_datapl(rtf, attrUnder ?
PTRLEN_LITERAL("\\ul ") :
PTRLEN_LITERAL("\\ulnone "));
} }
} }
@ -5233,42 +5230,35 @@ static void wintw_clip_write(
totallen++; totallen++;
} }
if (rtfsize < rtflen + totallen + 3) { put_data(rtf, before, blen);
rtfsize = rtflen + totallen + 512;
rtf = sresize(rtf, rtfsize, char);
}
strcpy(rtf + rtflen, before); rtflen += blen;
for (i = 0; i < multilen; i++) { for (i = 0; i < multilen; i++) {
if (tdata[tindex+i] == '\\' || if (tdata[tindex+i] == '\\' ||
tdata[tindex+i] == '{' || tdata[tindex+i] == '{' ||
tdata[tindex+i] == '}') { tdata[tindex+i] == '}') {
rtf[rtflen++] = '\\'; put_byte(rtf, '\\');
rtf[rtflen++] = tdata[tindex+i]; put_byte(rtf, tdata[tindex+i]);
} else if (tdata[tindex+i] == 0x0D || tdata[tindex+i] == 0x0A) { } else if (tdata[tindex+i] == 0x0D || tdata[tindex+i] == 0x0A) {
rtflen += sprintf(rtf+rtflen, "\\par\r\n"); put_datapl(rtf, PTRLEN_LITERAL("\\par\r\n"));
} else if (tdata[tindex+i] > 0x7E || tdata[tindex+i] < 0x20) { } else if (tdata[tindex+i] > 0x7E || tdata[tindex+i] < 0x20) {
rtflen += sprintf(rtf+rtflen, "\\'%02x", tdata[tindex+i]); strbuf_catf(rtf, "\\'%02x", tdata[tindex+i]);
} else { } else {
rtf[rtflen++] = tdata[tindex+i]; put_byte(rtf, tdata[tindex+i]);
} }
} }
strcpy(rtf + rtflen, after); rtflen += alen; put_data(rtf, after, alen);
tindex += multilen; tindex += multilen;
uindex++; uindex++;
} }
rtf[rtflen++] = '}'; /* Terminate RTF stream */ put_datapl(rtf, PTRLEN_LITERAL("}\0\0")); /* Terminate RTF stream */
rtf[rtflen++] = '\0';
rtf[rtflen++] = '\0';
clipdata3 = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, rtflen); clipdata3 = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, rtf->len);
if (clipdata3 && (lock3 = GlobalLock(clipdata3)) != NULL) { if (clipdata3 && (lock3 = GlobalLock(clipdata3)) != NULL) {
memcpy(lock3, rtf, rtflen); memcpy(lock3, rtf->u, rtf->len);
GlobalUnlock(clipdata3); GlobalUnlock(clipdata3);
} }
sfree(rtf); strbuf_free(rtf);
if (rgbtree) { if (rgbtree) {
rgbindex *rgbp; rgbindex *rgbp;

View File

@ -352,32 +352,21 @@ int main(int argc, char **argv)
!strcmp(p, "-no-sanitize-stderr")) { !strcmp(p, "-no-sanitize-stderr")) {
sanitise_stderr = FORCE_OFF; sanitise_stderr = FORCE_OFF;
} else if (*p != '-') { } else if (*p != '-') {
char *command; strbuf *cmdbuf = strbuf_new();
int cmdlen, cmdsize;
cmdlen = cmdsize = 0;
command = NULL;
while (argc) { while (argc > 0) {
while (*p) { if (cmdbuf->len > 0)
if (cmdlen >= cmdsize) { put_byte(cmdbuf, ' '); /* add space separator */
cmdsize = cmdlen + 512; put_datapl(cmdbuf, ptrlen_from_asciz(p));
command = sresize(command, cmdsize, char); if (--argc > 0)
} p = *++argv;
command[cmdlen++]=*p++;
}
if (cmdlen >= cmdsize) {
cmdsize = cmdlen + 512;
command = sresize(command, cmdsize, char);
}
command[cmdlen++]=' '; /* always add trailing space */
if (--argc) p = *++argv;
} }
if (cmdlen) command[--cmdlen]='\0';
/* change trailing blank to NUL */ conf_set_str(conf, CONF_remote_cmd, cmdbuf->s);
conf_set_str(conf, CONF_remote_cmd, command);
conf_set_str(conf, CONF_remote_cmd2, ""); conf_set_str(conf, CONF_remote_cmd2, "");
conf_set_bool(conf, CONF_nopty, true); /* command => no tty */ conf_set_bool(conf, CONF_nopty, true); /* command => no tty */
strbuf_free(cmdbuf);
break; /* done with cmdline */ break; /* done with cmdline */
} else { } else {
fprintf(stderr, "plink: unknown option \"%s\"\n", p); fprintf(stderr, "plink: unknown option \"%s\"\n", p);