File CVE-2015-7519.patch of Package rubygem-passenger.3847
diff --git a/ext/common/agent/Core/RequestHandler/SendRequest.cpp b/ext/common/agent/Core/RequestHandler/SendRequest.cpp
index 367ca34..190b6bf 100644
--- a/ext/common/agent/Core/RequestHandler/SendRequest.cpp
+++ b/ext/common/agent/Core/RequestHandler/SendRequest.cpp
@@ -138,6 +138,26 @@ sendHeaderToAppWithSessionProtocol(Client *client, Request *req) {
(void) ok; // Shut up compiler warning
}
+/**
+ * For CGI, alphanum headers with optional dashes are mapped to UPP3R_CAS3. This function can be used to reject
+ * non-alphanum/dash headers that would end up with the same mapping (e.g. upp3r_cas3 and upp3r-cas3 would end up
+ * the same, and potentially collide each other in the receiving application).
+ */
+static bool
+containsNonAlphaNumDash(const LString &s) {
+ const LString::Part *part = s.start;
+ while (part != NULL) {
+ for (unsigned int i = 0; i < part->size; i++) {
+ const char start = part->data[i];
+ if (start != '-' && !std::isalnum(start)) {
+ return true;
+ }
+ }
+ part = part->next;
+ }
+ return false;
+}
+
static void
sendBodyToAppWhenAppSinkIdle(Channel *_channel, unsigned int size) {
FdSinkChannel *channel = reinterpret_cast<FdSinkChannel *>(_channel);
@@ -426,12 +446,18 @@ constructHeaderForSessionProtocol(Request *req, char * restrict buffer, unsigned
ServerKit::HeaderTable::Iterator it(req->headers);
while (*it != NULL) {
- if ((it->header->hash == HTTP_CONTENT_LENGTH.hash()
- || it->header->hash == HTTP_CONTENT_TYPE.hash()
- || it->header->hash == HTTP_CONNECTION.hash())
- && (psg_lstr_cmp(&it->header->key, P_STATIC_STRING("content-type"))
- || psg_lstr_cmp(&it->header->key, P_STATIC_STRING("content-length"))
- || psg_lstr_cmp(&it->header->key, P_STATIC_STRING("connection"))))
+ // This header-skipping is not accounted for in determineHeaderSizeForSessionProtocol(), but
+ // since we are only reducing the size it just wastes some mem bytes.
+ if ((
+ (it->header->hash == HTTP_CONTENT_LENGTH.hash()
+ || it->header->hash == HTTP_CONTENT_TYPE.hash()
+ || it->header->hash == HTTP_CONNECTION.hash())
+ && (psg_lstr_cmp(&it->header->key, P_STATIC_STRING("content-type"))
+ || psg_lstr_cmp(&it->header->key, P_STATIC_STRING("content-length"))
+ || psg_lstr_cmp(&it->header->key, P_STATIC_STRING("connection"))
+ )
+ ) || containsNonAlphaNumDash(it->header->key)
+ )
{
it.next();
continue;