sk_new() on invocation; these functions become responsible for (eventually)
freeing it. The caller must not do anything with 'addr' after it's been passed
in. (Ick.)
Why:
A SOCKS5 crash appears to have been caused by overzealous freeing of
a SockAddr (ssh.c:1.257 [r2492]), which for proxied connections is
squirreled away long-term (and this can't easily be avoided).
It would have been nice to make a copy of the SockAddr, in case the caller has
a use for it, but one of the implementations (uxnet.c) hides a "struct
addrinfo" in there, and we have no defined way to duplicate those. (None of the
current callers _do_ have a further use for the SockAddr.)
As far as I can tell, everything _except_ proxying only needs addr for the
duration of the call, so sk_addr_free()s immediately. If I'm mistaken, it
should at least be easier to find the offending free()...
git-svn-id: svn://svn.tartarus.org/sgt/putty@3383
cda61777-01e9-0310-a592-
d414129be87e
ret->next->prev = &ret->next;
mactcp.socklist = ret;
+ sk_addr_free(addr); /* don't need this anymore */
+
return (Socket)ret;
}
ret->next->prev = &ret->next;
ot.socklist = ret;
+ /* XXX: don't know whether we can sk_addr_free(addr); */
+
return (Socket) ret;
}
};
/* proxy indirection layer */
+/* NB, control of 'addr' is passed via new_connection, which takes
+ * responsibility for freeing it */
Socket new_connection(SockAddr addr, char *hostname,
int port, int privport,
int oobinline, int nodelay, Plug plug,
const Config *cfg);
/* platform-dependent callback from new_connection() */
+/* (same caveat about addr as new_connection()) */
Socket platform_new_connection(SockAddr addr, char *hostname,
int port, int privport,
int oobinline, int nodelay, Plug plug,
void sk_addrcopy(SockAddr addr, char *buf);
void sk_addr_free(SockAddr addr);
+/* NB, control of 'addr' is passed via sk_new, which takes responsibility
+ * for freeing it, as for new_connection() */
Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
int nodelay, Plug p);
* Try to find host.
*/
addr = name_lookup(hostname, port, &dummy_realhost, cfg);
- if ((err = sk_addr_error(addr)) != NULL)
+ if ((err = sk_addr_error(addr)) != NULL) {
+ sk_addr_free(addr);
return err;
+ }
/*
* Open socket.
}
sk_set_private_ptr(*s, pr);
- sk_addr_free(addr);
return NULL;
}
Proxy_Socket ps = (Proxy_Socket) s;
sk_close(ps->sub_socket);
+ sk_addr_free(ps->remote_addr);
sfree(ps);
}
ret->fn = &socket_fn_table;
ret->cfg = *cfg; /* STRUCTURE COPY */
ret->plug = plug;
- ret->remote_addr = addr;
+ ret->remote_addr = addr; /* will need to be freed on close */
ret->remote_port = port;
ret->error = NULL;
if (sk_socket_error(ret->sub_socket) != NULL)
return (Socket) ret;
- sk_addr_free(proxy_addr);
-
/* start the proxy negotiation process... */
sk_set_frozen(ret->sub_socket, 0);
ret->negotiate(ret, PROXY_CHANGE_NEW);
sfree(buf);
}
addr = name_lookup(host, port, realhost, cfg);
- if ((err = sk_addr_error(addr)) != NULL)
+ if ((err = sk_addr_error(addr)) != NULL) {
+ sk_addr_free(addr);
return err;
+ }
if (port < 0)
port = 23; /* default telnet port */
if ((err = sk_socket_error(raw->s)) != NULL)
return err;
- sk_addr_free(addr);
-
return NULL;
}
sfree(buf);
}
addr = name_lookup(host, port, realhost, cfg);
- if ((err = sk_addr_error(addr)) != NULL)
+ if ((err = sk_addr_error(addr)) != NULL) {
+ sk_addr_free(addr);
return err;
+ }
if (port < 0)
port = 513; /* default rlogin port */
if ((err = sk_socket_error(rlogin->s)) != NULL)
return err;
- sk_addr_free(addr);
-
/*
* Send local username, remote username, terminal/speed
*/
ssh->fn = &fn_table;
ssh->s = new_connection(addr, *realhost, port,
0, 1, nodelay, (Plug) ssh, &ssh->cfg);
- sk_addr_free(addr);
if ((err = sk_socket_error(ssh->s)) != NULL) {
ssh->s = NULL;
return err;
sfree(buf);
}
addr = name_lookup(host, port, realhost, &telnet->cfg);
- if ((err = sk_addr_error(addr)) != NULL)
+ if ((err = sk_addr_error(addr)) != NULL) {
+ sk_addr_free(addr);
return err;
+ }
if (port < 0)
port = 23; /* default telnet port */
if ((err = sk_socket_error(telnet->s)) != NULL)
return err;
- sk_addr_free(addr);
-
/*
* Initialise option states.
*/
uxsel_tell(ret);
add234(sktree, ret);
+ sk_addr_free(addr);
+
return (Socket) ret;
}
uxsel_set(ret->from_cmd, 1, localproxy_select_result);
+ /* We are responsible for this and don't need it any more */
+ sk_addr_free(addr);
+
return (Socket) ret;
}
add234(sktree, ret);
+ /* We're done with 'addr' now. */
+ sk_addr_free(addr);
+
return (Socket) ret;
}
* Try to find host.
*/
addr = name_lookup(host, port, &dummy_realhost, cfg);
- if ((err = sk_addr_error(addr)) != NULL)
+ if ((err = sk_addr_error(addr)) != NULL) {
+ sk_addr_free(addr);
return err;
+ }
/*
* Open socket.
}
sk_set_private_ptr(*s, pr);
- sk_addr_free(addr);
return NULL;
}