Split into two patches.
The parser_unittests.patch adds tests for all the request line
permutations of content and garbage I could think of over the last few
days with their RFC 1945 and RFC 2616 expected outcomes. On the cases
which were not mentioned, ie binary crap, I've erred to leniency
accepting as 'unknown' content in the field with relevant cases assumed
to be HTTP/0.9.
The request-line parser existing in squid failed on several types of
test, mostly the ones centered around missing or invalid URIs.
So, parser_changes.patch contains an upgrade/fix to
HttpParserParseReqLine() handling HTTP request-lines as specific by
section 5.1 of the above RFCs. Specifically to handle a sequence of
unknown bytes up to a terminating LF (\n) octet. Nothing outside that is
relevant to this parser.
Changes:
* The semantics as previously documented are taken on. No changes
there, but documentation clarified a bit. Some things previously not
erroring are now doing so. External code impact is in the nature of
reduced special cases to be handled. Specifically raw-CR weirdness in
the request line fields. This occuring in URL was a vulnerability at
least once.
* Prior updates to HttpParser object for other parse stages opens the
possibility of this parse action returning HTTP status code directly.
Additions are done to make use of this (with the existing status codes
only).
* Input permutations where the unit-tests showed the old parser was
violating its own documentation have been fixed to produce expected outputs.
* Old parser operated three distinct potentially long parse loops.
Added several local variables to remember various octets seen while
searching for the terminal LF. This removed the need for two of the
parse re-scans (length of method, length of URI).
Future work TODO but outside the scope of this update and not going to
be added:
* making this part of HttpParser
* making HttpParser a trickle-scanner to speed up large request line
parsing.
* adding 6xx codes for internal use producing better errors on several
interesting error cases identified by this parser.
* using HttpParser fields output from this to seed the following
parser stages and prevent re-scanning this line to find bits.
Particularly the HttpRequest sanity checks.
Amos
=== modified file 'src/HttpMsg.cc'
--- src/HttpMsg.cc 2010-08-24 20:35:02 +0000
+++ src/HttpMsg.cc 2010-08-31 13:05:01 +0000
@@ -401,6 +401,10 @@
hdr->req_start = hdr->req_end = -1;
hdr->hdr_start = hdr->hdr_end = -1;
debugs(74, 5, "httpParseInit: Request buffer is " << buf);
+ hdr->m_start = hdr->m_end = -1;
+ hdr->u_start = hdr->u_end = -1;
+ hdr->v_start = hdr->v_end = -1;
+ hdr->v_maj = hdr->v_min = 0;
}
#if MSGDODEBUG
@@ -447,188 +451,234 @@
/**
* Attempt to parse the request line.
- *
- * This will set the values in hmsg that it determines. One may end up
- * with a partially-parsed buffer; the return value tells you whether
- * the values are valid or not.
- *
- * \retval 1 if parsed correctly
- * \retval 0 if more is needed
- * \retval -1 if error
- *
- * TODO:
- * * have it indicate "error" and "not enough" as two separate conditions!
- * * audit this code as off-by-one errors are probably everywhere!
+ * Governed by:
+ * RFC 1945 section 5.1
+ * RFC 2616 section 5.1
+ *
+ * Parsing state is stored between calls. However the current implementation
+ * begins parsing from scratch on every call.
+ * The return value tells you whether the parsing state fields are valid or not.
+ *
+ * \retval -1 an error occurred. request_parse_status indicates HTTP status result.
+ * \retval 1 successful parse
+ * \retval 0 more data is needed to complete the parse
*/
int
HttpParserParseReqLine(HttpParser *hmsg)
{
- int i = 0;
+ int i = 0, maj, min;
int retcode = 0;
- unsigned int maj = 0, min = 0;
- int last_whitespace = -1, line_end = -1;
+ int second_word = -1;
+ int first_whitespace = -1, last_whitespace = -1, line_end = -1;
+ // NP: line_end tracks the last byte BEFORE the \r\n or \n
- debugs(74, 5, "httpParserParseReqLine: parsing " << hmsg->buf);
+ debugs(74, 5, HERE << "parsing " << hmsg->buf);
PROF_start(HttpParserParseReqLine);
- /* Find \r\n - end of URL+Version (and the request) */
+
+ // Single-pass parse: (provided we have the whole line anyways)
+
+ hmsg->req_start = 0;
+#if 0 && USE_HTTP_VIOLATION
+ // NOTE: original parser version ignored prefix whitespace before the method.
+ // for now this hack retains that behaviour. WHY do we need this !?
+ //
+ for(;hmsg->req_start < hmsg->bufsiz && xisspace(hmsg->buf[hmsg->req_start]); hmsg->req_start++);
+#endif
hmsg->req_end = -1;
for (i = 0; i < hmsg->bufsiz; i++) {
+ // track first and last whitespace (SP only)
+ if (hmsg->buf[i] == ' ') {
+ last_whitespace = i;
+ if (first_whitespace < hmsg->req_start)
+ first_whitespace = i;
+ }
+
+ // track next non-SP/non-HT byte after first_whitespace
+ if (second_word < first_whitespace && hmsg->buf[i] != ' ' && hmsg->buf[i] != '\t') {
+ second_word = i;
+ }
+
+ // locate line terminator
if (hmsg->buf[i] == '\n') {
hmsg->req_end = i;
+ line_end = i - 1;
break;
}
- if (i < hmsg->bufsiz - 1 && hmsg->buf[i] == '\r' && hmsg->buf[i + 1] == '\n') {
- hmsg->req_end = i + 1;
- break;
+ if (i < hmsg->bufsiz - 1 && hmsg->buf[i] == '\r') {
+ if (hmsg->buf[i + 1] == '\n') {
+ hmsg->req_end = i + 1;
+ line_end = i - 1;
+ break;
+ } else {
+ // RFC 2616 section 5.1
+ // "No CR or LF is allowed except in the final CRLF sequence"
+ hmsg->request_parse_status = HTTP_BAD_REQUEST;
+ return -1;
+ }
}
}
if (hmsg->req_end == -1) {
- retcode = 0;
- goto finish;
- }
- assert(hmsg->buf[hmsg->req_end] == '\n');
- /* Start at the beginning again */
- i = 0;
-
- /* Find first non-whitespace - beginning of method */
- for (; i < hmsg->req_end && (xisspace(hmsg->buf[i])); i++);
- if (i >= hmsg->req_end) {
- retcode = 0;
- goto finish;
- }
- hmsg->m_start = i;
- hmsg->req_start = i;
-
- /* Find first whitespace - end of method */
- for (; i < hmsg->req_end && (! xisspace(hmsg->buf[i])); i++);
- if (i >= hmsg->req_end) {
- retcode = 0;
- goto finish;
- }
- hmsg->m_end = i - 1;
-
- /* Find first non-whitespace - beginning of URL+Version */
- for (; i < hmsg->req_end && (xisspace(hmsg->buf[i])); i++);
- if (i >= hmsg->req_end) {
- retcode = 0;
- goto finish;
- }
- hmsg->u_start = i;
-
- /* Find \r\n or \n - thats the end of the line. Keep track of the last whitespace! */
- for (; i <= hmsg->req_end; i++) {
- /* If \n - its end of line */
- if (hmsg->buf[i] == '\n') {
- line_end = i;
- break;
- }
- /* XXX could be off-by-one wrong! */
- if (hmsg->buf[i] == '\r' && (i + 1) <= hmsg->req_end && hmsg->buf[i+1] == '\n') {
- line_end = i;
- break;
- }
- /* If its a whitespace, note it as it'll delimit our version */
- if (hmsg->buf[i] == ' ' || hmsg->buf[i] == '\t') {
- last_whitespace = i;
- }
- }
- if (i > hmsg->req_end) {
- retcode = 0;
- goto finish;
+ PROF_stop(HttpParserParseReqLine);
+ debugs(74, 5, "Parser: retval 0: from " << hmsg->req_start <<
+ "->" << hmsg->req_end << ": needs more data to complete first line.");
+ return 0; // This is the only spot in this function where (0) is valid result.
+ }
+
+ // NP: we have now seen EOL, more-data (0) cannot occur.
+ // From here on any failure is -1, success is 1
+
+
+ // Input Validation:
+
+ // Process what we now know about the line structure into field offsets
+ // generating HTTP status for any aborts as we go.
+
+ // First non-whitespace = beginning of method
+ if (hmsg->req_start > line_end) {
+ hmsg->request_parse_status = HTTP_BAD_REQUEST;
+ retcode = -1;
+ goto finish;
+ }
+ hmsg->m_start = hmsg->req_start;
+
+ // First whitespace = end of method
+ if (first_whitespace > line_end || first_whitespace < hmsg->req_start) {
+ hmsg->request_parse_status = HTTP_BAD_REQUEST; // no method
+ retcode = -1;
+ goto finish;
+ }
+ hmsg->m_end = first_whitespace - 1;
+ if (hmsg->m_end < hmsg->m_start) {
+ hmsg->request_parse_status = HTTP_BAD_REQUEST; // missing URI?
+ retcode = -1;
+ goto finish;
+ }
+
+ // First non-whitespace after first SP = beginning of URL+Version
+ if (second_word > line_end || second_word < hmsg->req_start) {
+ hmsg->request_parse_status = HTTP_BAD_REQUEST; // missing URI
+ retcode = -1;
+ goto finish;
+ }
+ hmsg->u_start = second_word;
+
+ // RFC 1945: SP and version following URI are optional, marking version 0.9
+ // we identify this by the last whitespace being earlier than URI start
+ if (last_whitespace < second_word && last_whitespace >= hmsg->req_start) {
+ hmsg->v_maj = 0;
+ hmsg->v_min = 9;
+ hmsg->u_end = line_end;
+ hmsg->request_parse_status = HTTP_OK; // HTTP/0.9
+ retcode = 1;
+ goto finish;
+ } else {
+ // otherwise last whitespace is somewhere after end of URI.
+ hmsg->u_end = last_whitespace;
+ // crop any trailing whitespace in the area we think of as URI
+ for(;hmsg->u_end >= hmsg->u_start && xisspace(hmsg->buf[hmsg->u_end]); hmsg->u_end--);
+ }
+ if (hmsg->u_end < hmsg->u_start) {
+ hmsg->request_parse_status = HTTP_BAD_REQUEST; // missing URI
+ retcode = -1;
+ goto finish;
+ }
+
+ // Last whitespace SP = before start of protocol/version
+ if (last_whitespace >= line_end) {
+ hmsg->request_parse_status = HTTP_BAD_REQUEST; // missing version
+ retcode = -1;
+ goto finish;
+ }
+ hmsg->v_start = last_whitespace + 1;
+ hmsg->v_end = line_end;
+
+ // We only accept HTTP protocol requests right now.
+ // TODO: accept other protocols; RFC 2326 (RTSP protocol) etc
+ if ((hmsg->v_end - hmsg->v_start +1) < 5 || strncasecmp(&hmsg->buf[hmsg->v_start], "HTTP/", 5) != 0) {
+#if USE_HTTP_VIOLATIONS
+ // being lax; old parser accepted strange versions
+ hmsg->v_maj = 0;
+ hmsg->v_min = 9;
+ hmsg->u_end = line_end;
+ hmsg->request_parse_status = HTTP_OK; // treat as HTTP/0.9
+ retcode = 1;
+ goto finish;
+#else
+ hmsg->request_parse_status = HTTP_HTTP_VERSION_NOT_SUPPORTED; // protocol not supported / implemented.
+ retcode = -1;
+ goto finish;
+#endif
}
/* At this point we don't need the 'i' value; so we'll recycle it for version parsing */
- /*
- * At this point: line_end points to the first eol char (\r or \n);
- * last_whitespace points to the last whitespace char in the URL.
- * We know we have a full buffer here!
- */
- if (last_whitespace == -1) {
- maj = 0;
- min = 9;
- hmsg->u_end = line_end - 1;
- assert(hmsg->u_end >= hmsg->u_start);
- } else {
- /* Find the first non-whitespace after last_whitespace */
- /* XXX why <= vs < ? I do need to really re-audit all of this ..*/
- for (i = last_whitespace; i <= hmsg->req_end && xisspace(hmsg->buf[i]); i++);
- if (i > hmsg->req_end) {
- retcode = 0;
- goto finish;
- }
-
- /* is it http/ ? if so, we try parsing. If not, the URL is the whole line; version is 0.9 */
- if (i + 5 >= hmsg->req_end || (strncasecmp(&hmsg->buf[i], "HTTP/", 5) != 0)) {
- maj = 0;
- min = 9;
- hmsg->u_end = line_end - 1;
- assert(hmsg->u_end >= hmsg->u_start);
- } else {
- /* Ok, lets try parsing! Yes, this needs refactoring! */
- hmsg->v_start = i;
- i += 5;
-
- /* next should be 1 or more digits */
- maj = 0;
- for (; i < hmsg->req_end && (isdigit(hmsg->buf[i])) && maj < 65536; i++) {
- maj = maj * 10;
- maj = maj + (hmsg->buf[i]) - '0';
- }
- if (maj >= 65536) {
- retcode = -1;
- goto finish;
- }
- if (i >= hmsg->req_end) {
- retcode = 0;
- goto finish;
- }
-
- /* next should be .; we -have- to have this as we have a whole line.. */
- if (hmsg->buf[i] != '.') {
- retcode = 0;
- goto finish;
- }
- if (i + 1 >= hmsg->req_end) {
- retcode = 0;
- goto finish;
- }
-
- /* next should be one or more digits */
- i++;
- min = 0;
- for (; i < hmsg->req_end && (isdigit(hmsg->buf[i])) && min < 65536; i++) {
- min = min * 10;
- min = min + (hmsg->buf[i]) - '0';
- }
-
- if (min >= 65536) {
- retcode = -1;
- goto finish;
- }
-
- /* Find whitespace, end of version */
- hmsg->v_end = i;
- hmsg->u_end = last_whitespace - 1;
- }
- }
+ i = hmsg->v_start + sizeof("HTTP/") -1;
+
+ /* next should be 1 or more digits */
+ if (!isdigit(hmsg->buf[i])) {
+ hmsg->request_parse_status = HTTP_HTTP_VERSION_NOT_SUPPORTED;
+ retcode = -1;
+ goto finish;
+ }
+ maj = 0;
+ for (; i <= line_end && (isdigit(hmsg->buf[i])) && maj < 65536; i++) {
+ maj = maj * 10;
+ maj = maj + (hmsg->buf[i]) - '0';
+ }
+ // catch too-big values or missing remainders
+ if (maj >= 65536 || i > line_end) {
+ hmsg->request_parse_status = HTTP_HTTP_VERSION_NOT_SUPPORTED;
+ retcode = -1;
+ goto finish;
+ }
+ hmsg->v_maj = maj;
+
+ /* next should be .; we -have- to have this as we have a whole line.. */
+ if (hmsg->buf[i] != '.') {
+ hmsg->request_parse_status = HTTP_HTTP_VERSION_NOT_SUPPORTED;
+ retcode = -1;
+ goto finish;
+ }
+ // catch missing minor part
+ if (++i > line_end) {
+ hmsg->request_parse_status = HTTP_HTTP_VERSION_NOT_SUPPORTED;
+ retcode = -1;
+ goto finish;
+ }
+
+ /* next should be one or more digits */
+ if (!isdigit(hmsg->buf[i])) {
+ hmsg->request_parse_status = HTTP_HTTP_VERSION_NOT_SUPPORTED;
+ retcode = -1;
+ goto finish;
+ }
+ min = 0;
+ for (; i <= line_end && (isdigit(hmsg->buf[i])) && min < 65536; i++) {
+ min = min * 10;
+ min = min + (hmsg->buf[i]) - '0';
+ }
+ // catch too-big values or trailing garbage
+ if (min >= 65536 || i < line_end) {
+ hmsg->request_parse_status = HTTP_HTTP_VERSION_NOT_SUPPORTED;
+ retcode = -1;
+ goto finish;
+ }
+ hmsg->v_min = min;
/*
* Rightio - we have all the schtuff. Return true; we've got enough.
*/
retcode = 1;
+ hmsg->request_parse_status = HTTP_OK;
finish:
- hmsg->v_maj = maj;
- hmsg->v_min = min;
PROF_stop(HttpParserParseReqLine);
debugs(74, 5, "Parser: retval " << retcode << ": from " << hmsg->req_start <<
"->" << hmsg->req_end << ": method " << hmsg->m_start << "->" <<
hmsg->m_end << "; url " << hmsg->u_start << "->" << hmsg->u_end <<
- "; version " << hmsg->v_start << "->" << hmsg->v_end << " (" << maj <<
- "/" << min << ")");
+ "; version " << hmsg->v_start << "->" << hmsg->v_end << " (" << hmsg->v_maj <<
+ "/" << hmsg->v_min << ")");
return retcode;
}
-
=== modified file 'src/tests/testHttpRequest.cc'
--- src/tests/testHttpRequest.cc 2010-08-16 14:47:39 +0000
+++ src/tests/testHttpRequest.cc 2010-08-31 15:04:14 +0000
@@ -199,3 +199,752 @@
input.reset();
error = HTTP_STATUS_NONE;
}
+
+void
+testHttpRequest::testParseRequestLine()
+{
+ MemBuf input;
+ HttpParser output;
+ input.init();
+
+ // TEST: Do we comply with RFC 1945 section 5.1 ?
+ // TEST: Do we comply with RFC 2616 section 5.1 ?
+
+ // RFC 1945 : HTTP/0.9 simple-request
+ input.append("GET /\r\n", 7);
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == 1);
+ CPPUNIT_ASSERT_EQUAL(HTTP_OK, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(input.contentSize()-1, output.req_end);
+ CPPUNIT_ASSERT(memcmp("GET /\r\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(2, output.m_end);
+ CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.m_start], (output.m_end-output.m_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(4, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(4, output.u_end);
+ CPPUNIT_ASSERT(memcmp("/", &output.buf[output.u_start], (output.u_end-output.u_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(-1, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.v_end);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(9, output.v_min);
+ input.reset();
+
+ // RFC 1945 and 2616 : HTTP/1.0 full-request
+ input.append("GET / HTTP/1.0\r\n", 16);
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == 1);
+ CPPUNIT_ASSERT_EQUAL(HTTP_OK, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(input.contentSize()-1, output.req_end);
+ CPPUNIT_ASSERT(memcmp("GET / HTTP/1.0\r\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(2, output.m_end);
+ CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(4, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(4, output.u_end);
+ CPPUNIT_ASSERT(memcmp("/", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(6, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(13, output.v_end);
+ CPPUNIT_ASSERT(memcmp("HTTP/1.0", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(1, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_min);
+ input.reset();
+
+
+ // RFC 2616 : HTTP/1.1 full-request
+ input.append("GET / HTTP/1.1\r\n", 16);
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == 1);
+ CPPUNIT_ASSERT_EQUAL(HTTP_OK, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(input.contentSize()-1, output.req_end);
+ CPPUNIT_ASSERT(memcmp("GET / HTTP/1.1\r\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(2, output.m_end);
+ CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(4, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(4, output.u_end);
+ CPPUNIT_ASSERT(memcmp("/", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(6, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(13, output.v_end);
+ CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(1, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(1, output.v_min);
+ input.reset();
+
+ // RFC 2616 : future version full-request
+ input.append("GET / HTTP/10.12\r\n", 18);
+ //printf("TEST: '%s'\n",input.content());
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == 1);
+ CPPUNIT_ASSERT_EQUAL(HTTP_OK, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(input.contentSize()-1, output.req_end);
+ CPPUNIT_ASSERT(memcmp("GET / HTTP/10.12\r\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(2, output.m_end);
+ CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(4, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(4, output.u_end);
+ CPPUNIT_ASSERT(memcmp("/", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(6, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(15, output.v_end);
+ CPPUNIT_ASSERT(memcmp("HTTP/10.12", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(10, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(12, output.v_min);
+ input.reset();
+
+ // space padded URL
+ input.append("GET / HTTP/1.1\r\n", 21);
+ //printf("TEST: '%s'\n",input.content());
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == 1);
+ CPPUNIT_ASSERT_EQUAL(HTTP_OK, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(input.contentSize()-1, output.req_end);
+ CPPUNIT_ASSERT(memcmp("GET / HTTP/1.1\r\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(2, output.m_end);
+ CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(5, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(5, output.u_end);
+ CPPUNIT_ASSERT(memcmp("/", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(11, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(18, output.v_end);
+ CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(1, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(1, output.v_min);
+ input.reset();
+
+ // space padded version
+ // RFC 1945 and 2616 specify version is followed by CRLF. No intermediary bytes.
+ // NP: the terminal whitespace is a special case: invalid for even HTTP/0.9 with no version tag
+ input.append("GET / HTTP/1.1 \n", 16);
+ //printf("TEST: '%s'\n",input.content());
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == -1);
+ CPPUNIT_ASSERT_EQUAL(HTTP_BAD_REQUEST, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(input.contentSize()-1, output.req_end);
+ CPPUNIT_ASSERT(memcmp("GET / HTTP/1.1 \n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(2, output.m_end);
+ CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(4, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(13, output.u_end);
+ CPPUNIT_ASSERT(memcmp("/ HTTP/1.1", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(-1, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.v_end);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_min);
+ input.reset();
+
+ // whitespace inside URI. (nasty but happens)
+ input.append("GET /fo o/ HTTP/1.1\n", 20);
+ //printf("TEST: '%s'\n",input.content());
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == 1);
+ CPPUNIT_ASSERT_EQUAL(HTTP_OK, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(input.contentSize()-1, output.req_end);
+ CPPUNIT_ASSERT(memcmp("GET /fo o/ HTTP/1.1\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(2, output.m_end);
+ CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(4, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(9, output.u_end);
+ CPPUNIT_ASSERT(memcmp("/fo o/", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(11, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(18, output.v_end);
+ CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(1, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(1, output.v_min);
+ input.reset();
+
+ // additional data in buffer
+ input.append("GET / HTTP/1.1\nboo!", 23);
+ //printf("TEST: '%s'\n",input.content());
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == 1);
+ CPPUNIT_ASSERT_EQUAL(HTTP_OK, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(input.contentSize()-5, output.req_end);
+ CPPUNIT_ASSERT(memcmp("GET / HTTP/1.1\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(2, output.m_end);
+ CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(4, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(4, output.u_end); // strangeness generated by following RFC
+ CPPUNIT_ASSERT(memcmp("/", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(10, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(17, output.v_end);
+ CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(1, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(1, output.v_min);
+ input.reset();
+
+ // alternative EOL sequence: NL-only
+ input.append("GET / HTTP/1.1\n", 15);
+ //printf("TEST: '%s'\n",input.content());
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == 1);
+ CPPUNIT_ASSERT_EQUAL(HTTP_OK, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(input.contentSize()-1, output.req_end);
+ CPPUNIT_ASSERT(memcmp("GET / HTTP/1.1\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(2, output.m_end);
+ CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(4, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(4, output.u_end);
+ CPPUNIT_ASSERT(memcmp("/", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(6, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(13, output.v_end);
+ CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(1, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(1, output.v_min);
+ input.reset();
+
+ // alternative EOL sequence: double-NL-only
+ input.append("GET / HTTP/1.1\n\n", 16);
+ //printf("TEST: '%s'\n",input.content());
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == 1);
+ CPPUNIT_ASSERT_EQUAL(HTTP_OK, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(input.contentSize()-2, output.req_end);
+ CPPUNIT_ASSERT(memcmp("GET / HTTP/1.1\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(2, output.m_end);
+ CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(4, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(4, output.u_end);
+ CPPUNIT_ASSERT(memcmp("/", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(6, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(13, output.v_end);
+ CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(1, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(1, output.v_min);
+ input.reset();
+
+ // RFC 2616 : . method
+ input.append(". / HTTP/1.1\n", 13);
+ //printf("TEST: '%s'\n",input.content());
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == 1);
+ CPPUNIT_ASSERT_EQUAL(HTTP_OK, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(input.contentSize()-1, output.req_end);
+ CPPUNIT_ASSERT(memcmp(". / HTTP/1.1\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(0, output.m_end);
+ CPPUNIT_ASSERT(memcmp(".", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(2, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(2, output.u_end);
+ CPPUNIT_ASSERT(memcmp("/", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(4, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(11, output.v_end);
+ CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(1, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(1, output.v_min);
+ input.reset();
+
+ // OPTIONS with * URL
+ input.append("OPTIONS * HTTP/1.1\n", 19);
+ //printf("TEST: '%s'\n",input.content());
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == 1);
+ CPPUNIT_ASSERT_EQUAL(HTTP_OK, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(input.contentSize()-1, output.req_end);
+ CPPUNIT_ASSERT(memcmp("OPTIONS * HTTP/1.1\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(6, output.m_end);
+ CPPUNIT_ASSERT(memcmp("OPTIONS", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(8, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(8, output.u_end);
+ CPPUNIT_ASSERT(memcmp("*", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(10, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(17, output.v_end);
+ CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(1, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(1, output.v_min);
+ input.reset();
+
+ // unknown method
+ input.append("HELLOWORLD / HTTP/1.1\n", 22);
+ //printf("TEST: '%s'\n",input.content());
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == 1);
+ CPPUNIT_ASSERT_EQUAL(HTTP_OK, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(input.contentSize()-1, output.req_end);
+ CPPUNIT_ASSERT(memcmp("HELLOWORLD / HTTP/1.1\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(9, output.m_end);
+ CPPUNIT_ASSERT(memcmp("HELLOWORLD", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(11, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(11, output.u_end);
+ CPPUNIT_ASSERT(memcmp("/", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(13, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(20, output.v_end);
+ CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(1, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(1, output.v_min);
+ input.reset();
+
+ // This stage of the parser does not yet accept non-HTTP protocol names.
+ // violations mode treats them as HTTP/0.9 requests!
+ input.append("GET / FOO/1.0\n", 14);
+ //printf("TEST: '%s'\n",input.content());
+ HttpParserInit(&output, input.content(), input.contentSize());
+#if USE_HTTP_VIOLATIONS
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == 1);
+ CPPUNIT_ASSERT_EQUAL(HTTP_OK, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(12, output.u_end);
+ CPPUNIT_ASSERT(memcmp("/ FOO/1.0", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(9, output.v_min);
+#else
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == -1);
+ CPPUNIT_ASSERT_EQUAL(HTTP_HTTP_VERSION_NOT_SUPPORTED, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(4, output.u_end);
+ CPPUNIT_ASSERT(memcmp("/", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_min);
+#endif
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(input.contentSize()-1, output.req_end);
+ CPPUNIT_ASSERT(memcmp("GET / FOO/1.0\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(2, output.m_end);
+ CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(4, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(6, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(12, output.v_end);
+ CPPUNIT_ASSERT(memcmp("FOO/1.0", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0);
+ input.reset();
+
+ // space padded method (SP is reserved so invalid here)
+ input.append(" GET / HTTP/1.1\n", 16);
+ //printf("TEST: '%s'\n",input.content());
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == -1);
+ CPPUNIT_ASSERT_EQUAL(HTTP_BAD_REQUEST, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(input.contentSize()-1, output.req_end);
+ CPPUNIT_ASSERT(memcmp(" GET / HTTP/1.1\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.m_end);
+ CPPUNIT_ASSERT_EQUAL(-1, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.u_end);
+ CPPUNIT_ASSERT_EQUAL(-1, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.v_end);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_min);
+ input.reset();
+
+ // tab padded method (NP: tab is not SP so treated as any other binary)
+ input.append("\tGET / HTTP/1.1\n", 16);
+ //printf("TEST: '%s'\n",input.content());
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == 1);
+ CPPUNIT_ASSERT_EQUAL(HTTP_OK, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(input.contentSize()-1, output.req_end);
+ CPPUNIT_ASSERT(memcmp("\tGET / HTTP/1.1\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(3, output.m_end);
+ CPPUNIT_ASSERT(memcmp("\tGET", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(5, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(5, output.u_end);
+ CPPUNIT_ASSERT(memcmp("/", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(7, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(14, output.v_end);
+ CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(1, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(1, output.v_min);
+ input.reset();
+
+ input.append("GET", 3);
+ //printf("TEST: '%s'\n",input.content());
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == 0);
+ CPPUNIT_ASSERT_EQUAL(HTTP_STATUS_NONE, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.req_end);
+ CPPUNIT_ASSERT_EQUAL(-1, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.m_end);
+ CPPUNIT_ASSERT_EQUAL(-1, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.u_end);
+ CPPUNIT_ASSERT_EQUAL(-1, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.v_end);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_min);
+ input.reset();
+
+ input.append("GET ", 4);
+ //printf("TEST: '%s'\n",input.content());
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == 0);
+ CPPUNIT_ASSERT_EQUAL(HTTP_STATUS_NONE, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.req_end);
+ CPPUNIT_ASSERT_EQUAL(-1, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.m_end);
+ CPPUNIT_ASSERT_EQUAL(-1, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.u_end);
+ CPPUNIT_ASSERT_EQUAL(-1, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.v_end);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_min);
+ input.reset();
+
+ input.append("GET / HT", 8);
+ //printf("TEST: '%s'\n",input.content());
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == 0);
+ CPPUNIT_ASSERT_EQUAL(HTTP_STATUS_NONE, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.req_end);
+ CPPUNIT_ASSERT_EQUAL(-1, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.m_end);
+ CPPUNIT_ASSERT_EQUAL(-1, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.u_end);
+ CPPUNIT_ASSERT_EQUAL(-1, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.v_end);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_min);
+ input.reset();
+
+ input.append("GET / HTTP/1.1", 14);
+ //printf("TEST: '%s'\n",input.content());
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == 0);
+ CPPUNIT_ASSERT_EQUAL(HTTP_STATUS_NONE, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.req_end);
+ CPPUNIT_ASSERT_EQUAL(-1, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.m_end);
+ CPPUNIT_ASSERT_EQUAL(-1, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.u_end);
+ CPPUNIT_ASSERT_EQUAL(-1, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.v_end);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_min);
+ input.reset();
+
+ // method-only
+ input.append("A\n", 2);
+ //printf("TEST: '%s'\n",input.content());
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == -1);
+ CPPUNIT_ASSERT_EQUAL(HTTP_BAD_REQUEST, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(input.contentSize()-1, output.req_end);
+ CPPUNIT_ASSERT(memcmp("A\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.m_end);
+ CPPUNIT_ASSERT_EQUAL(-1, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.u_end);
+ CPPUNIT_ASSERT_EQUAL(-1, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.v_end);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_min);
+ input.reset();
+
+ // no method (but in a form which is ambiguous with HTTP/0.9 simple-request)
+ input.append("/ HTTP/1.0\n", 11);
+ //printf("TEST: '%s'\n",input.content());
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == 1);
+ CPPUNIT_ASSERT_EQUAL(HTTP_OK, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(input.contentSize()-1, output.req_end);
+ CPPUNIT_ASSERT(memcmp("/ HTTP/1.0\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(0, output.m_end);
+ CPPUNIT_ASSERT(memcmp("/", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(2, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(9, output.u_end);
+ CPPUNIT_ASSERT(memcmp("HTTP/1.0", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(-1, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.v_end);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(9, output.v_min);
+ input.reset();
+
+ // no method (an invalid format)
+ input.append(" / HTTP/1.0\n", 12);
+ //printf("TEST: '%s'\n",input.content());
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == -1);
+ CPPUNIT_ASSERT_EQUAL(HTTP_BAD_REQUEST, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(input.contentSize()-1, output.req_end);
+ CPPUNIT_ASSERT(memcmp(" / HTTP/1.0\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.m_end);
+ CPPUNIT_ASSERT_EQUAL(-1, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.u_end);
+ CPPUNIT_ASSERT_EQUAL(-1, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.v_end);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_min);
+ input.reset();
+
+ // binary code in method (strange but ...)
+ input.append("GET\x0B / HTTP/1.1\n", 16);
+ //printf("TEST: %d-%d/%d '%.*s'\n", output.req_start, output.req_end, input.contentSize(), 16, input.content());
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == 1);
+ CPPUNIT_ASSERT_EQUAL(HTTP_OK, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(input.contentSize()-1, output.req_end);
+ CPPUNIT_ASSERT(memcmp("GET\x0B / HTTP/1.1\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(3, output.m_end);
+ CPPUNIT_ASSERT(memcmp("GET\x0B", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(5, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(5, output.u_end);
+ CPPUNIT_ASSERT(memcmp("/", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(7, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(14, output.v_end);
+ CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(1, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(1, output.v_min);
+ input.reset();
+
+ // CR in method
+ // RFC 2616 sec 5.1 prohibits CR other than in terminator.
+ input.append("GET\r / HTTP/1.1\r\n", 16);
+ //printf("TEST: '%s'\n",input.content());
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == -1);
+ CPPUNIT_ASSERT_EQUAL(HTTP_BAD_REQUEST, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.req_end);
+ CPPUNIT_ASSERT_EQUAL(-1, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.m_end);
+ CPPUNIT_ASSERT_EQUAL(-1, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.u_end);
+ CPPUNIT_ASSERT_EQUAL(-1, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.v_end);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_min);
+ input.reset();
+
+ // binary code NUL! in method (strange but ...)
+ input.append("GET\0 / HTTP/1.1\n", 16);
+ //printf("TEST: %d-%d/%d '%.*s'\n", output.req_start, output.req_end, input.contentSize(), 16, input.content());
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == 1);
+ CPPUNIT_ASSERT_EQUAL(HTTP_OK, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(input.contentSize()-1, output.req_end);
+ CPPUNIT_ASSERT(memcmp("GET\0 / HTTP/1.1\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(3, output.m_end);
+ CPPUNIT_ASSERT(memcmp("GET\0", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(5, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(5, output.u_end);
+ CPPUNIT_ASSERT(memcmp("/", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(7, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(14, output.v_end);
+ CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(1, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(1, output.v_min);
+ input.reset();
+
+ // no URL (grammer otherwise correct)
+ input.append("GET HTTP/1.1\n", 14);
+ //printf("TEST: '%s'\n",input.content());
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == 1);
+ CPPUNIT_ASSERT_EQUAL(HTTP_OK, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(input.contentSize()-1, output.req_end);
+ CPPUNIT_ASSERT(memcmp("GET HTTP/1.1\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(2, output.m_end);
+ CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(5, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(12, output.u_end);
+ CPPUNIT_ASSERT_EQUAL(-1, output.v_start);
+ CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(-1, output.v_end);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(9, output.v_min);
+ input.reset();
+
+ // no URL (grammer invalid, ambiguous with RFC 1945 HTTP/0.9 simple-request)
+ input.append("GET HTTP/1.1\n", 13);
+ //printf("TEST: '%s'\n",input.content());
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == 1);
+ CPPUNIT_ASSERT_EQUAL(HTTP_OK, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(input.contentSize()-1, output.req_end);
+ CPPUNIT_ASSERT(memcmp("GET HTTP/1.1\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(2, output.m_end);
+ CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(4, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(11, output.u_end);
+ CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(-1, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.v_end);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(9, output.v_min);
+ input.reset();
+
+ // no version
+ input.append("GET / HTTP/\n", 12);
+ //printf("TEST: '%s'\n",input.content());
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == -1);
+ CPPUNIT_ASSERT_EQUAL(HTTP_HTTP_VERSION_NOT_SUPPORTED, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(input.contentSize()-1, output.req_end);
+ CPPUNIT_ASSERT(memcmp("GET / HTTP/\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(2, output.m_end);
+ CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(4, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(4, output.u_end);
+ CPPUNIT_ASSERT(memcmp("/", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(6, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(10, output.v_end);
+ CPPUNIT_ASSERT(memcmp("HTTP/", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_min);
+ input.reset();
+
+ // no major version
+ input.append("GET / HTTP/.1\n", 14);
+ //printf("TEST: '%s'\n",input.content());
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == -1);
+ CPPUNIT_ASSERT_EQUAL(HTTP_HTTP_VERSION_NOT_SUPPORTED, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(input.contentSize()-1, output.req_end);
+ CPPUNIT_ASSERT(memcmp("GET / HTTP/.1\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(2, output.m_end);
+ CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(4, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(4, output.u_end);
+ CPPUNIT_ASSERT(memcmp("/", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(6, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(12, output.v_end);
+ CPPUNIT_ASSERT(memcmp("HTTP/.1", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_min);
+ input.reset();
+
+ // no version dot
+ input.append("GET / HTTP/11\n", 14);
+ //printf("TEST: '%s'\n",input.content());
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == -1);
+ CPPUNIT_ASSERT_EQUAL(HTTP_HTTP_VERSION_NOT_SUPPORTED, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(input.contentSize()-1, output.req_end);
+ CPPUNIT_ASSERT(memcmp("GET / HTTP/11\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(2, output.m_end);
+ CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(4, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(4, output.u_end);
+ CPPUNIT_ASSERT(memcmp("/", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(6, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(12, output.v_end);
+ CPPUNIT_ASSERT(memcmp("HTTP/11", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_min);
+ input.reset();
+
+ // no minor version
+ input.append("GET / HTTP/1.\n", 14);
+ //printf("TEST: '%s'\n",input.content());
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == -1);
+ CPPUNIT_ASSERT_EQUAL(HTTP_HTTP_VERSION_NOT_SUPPORTED, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(input.contentSize()-1, output.req_end);
+ CPPUNIT_ASSERT(memcmp("GET / HTTP/1.\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(2, output.m_end);
+ CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(4, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(4, output.u_end);
+ CPPUNIT_ASSERT(memcmp("/", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(6, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(12, output.v_end);
+ CPPUNIT_ASSERT(memcmp("HTTP/1.", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(1, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_min);
+ input.reset();
+
+ // binary line
+ input.append("\xB\xC\xE\xF\n", 5);
+ //printf("TEST: binary-line\n");
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == -1);
+ CPPUNIT_ASSERT_EQUAL(HTTP_BAD_REQUEST, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(input.contentSize()-1, output.req_end);
+ CPPUNIT_ASSERT(memcmp("\xB\xC\xE\xF\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.m_end);
+ CPPUNIT_ASSERT_EQUAL(-1, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.u_end);
+ CPPUNIT_ASSERT_EQUAL(-1, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.v_end);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_min);
+ input.reset();
+
+ // mixed whitespace line
+ // We accept non-space binary bytes for method so first \t shows up as that
+ // but remaining space and tabs are skipped searching for URI-start
+ input.append("\t \t \t\n", 6);
+ //printf("TEST: mixed whitespace\n");
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == -1);
+ CPPUNIT_ASSERT_EQUAL(HTTP_BAD_REQUEST, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(input.contentSize()-1, output.req_end);
+ CPPUNIT_ASSERT(memcmp("\t \t \t\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(0, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(0, output.m_end);
+ CPPUNIT_ASSERT(memcmp("\t", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0);
+ CPPUNIT_ASSERT_EQUAL(-1, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.u_end);
+ CPPUNIT_ASSERT_EQUAL(-1, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.v_end);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_min);
+ input.reset();
+
+ // mixed whitespace line with CR middle
+ // CR aborts on sight, so even initial \t method is not marked as above
+ // (not when parsing clean with whole line available anyway)
+ input.append("\t \r \n", 6);
+ //printf("TEST: mixed whitespace with CR\n");
+ HttpParserInit(&output, input.content(), input.contentSize());
+ CPPUNIT_ASSERT(HttpParserParseReqLine(&output) == -1);
+ CPPUNIT_ASSERT_EQUAL(HTTP_BAD_REQUEST, output.request_parse_status);
+ CPPUNIT_ASSERT_EQUAL(0, output.req_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.req_end);
+ CPPUNIT_ASSERT_EQUAL(-1, output.m_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.m_end);
+ CPPUNIT_ASSERT_EQUAL(-1, output.u_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.u_end);
+ CPPUNIT_ASSERT_EQUAL(-1, output.v_start);
+ CPPUNIT_ASSERT_EQUAL(-1, output.v_end);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_maj);
+ CPPUNIT_ASSERT_EQUAL(0, output.v_min);
+ input.reset();
+}
=== modified file 'src/tests/testHttpRequest.h'
--- src/tests/testHttpRequest.h 2009-07-26 09:24:07 +0000
+++ src/tests/testHttpRequest.h 2010-08-29 02:50:26 +0000
@@ -15,6 +15,7 @@
CPPUNIT_TEST( testCreateFromUrl );
CPPUNIT_TEST( testIPv6HostColonBug );
CPPUNIT_TEST( testSanityCheckStartLine );
+ CPPUNIT_TEST( testParseRequestLine );
CPPUNIT_TEST_SUITE_END();
public:
@@ -25,6 +26,7 @@
void testCreateFromUrl();
void testIPv6HostColonBug();
void testSanityCheckStartLine();
+ void testParseRequestLine();
};
#endif