return CURLE_OK;
}
-/* The get_pathname() function is being borrowed from OpenSSH sftp.c
- version 4.6p1. */
+/* The original get_pathname() function came from OpenSSH sftp.c version
+ 4.6p1. */
/*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
*
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir)
+
+#define MAX_PATHLENGTH 65535 /* arbitrary long */
+
+CURLcode Curl_get_pathname(const char **cpp, char **path, const char *homedir)
{
const char *cp = *cpp, *end;
char quot;
- unsigned int i, j;
- size_t fullPathLength, pathLength;
- bool relativePath = false;
+ unsigned int i;
static const char WHITESPACE[] = " \t\r\n";
+ struct dynbuf out;
+ CURLcode result;
DEBUGASSERT(homedir);
- if(!*cp || !homedir) {
- *cpp = NULL;
- *path = NULL;
+ *path = NULL;
+ *cpp = NULL;
+ if(!*cp || !homedir)
return CURLE_QUOTE_ERROR;
- }
+
+ Curl_dyn_init(&out, MAX_PATHLENGTH);
+
/* Ignore leading whitespace */
cp += strspn(cp, WHITESPACE);
- /* Allocate enough space for home directory and filename + separator */
- fullPathLength = strlen(cp) + strlen(homedir) + 2;
- *path = malloc(fullPathLength);
- if(!*path)
- return CURLE_OUT_OF_MEMORY;
/* Check for quoted filenames */
if(*cp == '\"' || *cp == '\'') {
quot = *cp++;
/* Search for terminating quote, unescape some chars */
- for(i = j = 0; i <= strlen(cp); i++) {
+ for(i = 0; i <= strlen(cp); i++) {
if(cp[i] == quot) { /* Found quote */
i++;
- (*path)[j] = '\0';
break;
}
if(cp[i] == '\0') { /* End of string */
goto fail;
}
}
- (*path)[j++] = cp[i];
+ result = Curl_dyn_addn(&out, &cp[i], 1);
+ if(result)
+ return result;
}
- if(j == 0) {
+ if(!Curl_dyn_len(&out))
goto fail;
- }
- *cpp = cp + i + strspn(cp + i, WHITESPACE);
+
+ /* return pointer to second parameter if it exists */
+ *cpp = &cp[i] + strspn(&cp[i], WHITESPACE);
}
else {
/* Read to end of filename - either to whitespace or terminator */
end = strpbrk(cp, WHITESPACE);
if(!end)
end = strchr(cp, '\0');
+
/* return pointer to second parameter if it exists */
*cpp = end + strspn(end, WHITESPACE);
- pathLength = 0;
- relativePath = (cp[0] == '/' && cp[1] == '~' && cp[2] == '/');
+
/* Handling for relative path - prepend home directory */
- if(relativePath) {
- strcpy(*path, homedir);
- pathLength = strlen(homedir);
- (*path)[pathLength++] = '/';
- (*path)[pathLength] = '\0';
+ if(cp[0] == '/' && cp[1] == '~' && cp[2] == '/') {
+ result = Curl_dyn_add(&out, homedir);
+ if(!result)
+ result = Curl_dyn_addn(&out, "/", 1);
+ if(result)
+ return result;
cp += 3;
}
/* Copy path name up until first "whitespace" */
- memcpy(&(*path)[pathLength], cp, (int)(end - cp));
- pathLength += (int)(end - cp);
- (*path)[pathLength] = '\0';
+ result = Curl_dyn_addn(&out, cp, (end - cp));
+ if(result)
+ return result;
}
+ *path = Curl_dyn_ptr(&out);
return CURLE_OK;
fail:
- Curl_safefree(*path);
+ Curl_dyn_free(&out);
return CURLE_QUOTE_ERROR;
}
--- /dev/null
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "curlcheck.h"
+#include "curl_path.h"
+
+static CURLcode unit_setup(void)
+{
+ return CURLE_OK;
+}
+
+static void unit_stop(void)
+{
+}
+
+
+struct set {
+ const char *cp;
+ const char *expect; /* the returned content */
+ const char *next; /* what cp points to after the call */
+ const char *home;
+ CURLcode result;
+};
+
+UNITTEST_START
+#ifdef USE_SSH
+{
+#define LONG_A "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+#define LONG_AA LONG_A LONG_A LONG_A LONG_A LONG_A LONG_A LONG_A LONG_A LONG_A
+#define LONG_AAA LONG_AA LONG_AA LONG_AA LONG_AA LONG_AA LONG_AA LONG_AA
+#define LONG_AAAA LONG_AAA LONG_AAA LONG_AAA LONG_AAA LONG_AAA LONG_AAA
+#define LONG_AAAAA LONG_AAAA LONG_AAAA LONG_AAAA LONG_AAAA
+ int i;
+ int error = 0;
+ struct set list[] = {
+ { LONG_AAAAA " b", "", "", "", CURLE_TOO_LARGE},
+ { LONG_AA " c", LONG_AA, "c", "/", CURLE_OK},
+ { "\" " LONG_AA "\" c", " " LONG_AA, "c", "/", CURLE_OK},
+ { "a a", "a", "a", "/home/", CURLE_OK},
+ { "b a", "b", "a", "/", CURLE_OK},
+ { "a", "a", "", "/home/", CURLE_OK},
+ { "b", "b", "", "/", CURLE_OK},
+ { "\"foo bar\"\tb", "foo bar", "b", "/", CURLE_OK},
+ { "/~/hej", "/home/user/hej", "", "/home/user", CURLE_OK},
+ { "\"foo bar", "", "", "/", CURLE_QUOTE_ERROR},
+ { "\"foo\\\"bar\" a", "foo\"bar", "a", "/", CURLE_OK},
+ { "\"foo\\\'bar\" b", "foo\'bar", "b", "/", CURLE_OK},
+ { "\"foo\\\\bar\" c", "foo\\bar", "c", "/", CURLE_OK},
+ { "\"foo\\pbar\" c", "foo\\bar", "", "/", CURLE_QUOTE_ERROR},
+ { "\"\" c", "", "", "", CURLE_QUOTE_ERROR},
+ { "foo\"", "foo\"", "", "/", CURLE_OK},
+ { "foo \"", "foo", "\"", "/", CURLE_OK},
+ { NULL, NULL, NULL, NULL, CURLE_OK }
+ };
+
+ for(i = 0; list[i].home; i++) {
+ char *path;
+ const char *cp = list[i].cp;
+ CURLcode result = Curl_get_pathname(&cp, &path, list[i].home);
+ printf("%u - Curl_get_pathname(\"%s\", ... \"%s\") == %u\n", i,
+ list[i].cp, list[i].home, list[i].result);
+ if(result != list[i].result) {
+ printf("... returned %d\n", result);
+ error++;
+ }
+ if(!result) {
+ if(cp && strcmp(cp, list[i].next)) {
+ printf("... cp points to '%s', not '%s' as expected \n",
+ cp, list[i].next);
+ error++;
+ }
+ if(path && strcmp(path, list[i].expect)) {
+ printf("... gave '%s', not '%s' as expected \n",
+ path, list[i].expect);
+ error++;
+ }
+ curl_free(path);
+
+ }
+ }
+ return error;
+}
+#endif
+
+UNITTEST_STOP