- 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
diff --git a/sftp-client.c b/sftp-client.c
index 246e949..1eb8210 100644
--- a/sftp-client.c
+++ b/sftp-client.c
@@ -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 @@
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 @@
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 @@
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 @@
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 @@
{
int i;
+ if (s == NULL)
+ return;
for (i = 0; s[i]; i++) {
free(s[i]->filename);
free(s[i]->longname);