• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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