diff --git a/include/common/standard.h b/include/common/standard.h index 008208733..769aec661 100644 --- a/include/common/standard.h +++ b/include/common/standard.h @@ -227,6 +227,13 @@ char *encode_string(char *start, char *stop, const char escape, const fd_set *map, const char *string); +/* Decode an URL-encoded string in-place. The resulting string might + * be shorter. If some forbidden characters are found, the conversion is + * aborted, the string is truncated before the issue and non-zero is returned, + * otherwise the operation returns non-zero indicating success. + */ +int url_decode(char *string); + /* This one is 6 times faster than strtoul() on athlon, but does * no check at all. */ diff --git a/src/proto_http.c b/src/proto_http.c index 1fc7c94b9..69232f944 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -2932,6 +2932,9 @@ int http_process_req_stat_post(struct stream_interface *si, struct http_txn *txn *value++ = '\0'; } + if (!url_decode(key) || !url_decode(value)) + break; + /* Now we can check the key to see what to do */ if (!backend && strcmp(key, "b") == 0) { backend = value; diff --git a/src/standard.c b/src/standard.c index d3b9ef714..5c27bdbed 100644 --- a/src/standard.c +++ b/src/standard.c @@ -601,6 +601,40 @@ char *encode_string(char *start, char *stop, return start; } +/* Decode an URL-encoded string in-place. The resulting string might + * be shorter. If some forbidden characters are found, the conversion is + * aborted, the string is truncated before the issue and non-zero is returned, + * otherwise the operation returns non-zero indicating success. + */ +int url_decode(char *string) +{ + char *in, *out; + int ret = 0; + + in = string; + out = string; + while (*in) { + switch (*in) { + case '+' : + *out++ = ' '; + break; + case '%' : + if (!ishex(in[1]) || !ishex(in[2])) + goto end; + *out++ = (hex2i(in[1]) << 4) + hex2i(in[2]); + in += 2; + break; + default: + *out++ = *in; + break; + } + in++; + } + ret = 1; /* success */ + end: + *out = 0; + return ret; +} unsigned int str2ui(const char *s) {