[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] connect: fix memory leak in ssh_select


Hi,

Attached is a patch which fixes a leak in 'ssh_select'.  With the
following test, I'm able to observe rapidly growing memory usage
before the patch, and steady usage after.

--

#include <libssh/libssh.h>
#include <poll.h>
#include <stdio.h>
#include <time.h>

int main(int argc, char **argv) {
	int fd = open("/dev/null", 0x0);
	if (fd < 0)
		goto err;

        fd_set readfds;
	FD_SET(fd, &readfds);

	while (1) {
		ssh_channel cin[1] = { NULL, };
		ssh_channel cout[1] = { NULL, };
		struct timeval tv = { .tv_sec = 0, .tv_usec = 1000 };
		ssh_select(cin, cout, fd + 1, &readfds, &tv);
	}

	close(fd);
err:
	printf("something went wrong\n");
	return 0;
}

--
Thanks,
-Jon
From cd72b899eb7f368c4d5707f155ab746780308975 Mon Sep 17 00:00:00 2001
From: Jon Simons <jon@xxxxxxxxxxxxx>
Date: Thu, 31 Oct 2013 04:17:38 -0700
Subject: [PATCH] connect: fix memory leak in ssh_select

Balance 'ssh_event_add_fd' with 'ssh_event_remove_fd' in 'ssh_select'.

BUG: https://red.libssh.org/issues/128
---
 src/connect.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/src/connect.c b/src/connect.c
index f7965cb..b299d41 100644
--- a/src/connect.c
+++ b/src/connect.c
@@ -436,6 +436,7 @@ static int ssh_select_cb (socket_t fd, int revents, void *userdata){
  */
 int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
     fd_set *readfds, struct timeval *timeout) {
+  fd_set origfds;
   socket_t fd;
   int i,j;
   int rc;
@@ -449,9 +450,11 @@ int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
     ssh_event_add_session(event, channels[i]->session);
   }
 
+  FD_ZERO(&origfds);
   for (fd = 0; fd < maxfd ; fd++) {
       if (FD_ISSET(fd, readfds)) {
           ssh_event_add_fd(event, fd, POLLIN, ssh_select_cb, readfds);
+          FD_SET(fd, &origfds);
       }
   }
   outchannels[0] = NULL;
@@ -485,13 +488,17 @@ int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
     /* since there's nothing, let's fire the polling */
     rc = ssh_event_dopoll(event,tm);
     if (rc == SSH_ERROR){
-      ssh_event_free(event);
-      return SSH_ERROR;
+      goto out;
     }
     tm = ssh_timeout_update(&ts, base_tm);
     firstround=0;
   } while (1);
 out:
+  for (fd = 0; fd < maxfd; fd++) {
+    if (FD_ISSET(fd, &origfds)) {
+      ssh_event_remove_fd(event, fd);
+    }
+  }
   ssh_event_free(event);
   return SSH_OK;
 }
-- 
1.8.4.21.g992c386


Follow-Ups:
Re: [PATCH] connect: fix memory leak in ssh_selectAndreas Schneider <asn@xxxxxxxxxxxxxx>
Archive administrator: postmaster@lists.cynapses.org