]> asedeno.scripts.mit.edu Git - PuTTY.git/commitdiff
Allocate the SSH specials list dynamically.
authorSimon Tatham <anakin@pobox.com>
Mon, 21 Mar 2016 06:50:50 +0000 (06:50 +0000)
committerSimon Tatham <anakin@pobox.com>
Mon, 21 Mar 2016 06:50:50 +0000 (06:50 +0000)
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

diff --git a/ssh.c b/ssh.c
index da43bf0227d6aa3aff2f18ad8c8e2360075e9a8c..0bc37c13104354ff8db83e31e4cdc44d94f29260 100644 (file)
--- 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;
     }