Browse Source

Add support for malformed LF HTTP responses

master
JustAnotherArchivist 1 year ago
parent
commit
93e4140295
1 changed files with 25 additions and 14 deletions
  1. +25
    -14
      http-response-bodies.c

+ 25
- 14
http-response-bodies.c View File

@@ -158,12 +158,21 @@ checkstate:
}
if (memcmp(bufp, "HTTP/1.1 ", 9) == 0 || memcmp(bufp, "HTTP/1.0 ", 9) == 0) {
// Got some headers; find transfer encoding, content length, and end of headers
eoh = memmem(bufp, n, "\r\n\r\n", 4);
m0 = memmem(bufp, n, "\r\n\r\n", 4);
m1 = memmem(bufp, n, "\n\n", 2);
if (m0 && m1) {
eoh = (m0 < m1 ? m0 + 4 : m1 + 2);
} else if (m0) {
eoh = m0 + 4;
} else if (m1) {
eoh = m1 + 2;
} else {
eoh = NULL;
}
if (!eoh) {
fprintf(stderr, "Error: end of headers not found\n");
return 1;
}
eoh += 4;
DEBUG_PRINTF("Response body begins at %p (offset %zu)\n", (void*)eoh, eoh - bufp);

if (memcmp(bufp, "HTTP/1.0 ", 9) == 0) {
@@ -174,14 +183,15 @@ checkstate:
}
length = response_length - (eoh - bufp);
state = STATE_BODY;
} else if ((m0 = memcasemem(bufp, eoh - bufp, "\r\ncontent-length:", 17)) && m0 < eoh) {
} else if ((m0 = memcasemem(bufp, eoh - bufp, "\ncontent-length:", 16)) && m0 < eoh) {
DEBUG_PRINTF("Found Content-Length header at %p (offset %zu)\n", (void*)(m0 + 2), m0 + 2 - bufp);
m1 = memmem(m0 + 1, eoh - (m0 + 1), "\r\n", 2);
m1 = memmem(m0 + 1, eoh - (m0 + 1), "\n", 1);
if (!m1) {
fprintf(stderr, "Error: CRLF after Content-Length missing\n");
return 1;
}
m0 += 17;
if (*(m1 - 1) == '\r') --m1;
m0 += 16;
while (m0 < bufp + n && (*m0 == ' ' || *m0 == '\t')) ++m0;
if (sscanf(m0, "%zu%ln", &length, &nscan) <= 0) {
fprintf(stderr, "Error: invalid Content-Length\n");
@@ -205,18 +215,19 @@ checkstate:

state = STATE_BODY;
} else {
m0 = memcasemem(bufp, eoh - bufp, "\r\ntransfer-encoding:", 20);
m0 = memcasemem(bufp, eoh - bufp, "\ntransfer-encoding:", 19);
if (!m0 || m0 >= eoh) {
fprintf(stderr, "Error: Content-Length and Transfer-Encoding missing\n");
return 1;
}
DEBUG_PRINTF("Found Transfer-Encoding header at %p (offset %zu)\n", (void*)(m0 + 2), m0 + 2 - bufp);
m1 = memmem(m0 + 1, eoh - (m0 + 1), "\r\n", 2);
if (!m1 || m1 >= eoh - 2) {
DEBUG_PRINTF("Found Transfer-Encoding header at %p (offset %zu)\n", (void*)(m0 + 1), m0 + 1 - bufp);
m1 = memmem(m0 + 1, eoh - (m0 + 1), "\n", 1);
if (!m1 || m1 >= eoh - 1) {
fprintf(stderr, "Error: CRLF after Transfer-Encoding missing\n");
return 1;
}
m0 += 20;
m0 += 19;
if (*(m1 - 1) == '\r') --m1;
while (m0 < bufp + n && (*m0 == ' ' || *m0 == '\t')) ++m0;
if (memcmp(m0, "chunked", 7) != 0) {
fprintf(stderr, "Error: unsupported Transfer-Encoding\n");
@@ -234,15 +245,15 @@ checkstate:
}

if (html_fake_base) {
m0 = memcasemem(bufp, eoh - bufp, "\r\ncontent-type:", 15);
m0 = memcasemem(bufp, eoh - bufp, "\ncontent-type:", 14);
if (m0 && m0 < eoh) {
DEBUG_PRINTF("Found Content-Type header at %p (offset %zu)\n", (void*)(m0 + 2), m0 + 2 - bufp);
m1 = memmem(m0 + 1, eoh - (m0 + 1), "\r\n", 2);
DEBUG_PRINTF("Found Content-Type header at %p (offset %zu)\n", (void*)(m0 + 1), m0 + 1 - bufp);
m1 = memmem(m0 + 1, eoh - (m0 + 1), "\n", 1);
if (!m1) {
fprintf(stderr, "Error: CRLF after Content-Type missing\n");
return 1;
}
m0 += 15;
m0 += 14;
while (m0 < bufp + n && (*m0 == ' ' || *m0 == '\t')) ++m0;
if (memcmp(m0, "text/html", 9) == 0) {
DEBUG_PRINTF("Is HTML response, inserting fake base tag\n");


Loading…
Cancel
Save