1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-03-22 14:39:24 -05:00

Replace several ad-hoc string formatters with strbuf.

uxnet.c's sk_namelookup and the sorting-key construction in
pangofont_enum_fonts() were both using s[n]printf and strncpy into
buffers that had no real need to be fixed-size; format_telnet_command
and the GTK Event Log selection-data builder were doing their own
sresize loops, but now we have strbuf they can just use that and save
redoing the same work.
This commit is contained in:
Simon Tatham 2018-12-01 09:35:52 +00:00
parent 915be1f6f0
commit 4251d28f71
4 changed files with 60 additions and 134 deletions

98
proxy.c
View File

@ -1276,15 +1276,8 @@ int proxy_socks5_negotiate (ProxySocket *p, int change)
char *format_telnet_command(SockAddr *addr, int port, Conf *conf) char *format_telnet_command(SockAddr *addr, int port, Conf *conf)
{ {
char *fmt = conf_get_str(conf, CONF_proxy_telnet_command); char *fmt = conf_get_str(conf, CONF_proxy_telnet_command);
char *ret = NULL;
int retlen = 0, retsize = 0;
int so = 0, eo = 0; int so = 0, eo = 0;
#define ENSURE(n) do { \ strbuf *buf = strbuf_new();
if (retsize < retlen + n) { \
retsize = retlen + n + 512; \
ret = sresize(ret, retsize, char); \
} \
} while (0)
/* we need to escape \\, \%, \r, \n, \t, \x??, \0???, /* we need to escape \\, \%, \r, \n, \t, \x??, \0???,
* %%, %host, %port, %user, and %pass * %%, %host, %port, %user, and %pass
@ -1302,11 +1295,8 @@ char *format_telnet_command(SockAddr *addr, int port, Conf *conf)
/* if there was any unescaped text before the escape /* if there was any unescaped text before the escape
* character, send that now */ * character, send that now */
if (eo != so) { if (eo != so)
ENSURE(eo - so); put_data(buf, fmt + so, eo - so);
memcpy(ret + retlen, fmt + so, eo - so);
retlen += eo - so;
}
so = eo++; so = eo++;
@ -1323,32 +1313,27 @@ char *format_telnet_command(SockAddr *addr, int port, Conf *conf)
switch (fmt[eo]) { switch (fmt[eo]) {
case '\\': case '\\':
ENSURE(1); put_byte(buf, '\\');
ret[retlen++] = '\\';
eo++; eo++;
break; break;
case '%': case '%':
ENSURE(1); put_byte(buf, '%');
ret[retlen++] = '%';
eo++; eo++;
break; break;
case 'r': case 'r':
ENSURE(1); put_byte(buf, '\r');
ret[retlen++] = '\r';
eo++; eo++;
break; break;
case 'n': case 'n':
ENSURE(1); put_byte(buf, '\n');
ret[retlen++] = '\n';
eo++; eo++;
break; break;
case 't': case 't':
ENSURE(1); put_byte(buf, '\t');
ret[retlen++] = '\t';
eo++; eo++;
break; break;
@ -1371,16 +1356,14 @@ char *format_telnet_command(SockAddr *addr, int port, Conf *conf)
/* non hex character, so we abort and just /* non hex character, so we abort and just
* send the whole thing unescaped (including \x) * send the whole thing unescaped (including \x)
*/ */
ENSURE(1); put_byte(buf, '\\');
ret[retlen++] = '\\';
eo = so + 1; eo = so + 1;
break; break;
} }
/* we only extract two hex characters */ /* we only extract two hex characters */
if (i == 1) { if (i == 1) {
ENSURE(1); put_byte(buf, v);
ret[retlen++] = v;
eo++; eo++;
break; break;
} }
@ -1392,9 +1375,7 @@ char *format_telnet_command(SockAddr *addr, int port, Conf *conf)
break; break;
default: default:
ENSURE(2); put_data(buf, fmt + so, 2);
memcpy(ret+retlen, fmt + so, 2);
retlen += 2;
eo++; eo++;
break; break;
} }
@ -1406,61 +1387,37 @@ char *format_telnet_command(SockAddr *addr, int port, Conf *conf)
*/ */
if (fmt[eo] == '%') { if (fmt[eo] == '%') {
ENSURE(1); put_byte(buf, '%');
ret[retlen++] = '%';
eo++; eo++;
} }
else if (strnicmp(fmt + eo, "host", 4) == 0) { else if (strnicmp(fmt + eo, "host", 4) == 0) {
char dest[512]; char dest[512];
int destlen;
sk_getaddr(addr, dest, lenof(dest)); sk_getaddr(addr, dest, lenof(dest));
destlen = strlen(dest); put_data(buf, dest, strlen(dest));
ENSURE(destlen);
memcpy(ret+retlen, dest, destlen);
retlen += destlen;
eo += 4; eo += 4;
} }
else if (strnicmp(fmt + eo, "port", 4) == 0) { else if (strnicmp(fmt + eo, "port", 4) == 0) {
char portstr[8], portlen; strbuf_catf(buf, "%d", port);
portlen = sprintf(portstr, "%i", port);
ENSURE(portlen);
memcpy(ret + retlen, portstr, portlen);
retlen += portlen;
eo += 4; eo += 4;
} }
else if (strnicmp(fmt + eo, "user", 4) == 0) { else if (strnicmp(fmt + eo, "user", 4) == 0) {
char *username = conf_get_str(conf, CONF_proxy_username); const char *username = conf_get_str(conf, CONF_proxy_username);
int userlen = strlen(username); put_data(buf, username, strlen(username));
ENSURE(userlen);
memcpy(ret+retlen, username, userlen);
retlen += userlen;
eo += 4; eo += 4;
} }
else if (strnicmp(fmt + eo, "pass", 4) == 0) { else if (strnicmp(fmt + eo, "pass", 4) == 0) {
char *password = conf_get_str(conf, CONF_proxy_password); const char *password = conf_get_str(conf, CONF_proxy_password);
int passlen = strlen(password); put_data(buf, password, strlen(password));
ENSURE(passlen);
memcpy(ret+retlen, password, passlen);
retlen += passlen;
eo += 4; eo += 4;
} }
else if (strnicmp(fmt + eo, "proxyhost", 9) == 0) { else if (strnicmp(fmt + eo, "proxyhost", 9) == 0) {
char *host = conf_get_str(conf, CONF_proxy_host); const char *host = conf_get_str(conf, CONF_proxy_host);
int phlen = strlen(host); put_data(buf, host, strlen(host));
ENSURE(phlen);
memcpy(ret+retlen, host, phlen);
retlen += phlen;
eo += 9; eo += 9;
} }
else if (strnicmp(fmt + eo, "proxyport", 9) == 0) { else if (strnicmp(fmt + eo, "proxyport", 9) == 0) {
int port = conf_get_int(conf, CONF_proxy_port); int port = conf_get_int(conf, CONF_proxy_port);
char pport[50]; strbuf_catf(buf, "%d", port);
int pplen;
sprintf(pport, "%d", port);
pplen = strlen(pport);
ENSURE(pplen);
memcpy(ret+retlen, pport, pplen);
retlen += pplen;
eo += 9; eo += 9;
} }
else { else {
@ -1468,8 +1425,7 @@ char *format_telnet_command(SockAddr *addr, int port, Conf *conf)
* don't advance eo, so that we'll consider the * don't advance eo, so that we'll consider the
* text immediately following the % as unescaped. * text immediately following the % as unescaped.
*/ */
ENSURE(1); put_byte(buf, '%');
ret[retlen++] = '%';
} }
} }
@ -1479,16 +1435,10 @@ char *format_telnet_command(SockAddr *addr, int port, Conf *conf)
/* if there is any unescaped text at the end of the line, send it */ /* if there is any unescaped text at the end of the line, send it */
if (eo != so) { if (eo != so) {
ENSURE(eo - so); put_data(buf, fmt + so, eo - so);
memcpy(ret + retlen, fmt + so, eo - so);
retlen += eo - so;
} }
ENSURE(1); return strbuf_to_str(buf);
ret[retlen] = '\0';
return ret;
#undef ENSURE
} }
int proxy_telnet_negotiate (ProxySocket *p, int change) int proxy_telnet_negotiate (ProxySocket *p, int change)

View File

@ -3763,7 +3763,7 @@ struct eventlog_stuff {
char **events_initial; char **events_initial;
char **events_circular; char **events_circular;
int ninitial, ncircular, circular_first; int ninitial, ncircular, circular_first;
char *seldata; strbuf *seldata;
int sellen; int sellen;
bool ignore_selchange; bool ignore_selchange;
}; };
@ -3773,8 +3773,6 @@ static void eventlog_destroy(GtkWidget *widget, gpointer data)
eventlog_stuff *es = (eventlog_stuff *)data; eventlog_stuff *es = (eventlog_stuff *)data;
es->window = NULL; es->window = NULL;
sfree(es->seldata);
es->seldata = NULL;
dlg_cleanup(&es->dp); dlg_cleanup(&es->dp);
ctrl_free_box(es->eventbox); ctrl_free_box(es->eventbox);
} }
@ -3803,7 +3801,6 @@ static void eventlog_list_handler(union control *ctrl, dlgparam *dp,
dlg_update_done(ctrl, dp); dlg_update_done(ctrl, dp);
} else if (event == EVENT_SELCHANGE) { } else if (event == EVENT_SELCHANGE) {
int i; int i;
int selsize = 0;
/* /*
* If this SELCHANGE event is happening as a result of * If this SELCHANGE event is happening as a result of
@ -3817,36 +3814,15 @@ static void eventlog_list_handler(union control *ctrl, dlgparam *dp,
/* /*
* Construct the data to use as the selection. * Construct the data to use as the selection.
*/ */
sfree(es->seldata); es->seldata->len = 0;
es->seldata = NULL;
es->sellen = 0;
for (i = 0; i < es->ninitial; i++) { for (i = 0; i < es->ninitial; i++) {
if (dlg_listbox_issel(ctrl, dp, i)) { if (dlg_listbox_issel(ctrl, dp, i))
int extralen = strlen(es->events_initial[i]); strbuf_catf(es->seldata, "%s\n", es->events_initial[i]);
if (es->sellen + extralen + 2 > selsize) {
selsize = es->sellen + extralen + 512;
es->seldata = sresize(es->seldata, selsize, char);
}
strcpy(es->seldata + es->sellen, es->events_initial[i]);
es->sellen += extralen;
es->seldata[es->sellen++] = '\n';
}
} }
for (i = 0; i < es->ncircular; i++) { for (i = 0; i < es->ncircular; i++) {
if (dlg_listbox_issel(ctrl, dp, es->ninitial + i)) { if (dlg_listbox_issel(ctrl, dp, es->ninitial + i)) {
int j = (es->circular_first + i) % LOGEVENT_CIRCULAR_MAX; int j = (es->circular_first + i) % LOGEVENT_CIRCULAR_MAX;
int extralen = strlen(es->events_circular[j]); strbuf_catf(es->seldata, "%s\n", es->events_circular[j]);
if (es->sellen + extralen + 2 > selsize) {
selsize = es->sellen + extralen + 512;
es->seldata = sresize(es->seldata, selsize, char);
}
strcpy(es->seldata + es->sellen, es->events_circular[j]);
es->sellen += extralen;
es->seldata[es->sellen++] = '\n';
} }
} }
@ -3867,7 +3843,7 @@ void eventlog_selection_get(GtkWidget *widget, GtkSelectionData *seldata,
eventlog_stuff *es = (eventlog_stuff *)data; eventlog_stuff *es = (eventlog_stuff *)data;
gtk_selection_data_set(seldata, gtk_selection_data_get_target(seldata), 8, gtk_selection_data_set(seldata, gtk_selection_data_get_target(seldata), 8,
(unsigned char *)es->seldata, es->sellen); es->seldata->u, es->seldata->len);
} }
gint eventlog_selection_clear(GtkWidget *widget, GdkEventSelection *seldata, gint eventlog_selection_clear(GtkWidget *widget, GdkEventSelection *seldata,
@ -3891,9 +3867,6 @@ gint eventlog_selection_clear(GtkWidget *widget, GdkEventSelection *seldata,
#endif #endif
es->ignore_selchange = false; es->ignore_selchange = false;
sfree(es->seldata);
es->sellen = 0;
es->seldata = NULL;
return true; return true;
} }
@ -3983,6 +3956,7 @@ eventlog_stuff *eventlogstuff_new(void)
{ {
eventlog_stuff *es = snew(eventlog_stuff); eventlog_stuff *es = snew(eventlog_stuff);
memset(es, 0, sizeof(*es)); memset(es, 0, sizeof(*es));
es->seldata = strbuf_new();
return es; return es;
} }
@ -4000,6 +3974,7 @@ void eventlogstuff_free(eventlog_stuff *es)
sfree(es->events_circular[i]); sfree(es->events_circular[i]);
sfree(es->events_circular); sfree(es->events_circular);
} }
strbuf_free(es->seldata);
sfree(es); sfree(es);
} }

View File

@ -1882,8 +1882,7 @@ static void pangofont_enum_fonts(GtkWidget *widget, fontsel_add_entry callback,
* If so, go through them one by one. * If so, go through them one by one.
*/ */
for (k = 0; k < nsizes; k++) { for (k = 0; k < nsizes; k++) {
char *fullname; char *fullname, *stylekey;
char stylekey[128];
pango_font_description_set_size(desc, sizes[k]); pango_font_description_set_size(desc, sizes[k]);
@ -1893,27 +1892,27 @@ static void pangofont_enum_fonts(GtkWidget *widget, fontsel_add_entry callback,
* Construct the sorting key for font styles. * Construct the sorting key for font styles.
*/ */
{ {
char *p = stylekey; strbuf *buf = strbuf_new();
int n;
n = pango_font_description_get_weight(desc); int weight = pango_font_description_get_weight(desc);
/* Weight: normal, then lighter, then bolder */ /* Weight: normal, then lighter, then bolder */
if (n <= PANGO_WEIGHT_NORMAL) if (weight <= PANGO_WEIGHT_NORMAL)
n = PANGO_WEIGHT_NORMAL - n; weight = PANGO_WEIGHT_NORMAL - weight;
p += sprintf(p, "%4d", n); strbuf_catf(buf, "%4d", weight);
n = pango_font_description_get_style(desc); strbuf_catf(buf, " %2d",
p += sprintf(p, " %2d", n); pango_font_description_get_style(desc));
n = pango_font_description_get_stretch(desc); int stretch = pango_font_description_get_stretch(desc);
/* Stretch: closer to normal sorts earlier */ /* Stretch: closer to normal sorts earlier */
n = 2 * abs(PANGO_STRETCH_NORMAL - n) + stretch = 2 * abs(PANGO_STRETCH_NORMAL - stretch) +
(n < PANGO_STRETCH_NORMAL); (stretch < PANGO_STRETCH_NORMAL);
p += sprintf(p, " %2d", n); strbuf_catf(buf, " %2d", stretch);
n = pango_font_description_get_variant(desc); strbuf_catf(buf, " %2d",
p += sprintf(p, " %2d", n); pango_font_description_get_variant(desc));
stylekey = strbuf_to_str(buf);
} }
/* /*
@ -1926,6 +1925,7 @@ static void pangofont_enum_fonts(GtkWidget *widget, fontsel_add_entry callback,
(sizes == &dummysize ? 0 : PANGO_PIXELS(sizes[k])), (sizes == &dummysize ? 0 : PANGO_PIXELS(sizes[k])),
flags, &pangofont_vtable); flags, &pangofont_vtable);
sfree(stylekey);
g_free(fullname); g_free(fullname);
} }
if (sizes != &dummysize) if (sizes != &dummysize)

View File

@ -195,12 +195,11 @@ SockAddr *sk_namelookup(const char *host, char **canonicalname, int address_fami
struct hostent *h = NULL; struct hostent *h = NULL;
int n; int n;
#endif #endif
char realhost[8192]; strbuf *realhost;
/* Clear the structure and default to IPv4. */ /* Clear the structure and default to IPv4. */
memset(ret, 0, sizeof(SockAddr)); memset(ret, 0, sizeof(SockAddr));
ret->superfamily = UNRESOLVED; ret->superfamily = UNRESOLVED;
*realhost = '\0';
ret->error = NULL; ret->error = NULL;
ret->refcount = 1; ret->refcount = 1;
@ -225,11 +224,12 @@ SockAddr *sk_namelookup(const char *host, char **canonicalname, int address_fami
return ret; return ret;
} }
ret->superfamily = IP; ret->superfamily = IP;
*realhost = '\0';
realhost = strbuf_new();
if (ret->ais->ai_canonname != NULL) if (ret->ais->ai_canonname != NULL)
strncat(realhost, ret->ais->ai_canonname, sizeof(realhost) - 1); strbuf_catf(realhost, "%s", ret->ais->ai_canonname);
else else
strncat(realhost, host, sizeof(realhost) - 1); strbuf_catf(realhost, "%s", host);
#else #else
if ((a = inet_addr(host)) == (unsigned long)(in_addr_t)(-1)) { if ((a = inet_addr(host)) == (unsigned long)(in_addr_t)(-1)) {
/* /*
@ -248,10 +248,12 @@ SockAddr *sk_namelookup(const char *host, char **canonicalname, int address_fami
h_errno == TRY_AGAIN ? h_errno == TRY_AGAIN ?
"Temporary name service failure" : "Temporary name service failure" :
"gethostbyname: unknown error"); "gethostbyname: unknown error");
strbuf_free(realhost);
return ret; return ret;
} }
/* This way we are always sure the h->h_name is valid :) */ /* This way we are always sure the h->h_name is valid :) */
strncpy(realhost, h->h_name, sizeof(realhost)); realhost->len = 0;
strbuf_catf(realhost, "%s", h->h_name);
for (n = 0; h->h_addr_list[n]; n++); for (n = 0; h->h_addr_list[n]; n++);
ret->addresses = snewn(n, unsigned long); ret->addresses = snewn(n, unsigned long);
ret->naddresses = n; ret->naddresses = n;
@ -265,15 +267,14 @@ SockAddr *sk_namelookup(const char *host, char **canonicalname, int address_fami
* success return from inet_addr. * success return from inet_addr.
*/ */
ret->superfamily = IP; ret->superfamily = IP;
strncpy(realhost, host, sizeof(realhost)); realhost->len = 0;
strbuf_catf(realhost, "%s", host);
ret->addresses = snew(unsigned long); ret->addresses = snew(unsigned long);
ret->naddresses = 1; ret->naddresses = 1;
ret->addresses[0] = ntohl(a); ret->addresses[0] = ntohl(a);
} }
#endif #endif
realhost[lenof(realhost)-1] = '\0'; *canonicalname = strbuf_to_str(realhost);
*canonicalname = snewn(1+strlen(realhost), char);
strcpy(*canonicalname, realhost);
return ret; return ret;
} }