mirror of
https://github.com/emikulic/darkhttpd.git
synced 2023-08-10 21:13:08 +03:00
Add make_safe_url_new()
Contributed by: Bert Gijsbers
This commit is contained in:
parent
6b91b9dc05
commit
5f519fec8d
@ -116,20 +116,92 @@ static char *make_safe_url(char *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);
|
||||
memcpy(buf, data, size);
|
||||
buf[size] = 0;
|
||||
// Enable this to make sure the fuzzer is working.
|
||||
#if 0
|
||||
if (size > 2 && buf[2] == 'x') __builtin_trap();
|
||||
#endif
|
||||
char *safe = make_safe_url(buf);
|
||||
if (safe) {
|
||||
return buf;
|
||||
}
|
||||
|
||||
void check(char* safe) {
|
||||
if (safe == NULL) return;
|
||||
if (strstr(safe, "/../") != NULL) __builtin_trap();
|
||||
if (strstr(safe, "/./") != NULL) __builtin_trap();
|
||||
}
|
||||
free(buf); // Don't leak memory.
|
||||
|
||||
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.
|
||||
#if 0
|
||||
if (size > 2 && buf1[2] == 'x') __builtin_trap();
|
||||
#endif
|
||||
char *safe1 = make_safe_url(buf1);
|
||||
char *safe2 = make_safe_url(buf2);
|
||||
check(safe1);
|
||||
check(safe2);
|
||||
if (safe1 == NULL) {
|
||||
if (safe2 != NULL) __builtin_trap();
|
||||
} else {
|
||||
if (strcmp(safe1, safe2) != 0) __builtin_trap();
|
||||
}
|
||||
// Don't leak memory.
|
||||
free(buf1);
|
||||
free(buf2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user