]> git.ipfire.org Git - thirdparty/openssh-portable.git/commitdiff
- djm@cvs.openbsd.org 2013/12/05 22:59:45
authorDamien Miller <djm@mindrot.org>
Fri, 6 Dec 2013 23:31:08 +0000 (10:31 +1100)
committerDamien Miller <djm@mindrot.org>
Fri, 6 Dec 2013 23:31:08 +0000 (10:31 +1100)
     [sftp-client.c]
     fix memory leak in error path in do_readdir(); pointed out by
     Loganaden Velvindron @ AfriNIC in bz#2163

ChangeLog
sftp-client.c

index 410ae1b9ef2e14d5579776c8210680c6e27008a2..7c812e518260c10f11769e128614ec150597fe7e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+20131207
+ - (djm) OpenBSD CVS Sync
+   - djm@cvs.openbsd.org 2013/12/05 22:59:45
+     [sftp-client.c]
+     fix memory leak in error path in do_readdir(); pointed out by
+     Loganaden Velvindron @ AfriNIC in bz#2163
+
 20131205
  - (djm) OpenBSD CVS Sync
    - jmc@cvs.openbsd.org 2013/11/21 08:05:09
index 246e94982ee17a45c03500519d8027106cfab5fd..1eb821086f8f6169042e7f79030e12c1653dad33 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp-client.c,v 1.110 2013/12/04 04:20:01 djm Exp $ */
+/* $OpenBSD: sftp-client.c,v 1.111 2013/12/05 22:59:45 djm Exp $ */
 /*
  * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
  *
@@ -460,6 +460,10 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int print_flag,
        Buffer msg;
        u_int count, type, id, handle_len, i, expected_id, ents = 0;
        char *handle;
+       int status = SSH2_FX_FAILURE;
+
+       if (dir)
+               *dir = NULL;
 
        id = conn->msg_id++;
 
@@ -506,20 +510,12 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int print_flag,
                        fatal("ID mismatch (%u != %u)", id, expected_id);
 
                if (type == SSH2_FXP_STATUS) {
-                       int status = buffer_get_int(&msg);
-
+                       status = buffer_get_int(&msg);
                        debug3("Received SSH2_FXP_STATUS %d", status);
-
-                       if (status == SSH2_FX_EOF) {
+                       if (status == SSH2_FX_EOF)
                                break;
-                       } else {
-                               error("Couldn't read directory: %s",
-                                   fx2txt(status));
-                               do_close(conn, handle, handle_len);
-                               free(handle);
-                               buffer_free(&msg);
-                               return(status);
-                       }
+                       error("Couldn't read directory: %s", fx2txt(status));
+                       goto out;
                } else if (type != SSH2_FXP_NAME)
                        fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
                            SSH2_FXP_NAME, type);
@@ -547,10 +543,7 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int print_flag,
                        if (strchr(filename, '/') != NULL) {
                                error("Server sent suspect path \"%s\" "
                                    "during readdir of \"%s\"", filename, path);
-                               goto next;
-                       }
-
-                       if (dir) {
+                       } else if (dir) {
                                *dir = xrealloc(*dir, ents + 2, sizeof(**dir));
                                (*dir)[ents] = xcalloc(1, sizeof(***dir));
                                (*dir)[ents]->filename = xstrdup(filename);
@@ -558,24 +551,29 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int print_flag,
                                memcpy(&(*dir)[ents]->a, a, sizeof(*a));
                                (*dir)[++ents] = NULL;
                        }
- next:
                        free(filename);
                        free(longname);
                }
        }
+       status = 0;
 
+ out:
        buffer_free(&msg);
        do_close(conn, handle, handle_len);
        free(handle);
 
-       /* Don't return partial matches on interrupt */
-       if (interrupted && dir != NULL && *dir != NULL) {
+       if (status != 0 && dir != NULL) {
+               /* Don't return results on error */
+               free_sftp_dirents(*dir);
+               *dir = NULL;
+       } else if (interrupted && dir != NULL && *dir != NULL) {
+               /* Don't return partial matches on interrupt */
                free_sftp_dirents(*dir);
                *dir = xcalloc(1, sizeof(**dir));
                **dir = NULL;
        }
 
-       return 0;
+       return status;
 }
 
 int
@@ -588,6 +586,8 @@ void free_sftp_dirents(SFTP_DIRENT **s)
 {
        int i;
 
+       if (s == NULL)
+               return;
        for (i = 0; s[i]; i++) {
                free(s[i]->filename);
                free(s[i]->longname);