From 10a48c35917011b465b0cdce4521fb91839ee408 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Mon, 21 Mar 2016 06:50:50 +0000 Subject: [PATCH] Allocate the SSH specials list dynamically. The last list we returned is now stored in the main Ssh structure rather than being a static array in ssh_get_specials. The main point of this is that I want to start adding more dynamic things to it, for which I can't predict the array's max length in advance. But also this fixes a conceptual wrongness, in that if a process had more than one Ssh instance in it then their specials arrays would have taken turns occupying the old static array, and although the current single-threaded client code in the GUI front ends wouldn't have minded (it would have read out the contents just once immediately after get_specials returned), it still feels as if it was a bug waiting to happen. --- ssh.c | 44 ++++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/ssh.c b/ssh.c index da43bf02..0bc37c13 100644 --- a/ssh.c +++ b/ssh.c @@ -954,6 +954,11 @@ struct ssh_tag { */ struct ssh_gss_liblist *gsslibs; #endif + + /* + * The last list returned from get_specials. + */ + struct telnet_special *specials; }; #define logevent(s) logevent(ssh->frontend, s) @@ -11004,6 +11009,7 @@ static const char *ssh_init(void *frontend_handle, void **backend_handle, ssh->connshare = NULL; ssh->attempting_connshare = FALSE; ssh->session_started = FALSE; + ssh->specials = NULL; *backend_handle = ssh; @@ -11151,6 +11157,7 @@ static void ssh_free(void *handle) sfree(ssh->v_s); sfree(ssh->fullhostname); sfree(ssh->hostkey_str); + sfree(ssh->specials); if (ssh->crcda_ctx) { crcda_free_context(ssh->crcda_ctx); ssh->crcda_ctx = NULL; @@ -11364,19 +11371,24 @@ static const struct telnet_special *ssh_get_specials(void *handle) static const struct telnet_special specials_end[] = { {NULL, TS_EXITMENU} }; - /* XXX review this length for any changes: */ - static struct telnet_special ssh_specials[lenof(ssh2_ignore_special) + - lenof(ssh2_rekey_special) + - lenof(ssh2_session_specials) + - lenof(specials_end)]; + + struct telnet_special *specials = NULL; + int nspecials = 0, specialsize = 0; + Ssh ssh = (Ssh) handle; - int i = 0; -#define ADD_SPECIALS(name) \ - do { \ - assert((i + lenof(name)) <= lenof(ssh_specials)); \ - memcpy(&ssh_specials[i], name, sizeof name); \ - i += lenof(name); \ - } while(0) + + sfree(ssh->specials); + +#define ADD_SPECIALS(name) do \ + { \ + int len = lenof(name); \ + if (nspecials + len > specialsize) { \ + specialsize = (nspecials + len) * 5 / 4 + 32; \ + specials = sresize(specials, specialsize, struct telnet_special); \ + } \ + memcpy(specials+nspecials, name, len*sizeof(struct telnet_special)); \ + nspecials += len; \ + } while (0) if (ssh->version == 1) { /* Don't bother offering IGNORE if we've decided the remote @@ -11393,9 +11405,13 @@ static const struct telnet_special *ssh_get_specials(void *handle) ADD_SPECIALS(ssh2_session_specials); } /* else we're not ready yet */ - if (i) { + if (nspecials) ADD_SPECIALS(specials_end); - return ssh_specials; + + ssh->specials = specials; + + if (nspecials) { + return specials; } else { return NULL; } -- 2.45.2