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

Generalise strbuf_catf() into put_fmt().

marshal.h now provides a macro put_fmt() which allows you to write
arbitrary printf-formatted data to an arbitrary BinarySink.

We already had this facility for strbufs in particular, in the form of
strbuf_catf(). That was able to take advantage of knowing the inner
structure of a strbuf to minimise memory allocation (it would snprintf
directly into the strbuf's existing buffer if possible). For a general
black-box BinarySink we can't do that, so instead we dupvprintf into a
temporary buffer.

For consistency, I've removed strbuf_catf, and converted all uses of
it into the new put_fmt - and I've also added an extra vtable method
in the BinarySink API, so that put_fmt can still use strbuf_catf's
more efficient memory management when talking to a strbuf, and fall
back to the simpler strategy when that's not available.
This commit is contained in:
Simon Tatham 2021-11-19 10:23:32 +00:00
parent efee4e0eae
commit be8d3974ff
24 changed files with 217 additions and 193 deletions

View File

@ -684,11 +684,11 @@ static char *ecc_cache_str_shared(
strbuf *sb = strbuf_new();
if (curve_name)
strbuf_catf(sb, "%s,", curve_name);
put_fmt(sb, "%s,", curve_name);
char *hx = mp_get_hex(x);
char *hy = mp_get_hex(y);
strbuf_catf(sb, "0x%s,0x%s", hx, hy);
put_fmt(sb, "0x%s,0x%s", hx, hy);
sfree(hx);
sfree(hy);

View File

@ -42,20 +42,20 @@ static ssh2_mac *hmac_new(const ssh2_macalg *alg, ssh_cipher *cipher)
ctx->digest = snewn(ctx->hashalg->hlen, uint8_t);
ctx->text_name = strbuf_new();
strbuf_catf(ctx->text_name, "HMAC-%s%s",
ctx->hashalg->text_basename, extra->suffix);
put_fmt(ctx->text_name, "HMAC-%s%s",
ctx->hashalg->text_basename, extra->suffix);
if (extra->annotation || ctx->hashalg->annotation) {
strbuf_catf(ctx->text_name, " (");
put_fmt(ctx->text_name, " (");
const char *sep = "";
if (extra->annotation) {
strbuf_catf(ctx->text_name, "%s%s", sep, extra->annotation);
put_fmt(ctx->text_name, "%s%s", sep, extra->annotation);
sep = ", ";
}
if (ctx->hashalg->annotation) {
strbuf_catf(ctx->text_name, "%s%s", sep, ctx->hashalg->annotation);
put_fmt(ctx->text_name, "%s%s", sep, ctx->hashalg->annotation);
sep = ", ";
}
strbuf_catf(ctx->text_name, ")");
put_fmt(ctx->text_name, ")");
}
ctx->mac.vt = alg;

View File

@ -311,11 +311,11 @@ char *rsa_ssh1_fingerprint(RSAKey *key)
ssh_hash_final(hash, digest);
out = strbuf_new();
strbuf_catf(out, "%"SIZEu" ", mp_get_nbits(key->modulus));
put_fmt(out, "%"SIZEu" ", mp_get_nbits(key->modulus));
for (i = 0; i < 16; i++)
strbuf_catf(out, "%s%02x", i ? ":" : "", digest[i]);
put_fmt(out, "%s%02x", i ? ":" : "", digest[i]);
if (key->comment)
strbuf_catf(out, " %s", key->comment);
put_fmt(out, " %s", key->comment);
return strbuf_to_str(out);
}

View File

@ -410,10 +410,10 @@ strbuf *pockle_mpu(Pockle *pockle, mp_int *p)
memset(needed, 0, pockle->nlist * sizeof(bool));
needed[pr->index] = true;
strbuf_catf(sb, "[MPU - Primality Certificate]\nVersion 1.0\nBase 10\n\n"
"Proof for:\nN ");
put_fmt(sb, "[MPU - Primality Certificate]\nVersion 1.0\nBase 10\n\n"
"Proof for:\nN ");
mp_write_decimal(sb, p);
strbuf_catf(sb, "\n");
put_fmt(sb, "\n");
for (size_t index = pockle->nlist; index-- > 0 ;) {
if (!needed[index])
@ -421,27 +421,27 @@ strbuf *pockle_mpu(Pockle *pockle, mp_int *p)
pr = pockle->list[index];
if (mp_get_nbits(pr->prime) <= 64) {
strbuf_catf(sb, "\nType Small\nN ");
put_fmt(sb, "\nType Small\nN ");
mp_write_decimal(sb, pr->prime);
strbuf_catf(sb, "\n");
put_fmt(sb, "\n");
} else {
assert(pr->witness);
strbuf_catf(sb, "\nType BLS5\nN ");
put_fmt(sb, "\nType BLS5\nN ");
mp_write_decimal(sb, pr->prime);
strbuf_catf(sb, "\n");
put_fmt(sb, "\n");
for (size_t i = 0; i < pr->nfactors; i++) {
strbuf_catf(sb, "Q[%"SIZEu"] ", i+1);
put_fmt(sb, "Q[%"SIZEu"] ", i+1);
mp_write_decimal(sb, pr->factors[i]->prime);
assert(pr->factors[i]->index < index);
needed[pr->factors[i]->index] = true;
strbuf_catf(sb, "\n");
put_fmt(sb, "\n");
}
for (size_t i = 0; i < pr->nfactors + 1; i++) {
strbuf_catf(sb, "A[%"SIZEu"] ", i);
put_fmt(sb, "A[%"SIZEu"] ", i);
mp_write_decimal(sb, pr->witness);
strbuf_catf(sb, "\n");
put_fmt(sb, "\n");
}
strbuf_catf(sb, "----\n");
put_fmt(sb, "----\n");
}
}
sfree(needed);

View File

@ -4,6 +4,7 @@
#include "defs.h"
#include <stdio.h>
#include <stdarg.h>
/*
* A sort of 'abstract base class' or 'interface' or 'trait' which is
@ -12,6 +13,7 @@
*/
struct BinarySink {
void (*write)(BinarySink *sink, const void *data, size_t len);
void (*writefmtv)(BinarySink *sink, const char *fmt, va_list ap);
BinarySink *binarysink_;
};
@ -25,6 +27,7 @@ struct BinarySink {
#define BinarySink_IMPLEMENTATION BinarySink binarysink_[1]
#define BinarySink_INIT(obj, writefn) \
((obj)->binarysink_->write = (writefn), \
(obj)->binarysink_->writefmtv = NULL, \
(obj)->binarysink_->binarysink_ = (obj)->binarysink_)
/*
@ -139,6 +142,12 @@ struct BinarySink {
#define put_datapl(bs, pl) \
BinarySink_put_datapl(BinarySink_UPCAST(bs), pl)
/* Emit printf-formatted data, with no terminator. */
#define put_fmt(bs, ...) \
BinarySink_put_fmt(BinarySink_UPCAST(bs), __VA_ARGS__)
#define put_fmtv(bs, fmt, ap) \
BinarySink_put_fmtv(BinarySink_UPCAST(bs), fmt, ap)
/*
* The underlying real C functions that implement most of those
* macros. Generally you won't want to call these directly, because
@ -166,6 +175,8 @@ void BinarySink_put_asciz(BinarySink *, const char *str);
bool BinarySink_put_pstring(BinarySink *, const char *str);
void BinarySink_put_mp_ssh1(BinarySink *bs, mp_int *x);
void BinarySink_put_mp_ssh2(BinarySink *bs, mp_int *x);
void BinarySink_put_fmt(BinarySink *, const char *fmt, ...) PRINTF_LIKE(2, 3);
void BinarySink_put_fmtv(BinarySink *, const char *fmt, va_list ap);
/* ---------------------------------------------------------------------- */

2
misc.h
View File

@ -56,8 +56,6 @@ void *strbuf_append(strbuf *buf, size_t len);
void strbuf_shrink_to(strbuf *buf, size_t new_len);
void strbuf_shrink_by(strbuf *buf, size_t amount_to_remove);
char *strbuf_to_str(strbuf *buf); /* does free buf, but you must free result */
void strbuf_catf(strbuf *buf, const char *fmt, ...) PRINTF_LIKE(2, 3);
void strbuf_catfv(strbuf *buf, const char *fmt, va_list ap);
static inline void strbuf_clear(strbuf *buf) { strbuf_shrink_to(buf, 0); }
bool strbuf_chomp(strbuf *buf, char char_to_remove);

View File

@ -289,7 +289,7 @@ static void do_argsdone(Supdup *supdup, strbuf *outbuf, int c)
*/
// We only care about the new position.
strbuf_catf(outbuf, "\033[%d;%dH", supdup->td_args[2]+1, supdup->td_args[3]+1);
put_fmt(outbuf, "\033[%d;%dH", supdup->td_args[2]+1, supdup->td_args[3]+1);
break;
case TDMV0:
@ -298,7 +298,7 @@ static void do_argsdone(Supdup *supdup, strbuf *outbuf, int c)
General cursor position code. Followed by two bytes;
the new vertical and horizontal positions.
*/
strbuf_catf(outbuf, "\033[%d;%dH", supdup->td_args[0]+1, supdup->td_args[1]+1);
put_fmt(outbuf, "\033[%d;%dH", supdup->td_args[0]+1, supdup->td_args[1]+1);
break;
case TDEOF:
@ -312,7 +312,7 @@ static void do_argsdone(Supdup *supdup, strbuf *outbuf, int c)
lines lower on the screen than the cursor. The cursor
does not move.
*/
strbuf_catf(outbuf, "\033[J");
put_fmt(outbuf, "\033[J");
break;
case TDEOL:
@ -321,7 +321,7 @@ static void do_argsdone(Supdup *supdup, strbuf *outbuf, int c)
position the cursor is at and all positions to the right
on the same line. The cursor does not move.
*/
strbuf_catf(outbuf, "\033[K");
put_fmt(outbuf, "\033[K");
break;
case TDDLF:
@ -329,7 +329,7 @@ static void do_argsdone(Supdup *supdup, strbuf *outbuf, int c)
Clear the character position the cursor is on. The
cursor does not move.
*/
strbuf_catf(outbuf, "\033[X");
put_fmt(outbuf, "\033[X");
break;
case TDCRL:
@ -339,7 +339,7 @@ static void do_argsdone(Supdup *supdup, strbuf *outbuf, int c)
that line. If the cursor is at the bottom line, scroll
up.
*/
strbuf_catf(outbuf, "\015\012");
put_fmt(outbuf, "\015\012");
break;
case TDNOP:
@ -383,7 +383,7 @@ static void do_argsdone(Supdup *supdup, strbuf *outbuf, int c)
line.
*/
strbuf_catf(outbuf, "\033[C");
put_fmt(outbuf, "\033[C");
break;
case TDCLR:
@ -391,7 +391,7 @@ static void do_argsdone(Supdup *supdup, strbuf *outbuf, int c)
Erase the screen. Home the cursor to the top left hand
corner of the screen.
*/
strbuf_catf(outbuf, "\033[2J\033[H");
put_fmt(outbuf, "\033[2J\033[H");
break;
case TDBEL:
@ -399,7 +399,7 @@ static void do_argsdone(Supdup *supdup, strbuf *outbuf, int c)
Generate an audio tone, bell, whatever.
*/
strbuf_catf(outbuf, "\007");
put_fmt(outbuf, "\007");
break;
case TDILP:
@ -410,7 +410,7 @@ static void do_argsdone(Supdup *supdup, strbuf *outbuf, int c)
on and all lines below it move down; lines moved off the
bottom of the screen are lost.
*/
strbuf_catf(outbuf, "\033[%dL", supdup->td_args[0]);
put_fmt(outbuf, "\033[%dL", supdup->td_args[0]);
break;
case TDDLP:
@ -421,7 +421,7 @@ static void do_argsdone(Supdup *supdup, strbuf *outbuf, int c)
Newly- created lines at the bottom of the screen are
blank.
*/
strbuf_catf(outbuf, "\033[%dM", supdup->td_args[0]);
put_fmt(outbuf, "\033[%dM", supdup->td_args[0]);
break;
case TDICP:
@ -432,7 +432,7 @@ static void do_argsdone(Supdup *supdup, strbuf *outbuf, int c)
current line move to the right; characters moved off the
end of the line are lost.
*/
strbuf_catf(outbuf, "\033[%d@", supdup->td_args[0]);
put_fmt(outbuf, "\033[%d@", supdup->td_args[0]);
break;
case TDDCP:
@ -442,7 +442,7 @@ static void do_argsdone(Supdup *supdup, strbuf *outbuf, int c)
the one the cursor is on. Newly-created characters at
the end of the line are blank.
*/
strbuf_catf(outbuf, "\033[%dP", supdup->td_args[0]);
put_fmt(outbuf, "\033[%dP", supdup->td_args[0]);
break;
case TDBOW:

View File

@ -1369,7 +1369,7 @@ char *format_telnet_command(SockAddr *addr, int port, Conf *conf)
eo += 4;
}
else if (strnicmp(fmt + eo, "port", 4) == 0) {
strbuf_catf(buf, "%d", port);
put_fmt(buf, "%d", port);
eo += 4;
}
else if (strnicmp(fmt + eo, "user", 4) == 0) {
@ -1389,7 +1389,7 @@ char *format_telnet_command(SockAddr *addr, int port, Conf *conf)
}
else if (strnicmp(fmt + eo, "proxyport", 9) == 0) {
int port = conf_get_int(conf, CONF_proxy_port);
strbuf_catf(buf, "%d", port);
put_fmt(buf, "%d", port);
eo += 9;
}
else {

View File

@ -536,7 +536,7 @@ static void scp_source_send_E(ScpSource *scp)
assert(scp->n_pending_commands == 0);
scp->pending_commands[scp->n_pending_commands++] = cmd = strbuf_new();
strbuf_catf(cmd, "E\012");
put_fmt(cmd, "E\012");
}
static void scp_source_send_CD(
@ -550,7 +550,7 @@ static void scp_source_send_CD(
if (scp->send_file_times && (attrs.flags & SSH_FILEXFER_ATTR_ACMODTIME)) {
scp->pending_commands[scp->n_pending_commands++] = cmd = strbuf_new();
/* Our SFTP-based filesystem API doesn't support microsecond times */
strbuf_catf(cmd, "T%lu 0 %lu 0\012", attrs.mtime, attrs.atime);
put_fmt(cmd, "T%lu 0 %lu 0\012", attrs.mtime, attrs.atime);
}
const char *slash;
@ -559,9 +559,9 @@ static void scp_source_send_CD(
slash+1, name.len - (slash+1 - (const char *)name.ptr));
scp->pending_commands[scp->n_pending_commands++] = cmd = strbuf_new();
strbuf_catf(cmd, "%c%04o %"PRIu64" %.*s\012", cmdchar,
(unsigned)(attrs.permissions & 07777),
size, PTRLEN_PRINTF(name));
put_fmt(cmd, "%c%04o %"PRIu64" %.*s\012", cmdchar,
(unsigned)(attrs.permissions & 07777),
size, PTRLEN_PRINTF(name));
if (cmdchar == 'C') {
/* We'll also wait for an ack before sending the file data,

View File

@ -1550,33 +1550,33 @@ strbuf *ppk_save_sb(ssh2_userkey *key, const char *passphrase,
}
strbuf *out = strbuf_new_nm();
strbuf_catf(out, "PuTTY-User-Key-File-%u: %s\n",
params.fmt_version, ssh_key_ssh_id(key->key));
strbuf_catf(out, "Encryption: %s\n", cipherstr);
strbuf_catf(out, "Comment: %s\n", key->comment);
strbuf_catf(out, "Public-Lines: %d\n", base64_lines(pub_blob->len));
put_fmt(out, "PuTTY-User-Key-File-%u: %s\n",
params.fmt_version, ssh_key_ssh_id(key->key));
put_fmt(out, "Encryption: %s\n", cipherstr);
put_fmt(out, "Comment: %s\n", key->comment);
put_fmt(out, "Public-Lines: %d\n", base64_lines(pub_blob->len));
base64_encode_s(BinarySink_UPCAST(out), pub_blob->u, pub_blob->len, 64);
if (params.fmt_version == 3 && ciphertype->keylen != 0) {
strbuf_catf(out, "Key-Derivation: %s\n",
params.argon2_flavour == Argon2d ? "Argon2d" :
params.argon2_flavour == Argon2i ? "Argon2i" : "Argon2id");
strbuf_catf(out, "Argon2-Memory: %"PRIu32"\n", params.argon2_mem);
put_fmt(out, "Key-Derivation: %s\n",
params.argon2_flavour == Argon2d ? "Argon2d" :
params.argon2_flavour == Argon2i ? "Argon2i" : "Argon2id");
put_fmt(out, "Argon2-Memory: %"PRIu32"\n", params.argon2_mem);
assert(!params.argon2_passes_auto);
strbuf_catf(out, "Argon2-Passes: %"PRIu32"\n", params.argon2_passes);
strbuf_catf(out, "Argon2-Parallelism: %"PRIu32"\n",
params.argon2_parallelism);
strbuf_catf(out, "Argon2-Salt: ");
put_fmt(out, "Argon2-Passes: %"PRIu32"\n", params.argon2_passes);
put_fmt(out, "Argon2-Parallelism: %"PRIu32"\n",
params.argon2_parallelism);
put_fmt(out, "Argon2-Salt: ");
for (size_t i = 0; i < passphrase_salt->len; i++)
strbuf_catf(out, "%02x", passphrase_salt->u[i]);
strbuf_catf(out, "\n");
put_fmt(out, "%02x", passphrase_salt->u[i]);
put_fmt(out, "\n");
}
strbuf_catf(out, "Private-Lines: %d\n", base64_lines(priv_encrypted_len));
put_fmt(out, "Private-Lines: %d\n", base64_lines(priv_encrypted_len));
base64_encode_s(BinarySink_UPCAST(out),
priv_blob_encrypted, priv_encrypted_len, 64);
strbuf_catf(out, "Private-MAC: ");
put_fmt(out, "Private-MAC: ");
for (i = 0; i < macalg->len; i++)
strbuf_catf(out, "%02x", priv_mac[i]);
strbuf_catf(out, "\n");
put_fmt(out, "%02x", priv_mac[i]);
put_fmt(out, "\n");
strbuf_free(cipher_mac_keys_blob);
strbuf_free(passphrase_salt);
@ -1740,7 +1740,7 @@ static void ssh2_fingerprint_blob_md5(ptrlen blob, strbuf *sb)
hash_simple(&ssh_md5, blob, digest);
for (unsigned i = 0; i < 16; i++)
strbuf_catf(sb, "%02x%s", digest[i], i==15 ? "" : ":");
put_fmt(sb, "%02x%s", digest[i], i==15 ? "" : ":");
}
static void ssh2_fingerprint_blob_sha256(ptrlen blob, strbuf *sb)
@ -1778,9 +1778,9 @@ char *ssh2_fingerprint_blob(ptrlen blob, FingerprintType fptype)
const ssh_keyalg *alg = find_pubkey_alg_len(algname);
if (alg) {
int bits = ssh_key_public_bits(alg, blob);
strbuf_catf(sb, "%.*s %d ", PTRLEN_PRINTF(algname), bits);
put_fmt(sb, "%.*s %d ", PTRLEN_PRINTF(algname), bits);
} else {
strbuf_catf(sb, "%.*s ", PTRLEN_PRINTF(algname));
put_fmt(sb, "%.*s ", PTRLEN_PRINTF(algname));
}
}

View File

@ -592,7 +592,7 @@ static struct mpint_list get_mpint_list(BinarySource *in)
static void finaliser_return_uint(strbuf *out, void *ctx)
{
unsigned *uval = (unsigned *)ctx;
strbuf_catf(out, "%u\n", *uval);
put_fmt(out, "%u\n", *uval);
sfree(uval);
}
@ -620,7 +620,7 @@ static void finaliser_return_opt_string_asciz(strbuf *out, void *ctx)
char *val = *valp;
sfree(valp);
if (!val)
strbuf_catf(out, "NULL\n");
put_fmt(out, "NULL\n");
else
return_val_string_asciz(out, val);
}
@ -639,7 +639,7 @@ static void finaliser_return_opt_string_asciz_const(strbuf *out, void *ctx)
const char *val = *valp;
sfree(valp);
if (!val)
strbuf_catf(out, "NULL\n");
put_fmt(out, "NULL\n");
else
return_val_string_asciz_const(out, val);
}
@ -676,29 +676,29 @@ GET_CONSUMED_FN(pcs)
static void return_int(strbuf *out, intmax_t u)
{
strbuf_catf(out, "%"PRIdMAX"\n", u);
put_fmt(out, "%"PRIdMAX"\n", u);
}
static void return_uint(strbuf *out, uintmax_t u)
{
strbuf_catf(out, "0x%"PRIXMAX"\n", u);
put_fmt(out, "0x%"PRIXMAX"\n", u);
}
static void return_boolean(strbuf *out, bool b)
{
strbuf_catf(out, "%s\n", b ? "true" : "false");
put_fmt(out, "%s\n", b ? "true" : "false");
}
static void return_pocklestatus(strbuf *out, PockleStatus status)
{
switch (status) {
default:
strbuf_catf(out, "POCKLE_BAD_STATUS_VALUE\n");
put_fmt(out, "POCKLE_BAD_STATUS_VALUE\n");
break;
#define STATUS_CASE(id) \
case id: \
strbuf_catf(out, "%s\n", #id); \
put_fmt(out, "%s\n", #id); \
break;
POCKLE_STATUSES(STATUS_CASE);
@ -711,11 +711,11 @@ static void return_pocklestatus(strbuf *out, PockleStatus status)
static void return_mr_result(strbuf *out, struct mr_result result)
{
if (!result.passed)
strbuf_catf(out, "failed\n");
put_fmt(out, "failed\n");
else if (!result.potential_primitive_root)
strbuf_catf(out, "passed\n");
put_fmt(out, "passed\n");
else
strbuf_catf(out, "passed+ppr\n");
put_fmt(out, "passed+ppr\n");
}
static void return_val_string_asciz_const(strbuf *out, const char *s)
@ -735,7 +735,7 @@ static void return_val_string_asciz(strbuf *out, char *s)
static void return_opt_##type_name(strbuf *out, c_type ptr) \
{ \
if (!ptr) \
strbuf_catf(out, "NULL\n"); \
put_fmt(out, "NULL\n"); \
else \
return_##type_name(out, ptr); \
}
@ -750,7 +750,7 @@ NULLABLE_RETURN_WRAPPER(val_mpint, mp_int *)
static void handle_hello(BinarySource *in, strbuf *out)
{
strbuf_catf(out, "hello, world\n");
put_fmt(out, "hello, world\n");
}
static void rsa_free(RSAKey *rsa)
@ -803,7 +803,7 @@ static void handle_getstring(BinarySource *in, strbuf *out)
if (c > ' ' && c < 0x7F && c != '%') {
put_byte(out, c);
} else {
strbuf_catf(out, "%%%02X", 0xFFU & (unsigned)c);
put_fmt(out, "%%%02X", 0xFFU & (unsigned)c);
}
}
put_byte(out, '\n');
@ -822,7 +822,7 @@ static void handle_mp_dump(BinarySource *in, strbuf *out)
{
mp_int *mp = get_val_mpint(in);
for (size_t i = mp_max_bytes(mp); i-- > 0 ;)
strbuf_catf(out, "%02X", mp_get_byte(mp, i));
put_fmt(out, "%02X", mp_get_byte(mp, i));
put_byte(out, '\n');
}
@ -1320,26 +1320,26 @@ strbuf *get_implementations_commasep(ptrlen alg)
put_datapl(out, alg);
if (ptrlen_startswith(alg, PTRLEN_LITERAL("aes"), NULL)) {
strbuf_catf(out, ",%.*s_sw", PTRLEN_PRINTF(alg));
put_fmt(out, ",%.*s_sw", PTRLEN_PRINTF(alg));
#if HAVE_AES_NI
strbuf_catf(out, ",%.*s_ni", PTRLEN_PRINTF(alg));
put_fmt(out, ",%.*s_ni", PTRLEN_PRINTF(alg));
#endif
#if HAVE_NEON_CRYPTO
strbuf_catf(out, ",%.*s_neon", PTRLEN_PRINTF(alg));
put_fmt(out, ",%.*s_neon", PTRLEN_PRINTF(alg));
#endif
} else if (ptrlen_startswith(alg, PTRLEN_LITERAL("sha256"), NULL) ||
ptrlen_startswith(alg, PTRLEN_LITERAL("sha1"), NULL)) {
strbuf_catf(out, ",%.*s_sw", PTRLEN_PRINTF(alg));
put_fmt(out, ",%.*s_sw", PTRLEN_PRINTF(alg));
#if HAVE_SHA_NI
strbuf_catf(out, ",%.*s_ni", PTRLEN_PRINTF(alg));
put_fmt(out, ",%.*s_ni", PTRLEN_PRINTF(alg));
#endif
#if HAVE_NEON_CRYPTO
strbuf_catf(out, ",%.*s_neon", PTRLEN_PRINTF(alg));
put_fmt(out, ",%.*s_neon", PTRLEN_PRINTF(alg));
#endif
} else if (ptrlen_startswith(alg, PTRLEN_LITERAL("sha512"), NULL)) {
strbuf_catf(out, ",%.*s_sw", PTRLEN_PRINTF(alg));
put_fmt(out, ",%.*s_sw", PTRLEN_PRINTF(alg));
#if HAVE_NEON_SHA512
strbuf_catf(out, ",%.*s_neon", PTRLEN_PRINTF(alg));
put_fmt(out, ",%.*s_neon", PTRLEN_PRINTF(alg));
#endif
}

View File

@ -3615,12 +3615,12 @@ int gtk_seat_confirm_ssh_host_key(
strbuf *sb = strbuf_new();
if (fingerprints[SSH_FPTYPE_SHA256])
strbuf_catf(sb, "SHA256 fingerprint: %s\n",
fingerprints[SSH_FPTYPE_SHA256]);
put_fmt(sb, "SHA256 fingerprint: %s\n",
fingerprints[SSH_FPTYPE_SHA256]);
if (fingerprints[SSH_FPTYPE_MD5])
strbuf_catf(sb, "MD5 fingerprint: %s\n",
fingerprints[SSH_FPTYPE_MD5]);
strbuf_catf(sb, "Full text of host's public key:");
put_fmt(sb, "MD5 fingerprint: %s\n",
fingerprints[SSH_FPTYPE_MD5]);
put_fmt(sb, "Full text of host's public key:");
/* We have to manually wrap the public key, or else the GtkLabel
* will resize itself to accommodate the longest word, which will
* lead to a hilariously wide message box. */
@ -3943,12 +3943,12 @@ static void eventlog_list_handler(union control *ctrl, dlgparam *dp,
strbuf_clear(es->seldata);
for (i = 0; i < es->ninitial; i++) {
if (dlg_listbox_issel(ctrl, dp, i))
strbuf_catf(es->seldata, "%s\n", es->events_initial[i]);
put_fmt(es->seldata, "%s\n", es->events_initial[i]);
}
for (i = 0; i < es->ncircular; i++) {
if (dlg_listbox_issel(ctrl, dp, es->ninitial + i)) {
int j = (es->circular_first + i) % LOGEVENT_CIRCULAR_MAX;
strbuf_catf(es->seldata, "%s\n", es->events_circular[j]);
put_fmt(es->seldata, "%s\n", es->events_circular[j]);
}
}

View File

@ -232,9 +232,9 @@ SockAddr *sk_namelookup(const char *host, char **canonicalname, int address_fami
ret->superfamily = IP;
if (ret->ais->ai_canonname != NULL)
strbuf_catf(realhost, "%s", ret->ais->ai_canonname);
put_fmt(realhost, "%s", ret->ais->ai_canonname);
else
strbuf_catf(realhost, "%s", host);
put_fmt(realhost, "%s", host);
#else
if ((a = inet_addr(host)) == (unsigned long)(in_addr_t)(-1)) {
/*
@ -258,7 +258,7 @@ SockAddr *sk_namelookup(const char *host, char **canonicalname, int address_fami
}
/* This way we are always sure the h->h_name is valid :) */
strbuf_clear(realhost);
strbuf_catf(realhost, "%s", h->h_name);
put_fmt(realhost, "%s", h->h_name);
for (n = 0; h->h_addr_list[n]; n++);
ret->addresses = snewn(n, unsigned long);
ret->naddresses = n;
@ -273,7 +273,7 @@ SockAddr *sk_namelookup(const char *host, char **canonicalname, int address_fami
*/
ret->superfamily = IP;
strbuf_clear(realhost);
strbuf_catf(realhost, "%s", host);
put_fmt(realhost, "%s", host);
ret->addresses = snew(unsigned long);
ret->naddresses = 1;
ret->addresses[0] = ntohl(a);

View File

@ -170,8 +170,8 @@ static char *format_sockaddr(const void *addr, int family)
const uint32_t *addrwords = (const uint32_t *)a->sin6_addr.s6_addr;
for (int i = 0; i < 4; i++)
strbuf_catf(sb, "%08X", addrwords[i]);
strbuf_catf(sb, ":%04X", ntohs(a->sin6_port));
put_fmt(sb, "%08X", addrwords[i]);
put_fmt(sb, ":%04X", ntohs(a->sin6_port));
return strbuf_to_str(sb);
} else {

View File

@ -173,7 +173,7 @@ static char *make_filename(int index, const char *subname)
if (index == INDEX_SESSION) {
strbuf *sb = strbuf_new();
tmp = make_filename(INDEX_SESSIONDIR, NULL);
strbuf_catf(sb, "%s/", tmp);
put_fmt(sb, "%s/", tmp);
sfree(tmp);
make_session_filename(subname, sb);
return strbuf_to_str(sb);

View File

@ -1904,19 +1904,19 @@ static void pangofont_enum_fonts(GtkWidget *widget, fontsel_add_entry callback,
/* Weight: normal, then lighter, then bolder */
if (weight <= PANGO_WEIGHT_NORMAL)
weight = PANGO_WEIGHT_NORMAL - weight;
strbuf_catf(buf, "%4d", weight);
put_fmt(buf, "%4d", weight);
strbuf_catf(buf, " %2d",
pango_font_description_get_style(desc));
put_fmt(buf, " %2d",
pango_font_description_get_style(desc));
int stretch = pango_font_description_get_stretch(desc);
/* Stretch: closer to normal sorts earlier */
stretch = 2 * abs(PANGO_STRETCH_NORMAL - stretch) +
(stretch < PANGO_STRETCH_NORMAL);
strbuf_catf(buf, " %2d", stretch);
put_fmt(buf, " %2d", stretch);
strbuf_catf(buf, " %2d",
pango_font_description_get_variant(desc));
put_fmt(buf, " %2d",
pango_font_description_get_variant(desc));
stylekey = strbuf_to_str(buf);
}

View File

@ -18,7 +18,7 @@ void seat_antispoof_msg(InteractionReadySeat iseat, const char *msg)
* wouldn't be able to mimic it within our line-length
* constraint.
*/
strbuf_catf(sb, "-- %s ", msg);
put_fmt(sb, "-- %s ", msg);
while (sb->len < 78)
put_byte(sb, '-');
}

View File

@ -10,26 +10,25 @@ char *buildinfo(const char *newline)
{
strbuf *buf = strbuf_new();
strbuf_catf(buf, "Build platform: %d-bit %s",
(int)(CHAR_BIT * sizeof(void *)),
BUILDINFO_PLATFORM);
put_fmt(buf, "Build platform: %d-bit %s",
(int)(CHAR_BIT * sizeof(void *)), BUILDINFO_PLATFORM);
#ifdef __clang_version__
#define FOUND_COMPILER
strbuf_catf(buf, "%sCompiler: clang %s", newline, __clang_version__);
put_fmt(buf, "%sCompiler: clang %s", newline, __clang_version__);
#elif defined __GNUC__ && defined __VERSION__
#define FOUND_COMPILER
strbuf_catf(buf, "%sCompiler: gcc %s", newline, __VERSION__);
put_fmt(buf, "%sCompiler: gcc %s", newline, __VERSION__);
#endif
#if defined _MSC_VER
#ifndef FOUND_COMPILER
#define FOUND_COMPILER
strbuf_catf(buf, "%sCompiler: ", newline);
put_fmt(buf, "%sCompiler: ", newline);
#else
strbuf_catf(buf, ", emulating ");
put_fmt(buf, ", emulating ");
#endif
strbuf_catf(buf, "Visual Studio");
put_fmt(buf, "Visual Studio");
#if 0
/*
@ -51,69 +50,69 @@ char *buildinfo(const char *newline)
* 19.28.29500.* and going up. Hence, 19 28 29500 is what we
* compare _MSC_FULL_VER against above.
*/
strbuf_catf(buf, " 2019 (16.9)");
put_fmt(buf, " 2019 (16.9)");
#elif _MSC_VER == 1928
strbuf_catf(buf, " 2019 (16.8)");
put_fmt(buf, " 2019 (16.8)");
#elif _MSC_VER == 1927
strbuf_catf(buf, " 2019 (16.7)");
put_fmt(buf, " 2019 (16.7)");
#elif _MSC_VER == 1926
strbuf_catf(buf, " 2019 (16.6)");
put_fmt(buf, " 2019 (16.6)");
#elif _MSC_VER == 1925
strbuf_catf(buf, " 2019 (16.5)");
put_fmt(buf, " 2019 (16.5)");
#elif _MSC_VER == 1924
strbuf_catf(buf, " 2019 (16.4)");
put_fmt(buf, " 2019 (16.4)");
#elif _MSC_VER == 1923
strbuf_catf(buf, " 2019 (16.3)");
put_fmt(buf, " 2019 (16.3)");
#elif _MSC_VER == 1922
strbuf_catf(buf, " 2019 (16.2)");
put_fmt(buf, " 2019 (16.2)");
#elif _MSC_VER == 1921
strbuf_catf(buf, " 2019 (16.1)");
put_fmt(buf, " 2019 (16.1)");
#elif _MSC_VER == 1920
strbuf_catf(buf, " 2019 (16.0)");
put_fmt(buf, " 2019 (16.0)");
#elif _MSC_VER == 1916
strbuf_catf(buf, " 2017 version 15.9");
put_fmt(buf, " 2017 version 15.9");
#elif _MSC_VER == 1915
strbuf_catf(buf, " 2017 version 15.8");
put_fmt(buf, " 2017 version 15.8");
#elif _MSC_VER == 1914
strbuf_catf(buf, " 2017 version 15.7");
put_fmt(buf, " 2017 version 15.7");
#elif _MSC_VER == 1913
strbuf_catf(buf, " 2017 version 15.6");
put_fmt(buf, " 2017 version 15.6");
#elif _MSC_VER == 1912
strbuf_catf(buf, " 2017 version 15.5");
put_fmt(buf, " 2017 version 15.5");
#elif _MSC_VER == 1911
strbuf_catf(buf, " 2017 version 15.3");
put_fmt(buf, " 2017 version 15.3");
#elif _MSC_VER == 1910
strbuf_catf(buf, " 2017 RTW (15.0)");
put_fmt(buf, " 2017 RTW (15.0)");
#elif _MSC_VER == 1900
strbuf_catf(buf, " 2015 (14.0)");
put_fmt(buf, " 2015 (14.0)");
#elif _MSC_VER == 1800
strbuf_catf(buf, " 2013 (12.0)");
put_fmt(buf, " 2013 (12.0)");
#elif _MSC_VER == 1700
strbuf_catf(buf, " 2012 (11.0)");
put_fmt(buf, " 2012 (11.0)");
#elif _MSC_VER == 1600
strbuf_catf(buf, " 2010 (10.0)");
put_fmt(buf, " 2010 (10.0)");
#elif _MSC_VER == 1500
strbuf_catf(buf, " 2008 (9.0)");
put_fmt(buf, " 2008 (9.0)");
#elif _MSC_VER == 1400
strbuf_catf(buf, " 2005 (8.0)");
put_fmt(buf, " 2005 (8.0)");
#elif _MSC_VER == 1310
strbuf_catf(buf, " .NET 2003 (7.1)");
put_fmt(buf, " .NET 2003 (7.1)");
#elif _MSC_VER == 1300
strbuf_catf(buf, " .NET 2002 (7.0)");
put_fmt(buf, " .NET 2002 (7.0)");
#elif _MSC_VER == 1200
strbuf_catf(buf, " 6.0");
put_fmt(buf, " 6.0");
#else
strbuf_catf(buf, ", unrecognised version");
put_fmt(buf, ", unrecognised version");
#endif
strbuf_catf(buf, ", _MSC_VER=%d", (int)_MSC_VER);
put_fmt(buf, ", _MSC_VER=%d", (int)_MSC_VER);
#endif
#ifdef BUILDINFO_GTK
{
char *gtk_buildinfo = buildinfo_gtk_version();
if (gtk_buildinfo) {
strbuf_catf(buf, "%sCompiled against GTK version %s",
newline, gtk_buildinfo);
put_fmt(buf, "%sCompiled against GTK version %s",
newline, gtk_buildinfo);
sfree(gtk_buildinfo);
}
}
@ -122,34 +121,34 @@ char *buildinfo(const char *newline)
{
int echm = has_embedded_chm();
if (echm >= 0)
strbuf_catf(buf, "%sEmbedded HTML Help file: %s", newline,
echm ? "yes" : "no");
put_fmt(buf, "%sEmbedded HTML Help file: %s", newline,
echm ? "yes" : "no");
}
#endif
#if defined _WINDOWS && defined MINEFIELD
strbuf_catf(buf, "%sBuild option: MINEFIELD", newline);
put_fmt(buf, "%sBuild option: MINEFIELD", newline);
#endif
#ifdef NO_IPV6
strbuf_catf(buf, "%sBuild option: NO_IPV6", newline);
put_fmt(buf, "%sBuild option: NO_IPV6", newline);
#endif
#ifdef NO_GSSAPI
strbuf_catf(buf, "%sBuild option: NO_GSSAPI", newline);
put_fmt(buf, "%sBuild option: NO_GSSAPI", newline);
#endif
#ifdef STATIC_GSSAPI
strbuf_catf(buf, "%sBuild option: STATIC_GSSAPI", newline);
put_fmt(buf, "%sBuild option: STATIC_GSSAPI", newline);
#endif
#ifdef UNPROTECT
strbuf_catf(buf, "%sBuild option: UNPROTECT", newline);
put_fmt(buf, "%sBuild option: UNPROTECT", newline);
#endif
#ifdef FUZZING
strbuf_catf(buf, "%sBuild option: FUZZING", newline);
put_fmt(buf, "%sBuild option: FUZZING", newline);
#endif
#ifdef DEBUG
strbuf_catf(buf, "%sBuild option: DEBUG", newline);
put_fmt(buf, "%sBuild option: DEBUG", newline);
#endif
strbuf_catf(buf, "%sSource commit: %s", newline, commitid);
put_fmt(buf, "%sSource commit: %s", newline, commitid);
return strbuf_to_str(buf);
}

View File

@ -1,4 +1,5 @@
#include <assert.h>
#include <stdarg.h>
#include <stddef.h>
#include <string.h>
@ -99,6 +100,25 @@ bool BinarySink_put_pstring(BinarySink *bs, const char *str)
return true;
}
void BinarySink_put_fmtv(BinarySink *bs, const char *fmt, va_list ap)
{
if (bs->writefmtv) {
bs->writefmtv(bs, fmt, ap);
} else {
char *str = dupvprintf(fmt, ap);
bs->write(bs, str, strlen(str));
burnstr(str);
}
}
void BinarySink_put_fmt(BinarySink *bs, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
BinarySink_put_fmtv(bs, fmt, ap);
va_end(ap);
}
/* ---------------------------------------------------------------------- */
static bool BinarySource_data_avail(BinarySource *src, size_t wanted)

View File

@ -60,10 +60,21 @@ static void strbuf_BinarySink_write(
memcpy(strbuf_append(buf_o, len), data, len);
}
static void strbuf_BinarySink_writefmtv(
BinarySink *bs, const char *fmt, va_list ap)
{
strbuf *buf_o = BinarySink_DOWNCAST(bs, strbuf);
struct strbuf_impl *buf = container_of(buf_o, struct strbuf_impl, visible);
STRBUF_SET_PTR(buf, dupvprintf_inner(buf->visible.s, buf->visible.len,
&buf->size, fmt, ap));
buf->visible.len += strlen(buf->visible.s + buf->visible.len);
}
static strbuf *strbuf_new_general(bool nm)
{
struct strbuf_impl *buf = snew(struct strbuf_impl);
BinarySink_INIT(&buf->visible, strbuf_BinarySink_write);
buf->visible.binarysink_->writefmtv = strbuf_BinarySink_writefmtv;
buf->visible.len = 0;
buf->size = 512;
buf->nm = nm;
@ -89,21 +100,6 @@ char *strbuf_to_str(strbuf *buf_o)
sfree(buf);
return ret;
}
void strbuf_catfv(strbuf *buf_o, const char *fmt, va_list ap)
{
struct strbuf_impl *buf = container_of(buf_o, struct strbuf_impl, visible);
STRBUF_SET_PTR(buf, dupvprintf_inner(buf->visible.s, buf->visible.len,
&buf->size, fmt, ap));
buf->visible.len += strlen(buf->visible.s + buf->visible.len);
}
void strbuf_catf(strbuf *buf_o, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
strbuf_catfv(buf_o, fmt, ap);
va_end(ap);
}
strbuf *strbuf_new_for_agent_query(void)
{
strbuf *buf = strbuf_new();

View File

@ -335,7 +335,7 @@ static void keylist_update_callback(
switch (key->ssh_version) {
case 1: {
strbuf_catf(listentry, "ssh1\t%s\t%s", fingerprint, comment);
put_fmt(listentry, "ssh1\t%s\t%s", fingerprint, comment);
/*
* Replace the space in the fingerprint (between bit count and
@ -390,15 +390,15 @@ static void keylist_update_callback(
put_byte(listentry, c);
}
strbuf_catf(listentry, "\t%s", comment);
put_fmt(listentry, "\t%s", comment);
break;
}
}
if (ext_flags & LIST_EXTENDED_FLAG_HAS_NO_CLEARTEXT_KEY) {
strbuf_catf(listentry, "\t(encrypted)");
put_fmt(listentry, "\t(encrypted)");
} else if (ext_flags & LIST_EXTENDED_FLAG_HAS_ENCRYPTED_KEY_FILE) {
strbuf_catf(listentry, "\t(re-encryptable)");
put_fmt(listentry, "\t(re-encryptable)");
/* At least one key can be re-encrypted */
ctx->enable_reencrypt_controls = true;

View File

@ -318,7 +318,7 @@ void enum_settings_finish(settings_e *e)
static void hostkey_regname(strbuf *sb, const char *hostname,
int port, const char *keytype)
{
strbuf_catf(sb, "%s@%d:", keytype, port);
put_fmt(sb, "%s@%d:", keytype, port);
escape_registry_key(hostname, sb);
}

View File

@ -514,7 +514,7 @@ int main(int argc, char **argv)
strbuf *cmdline = strbuf_new();
char *p;
strbuf_catf(cmdline, "%s -splat ", argv[0]);
put_fmt(cmdline, "%s -splat ", argv[0]);
printf(" {\"");
size_t args_start = cmdline->len;
for (p = argv[2]; *p; p++) {

View File

@ -4946,7 +4946,7 @@ static void wintw_clip_write(
get_unitab(CP_ACP, unitab, 0);
strbuf_catf(
put_fmt(
rtf, "{\\rtf1\\ansi\\deff0{\\fonttbl\\f0\\fmodern %s;}\\f0\\fs%d",
font->name, font->height*2);
@ -5034,16 +5034,16 @@ static void wintw_clip_write(
for (i = 0; i < OSC4_NCOLOURS; i++) {
if (palette[i] != 0) {
const PALETTEENTRY *pe = &logpal->palPalEntry[i];
strbuf_catf(rtf, "\\red%d\\green%d\\blue%d;",
pe->peRed, pe->peGreen, pe->peBlue);
put_fmt(rtf, "\\red%d\\green%d\\blue%d;",
pe->peRed, pe->peGreen, pe->peBlue);
}
}
if (rgbtree) {
rgbindex *rgbp;
for (i = 0; (rgbp = index234(rgbtree, i)) != NULL; i++)
strbuf_catf(rtf, "\\red%d\\green%d\\blue%d;",
GetRValue(rgbp->ref), GetGValue(rgbp->ref),
GetBValue(rgbp->ref));
put_fmt(rtf, "\\red%d\\green%d\\blue%d;",
GetRValue(rgbp->ref), GetGValue(rgbp->ref),
GetBValue(rgbp->ref));
}
put_datapl(rtf, PTRLEN_LITERAL("}"));
}
@ -5162,13 +5162,13 @@ static void wintw_clip_write(
lastfgcolour = fgcolour;
lastfg = fg;
if (fg == -1) {
strbuf_catf(rtf, "\\cf%d ",
(fgcolour >= 0) ? palette[fgcolour] : 0);
put_fmt(rtf, "\\cf%d ",
(fgcolour >= 0) ? palette[fgcolour] : 0);
} else {
rgbindex rgb, *rgbp;
rgb.ref = fg;
if ((rgbp = find234(rgbtree, &rgb, NULL)) != NULL)
strbuf_catf(rtf, "\\cf%d ", rgbp->index);
put_fmt(rtf, "\\cf%d ", rgbp->index);
}
}
@ -5176,13 +5176,13 @@ static void wintw_clip_write(
lastbgcolour = bgcolour;
lastbg = bg;
if (bg == -1)
strbuf_catf(rtf, "\\highlight%d ",
(bgcolour >= 0) ? palette[bgcolour] : 0);
put_fmt(rtf, "\\highlight%d ",
(bgcolour >= 0) ? palette[bgcolour] : 0);
else {
rgbindex rgb, *rgbp;
rgb.ref = bg;
if ((rgbp = find234(rgbtree, &rgb, NULL)) != NULL)
strbuf_catf(rtf, "\\highlight%d ", rgbp->index);
put_fmt(rtf, "\\highlight%d ", rgbp->index);
}
}
@ -5243,7 +5243,7 @@ static void wintw_clip_write(
} else if (tdata[tindex+i] == 0x0D || tdata[tindex+i] == 0x0A) {
put_datapl(rtf, PTRLEN_LITERAL("\\par\r\n"));
} else if (tdata[tindex+i] > 0x7E || tdata[tindex+i] < 0x20) {
strbuf_catf(rtf, "\\'%02x", tdata[tindex+i]);
put_fmt(rtf, "\\'%02x", tdata[tindex+i]);
} else {
put_byte(rtf, tdata[tindex+i]);
}