Fix major memory leak in sftp_cmd_ls (thanks to Hans-Juergen Petrich
[u/mdw/putty] / psftp.c
diff --git a/psftp.c b/psftp.c
index 302e1a7..ae509f3 100644 (file)
--- a/psftp.c
+++ b/psftp.c
@@ -25,7 +25,7 @@
  */
 
 static int psftp_connect(char *userhost, char *user, int portnumber);
-static void do_sftp_init(void);
+static int do_sftp_init(void);
 
 /* ----------------------------------------------------------------------
  * sftp client state.
@@ -188,15 +188,15 @@ int sftp_cmd_quit(struct sftp_command *cmd)
  */
 static int sftp_ls_compare(const void *av, const void *bv)
 {
-    const struct fxp_name *a = (const struct fxp_name *) av;
-    const struct fxp_name *b = (const struct fxp_name *) bv;
-    return strcmp(a->filename, b->filename);
+    const struct fxp_name *const *a = (const struct fxp_name *const *) av;
+    const struct fxp_name *const *b = (const struct fxp_name *const *) bv;
+    return strcmp((*a)->filename, (*b)->filename);
 }
 int sftp_cmd_ls(struct sftp_command *cmd)
 {
     struct fxp_handle *dirh;
     struct fxp_names *names;
-    struct fxp_name *ournames;
+    struct fxp_name **ournames;
     int nnames, namesize;
     char *dir, *cdir;
     int i;
@@ -247,9 +247,8 @@ int sftp_cmd_ls(struct sftp_command *cmd)
            }
 
            for (i = 0; i < names->nnames; i++)
-               ournames[nnames++] = names->names[i];
+               ournames[nnames++] = fxp_dup_name(&names->names[i]);
 
-           names->nnames = 0;         /* prevent free_names */
            fxp_free_names(names);
        }
        fxp_close(dirh);
@@ -263,8 +262,11 @@ int sftp_cmd_ls(struct sftp_command *cmd)
        /*
         * And print them.
         */
-       for (i = 0; i < nnames; i++)
-           printf("%s\n", ournames[i].longname);
+       for (i = 0; i < nnames; i++) {
+           printf("%s\n", ournames[i]->longname);
+           fxp_free_name(ournames[i]);
+       }
+       sfree(ournames);
     }
 
     sfree(cdir);
@@ -1361,7 +1363,7 @@ struct sftp_command *sftp_getcmd(FILE *fp, int mode, int modeflags)
     return cmd;
 }
 
-static void do_sftp_init(void)
+static int do_sftp_init(void)
 {
     /*
      * Do protocol initialisation. 
@@ -1369,7 +1371,7 @@ static void do_sftp_init(void)
     if (!fxp_init()) {
        fprintf(stderr,
                "Fatal: unable to initialise SFTP: %s\n", fxp_error());
-       return;
+       return 1;                      /* failure */
     }
 
     /*
@@ -1385,6 +1387,7 @@ static void do_sftp_init(void)
        printf("Remote working directory is %s\n", homedir);
     }
     pwd = dupstr(homedir);
+    return 0;
 }
 
 void do_sftp(int mode, int modeflags, char *batchfile)
@@ -1452,7 +1455,7 @@ void fatalbox(char *fmt, ...)
     strcat(str, "\n");
     fputs(str, stderr);
 
-    exit(1);
+    cleanup_exit(1);
 }
 void connection_fatal(char *fmt, ...)
 {
@@ -1465,7 +1468,7 @@ void connection_fatal(char *fmt, ...)
     strcat(str, "\n");
     fputs(str, stderr);
 
-    exit(1);
+    cleanup_exit(1);
 }
 
 void ldisc_send(char *buf, int len, int interactive)
@@ -1511,6 +1514,8 @@ int from_backend(int is_stderr, char *data, int datalen)
     unsigned char *p = (unsigned char *) data;
     unsigned len = (unsigned) datalen;
 
+    assert(len > 0);
+
     /*
      * stderr data is just spouted to local stderr and otherwise
      * ignored.
@@ -1624,11 +1629,11 @@ static void init_winsock(void)
     winsock_ver = MAKEWORD(1, 1);
     if (WSAStartup(winsock_ver, &wsadata)) {
        fprintf(stderr, "Unable to initialise WinSock");
-       exit(1);
+       cleanup_exit(1);
     }
     if (LOBYTE(wsadata.wVersion) != 1 || HIBYTE(wsadata.wVersion) != 1) {
        fprintf(stderr, "WinSock version is incompatible with 1.1");
-       exit(1);
+       cleanup_exit(1);
     }
 }
 
@@ -1647,7 +1652,7 @@ static void usage(void)
     printf("  -v        show verbose messages\n");
     printf("  -P port   connect to specified port\n");
     printf("  -pw passw login with specified password\n");
-    exit(1);
+    cleanup_exit(1);
 }
 
 /*
@@ -1717,7 +1722,7 @@ static int psftp_connect(char *userhost, char *user, int portnumber)
        printf("login as: ");
        if (!fgets(cfg.username, sizeof(cfg.username), stdin)) {
            fprintf(stderr, "psftp: aborting\n");
-           exit(1);
+           cleanup_exit(1);
        } else {
            int len = strlen(cfg.username);
            if (cfg.username[len - 1] == '\n')
@@ -1847,7 +1852,8 @@ int main(int argc, char *argv[])
     if (userhost) {
        if (psftp_connect(userhost, user, portnumber))
            return 1;
-       do_sftp_init();
+       if (do_sftp_init())
+           return 1;
     } else {
        printf("psftp: no hostname specified; use \"open host.name\""
            " to connect\n");