diff --git a/lib/client/client-handshake.c b/lib/client/client-handshake.c
index ff98dc025a9e3d1dedf457e101fa75f9c2b4f284..c2873a90fafdaf13ff4a7857f29303e4c6087ef9 100644
--- a/lib/client/client-handshake.c
+++ b/lib/client/client-handshake.c
@@ -683,6 +683,34 @@ html_parser_cb(const hubbub_token *token, void *pw)
 }
 #endif
 
+static char *
+lws_strdup(const char *s)
+{
+	char *d = lws_malloc(strlen(s) + 1, "strdup");
+
+	if (d)
+		strcpy(d, s);
+
+	return d;
+}
+
+void
+lws_client_stash_destroy(struct lws *wsi)
+{
+	if (!wsi || !wsi->stash)
+		return;
+
+	lws_free_set_NULL(wsi->stash->address);
+	lws_free_set_NULL(wsi->stash->path);
+	lws_free_set_NULL(wsi->stash->host);
+	lws_free_set_NULL(wsi->stash->origin);
+	lws_free_set_NULL(wsi->stash->protocol);
+	lws_free_set_NULL(wsi->stash->method);
+	lws_free_set_NULL(wsi->stash->iface);
+
+	lws_free_set_NULL(wsi->stash);
+}
+
 LWS_VISIBLE struct lws *
 lws_client_connect_via_info(struct lws_client_connect_info *i)
 {
@@ -771,44 +799,39 @@ lws_client_connect_via_info(struct lws_client_connect_info *i)
 	 * things pointed to have gone out of scope.
 	 */
 
-	wsi->stash = lws_malloc(sizeof(*wsi->stash), "client stash");
+	wsi->stash = lws_zalloc(sizeof(*wsi->stash), "client stash");
 	if (!wsi->stash) {
 		lwsl_err("%s: OOM\n", __func__);
-		goto bail;
+		goto bail1;
 	}
 
-	wsi->stash->origin[0] = '\0';
-	wsi->stash->protocol[0] = '\0';
-	wsi->stash->method[0] = '\0';
-	wsi->stash->iface[0] = '\0';
-
-	strncpy(wsi->stash->address, i->address,
-		sizeof(wsi->stash->address) - 1);
-	strncpy(wsi->stash->path, i->path,
-		sizeof(wsi->stash->path) - 1);
-	strncpy(wsi->stash->host, i->host,
-		sizeof(wsi->stash->host) - 1);
-	if (i->origin)
-		strncpy(wsi->stash->origin, i->origin,
-			sizeof(wsi->stash->origin) - 1);
-	if (i->protocol)
-		strncpy(wsi->stash->protocol, i->protocol,
-			sizeof(wsi->stash->protocol) - 1);
-	if (i->method)
-		strncpy(wsi->stash->method, i->method,
-			sizeof(wsi->stash->method) - 1);
-	if (i->iface)
-		strncpy(wsi->stash->iface, i->iface,
-			sizeof(wsi->stash->iface) - 1);
-
-	wsi->stash->address[sizeof(wsi->stash->address) - 1] = '\0';
-	wsi->stash->path[sizeof(wsi->stash->path) - 1] = '\0';
-	wsi->stash->host[sizeof(wsi->stash->host) - 1] = '\0';
-	wsi->stash->origin[sizeof(wsi->stash->origin) - 1] = '\0';
-	wsi->stash->protocol[sizeof(wsi->stash->protocol) - 1] = '\0';
-	wsi->stash->method[sizeof(wsi->stash->method) - 1] = '\0';
-	wsi->stash->iface[sizeof(wsi->stash->iface) - 1] = '\0';
+	wsi->stash->address = lws_strdup(i->address);
+	wsi->stash->path = lws_strdup(i->path);
+	wsi->stash->host = lws_strdup(i->host);
+
+	if (!wsi->stash->address || !wsi->stash->path || !wsi->stash->host)
+		goto bail1;
 
+	if (i->origin) {
+		wsi->stash->origin = lws_strdup(i->origin);
+		if (!wsi->stash->origin)
+			goto bail1;
+	}
+	if (i->protocol) {
+		wsi->stash->protocol = lws_strdup(i->protocol);
+		if (!wsi->stash->protocol)
+			goto bail1;
+	}
+	if (i->method) {
+		wsi->stash->method = lws_strdup(i->method);
+		if (!wsi->stash->method)
+			goto bail1;
+	}
+	if (i->iface) {
+		wsi->stash->iface = lws_strdup(i->iface);
+		if (!wsi->stash->iface)
+			goto bail1;
+	}
 	if (i->pwsi)
 		*i->pwsi = wsi;
 
@@ -821,7 +844,7 @@ lws_client_connect_via_info(struct lws_client_connect_info *i)
 		 * if we failed here, the connection is already closed
 		 * and freed.
 		 */
-		goto bail1;
+		goto bail2;
 	}
 
 	if (i->parent_wsi) {
@@ -840,10 +863,13 @@ lws_client_connect_via_info(struct lws_client_connect_info *i)
 
 	return wsi;
 
+bail1:
+	lws_client_stash_destroy(wsi);
+
 bail:
 	lws_free(wsi);
 
-bail1:
+bail2:
 	if (i->pwsi)
 		*i->pwsi = NULL;
 
@@ -874,7 +900,7 @@ lws_client_connect_via_info2(struct lws *wsi)
 	if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_HOST, stash->host))
 		goto bail1;
 
-	if (stash->origin[0])
+	if (stash->origin)
 		if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_ORIGIN,
 					  stash->origin))
 			goto bail1;
@@ -882,22 +908,22 @@ lws_client_connect_via_info2(struct lws *wsi)
 	 * this is a list of protocols we tell the server we're okay with
 	 * stash it for later when we compare server response with it
 	 */
-	if (stash->protocol[0])
+	if (stash->protocol)
 		if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS,
 					  stash->protocol))
 			goto bail1;
-	if (stash->method[0])
+	if (stash->method)
 		if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_METHOD,
 					  stash->method))
 			goto bail1;
-	if (stash->iface[0])
+	if (stash->iface)
 		if (lws_hdr_simple_create(wsi, _WSI_TOKEN_CLIENT_IFACE,
 					  stash->iface))
 			goto bail1;
 
 #if defined(LWS_WITH_SOCKS5)
 	if (!wsi->vhost->socks_proxy_port)
-		lws_free_set_NULL(wsi->stash);
+		lws_client_stash_destroy(wsi);
 #endif
 
 	/*
diff --git a/lib/client/client.c b/lib/client/client.c
index 86a141832e6f6c17445de4d9373ba73e1e3303d6..f2a2f6738b0f189095e1f3e88b7603c2842b5ebd 100644
--- a/lib/client/client.c
+++ b/lib/client/client.c
@@ -196,7 +196,7 @@ socks_reply_fail:
 			lwsl_client("socks connect OK\n");
 
 			/* free stash since we are done with it */
-			lws_free_set_NULL(wsi->stash);
+			lws_client_stash_destroy(wsi);
 			if (lws_hdr_simple_create(wsi,
 						  _WSI_TOKEN_CLIENT_PEER_ADDRESS,
 						  wsi->vhost->socks_proxy_address))
@@ -539,8 +539,7 @@ lws_client_interpret_server_handshake(struct lws *wsi)
 	int more = 1;
 	void *v;
 #endif
-	if (wsi->stash)
-		lws_free_set_NULL(wsi->stash);
+	lws_client_stash_destroy(wsi);
 
 	ah = wsi->ah;
 	if (!wsi->do_ws) {
diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c
index 1514356297746243f735bf6e889f12a0e0aa7c1e..87e29601aa3acda1c8fa4001a3fe81734b19a30a 100644
--- a/lib/libwebsockets.c
+++ b/lib/libwebsockets.c
@@ -494,7 +494,7 @@ lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason)
 #endif
 
 #if !defined(LWS_NO_CLIENT)
-	lws_free_set_NULL(wsi->stash);
+	lws_client_stash_destroy(wsi);
 #endif
 
 	if (wsi->mode == LWSCM_RAW) {
@@ -663,7 +663,11 @@ just_kill_connection:
 	}
 
 	if (wsi->mode & LWSCM_FLAG_IMPLIES_CALLBACK_CLOSED_CLIENT_HTTP) {
-		wsi->vhost->protocols[0].callback(wsi,
+		const struct lws_protocols *pro = wsi->protocol;
+
+		if (!wsi->protocol)
+			pro = &wsi->vhost->protocols[0];
+		pro->callback(wsi,
 					LWS_CALLBACK_CLOSED_CLIENT_HTTP,
 						  wsi->user_space, NULL, 0);
 		wsi->told_user_closed = 1;
diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h
index 307e28380f74702c7405f37fa7da0388ff49ce6a..22be056102a4c13132044c9a9c23138dbb9c2c71 100644
--- a/lib/private-libwebsockets.h
+++ b/lib/private-libwebsockets.h
@@ -1325,13 +1325,13 @@ enum uri_esc_states {
 
 #ifndef LWS_NO_CLIENT
 struct client_info_stash {
-	char address[256];
-	char path[4096];
-	char host[256];
-	char origin[256];
-	char protocol[256];
-	char method[16];
-	char iface[16];
+	char *address;
+	char *path;
+	char *host;
+	char *origin;
+	char *protocol;
+	char *method;
+	char *iface;
 };
 #endif
 
@@ -2109,6 +2109,9 @@ lws_client_connect_via_info2(struct lws *wsi);
 LWS_EXTERN int
 _lws_destroy_ah(struct lws_context_per_thread *pt, struct allocated_headers *ah);
 
+LWS_EXTERN void
+lws_client_stash_destroy(struct lws *wsi);
+
 /*
  * EXTENSIONS
  */