diff --git a/Recipe b/Recipe index 6cb794bf..90f27c59 100644 --- a/Recipe +++ b/Recipe @@ -395,7 +395,7 @@ testcrypt : [C] testcrypt SSHCRYPTO sshprng sshprime marshal utils + memory tree234 winmiscs testsc : [UT] testsc SSHCRYPTO marshal utils memory tree234 wildcard + sshmac uxutils -testzlib : [UT] testzlib sshzlib memory +testzlib : [UT] testzlib sshzlib utils marshal memory uppity : [UT] uxserver SSHSERVER UXMISC uxsignal uxnoise uxgss uxnogtk + uxpty uxsftpserver ux_x11 uxagentsock diff --git a/cmdline.c b/cmdline.c index f4dea071..083231f1 100644 --- a/cmdline.c +++ b/cmdline.c @@ -563,10 +563,7 @@ int cmdline_process_param(const char *p, char *value, } if (!strcmp(p, "-m")) { const char *filename; - char *command; - int cmdlen, cmdsize; FILE *fp; - int c, d; RETURN(2); UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK); @@ -574,29 +571,24 @@ int cmdline_process_param(const char *p, char *value, filename = value; - cmdlen = cmdsize = 0; - command = NULL; fp = fopen(filename, "r"); if (!fp) { cmdline_error("unable to open command file \"%s\"", filename); return ret; } - do { - c = fgetc(fp); - d = c; - if (c == EOF) - d = 0; - if (cmdlen >= cmdsize) { - cmdsize = cmdlen + 512; - command = sresize(command, cmdsize, char); - } - command[cmdlen++] = d; - } while (c != EOF); + strbuf *command = strbuf_new(); + char readbuf[4096]; + while (1) { + size_t nread = fread(readbuf, 1, sizeof(readbuf), fp); + if (nread == 0) + break; + put_data(command, readbuf, nread); + } 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_bool(conf, CONF_nopty, true); /* command => no terminal */ - sfree(command); + strbuf_free(command); } if (!strcmp(p, "-P")) { RETURN(2); diff --git a/import.c b/import.c index eca4fa1a..576bb315 100644 --- a/import.c +++ b/import.c @@ -1084,8 +1084,7 @@ struct openssh_new_key { /* This too points to a position within keyblob */ ptrlen private; - unsigned char *keyblob; - int keyblob_len, keyblob_size; + strbuf *keyblob; }; 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; ret = snew(struct openssh_new_key); - ret->keyblob = NULL; - ret->keyblob_len = ret->keyblob_size = 0; + ret->keyblob = strbuf_new(); fp = f_open(filename, "r", false); if (!fp) { @@ -1153,14 +1151,7 @@ static struct openssh_new_key *load_openssh_new_key(const Filename *filename, goto error; } - if (ret->keyblob_len + len > ret->keyblob_size) { - 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; + put_data(ret->keyblob, out, len); smemclr(out, sizeof(out)); } @@ -1175,12 +1166,12 @@ static struct openssh_new_key *load_openssh_new_key(const Filename *filename, fclose(fp); fp = NULL; - if (ret->keyblob_len == 0 || !ret->keyblob) { + if (ret->keyblob->len == 0 || !ret->keyblob) { errmsg = "key body not present"; 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) { 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)); if (ret) { - if (ret->keyblob) { - smemclr(ret->keyblob, ret->keyblob_size); - sfree(ret->keyblob); - } + strbuf_free(ret->keyblob); smemclr(ret, sizeof(*ret)); sfree(ret); } @@ -1308,8 +1296,7 @@ static bool openssh_new_encrypted(const Filename *filename) if (!key) return false; ret = (key->cipher != ON_E_NONE); - smemclr(key->keyblob, key->keyblob_size); - sfree(key->keyblob); + strbuf_free(key->keyblob); smemclr(key, sizeof(*key)); sfree(key); return ret; @@ -1483,8 +1470,7 @@ static ssh2_userkey *openssh_new_read( ssh_key_free(retkey->key); sfree(retkey); } - smemclr(key->keyblob, key->keyblob_size); - sfree(key->keyblob); + strbuf_free(key->keyblob); smemclr(key, sizeof(*key)); sfree(key); if (errmsg_p) *errmsg_p = errmsg; @@ -1714,8 +1700,7 @@ static bool openssh_auto_write( struct sshcom_key { char comment[256]; /* allowing any length is overkill */ - unsigned char *keyblob; - int keyblob_len, keyblob_size; + strbuf *keyblob; }; 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->comment[0] = '\0'; - ret->keyblob = NULL; - ret->keyblob_len = ret->keyblob_size = 0; + ret->keyblob = strbuf_new(); fp = f_open(filename, "r", false); if (!fp) { @@ -1831,14 +1815,7 @@ static struct sshcom_key *load_sshcom_key(const Filename *filename, goto error; } - if (ret->keyblob_len + len > ret->keyblob_size) { - 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; + put_data(ret->keyblob, out, len); } p++; @@ -1849,7 +1826,7 @@ static struct sshcom_key *load_sshcom_key(const Filename *filename, line = NULL; } - if (ret->keyblob_len == 0 || !ret->keyblob) { + if (ret->keyblob->len == 0) { errmsg = "key body not present"; goto error; } @@ -1868,10 +1845,7 @@ static struct sshcom_key *load_sshcom_key(const Filename *filename, line = NULL; } if (ret) { - if (ret->keyblob) { - smemclr(ret->keyblob, ret->keyblob_size); - sfree(ret->keyblob); - } + strbuf_free(ret->keyblob); smemclr(ret, sizeof(*ret)); sfree(ret); } @@ -1890,7 +1864,7 @@ static bool sshcom_encrypted(const Filename *filename, char **comment) if (!key) 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) goto done; /* key is invalid */ @@ -1905,8 +1879,7 @@ static bool sshcom_encrypted(const Filename *filename, char **comment) done: if (key) { *comment = dupstr(key->comment); - smemclr(key->keyblob, key->keyblob_size); - sfree(key->keyblob); + strbuf_free(key->keyblob); smemclr(key, sizeof(*key)); sfree(key); } else { @@ -1983,7 +1956,7 @@ static ssh2_userkey *sshcom_read( if (!key) 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) { errmsg = "key does not begin with magic number"; @@ -2158,8 +2131,7 @@ static ssh2_userkey *sshcom_read( if (blob) { strbuf_free(blob); } - smemclr(key->keyblob, key->keyblob_size); - sfree(key->keyblob); + strbuf_free(key->keyblob); smemclr(key, sizeof(*key)); sfree(key); if (errmsg_p) *errmsg_p = errmsg; diff --git a/logging.c b/logging.c index 51444ea3..bfe90b52 100644 --- a/logging.c +++ b/logging.c @@ -450,14 +450,11 @@ static Filename *xlatlognam(Filename *src, char *hostname, int port, { char buf[32], *bufp; int size; - char *buffer; - int buflen, bufsize; + strbuf *buffer; const char *s; Filename *ret; - bufsize = FILENAME_MAX; - buffer = snewn(bufsize, char); - buflen = 0; + buffer = strbuf_new(); s = filename_to_str(src); while (*s) { @@ -504,20 +501,15 @@ static Filename *xlatlognam(Filename *src, char *hostname, int port, buf[0] = *s++; size = 1; } - if (bufsize <= buflen + size) { - bufsize = (buflen + size) * 5 / 4 + 512; - buffer = sresize(buffer, bufsize, char); - } while (size-- > 0) { char c = *bufp++; if (sanitise) c = filename_char_sanitise(c); - buffer[buflen++] = c; + put_byte(buffer, c); } } - buffer[buflen] = '\0'; - ret = filename_from_str(buffer); - sfree(buffer); + ret = filename_from_str(buffer->s); + strbuf_free(buffer); return ret; } diff --git a/pscp.c b/pscp.c index 210a8559..c78d25f6 100644 --- a/pscp.c +++ b/pscp.c @@ -1096,7 +1096,7 @@ int scp_sink_init(void) #define SCP_SINK_RETRY 4 /* not an action; just try again */ struct scp_sink_action { 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) */ long permissions; /* access permissions (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; } else { act->action = SCP_SINK_DIR; - act->buf = dupstr(stripslashes(fname, false)); - act->name = act->buf; + act->buf->len = 0; + put_asciz(act->buf, stripslashes(fname, false)); + act->name = act->buf->s; act->size = 0; /* duhh, it's a directory */ act->permissions = 07777 & attrs.permissions; 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. */ act->action = SCP_SINK_FILE; - act->buf = dupstr(stripslashes(fname, false)); - act->name = act->buf; + act->buf->len = 0; + put_asciz(act->buf, stripslashes(fname, false)); + act->name = act->buf->s; if (attrs.flags & SSH_FILEXFER_ATTR_SIZE) { act->size = attrs.size; } else @@ -1369,46 +1371,38 @@ int scp_get_sink_action(struct scp_sink_action *act) } else { bool done = false; - int i, bufsize; int action; char ch; act->settime = false; - act->buf = NULL; - bufsize = 0; + act->buf->len = 0; while (!done) { if (!ssh_scp_recv(&ch, 1)) return 1; if (ch == '\n') bump("Protocol error: Unexpected newline"); - i = 0; action = ch; do { if (!ssh_scp_recv(&ch, 1)) bump("Lost connection"); - if (i >= bufsize) { - bufsize = i + 128; - act->buf = sresize(act->buf, bufsize, char); - } - act->buf[i++] = ch; + put_byte(act->buf, ch); } while (ch != '\n'); - act->buf[i - 1] = '\0'; switch (action) { case '\01': /* error */ - with_stripctrl(san, act->buf) + with_stripctrl(san, act->buf->s) tell_user(stderr, "%s", san); errs++; continue; /* go round again */ case '\02': /* fatal error */ - with_stripctrl(san, act->buf) + with_stripctrl(san, act->buf->s) bump("%s", san); case 'E': backend_send(backend, "", 1); act->action = SCP_SINK_ENDDIR; return 0; 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->settime = true; backend_send(backend, "", 1); @@ -1438,10 +1432,11 @@ int scp_get_sink_action(struct scp_sink_action *act) * 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) bump("Protocol error: Illegal file descriptor format"); - act->name = act->buf + i; + act->name = act->buf->s + i; return 0; } } @@ -1758,13 +1753,17 @@ static void sink(const char *targ, const char *src) bump("%s: Not a directory", targ); scp_sink_init(); + + struct scp_sink_action act; + act.buf = strbuf_new(); + while (1) { - struct scp_sink_action act; + if (scp_get_sink_action(&act)) - return; + goto out; if (act.action == SCP_SINK_ENDDIR) - return; + goto out; if (act.action == SCP_SINK_RETRY) continue; @@ -1889,7 +1888,7 @@ static void sink(const char *targ, const char *src) if (scp_accept_filexfer()) { sfree(destfname); close_wfile(f); - return; + goto out; } stat_bytes = 0; @@ -1947,8 +1946,9 @@ static void sink(const char *targ, const char *src) (void) scp_finish_filerecv(); sfree(stat_name); sfree(destfname); - sfree(act.buf); } + out: + strbuf_free(act.buf); } /* diff --git a/sshpubk.c b/sshpubk.c index b693b244..2102426e 100644 --- a/sshpubk.c +++ b/sshpubk.c @@ -490,32 +490,19 @@ static bool read_header(FILE * fp, char *header) static char *read_body(FILE * fp) { - char *text; - int len; - int size; - int c; - - size = 128; - text = snewn(size, char); - len = 0; - text[len] = '\0'; + strbuf *buf = strbuf_new(); while (1) { - c = fgetc(fp); + int c = fgetc(fp); if (c == '\r' || c == '\n' || c == EOF) { if (c != EOF) { c = fgetc(fp); if (c != '\r' && c != '\n') ungetc(c, fp); } - return text; + return strbuf_to_str(buf); } - if (len + 1 >= size) { - size += 128; - text = sresize(text, size, char); - } - text[len++] = c; - text[len] = '\0'; + put_byte(buf, c); } } @@ -847,8 +834,7 @@ bool rfc4716_loadpub(FILE *fp, char **algorithm, const char *error; char *line, *colon, *value; char *comment = NULL; - unsigned char *pubblob = NULL; - int pubbloblen, pubblobsize; + strbuf *pubblob = NULL; char base64in[4]; unsigned char base64out[3]; int base64bytes; @@ -909,9 +895,7 @@ bool rfc4716_loadpub(FILE *fp, char **algorithm, * Now line contains the initial line of base64 data. Loop round * while it still does contain base64. */ - pubblobsize = 4096; - pubblob = snewn(pubblobsize, unsigned char); - pubbloblen = 0; + pubblob = strbuf_new(); base64bytes = 0; while (line && line[0] != '-') { char *p; @@ -919,12 +903,7 @@ bool rfc4716_loadpub(FILE *fp, char **algorithm, base64in[base64bytes++] = *p; if (base64bytes == 4) { int n = base64_decode_atom(base64in, base64out); - if (pubbloblen + n > pubblobsize) { - pubblobsize = (pubbloblen + n) * 5 / 4 + 1024; - pubblob = sresize(pubblob, pubblobsize, unsigned char); - } - memcpy(pubblob + pubbloblen, base64out, n); - pubbloblen += n; + put_data(pubblob, base64out, n); 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 * start of the public blob. */ - if (pubbloblen < 4) { + if (pubblob->len < 4) { error = "not enough data in SSH-2 public key file"; goto error; } - alglen = toint(GET_32BIT_MSB_FIRST(pubblob)); - if (alglen < 0 || alglen > pubbloblen-4) { + alglen = toint(GET_32BIT_MSB_FIRST(pubblob->u)); + if (alglen < 0 || alglen > pubblob->len-4) { error = "invalid algorithm prefix in SSH-2 public key file"; goto error; } if (algorithm) - *algorithm = dupprintf("%.*s", alglen, pubblob+4); + *algorithm = dupprintf("%.*s", alglen, pubblob->s+4); if (commentptr) *commentptr = comment; else sfree(comment); - put_data(bs, pubblob, pubbloblen); - sfree(pubblob); + put_datapl(bs, ptrlen_from_strbuf(pubblob)); + strbuf_free(pubblob); return true; error: sfree(line); sfree(comment); - sfree(pubblob); + if (pubblob) + strbuf_free(pubblob); if (errorstr) *errorstr = error; return false; diff --git a/sshverstring.c b/sshverstring.c index 23085cd3..0b9152f3 100644 --- a/sshverstring.c +++ b/sshverstring.c @@ -28,8 +28,7 @@ struct ssh_verstring_state { int remote_bugs; char prefix[PREFIX_MAXLEN]; char *impl_name; - char *vstring; - size_t vslen, vstrsize; + strbuf *vstring; char *protoversion; const char *softwareversion; @@ -93,6 +92,7 @@ BinaryPacketProtocol *ssh_verstring_new( s->our_protoversion = dupstr(protoversion); s->receiver = rcv; s->impl_name = dupstr(impl_name); + s->vstring = strbuf_new(); /* * 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); conf_free(s->conf); sfree(s->impl_name); - sfree(s->vstring); + strbuf_free(s->vstring); sfree(s->protoversion); sfree(s->our_vstring); sfree(s->our_protoversion); @@ -271,12 +271,9 @@ void ssh_verstring_handle_input(BinaryPacketProtocol *bpp) 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; - s->vstring = snewn(s->vstrsize, char); - memcpy(s->vstring, s->prefix_wanted.ptr, s->prefix_wanted.len); - s->vslen = s->prefix_wanted.len; + put_data(s->vstring, s->prefix_wanted.ptr, s->prefix_wanted.len); /* * 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; } - if (s->vslen >= s->vstrsize - 1 || - 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; + put_datapl(s->vstring, data); bufchain_consume(s->bpp.in_raw, data.len); 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 * a NUL terminator. */ - while (s->vslen > 0 && - (s->vstring[s->vslen-1] == '\r' || - s->vstring[s->vslen-1] == '\n')) - s->vslen--; - s->vstring[s->vslen] = '\0'; + while (s->vstring->len > 0 && + (s->vstring->s[s->vstring->len-1] == '\r' || + s->vstring->s[s->vstring->len-1] == '\n')) + s->vstring->len--; + 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 @@ -324,7 +314,7 @@ void ssh_verstring_handle_input(BinaryPacketProtocol *bpp) * 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, "-"); s->protoversion = dupprintf("%.*s", pv_len, pv_start); s->softwareversion = pv_start + pv_len; @@ -614,7 +604,7 @@ const char *ssh_verstring_get_remote(BinaryPacketProtocol *bpp) { struct ssh_verstring_state *s = container_of(bpp, struct ssh_verstring_state, bpp); - return s->vstring; + return s->vstring->s; } const char *ssh_verstring_get_local(BinaryPacketProtocol *bpp) diff --git a/sshzlib.c b/sshzlib.c index 52a5feee..480b9972 100644 --- a/sshzlib.c +++ b/sshzlib.c @@ -342,8 +342,7 @@ static void lz77_compress(struct LZ77Context *ctx, */ struct Outbuf { - unsigned char *outbuf; - int outlen, outsize; + strbuf *outbuf; unsigned long outbits; int noutbits; bool firstblock; @@ -355,11 +354,7 @@ static void outbits(struct Outbuf *out, unsigned long bits, int nbits) out->outbits |= bits << out->noutbits; out->noutbits += nbits; while (out->noutbits >= 8) { - if (out->outlen >= out->outsize) { - out->outsize = out->outlen + 64; - out->outbuf = sresize(out->outbuf, out->outsize, unsigned char); - } - out->outbuf[out->outlen++] = (unsigned char) (out->outbits & 0xFF); + put_byte(out->outbuf, out->outbits & 0xFF); out->outbits >>= 8; out->noutbits -= 8; } @@ -589,6 +584,7 @@ ssh_compressor *zlib_compress_init(void) comp->ectx.match = zlib_match; out = snew(struct Outbuf); + out->outbuf = NULL; out->outbits = out->noutbits = 0; out->firstblock = true; comp->ectx.userdata = out; @@ -600,7 +596,10 @@ void zlib_compress_cleanup(ssh_compressor *sc) { struct ssh_zlib_compressor *comp = 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); } @@ -615,8 +614,8 @@ void zlib_compress_block(ssh_compressor *sc, struct Outbuf *out = (struct Outbuf *) comp->ectx.userdata; bool in_block; - out->outbuf = NULL; - out->outlen = out->outsize = 0; + assert(!out->outbuf); + out->outbuf = strbuf_new(); /* * 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 * blocks. */ - while (out->outlen < minlen) { + while (out->outbuf->len < minlen) { outbits(out, 0, 7); /* close block */ outbits(out, 2, 3); /* open new static block */ } - *outblock = out->outbuf; - *outlen = out->outlen; + *outlen = out->outbuf->len; + *outblock = (unsigned char *)strbuf_to_str(out->outbuf); + out->outbuf = NULL; } /* ---------------------------------------------------------------------- @@ -855,8 +855,7 @@ struct zlib_decompress_ctx { int nbits; unsigned char window[WINSIZE]; int winpos; - unsigned char *outblk; - int outlen, outsize; + strbuf *outblk; ssh_decompressor dc; }; @@ -878,6 +877,7 @@ ssh_decompressor *zlib_decompress_init(void) dctx->bits = 0; dctx->nbits = 0; dctx->winpos = 0; + dctx->outblk = NULL; dctx->dc.vt = &ssh_zlib; return &dctx->dc; @@ -896,6 +896,8 @@ void zlib_decompress_cleanup(ssh_decompressor *dc) zlib_freetable(&dctx->lenlentable); zlib_freetable(&dctx->staticlentable); zlib_freetable(&dctx->staticdisttable); + if (dctx->outblk) + strbuf_free(dctx->outblk); sfree(dctx); } @@ -935,11 +937,7 @@ static void zlib_emit_char(struct zlib_decompress_ctx *dctx, int c) { dctx->window[dctx->winpos] = c; dctx->winpos = (dctx->winpos + 1) & (WINSIZE - 1); - if (dctx->outlen >= dctx->outsize) { - dctx->outsize = dctx->outlen + 512; - dctx->outblk = sresize(dctx->outblk, dctx->outsize, unsigned char); - } - dctx->outblk[dctx->outlen++] = c; + put_byte(dctx->outblk, c); } #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 }; - dctx->outblk = snewn(256, unsigned char); - dctx->outsize = 256; - dctx->outlen = 0; + assert(!dctx->outblk); + dctx->outblk = strbuf_new(); while (len > 0 || dctx->nbits > 0) { while (dctx->nbits < 24 && len > 0) { @@ -1185,13 +1182,13 @@ bool zlib_decompress_block(ssh_decompressor *dc, } finished: - *outblock = dctx->outblk; - *outlen = dctx->outlen; + *outlen = dctx->outblk->len; + *outblock = (unsigned char *)strbuf_to_str(dctx->outblk); + dctx->outblk = NULL; return true; decode_error: - sfree(dctx->outblk); - *outblock = dctx->outblk = NULL; + *outblock = NULL; *outlen = 0; return false; } diff --git a/telnet.c b/telnet.c index 8199c7d9..74f36999 100644 --- a/telnet.c +++ b/telnet.c @@ -184,9 +184,8 @@ struct Telnet { bool activated; size_t bufsize; bool in_synch; - int sb_opt, sb_len; - unsigned char *sb_buf; - int sb_size; + int sb_opt; + strbuf *sb_buf; bool session_started; enum { @@ -363,7 +362,7 @@ static void process_subneg(Telnet *telnet) switch (telnet->sb_opt) { 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); b = snewn(20 + strlen(termspeed), unsigned char); b[0] = IAC; @@ -382,7 +381,7 @@ static void process_subneg(Telnet *telnet) logevent(telnet->logctx, "server:\tSB TSPEED "); break; 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); b = snewn(20 + strlen(termtype), unsigned char); b[0] = IAC; @@ -405,8 +404,8 @@ static void process_subneg(Telnet *telnet) break; case TELOPT_OLD_ENVIRON: case TELOPT_NEW_ENVIRON: - p = telnet->sb_buf; - q = p + telnet->sb_len; + p = telnet->sb_buf->u; + q = p + telnet->sb_buf->len; if (p < q && *p == TELQUAL_SEND) { p++; 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; case SEENSB: telnet->sb_opt = c; - telnet->sb_len = 0; + telnet->sb_buf->len = 0; telnet->state = SUBNEGOT; break; case SUBNEGOT: @@ -589,12 +588,7 @@ static void do_telnet_read(Telnet *telnet, const char *buf, size_t len) telnet->state = SUBNEG_IAC; else { subneg_addchar: - if (telnet->sb_len >= telnet->sb_size) { - telnet->sb_size += SB_DELTA; - telnet->sb_buf = sresize(telnet->sb_buf, telnet->sb_size, - unsigned char); - } - telnet->sb_buf[telnet->sb_len++] = c; + put_byte(telnet->sb_buf, c); telnet->state = SUBNEGOT; /* in case we came here by goto */ } break; @@ -704,8 +698,7 @@ static const char *telnet_init(Seat *seat, Backend **backend_handle, telnet->echoing = true; telnet->editing = true; telnet->activated = false; - telnet->sb_buf = NULL; - telnet->sb_size = 0; + telnet->sb_buf = strbuf_new(); telnet->seat = seat; telnet->logctx = logctx; 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); - sfree(telnet->sb_buf); + strbuf_free(telnet->sb_buf); if (telnet->s) sk_close(telnet->s); if (telnet->pinger) diff --git a/unix/uxplink.c b/unix/uxplink.c index 9e687075..5aae9e49 100644 --- a/unix/uxplink.c +++ b/unix/uxplink.c @@ -679,32 +679,21 @@ int main(int argc, char **argv) !strcmp(p, "-no-sanitize-stderr")) { sanitise_stderr = FORCE_OFF; } else if (*p != '-') { - char *command; - int cmdlen, cmdsize; - cmdlen = cmdsize = 0; - command = NULL; + strbuf *cmdbuf = strbuf_new(); - while (argc) { - while (*p) { - if (cmdlen >= cmdsize) { - cmdsize = cmdlen + 512; - command = sresize(command, cmdsize, char); - } - command[cmdlen++]=*p++; - } - if (cmdlen >= cmdsize) { - cmdsize = cmdlen + 512; - command = sresize(command, cmdsize, char); - } - command[cmdlen++]=' '; /* always add trailing space */ - if (--argc) p = *++argv; + while (argc > 0) { + if (cmdbuf->len > 0) + put_byte(cmdbuf, ' '); /* add space separator */ + put_datapl(cmdbuf, ptrlen_from_asciz(p)); + if (--argc > 0) + p = *++argv; } - if (cmdlen) command[--cmdlen]='\0'; - /* change trailing blank to NUL */ - conf_set_str(conf, CONF_remote_cmd, command); + + conf_set_str(conf, CONF_remote_cmd, cmdbuf->s); conf_set_str(conf, CONF_remote_cmd2, ""); conf_set_bool(conf, CONF_nopty, true); /* command => no tty */ + strbuf_free(cmdbuf); break; /* done with cmdline */ } else { fprintf(stderr, "plink: unknown option \"%s\"\n", p); diff --git a/unix/uxstore.c b/unix/uxstore.c index 409a5787..c66d92b0 100644 --- a/unix/uxstore.c +++ b/unix/uxstore.c @@ -548,34 +548,33 @@ bool enum_settings_next(settings_e *handle, strbuf *out) { struct dirent *de; struct stat st; - char *fullpath; - int maxlen, thislen, len; + strbuf *fullpath; if (!handle->dp) return NULL; - fullpath = make_filename(INDEX_SESSIONDIR, NULL); - maxlen = len = strlen(fullpath); + fullpath = strbuf_new(); + + 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 ) { - thislen = len + 1 + strlen(de->d_name); - if (maxlen < thislen) { - maxlen = thislen; - fullpath = sresize(fullpath, maxlen+1, char); - } - fullpath[len] = '/'; - strncpy(fullpath+len+1, de->d_name, thislen - (len+1)); - fullpath[thislen] = '\0'; + fullpath->len = baselen; + put_datapl(fullpath, ptrlen_from_asciz(de->d_name)); - 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 */ decode_session_filename(de->d_name, out); - sfree(fullpath); + strbuf_free(fullpath); return true; } - sfree(fullpath); + strbuf_free(fullpath); return false; } diff --git a/windows/window.c b/windows/window.c index 65d8abf9..781e8b88 100644 --- a/windows/window.c +++ b/windows/window.c @@ -4924,11 +4924,10 @@ static void wintw_clip_write( if (conf_get_bool(conf, CONF_rtf_paste)) { wchar_t unitab[256]; - char *rtf = NULL; + strbuf *rtf = strbuf_new(); unsigned char *tdata = (unsigned char *)lock2; wchar_t *udata = (wchar_t *)lock; - int rtflen = 0, uindex = 0, tindex = 0; - int rtfsize = 0; + int uindex = 0, tindex = 0; int multilen, blen, alen, totallen, i; char before[16], after[4]; int fgcolour, lastfgcolour = -1; @@ -4944,10 +4943,9 @@ static void wintw_clip_write( get_unitab(CP_ACP, unitab, 0); - rtfsize = 100 + strlen(font->name); - rtf = snewn(rtfsize, char); - rtflen = sprintf(rtf, "{\\rtf1\\ansi\\deff0{\\fonttbl\\f0\\fmodern %s;}\\f0\\fs%d", - font->name, font->height*2); + strbuf_catf( + rtf, "{\\rtf1\\ansi\\deff0{\\fonttbl\\f0\\fmodern %s;}\\f0\\fs%d", + font->name, font->height*2); /* * Add colour palette @@ -5028,23 +5026,23 @@ static void wintw_clip_write( /* * Finally - Write the colour table */ - rtf = sresize(rtf, rtfsize + (numcolours * 25), char); - strcat(rtf, "{\\colortbl ;"); - rtflen = strlen(rtf); + put_datapl(rtf, PTRLEN_LITERAL("{\\colortbl ;")); for (i = 0; i < NALLCOLOURS; i++) { 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) { rgbindex *rgbp; for (i = 0; (rgbp = index234(rgbtree, i)) != NULL; i++) - rtflen += sprintf(&rtf[rtflen], "\\red%d\\green%d\\blue%d;", - GetRValue(rgbp->ref), GetGValue(rgbp->ref), GetBValue(rgbp->ref)); + strbuf_catf(rtf, "\\red%d\\green%d\\blue%d;", + GetRValue(rgbp->ref), GetGValue(rgbp->ref), + GetBValue(rgbp->ref)); } - strcpy(&rtf[rtflen], "}"); - rtflen ++; + put_datapl(rtf, PTRLEN_LITERAL("}")); } /* @@ -5078,11 +5076,6 @@ static void wintw_clip_write( * Set text attributes */ if (attr) { - if (rtfsize < rtflen + 64) { - rtfsize = rtflen + 512; - rtf = sresize(rtf, rtfsize, char); - } - /* * Determine foreground and background colours */ @@ -5165,14 +5158,14 @@ static void wintw_clip_write( if ((lastfgcolour != fgcolour) || (lastfg != fg)) { lastfgcolour = fgcolour; lastfg = fg; - if (fg == -1) - rtflen += sprintf(&rtf[rtflen], "\\cf%d ", - (fgcolour >= 0) ? palette[fgcolour] : 0); - else { + if (fg == -1) { + strbuf_catf(rtf, "\\cf%d ", + (fgcolour >= 0) ? palette[fgcolour] : 0); + } else { rgbindex rgb, *rgbp; rgb.ref = fg; 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; lastbg = bg; if (bg == -1) - rtflen += sprintf(&rtf[rtflen], "\\highlight%d ", - (bgcolour >= 0) ? palette[bgcolour] : 0); + strbuf_catf(rtf, "\\highlight%d ", + (bgcolour >= 0) ? palette[bgcolour] : 0); else { rgbindex rgb, *rgbp; rgb.ref = bg; 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) { lastAttrBold = attrBold; - rtflen += sprintf(&rtf[rtflen], "%s", attrBold ? "\\b " : "\\b0 "); + put_datapl(rtf, attrBold ? + PTRLEN_LITERAL("\\b ") : + PTRLEN_LITERAL("\\b0 ")); } if (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++; } - if (rtfsize < rtflen + totallen + 3) { - rtfsize = rtflen + totallen + 512; - rtf = sresize(rtf, rtfsize, char); - } - - strcpy(rtf + rtflen, before); rtflen += blen; + put_data(rtf, before, blen); for (i = 0; i < multilen; i++) { if (tdata[tindex+i] == '\\' || tdata[tindex+i] == '{' || tdata[tindex+i] == '}') { - rtf[rtflen++] = '\\'; - rtf[rtflen++] = tdata[tindex+i]; + put_byte(rtf, '\\'); + put_byte(rtf, tdata[tindex+i]); } 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) { - rtflen += sprintf(rtf+rtflen, "\\'%02x", tdata[tindex+i]); + strbuf_catf(rtf, "\\'%02x", tdata[tindex+i]); } 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; uindex++; } - rtf[rtflen++] = '}'; /* Terminate RTF stream */ - rtf[rtflen++] = '\0'; - rtf[rtflen++] = '\0'; + put_datapl(rtf, PTRLEN_LITERAL("}\0\0")); /* Terminate RTF stream */ - clipdata3 = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, rtflen); + clipdata3 = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, rtf->len); if (clipdata3 && (lock3 = GlobalLock(clipdata3)) != NULL) { - memcpy(lock3, rtf, rtflen); + memcpy(lock3, rtf->u, rtf->len); GlobalUnlock(clipdata3); } - sfree(rtf); + strbuf_free(rtf); if (rgbtree) { rgbindex *rgbp; diff --git a/windows/winplink.c b/windows/winplink.c index 80933b38..0bcb6564 100644 --- a/windows/winplink.c +++ b/windows/winplink.c @@ -352,32 +352,21 @@ int main(int argc, char **argv) !strcmp(p, "-no-sanitize-stderr")) { sanitise_stderr = FORCE_OFF; } else if (*p != '-') { - char *command; - int cmdlen, cmdsize; - cmdlen = cmdsize = 0; - command = NULL; + strbuf *cmdbuf = strbuf_new(); - while (argc) { - while (*p) { - if (cmdlen >= cmdsize) { - cmdsize = cmdlen + 512; - command = sresize(command, cmdsize, char); - } - command[cmdlen++]=*p++; - } - if (cmdlen >= cmdsize) { - cmdsize = cmdlen + 512; - command = sresize(command, cmdsize, char); - } - command[cmdlen++]=' '; /* always add trailing space */ - if (--argc) p = *++argv; + while (argc > 0) { + if (cmdbuf->len > 0) + put_byte(cmdbuf, ' '); /* add space separator */ + put_datapl(cmdbuf, ptrlen_from_asciz(p)); + if (--argc > 0) + p = *++argv; } - if (cmdlen) command[--cmdlen]='\0'; - /* change trailing blank to NUL */ - conf_set_str(conf, CONF_remote_cmd, command); + + conf_set_str(conf, CONF_remote_cmd, cmdbuf->s); conf_set_str(conf, CONF_remote_cmd2, ""); conf_set_bool(conf, CONF_nopty, true); /* command => no tty */ + strbuf_free(cmdbuf); break; /* done with cmdline */ } else { fprintf(stderr, "plink: unknown option \"%s\"\n", p);