1From 4e2b52b5f7a3bf50a0f1494155717b02cc1df6d6 Mon Sep 17 00:00:00 2001 2From: Daniel Stenberg <daniel@haxx.se> 3Date: Thu, 9 Mar 2023 16:22:11 +0100 4Subject: [PATCH] curl_path: create the new path with dynbuf 5 6Closes #10729 7--- 8 lib/curl_path.c | 75 +++++++++++++++++++++++-------------------------- 9 1 file changed, 35 insertions(+), 40 deletions(-) 10 11--- a/lib/curl_path.c 12+++ b/lib/curl_path.c 13@@ -30,70 +30,65 @@ 14 #include "escape.h" 15 #include "memdebug.h" 16 17+#define MAX_SSHPATH_LEN 100000 /* arbitrary */ 18+ 19 /* figure out the path to work with in this particular request */ 20 CURLcode Curl_getworkingpath(struct Curl_easy *data, 21 char *homedir, /* when SFTP is used */ 22 char **path) /* returns the allocated 23 real path to work with */ 24 { 25- char *real_path = NULL; 26 char *working_path; 27 size_t working_path_len; 28+ struct dynbuf npath; 29 CURLcode result = 30 Curl_urldecode(data, data->state.up.path, 0, &working_path, 31 &working_path_len, REJECT_ZERO); 32 if(result) 33 return result; 34 35+ /* new path to switch to in case we need to */ 36+ Curl_dyn_init(&npath, MAX_SSHPATH_LEN); 37+ 38 /* Check for /~/, indicating relative to the user's home directory */ 39- if(data->conn->handler->protocol & CURLPROTO_SCP) { 40- real_path = malloc(working_path_len + 1); 41- if(!real_path) { 42+ if((data->conn->handler->protocol & CURLPROTO_SCP) && 43+ (working_path_len > 3) && (!memcmp(working_path, "/~/", 3))) { 44+ /* It is referenced to the home directory, so strip the leading '/~/' */ 45+ if(Curl_dyn_addn(&npath, &working_path[3], working_path_len - 3)) { 46 free(working_path); 47 return CURLE_OUT_OF_MEMORY; 48 } 49- if((working_path_len > 3) && (!memcmp(working_path, "/~/", 3))) 50- /* It is referenced to the home directory, so strip the leading '/~/' */ 51- memcpy(real_path, working_path + 3, working_path_len - 2); 52- else 53- memcpy(real_path, working_path, 1 + working_path_len); 54 } 55- else if(data->conn->handler->protocol & CURLPROTO_SFTP) { 56- if((working_path_len > 1) && (working_path[1] == '~')) { 57- size_t homelen = strlen(homedir); 58- real_path = malloc(homelen + working_path_len + 1); 59- if(!real_path) { 60- free(working_path); 61- return CURLE_OUT_OF_MEMORY; 62- } 63- /* It is referenced to the home directory, so strip the 64- leading '/' */ 65- memcpy(real_path, homedir, homelen); 66- /* Only add a trailing '/' if homedir does not end with one */ 67- if(homelen == 0 || real_path[homelen - 1] != '/') { 68- real_path[homelen] = '/'; 69- homelen++; 70- real_path[homelen] = '\0'; 71- } 72- if(working_path_len > 3) { 73- memcpy(real_path + homelen, working_path + 3, 74- 1 + working_path_len -3); 75- } 76+ else if((data->conn->handler->protocol & CURLPROTO_SFTP) && 77+ (working_path_len > 2) && !memcmp(working_path, "/~/", 3)) { 78+ size_t len; 79+ const char *p; 80+ int copyfrom = 3; 81+ if(Curl_dyn_add(&npath, homedir)) { 82+ free(working_path); 83+ return CURLE_OUT_OF_MEMORY; 84 } 85- else { 86- real_path = malloc(working_path_len + 1); 87- if(!real_path) { 88- free(working_path); 89- return CURLE_OUT_OF_MEMORY; 90- } 91- memcpy(real_path, working_path, 1 + working_path_len); 92+ /* Copy a separating '/' if homedir does not end with one */ 93+ len = Curl_dyn_len(&npath); 94+ p = Curl_dyn_ptr(&npath); 95+ if(len && (p[len-1] != '/')) 96+ copyfrom = 2; 97+ 98+ if(Curl_dyn_addn(&npath, 99+ &working_path[copyfrom], working_path_len - copyfrom)) { 100+ free(working_path); 101+ return CURLE_OUT_OF_MEMORY; 102 } 103 } 104 105- free(working_path); 106+ if(Curl_dyn_len(&npath)) { 107+ free(working_path); 108 109- /* store the pointer for the caller to receive */ 110- *path = real_path; 111+ /* store the pointer for the caller to receive */ 112+ *path = Curl_dyn_ptr(&npath); 113+ } 114+ else 115+ *path = working_path; 116 117 return CURLE_OK; 118 } 119