1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-06-30 19:12:48 -05:00

Rewrite some manual char-buffer-handling code.

In the course of recent refactorings I noticed a couple of cases where
we were doing old-fashioned preallocation of a char array with some
conservative maximum size, then writing into it via *p++ or similar
and hoping we got the calculation right.

Now we have strbuf and dupcat, so we shouldn't ever have to do that.
Fixed as many cases as I could find by searching for allocations of
the form 'snewn(foo, char)'.

Particularly worth a mention was the Windows GSSAPI setup code, which
was directly using the Win32 Registry API, and looks much more legible
using the windows/utils/registry.c wrappers. (But that was why I had
to enhance them in the previous commit so as to be able to open
registry keys read-only: without that, the open operation would
actually fail on this key, which is not user-writable.)

Also unix/askpass.c, which was doing a careful reallocation of its
buffer to avoid secrets being left behind in the vacated memory -
which is now just a matter of ensuring we called strbuf_new_nm().
This commit is contained in:
Simon Tatham
2022-09-13 15:00:26 +01:00
parent 7339e00f4a
commit 6cf6682c54
13 changed files with 174 additions and 291 deletions

View File

@ -46,8 +46,7 @@ struct askpass_ctx {
GdkColor cols[3];
#endif
char *error_message; /* if we finish without a passphrase */
char *passphrase; /* if we finish with one */
int passlen, passsize;
strbuf *passphrase; /* if we finish with one */
#if GTK_CHECK_VERSION(3,20,0)
GdkSeat *seat; /* for gdk_seat_grab */
#elif GTK_CHECK_VERSION(3,0,0)
@ -107,48 +106,30 @@ static void visually_acknowledge_keypress(struct askpass_ctx *ctx)
ctx->active_area = new_active;
}
static int last_char_len(struct askpass_ctx *ctx)
static size_t last_char_start(struct askpass_ctx *ctx)
{
/*
* GTK always encodes in UTF-8, so we can do this in a fixed way.
*/
int i;
assert(ctx->passlen > 0);
i = ctx->passlen - 1;
while ((unsigned)((unsigned char)ctx->passphrase[i] - 0x80) < 0x40) {
assert(ctx->passphrase->len > 0);
size_t i = ctx->passphrase->len - 1;
while ((unsigned)(ctx->passphrase->u[i] - 0x80) < 0x40) {
if (i == 0)
break;
i--;
}
return ctx->passlen - i;
return i;
}
static void add_text_to_passphrase(struct askpass_ctx *ctx, gchar *str)
{
int len = strlen(str);
if (ctx->passlen + len >= ctx->passsize) {
/* Take some care with buffer expansion, because there are
* pieces of passphrase in the old buffer so we should ensure
* realloc doesn't leave a copy lying around in the address
* space. */
int oldsize = ctx->passsize;
char *newbuf;
ctx->passsize = (ctx->passlen + len) * 5 / 4 + 1024;
newbuf = snewn(ctx->passsize, char);
memcpy(newbuf, ctx->passphrase, oldsize);
smemclr(ctx->passphrase, oldsize);
sfree(ctx->passphrase);
ctx->passphrase = newbuf;
}
strcpy(ctx->passphrase + ctx->passlen, str);
ctx->passlen += len;
put_datapl(ctx->passphrase, ptrlen_from_asciz(str));
visually_acknowledge_keypress(ctx);
}
static void cancel_askpass(struct askpass_ctx *ctx, const char *msg)
{
smemclr(ctx->passphrase, ctx->passsize);
strbuf_free(ctx->passphrase);
ctx->passphrase = NULL;
ctx->error_message = dupstr(msg);
gtk_main_quit();
@ -182,7 +163,7 @@ static gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
if (event->type == GDK_KEY_PRESS) {
if (!strcmp(event->string, "\x15")) {
/* Ctrl-U. Wipe out the whole line */
ctx->passlen = 0;
strbuf_clear(ctx->passphrase);
visually_acknowledge_keypress(ctx);
} else if (!strcmp(event->string, "\x17")) {
/* Ctrl-W. Delete back to the last space->nonspace
@ -190,20 +171,21 @@ static gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
* way (mimicking terminal drivers), and don't attempt
* to second-guess exciting Unicode space
* characters. */
while (ctx->passlen > 0) {
while (ctx->passphrase->len > 0) {
char deleted, prior;
ctx->passlen -= last_char_len(ctx);
deleted = ctx->passphrase[ctx->passlen];
prior = (ctx->passlen == 0 ? ' ' :
ctx->passphrase[ctx->passlen-1]);
size_t newlen = last_char_start(ctx);
deleted = ctx->passphrase->s[newlen];
strbuf_shrink_to(ctx->passphrase, newlen);
prior = (ctx->passphrase->len == 0 ? ' ' :
ctx->passphrase->s[ctx->passphrase->len-1]);
if (!g_ascii_isspace(deleted) && g_ascii_isspace(prior))
break;
}
visually_acknowledge_keypress(ctx);
} else if (event->keyval == GDK_KEY_BackSpace) {
/* Backspace. Delete one character. */
if (ctx->passlen > 0)
ctx->passlen -= last_char_len(ctx);
if (ctx->passphrase->len > 0)
strbuf_shrink_to(ctx->passphrase, last_char_start(ctx));
visually_acknowledge_keypress(ctx);
#if !GTK_CHECK_VERSION(2,0,0)
} else if (event->string[0]) {
@ -427,9 +409,7 @@ static const char *gtk_askpass_setup(struct askpass_ctx *ctx,
int i;
GtkBox *action_area;
ctx->passlen = 0;
ctx->passsize = 2048;
ctx->passphrase = snewn(ctx->passsize, char);
ctx->passphrase = strbuf_new_nm();
/*
* Create widgets.
@ -553,11 +533,6 @@ static void gtk_askpass_cleanup(struct askpass_ctx *ctx)
#endif
gtk_grab_remove(ctx->promptlabel);
if (ctx->passphrase) {
assert(ctx->passlen < ctx->passsize);
ctx->passphrase[ctx->passlen] = '\0';
}
gtk_widget_destroy(ctx->dialog);
}
@ -612,7 +587,7 @@ char *gtk_askpass_main(const char *display, const char *wintitle,
if (ctx->passphrase) {
*success = true;
return ctx->passphrase;
return strbuf_to_str(ctx->passphrase);
} else {
*success = false;
return ctx->error_message;

View File

@ -594,9 +594,7 @@ void dlg_listbox_addwithid(dlgcontrol *ctrl, dlgparam *dp,
cols = cols ? cols : 1;
for (i = 0; i < cols; i++) {
int collen = strcspn(text, "\t");
char *tmpstr = snewn(collen+1, char);
memcpy(tmpstr, text, collen);
tmpstr[collen] = '\0';
char *tmpstr = mkstr(make_ptrlen(text, collen));
gtk_list_store_set(uc->listmodel, &iter, i+1, tmpstr, -1);
sfree(tmpstr);
text += collen;

View File

@ -1228,9 +1228,8 @@ Backend *pty_backend_create(
char *shellname;
if (conf_get_bool(conf, CONF_login_shell)) {
const char *p = strrchr(shell, '/');
shellname = snewn(2+strlen(shell), char);
p = p ? p+1 : shell;
sprintf(shellname, "-%s", p);
shellname = dupprintf("-%s", p);
} else
shellname = (char *)shell;
execl(shell, shellname, (void *)NULL);

View File

@ -321,7 +321,6 @@ static int keycmp(void *av, void *bv)
void provide_xrm_string(const char *string, const char *progname)
{
const char *p, *q;
char *key;
struct skeyval *xrms, *ret;
p = q = strchr(string, ':');
@ -330,14 +329,13 @@ void provide_xrm_string(const char *string, const char *progname)
" \"%s\"\n", progname, string);
return;
}
q++;
xrms = snew(struct skeyval);
while (p > string && p[-1] != '.' && p[-1] != '*')
p--;
xrms = snew(struct skeyval);
key = snewn(q-p, char);
memcpy(key, p, q-p);
key[q-p-1] = '\0';
xrms->key = key;
xrms->key = mkstr(make_ptrlen(p, q-p));
q++;
while (*q && isspace((unsigned char)*q))
q++;
xrms->value = dupstr(q);