*
* RETURNS
*
- * an allocated dedotdotified output string
+ * Zero for success and 'out' set to an allocated dedotdotified string.
*/
-UNITTEST char *dedotdotify(const char *input, size_t clen);
-UNITTEST char *dedotdotify(const char *input, size_t clen)
+UNITTEST int dedotdotify(const char *input, size_t clen, char **outp);
+UNITTEST int dedotdotify(const char *input, size_t clen, char **outp)
{
- char *out = malloc(clen + 1);
char *outptr;
const char *orginput = input;
char *queryp;
+ char *out;
+
+ *outp = NULL;
+ /* the path always starts with a slash, and a slash has not dot */
+ if((clen < 2) || !memchr(input, '.', clen))
+ return 0;
+
+ out = malloc(clen + 1);
if(!out)
- return NULL; /* out of memory */
+ return 1; /* out of memory */
*out = 0; /* null-terminates, for inputs like "./" */
outptr = out;
- if(!*input)
- /* zero length input string, return that */
- return out;
-
/*
* To handle query-parts properly, we must find it and remove it during the
* dotdot-operation and then append it again at the end to the output
memcpy(outptr, &orginput[oindex], qlen + 1); /* include zero byte */
}
- return out;
+ *outp = out;
+ return 0; /* success */
}
static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
if(!(flags & CURLU_PATH_AS_IS)) {
/* remove ../ and ./ sequences according to RFC3986 */
- char *newp = dedotdotify((char *)path, pathlen);
- if(!newp) {
+ char *dedot;
+ int err = dedotdotify((char *)path, pathlen, &dedot);
+ if(err) {
result = CURLUE_OUT_OF_MEMORY;
goto fail;
}
- free(u->path);
- u->path = newp;
+ if(dedot) {
+ free(u->path);
+ u->path = dedot;
+ }
}
}
#include "curlcheck.h"
/* copied from urlapi.c */
-extern char *dedotdotify(const char *input, size_t clen);
+extern int dedotdotify(const char *input, size_t clen, char **out);
#include "memdebug.h"
{ "/1/./..", "/" },
{ "/1/./../2", "/2" },
{ "/hello/1/./../2", "/hello/2" },
- { "test/this", "test/this" },
+ { "test/this", NULL },
{ "test/this/../now", "test/now" },
{ "/1../moo../foo", "/1../moo../foo"},
{ "/../../moo", "/moo"},
{ "/../../moo?andnot/../yay", "/moo?andnot/../yay"},
{ "/123?foo=/./&bar=/../", "/123?foo=/./&bar=/../"},
{ "/../moo/..?what", "/?what" },
- { "/", "/" },
- { "", "" },
+ { "/", NULL },
+ { "", NULL },
{ "/.../", "/.../" },
{ "./moo", "moo" },
{ "../moo", "moo" },
{ "/.", "/" },
{ "/..", "/" },
{ "/moo/..", "/" },
- { "..", "" },
- { ".", "" },
+ { "/..", "/" },
+ { "/.", "/" },
};
for(i = 0; i < sizeof(pairs)/sizeof(pairs[0]); i++) {
- char *out = dedotdotify(pairs[i].input, strlen(pairs[i].input));
- abort_unless(out != NULL, "returned NULL!");
+ char *out;
+ int err = dedotdotify(pairs[i].input, strlen(pairs[i].input), &out);
+ abort_unless(err == 0, "returned error");
+ abort_if(err && out, "returned error with output");
- if(strcmp(out, pairs[i].output)) {
+ if(out && strcmp(out, pairs[i].output)) {
fprintf(stderr, "Test %u: '%s' gave '%s' instead of '%s'\n",
i, pairs[i].input, out, pairs[i].output);
fail("Test case output mismatched");
fails++;
}
+ else if(!out && pairs[i].output) {
+ fprintf(stderr, "Test %u: '%s' gave '%s' instead of NULL\n",
+ i, pairs[i].input, out);
+ fail("Test case output mismatched");
+ fails++;
+ }
else
fprintf(stderr, "Test %u: OK\n", i);
free(out);