Add make_safe_url_new()

Contributed by: Bert Gijsbers
This commit is contained in:
Emil Mikulic 2018-12-09 23:13:28 +11:00
parent 6b91b9dc05
commit 5f519fec8d

View File

@ -116,20 +116,92 @@ static char *make_safe_url(char *url) {
return url; return url;
} }
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { char *make_safe_url_new(char *const url) {
char *src = url, *dst;
#define ends(c) ((c) == '/' || (c) == '\0')
/* URLs not starting with a slash are illegal. */
if (*src != '/')
return NULL;
/* Fast case: skip until first double-slash or dot-dir. */
for ( ; *src && *src != '?'; ++src) {
if (*src == '/') {
if (src[1] == '/')
break;
else if (src[1] == '.') {
if (ends(src[2]))
break;
else if (src[2] == '.' && ends(src[3]))
break;
}
}
}
/* Copy to dst, while collapsing multi-slashes and handling dot-dirs. */
dst = src;
while (*src && *src != '?') {
if (*src != '/')
*dst++ = *src++;
else if (*++src == '/')
;
else if (*src != '.')
*dst++ = '/';
else if (ends(src[1]))
/* Ignore single-dot component. */
++src;
else if (src[1] == '.' && ends(src[2])) {
/* Double-dot component. */
src += 2;
if (dst == url)
return NULL; /* Illegal URL */
else
/* Backtrack to previous slash. */
while (*--dst != '/' && dst > url);
}
else
*dst++ = '/';
}
if (dst == url)
++dst;
*dst = '\0';
return url;
#undef ends
}
char* dup(const uint8_t *data, size_t size) {
char *buf = malloc(size + 1); char *buf = malloc(size + 1);
memcpy(buf, data, size); memcpy(buf, data, size);
buf[size] = 0; buf[size] = 0;
return buf;
}
void check(char* safe) {
if (safe == NULL) return;
if (strstr(safe, "/../") != NULL) __builtin_trap();
if (strstr(safe, "/./") != NULL) __builtin_trap();
}
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
char *buf1 = dup(data, size);
char *buf2 = dup(data, size);
// Enable this to make sure the fuzzer is working. // Enable this to make sure the fuzzer is working.
#if 0 #if 0
if (size > 2 && buf[2] == 'x') __builtin_trap(); if (size > 2 && buf1[2] == 'x') __builtin_trap();
#endif #endif
char *safe = make_safe_url(buf); char *safe1 = make_safe_url(buf1);
if (safe) { char *safe2 = make_safe_url(buf2);
if (strstr(safe, "/../") != NULL) __builtin_trap(); check(safe1);
if (strstr(safe, "/./") != NULL) __builtin_trap(); check(safe2);
if (safe1 == NULL) {
if (safe2 != NULL) __builtin_trap();
} else {
if (strcmp(safe1, safe2) != 0) __builtin_trap();
} }
free(buf); // Don't leak memory. // Don't leak memory.
free(buf1);
free(buf2);
return 0; return 0;
} }