From: Francesco Chemolli Date: Wed, 11 Dec 2013 17:53:13 +0000 (+0100) Subject: Merged from trunk X-Git-Tag: merge-candidate-3-v1~506^2~110 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0efb166e0de7babf871c43fb57869dcd77b243f8;p=thirdparty%2Fsquid.git Merged from trunk --- 0efb166e0de7babf871c43fb57869dcd77b243f8 diff --cc configure.ac index 2e956d232a,d88e661c0d..d42f07f776 --- a/configure.ac +++ b/configure.ac @@@ -3388,100 -3391,99 +3391,100 @@@ AC_MSG_NOTICE([BUILD EXTRA C++ FLAGS: $ dnl Clean up after OSF/1 core dump bug rm -f core - AC_CONFIG_FILES([\ - Makefile \ - compat/Makefile \ - lib/Makefile \ - lib/ntlmauth/Makefile \ - lib/libTrie/Makefile \ - lib/libTrie/test/Makefile \ - lib/profiler/Makefile \ - lib/rfcnb/Makefile \ - lib/smblib/Makefile \ - scripts/Makefile \ - src/Makefile \ - src/anyp/Makefile \ - src/base/Makefile \ - src/acl/Makefile \ - src/fs/Makefile \ - src/repl/Makefile \ - src/auth/Makefile \ - src/auth/basic/Makefile \ - src/auth/digest/Makefile \ - src/auth/negotiate/Makefile \ - src/auth/ntlm/Makefile \ - src/adaptation/Makefile \ - src/adaptation/icap/Makefile \ - src/adaptation/ecap/Makefile \ - src/comm/Makefile \ - src/esi/Makefile \ - src/eui/Makefile \ - src/format/Makefile \ - src/http/Makefile \ - src/icmp/Makefile \ - src/ident/Makefile \ - src/ip/Makefile \ - src/log/Makefile \ - src/ipc/Makefile \ - src/ssl/Makefile \ - src/mgr/Makefile \ - src/parser/Makefile \ - src/snmp/Makefile \ - contrib/Makefile \ - snmplib/Makefile \ - icons/Makefile \ - errors/Makefile \ - test-suite/Makefile \ - doc/Makefile \ - doc/manuals/Makefile \ - helpers/Makefile \ - helpers/basic_auth/Makefile \ - helpers/basic_auth/DB/Makefile \ - helpers/basic_auth/fake/Makefile \ - helpers/basic_auth/getpwnam/Makefile \ - helpers/basic_auth/LDAP/Makefile \ - helpers/basic_auth/MSNT/Makefile \ - helpers/basic_auth/MSNT-multi-domain/Makefile \ - helpers/basic_auth/NCSA/Makefile \ - helpers/basic_auth/NIS/Makefile \ - helpers/basic_auth/PAM/Makefile \ - helpers/basic_auth/POP3/Makefile \ - helpers/basic_auth/RADIUS/Makefile \ - helpers/basic_auth/SASL/Makefile \ - helpers/basic_auth/SMB/Makefile \ - helpers/basic_auth/SSPI/Makefile \ - helpers/digest_auth/Makefile \ - helpers/digest_auth/eDirectory/Makefile \ - helpers/digest_auth/file/Makefile \ - helpers/digest_auth/LDAP/Makefile \ - helpers/ntlm_auth/Makefile \ - helpers/ntlm_auth/fake/Makefile \ - helpers/ntlm_auth/smb_lm/Makefile \ - helpers/ntlm_auth/SSPI/Makefile \ - helpers/negotiate_auth/Makefile \ - helpers/negotiate_auth/kerberos/Makefile \ - helpers/negotiate_auth/SSPI/Makefile \ - helpers/negotiate_auth/wrapper/Makefile \ - helpers/external_acl/Makefile \ - helpers/external_acl/AD_group/Makefile \ - helpers/external_acl/eDirectory_userip/Makefile \ - helpers/external_acl/file_userip/Makefile \ - helpers/external_acl/kerberos_ldap_group/Makefile \ - helpers/external_acl/LDAP_group/Makefile \ - helpers/external_acl/LM_group/Makefile \ - helpers/external_acl/session/Makefile \ - helpers/external_acl/SQL_session/Makefile \ - helpers/external_acl/unix_group/Makefile \ - helpers/external_acl/wbinfo_group/Makefile \ - helpers/external_acl/time_quota/Makefile \ - helpers/log_daemon/Makefile \ - helpers/log_daemon/DB/Makefile \ - helpers/log_daemon/file/Makefile \ - helpers/url_rewrite/Makefile \ - helpers/url_rewrite/fake/Makefile \ - helpers/ssl/Makefile \ - helpers/storeid_rewrite/Makefile \ - helpers/storeid_rewrite/file/Makefile \ + AC_CONFIG_FILES([ + Makefile + compat/Makefile + lib/Makefile + lib/ntlmauth/Makefile + lib/libTrie/Makefile + lib/libTrie/test/Makefile + lib/profiler/Makefile + lib/rfcnb/Makefile + lib/smblib/Makefile + lib/snmplib/Makefile + scripts/Makefile + src/Makefile + src/anyp/Makefile + src/base/Makefile + src/acl/Makefile + src/fs/Makefile + src/repl/Makefile + src/auth/Makefile + src/auth/basic/Makefile + src/auth/digest/Makefile + src/auth/negotiate/Makefile + src/auth/ntlm/Makefile + src/adaptation/Makefile + src/adaptation/icap/Makefile + src/adaptation/ecap/Makefile + src/comm/Makefile + src/esi/Makefile + src/eui/Makefile + src/format/Makefile + src/http/Makefile + src/icmp/Makefile + src/ident/Makefile + src/ip/Makefile + src/log/Makefile + src/ipc/Makefile + src/ssl/Makefile + src/mgr/Makefile ++ src/parser/Makefile + src/snmp/Makefile + contrib/Makefile + icons/Makefile + errors/Makefile + test-suite/Makefile + doc/Makefile + doc/manuals/Makefile + helpers/Makefile + helpers/basic_auth/Makefile + helpers/basic_auth/DB/Makefile + helpers/basic_auth/fake/Makefile + helpers/basic_auth/getpwnam/Makefile + helpers/basic_auth/LDAP/Makefile + helpers/basic_auth/MSNT/Makefile + helpers/basic_auth/MSNT-multi-domain/Makefile + helpers/basic_auth/NCSA/Makefile + helpers/basic_auth/NIS/Makefile + helpers/basic_auth/PAM/Makefile + helpers/basic_auth/POP3/Makefile + helpers/basic_auth/RADIUS/Makefile + helpers/basic_auth/SASL/Makefile + helpers/basic_auth/SMB/Makefile + helpers/basic_auth/SSPI/Makefile + helpers/digest_auth/Makefile + helpers/digest_auth/eDirectory/Makefile + helpers/digest_auth/file/Makefile + helpers/digest_auth/LDAP/Makefile + helpers/ntlm_auth/Makefile + helpers/ntlm_auth/fake/Makefile + helpers/ntlm_auth/smb_lm/Makefile + helpers/ntlm_auth/SSPI/Makefile + helpers/negotiate_auth/Makefile + helpers/negotiate_auth/kerberos/Makefile + helpers/negotiate_auth/SSPI/Makefile + helpers/negotiate_auth/wrapper/Makefile + helpers/external_acl/Makefile + helpers/external_acl/AD_group/Makefile + helpers/external_acl/eDirectory_userip/Makefile + helpers/external_acl/file_userip/Makefile + helpers/external_acl/kerberos_ldap_group/Makefile + helpers/external_acl/LDAP_group/Makefile + helpers/external_acl/LM_group/Makefile + helpers/external_acl/session/Makefile + helpers/external_acl/SQL_session/Makefile + helpers/external_acl/unix_group/Makefile + helpers/external_acl/wbinfo_group/Makefile + helpers/external_acl/time_quota/Makefile + helpers/log_daemon/Makefile + helpers/log_daemon/DB/Makefile + helpers/log_daemon/file/Makefile + helpers/url_rewrite/Makefile + helpers/url_rewrite/fake/Makefile + helpers/ssl/Makefile + helpers/storeid_rewrite/Makefile + helpers/storeid_rewrite/file/Makefile tools/Makefile tools/purge/Makefile ]) diff --cc src/tests/testHttpParser.cc index c2f4d940ba,9c22b6799d..da3ffde976 --- a/src/tests/testHttpParser.cc +++ b/src/tests/testHttpParser.cc @@@ -791,282 -846,256 +850,304 @@@ testHttpParser::testParseRequestLineInv input.init(); // no method (but in a form which is ambiguous with HTTP/0.9 simple-request) - // XXX: Bug: HTTP/0.9 requires method to be "GET" - input.append("/ HTTP/1.0\n", 11); - //printf("TEST: '%s'\n",input.content()); - output.reset(input.content(), input.contentSize()); - CPPUNIT_ASSERT_EQUAL(1, HttpParserParseReqLine(&output)); - CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status); - CPPUNIT_ASSERT_EQUAL(0, output.req.start); - CPPUNIT_ASSERT_EQUAL((int)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.req.m_start); - CPPUNIT_ASSERT_EQUAL(0, output.req.m_end); - CPPUNIT_ASSERT(memcmp("/", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)) == 0); - CPPUNIT_ASSERT_EQUAL(2, output.req.u_start); - CPPUNIT_ASSERT_EQUAL(9, output.req.u_end); - CPPUNIT_ASSERT(memcmp("HTTP/1.0", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)) == 0); - CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start); - CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end); - CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj); - CPPUNIT_ASSERT_EQUAL(9, output.req.v_min); - input.reset(); + { + // XXX: Bug: HTTP/0.9 requires method to be "GET" + input.append("/ HTTP/1.0\n", 11); + //printf("TEST: '%s'\n",input.content()); + output.reset(input.content(), input.contentSize()); + CPPUNIT_ASSERT_EQUAL(1, HttpParserParseReqLine(&output)); + CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status); + CPPUNIT_ASSERT_EQUAL(0, output.req.start); + CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end); + CPPUNIT_ASSERT_EQUAL(0, memcmp("/ HTTP/1.0\n", &output.buf[output.req.start],(output.req.end-output.req.start+1))); + CPPUNIT_ASSERT_EQUAL(0, output.req.m_start); + CPPUNIT_ASSERT_EQUAL(0, output.req.m_end); + CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1))); + CPPUNIT_ASSERT_EQUAL(2, output.req.u_start); + CPPUNIT_ASSERT_EQUAL(9, output.req.u_end); + CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.0", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1))); + CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start); + CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end); + CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj); + CPPUNIT_ASSERT_EQUAL(9, output.req.v_min); + input.reset(); + } // RELAXED no method (an invalid format) - input.append(" / HTTP/1.0\n", 12); - //printf("TEST: '%s'\n",input.content()); - output.reset(input.content(), input.contentSize()); - // When tolerantly ignoring SP prefix this case becomes ambiguous with HTTP/0.9 simple-request) - Config.onoff.relaxed_header_parser = 1; - CPPUNIT_ASSERT_EQUAL(1, HttpParserParseReqLine(&output)); - CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status); - CPPUNIT_ASSERT_EQUAL(1, output.req.start); - CPPUNIT_ASSERT_EQUAL((int)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(1, output.req.m_start); - CPPUNIT_ASSERT_EQUAL(1, output.req.m_end); - CPPUNIT_ASSERT(memcmp("/", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)) == 0); - CPPUNIT_ASSERT_EQUAL(3, output.req.u_start); - CPPUNIT_ASSERT_EQUAL(10, output.req.u_end); - CPPUNIT_ASSERT(memcmp("HTTP/1.0", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)) == 0); - CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start); - CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end); - CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj); - CPPUNIT_ASSERT_EQUAL(9, output.req.v_min); - input.reset(); + { + input.append(" / HTTP/1.0\n", 12); + //printf("TEST: '%s'\n",input.content()); + output.reset(input.content(), input.contentSize()); + // When tolerantly ignoring SP prefix this case becomes ambiguous with HTTP/0.9 simple-request) + Config.onoff.relaxed_header_parser = 1; + CPPUNIT_ASSERT_EQUAL(1, HttpParserParseReqLine(&output)); + CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status); + CPPUNIT_ASSERT_EQUAL(1, output.req.start); + CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end); + CPPUNIT_ASSERT_EQUAL(0, memcmp("/ HTTP/1.0\n", &output.buf[output.req.start],(output.req.end-output.req.start+1))); + CPPUNIT_ASSERT_EQUAL(1, output.req.m_start); + CPPUNIT_ASSERT_EQUAL(1, output.req.m_end); + CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1))); + CPPUNIT_ASSERT_EQUAL(3, output.req.u_start); + CPPUNIT_ASSERT_EQUAL(10, output.req.u_end); + CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.0", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1))); + CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start); + CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end); + CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj); + CPPUNIT_ASSERT_EQUAL(9, output.req.v_min); + input.reset(); + } // STRICT no method (an invalid format) - input.append(" / HTTP/1.0\n", 12); - //printf("TEST: '%s'\n",input.content()); - output.reset(input.content(), input.contentSize()); - // When tolerantly ignoring SP prefix this case becomes ambiguous with HTTP/0.9 simple-request) - Config.onoff.relaxed_header_parser = 0; - CPPUNIT_ASSERT_EQUAL(-1, HttpParserParseReqLine(&output)); - CPPUNIT_ASSERT_EQUAL(Http::scBadRequest, output.request_parse_status); - CPPUNIT_ASSERT_EQUAL(0, output.req.start); - CPPUNIT_ASSERT_EQUAL((int)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.req.m_start); - CPPUNIT_ASSERT_EQUAL(-1, output.req.m_end); - CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start); - CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end); - CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start); - CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end); - CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj); - CPPUNIT_ASSERT_EQUAL(0, output.req.v_min); - input.reset(); + { + input.append(" / HTTP/1.0\n", 12); + //printf("TEST: '%s'\n",input.content()); + output.reset(input.content(), input.contentSize()); + // When tolerantly ignoring SP prefix this case becomes ambiguous with HTTP/0.9 simple-request) + Config.onoff.relaxed_header_parser = 0; + CPPUNIT_ASSERT_EQUAL(-1, HttpParserParseReqLine(&output)); + CPPUNIT_ASSERT_EQUAL(Http::scBadRequest, output.request_parse_status); + CPPUNIT_ASSERT_EQUAL(0, output.req.start); + CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end); + CPPUNIT_ASSERT_EQUAL(0, memcmp(" / HTTP/1.0\n", &output.buf[output.req.start],(output.req.end-output.req.start+1))); + CPPUNIT_ASSERT_EQUAL(0, output.req.m_start); + CPPUNIT_ASSERT_EQUAL(-1, output.req.m_end); + CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start); + CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end); + CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start); + CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end); + CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj); + CPPUNIT_ASSERT_EQUAL(0, output.req.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()); - output.reset(input.content(), input.contentSize()); - CPPUNIT_ASSERT_EQUAL(1, HttpParserParseReqLine(&output)); - CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status); - CPPUNIT_ASSERT_EQUAL(0, output.req.start); - CPPUNIT_ASSERT_EQUAL((int)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.req.m_start); - CPPUNIT_ASSERT_EQUAL(3, output.req.m_end); - CPPUNIT_ASSERT(memcmp("GET\x0B", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)) == 0); - CPPUNIT_ASSERT_EQUAL(5, output.req.u_start); - CPPUNIT_ASSERT_EQUAL(5, output.req.u_end); - CPPUNIT_ASSERT(memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)) == 0); - CPPUNIT_ASSERT_EQUAL(7, output.req.v_start); - CPPUNIT_ASSERT_EQUAL(14, output.req.v_end); - CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)) == 0); - CPPUNIT_ASSERT_EQUAL(1, output.req.v_maj); - CPPUNIT_ASSERT_EQUAL(1, output.req.v_min); - input.reset(); + { + 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()); + output.reset(input.content(), input.contentSize()); + CPPUNIT_ASSERT_EQUAL(1, HttpParserParseReqLine(&output)); + CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status); + CPPUNIT_ASSERT_EQUAL(0, output.req.start); + CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end); + CPPUNIT_ASSERT_EQUAL(0, memcmp("GET\x0B / HTTP/1.1\n", &output.buf[output.req.start],(output.req.end-output.req.start+1))); + CPPUNIT_ASSERT_EQUAL(0, output.req.m_start); + CPPUNIT_ASSERT_EQUAL(3, output.req.m_end); + CPPUNIT_ASSERT_EQUAL(0, memcmp("GET\x0B", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1))); + CPPUNIT_ASSERT_EQUAL(5, output.req.u_start); + CPPUNIT_ASSERT_EQUAL(5, output.req.u_end); + CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1))); + CPPUNIT_ASSERT_EQUAL(7, output.req.v_start); + CPPUNIT_ASSERT_EQUAL(14, output.req.v_end); + CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1))); + CPPUNIT_ASSERT_EQUAL(1, output.req.v_maj); + CPPUNIT_ASSERT_EQUAL(1, output.req.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()); - output.reset(input.content(), input.contentSize()); - CPPUNIT_ASSERT_EQUAL(-1, HttpParserParseReqLine(&output)); - CPPUNIT_ASSERT_EQUAL(Http::scBadRequest, output.request_parse_status); - CPPUNIT_ASSERT_EQUAL(0, output.req.start); - CPPUNIT_ASSERT_EQUAL(-1, output.req.end); - CPPUNIT_ASSERT_EQUAL(-1, output.req.m_start); - CPPUNIT_ASSERT_EQUAL(-1, output.req.m_end); - CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start); - CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end); - CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start); - CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end); - CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj); - CPPUNIT_ASSERT_EQUAL(0, output.req.v_min); - input.reset(); + { + // 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()); + output.reset(input.content(), input.contentSize()); + CPPUNIT_ASSERT_EQUAL(-1, HttpParserParseReqLine(&output)); + CPPUNIT_ASSERT_EQUAL(Http::scBadRequest, output.request_parse_status); + CPPUNIT_ASSERT_EQUAL(0, output.req.start); + CPPUNIT_ASSERT_EQUAL(-1, output.req.end); + CPPUNIT_ASSERT_EQUAL(-1, output.req.m_start); + CPPUNIT_ASSERT_EQUAL(-1, output.req.m_end); + CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start); + CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end); + CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start); + CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end); + CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj); + CPPUNIT_ASSERT_EQUAL(0, output.req.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()); - output.reset(input.content(), input.contentSize()); - CPPUNIT_ASSERT_EQUAL(1, HttpParserParseReqLine(&output)); - CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status); - CPPUNIT_ASSERT_EQUAL(0, output.req.start); - CPPUNIT_ASSERT_EQUAL((int)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.req.m_start); - CPPUNIT_ASSERT_EQUAL(3, output.req.m_end); - CPPUNIT_ASSERT(memcmp("GET\0", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)) == 0); - CPPUNIT_ASSERT_EQUAL(5, output.req.u_start); - CPPUNIT_ASSERT_EQUAL(5, output.req.u_end); - CPPUNIT_ASSERT(memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)) == 0); - CPPUNIT_ASSERT_EQUAL(7, output.req.v_start); - CPPUNIT_ASSERT_EQUAL(14, output.req.v_end); - CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1)) == 0); - CPPUNIT_ASSERT_EQUAL(1, output.req.v_maj); - CPPUNIT_ASSERT_EQUAL(1, output.req.v_min); - input.reset(); + { + 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()); + output.reset(input.content(), input.contentSize()); + CPPUNIT_ASSERT_EQUAL(1, HttpParserParseReqLine(&output)); + CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status); + CPPUNIT_ASSERT_EQUAL(0, output.req.start); + CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end); + CPPUNIT_ASSERT_EQUAL(0, memcmp("GET\0 / HTTP/1.1\n", &output.buf[output.req.start],(output.req.end-output.req.start+1))); + CPPUNIT_ASSERT_EQUAL(0, output.req.m_start); + CPPUNIT_ASSERT_EQUAL(3, output.req.m_end); + CPPUNIT_ASSERT_EQUAL(0, memcmp("GET\0", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1))); + CPPUNIT_ASSERT_EQUAL(5, output.req.u_start); + CPPUNIT_ASSERT_EQUAL(5, output.req.u_end); + CPPUNIT_ASSERT_EQUAL(0, memcmp("/", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1))); + CPPUNIT_ASSERT_EQUAL(7, output.req.v_start); + CPPUNIT_ASSERT_EQUAL(14, output.req.v_end); + CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output.buf[output.req.v_start],(output.req.v_end-output.req.v_start+1))); + CPPUNIT_ASSERT_EQUAL(1, output.req.v_maj); + CPPUNIT_ASSERT_EQUAL(1, output.req.v_min); + input.reset(); + } // no URL (grammer otherwise correct) - input.append("GET HTTP/1.1\n", 14); - //printf("TEST: '%s'\n",input.content()); - output.reset(input.content(), input.contentSize()); - CPPUNIT_ASSERT_EQUAL(1, HttpParserParseReqLine(&output)); - CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status); - CPPUNIT_ASSERT_EQUAL(0, output.req.start); - CPPUNIT_ASSERT_EQUAL((int)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.req.m_start); - CPPUNIT_ASSERT_EQUAL(2, output.req.m_end); - CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)) == 0); - CPPUNIT_ASSERT_EQUAL(5, output.req.u_start); - CPPUNIT_ASSERT_EQUAL(12, output.req.u_end); - CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start); - CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)) == 0); - CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end); - CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj); - CPPUNIT_ASSERT_EQUAL(9, output.req.v_min); - input.reset(); + { + input.append("GET HTTP/1.1\n", 14); + //printf("TEST: '%s'\n",input.content()); + output.reset(input.content(), input.contentSize()); + CPPUNIT_ASSERT_EQUAL(1, HttpParserParseReqLine(&output)); + CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status); + CPPUNIT_ASSERT_EQUAL(0, output.req.start); + CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end); + CPPUNIT_ASSERT_EQUAL(0, memcmp("GET HTTP/1.1\n", &output.buf[output.req.start],(output.req.end-output.req.start+1))); + CPPUNIT_ASSERT_EQUAL(0, output.req.m_start); + CPPUNIT_ASSERT_EQUAL(2, output.req.m_end); + CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1))); + CPPUNIT_ASSERT_EQUAL(5, output.req.u_start); + CPPUNIT_ASSERT_EQUAL(12, output.req.u_end); + CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start); + CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1))); + CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end); + CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj); + CPPUNIT_ASSERT_EQUAL(9, output.req.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()); - output.reset(input.content(), input.contentSize()); - CPPUNIT_ASSERT_EQUAL(1, HttpParserParseReqLine(&output)); - CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status); - CPPUNIT_ASSERT_EQUAL(0, output.req.start); - CPPUNIT_ASSERT_EQUAL((int)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.req.m_start); - CPPUNIT_ASSERT_EQUAL(2, output.req.m_end); - CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)) == 0); - CPPUNIT_ASSERT_EQUAL(4, output.req.u_start); - CPPUNIT_ASSERT_EQUAL(11, output.req.u_end); - CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1)) == 0); - CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start); - CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end); - CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj); - CPPUNIT_ASSERT_EQUAL(9, output.req.v_min); - input.reset(); + { + input.append("GET HTTP/1.1\n", 13); + //printf("TEST: '%s'\n",input.content()); + output.reset(input.content(), input.contentSize()); + CPPUNIT_ASSERT_EQUAL(1, HttpParserParseReqLine(&output)); + CPPUNIT_ASSERT_EQUAL(Http::scOkay, output.request_parse_status); + CPPUNIT_ASSERT_EQUAL(0, output.req.start); + CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end); + CPPUNIT_ASSERT_EQUAL(0, memcmp("GET HTTP/1.1\n", &output.buf[output.req.start],(output.req.end-output.req.start+1))); + CPPUNIT_ASSERT_EQUAL(0, output.req.m_start); + CPPUNIT_ASSERT_EQUAL(2, output.req.m_end); + CPPUNIT_ASSERT_EQUAL(0, memcmp("GET", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1))); + CPPUNIT_ASSERT_EQUAL(4, output.req.u_start); + CPPUNIT_ASSERT_EQUAL(11, output.req.u_end); + CPPUNIT_ASSERT_EQUAL(0, memcmp("HTTP/1.1", &output.buf[output.req.u_start],(output.req.u_end-output.req.u_start+1))); + CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start); + CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end); + CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj); + CPPUNIT_ASSERT_EQUAL(9, output.req.v_min); + input.reset(); + } // binary line - input.append("\xB\xC\xE\xF\n", 5); - //printf("TEST: binary-line\n"); - output.reset(input.content(), input.contentSize()); - CPPUNIT_ASSERT_EQUAL(-1, HttpParserParseReqLine(&output)); - CPPUNIT_ASSERT_EQUAL(Http::scBadRequest, output.request_parse_status); - CPPUNIT_ASSERT_EQUAL(0, output.req.start); - CPPUNIT_ASSERT_EQUAL((int)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.req.m_start); - CPPUNIT_ASSERT_EQUAL(-1, output.req.m_end); - CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start); - CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end); - CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start); - CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end); - CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj); - CPPUNIT_ASSERT_EQUAL(0, output.req.v_min); - input.reset(); + { + input.append("\xB\xC\xE\xF\n", 5); + //printf("TEST: binary-line\n"); + output.reset(input.content(), input.contentSize()); + CPPUNIT_ASSERT_EQUAL(-1, HttpParserParseReqLine(&output)); + CPPUNIT_ASSERT_EQUAL(Http::scBadRequest, output.request_parse_status); + CPPUNIT_ASSERT_EQUAL(0, output.req.start); + CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end); + CPPUNIT_ASSERT_EQUAL(0, memcmp("\xB\xC\xE\xF\n", &output.buf[output.req.start],(output.req.end-output.req.start+1))); + CPPUNIT_ASSERT_EQUAL(0, output.req.m_start); + CPPUNIT_ASSERT_EQUAL(-1, output.req.m_end); + CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start); + CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end); + CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start); + CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end); + CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj); + CPPUNIT_ASSERT_EQUAL(0, output.req.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"); - output.reset(input.content(), input.contentSize()); - CPPUNIT_ASSERT_EQUAL(-1, HttpParserParseReqLine(&output)); - CPPUNIT_ASSERT_EQUAL(Http::scBadRequest, output.request_parse_status); - CPPUNIT_ASSERT_EQUAL(0, output.req.start); - CPPUNIT_ASSERT_EQUAL((int)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.req.m_start); - CPPUNIT_ASSERT_EQUAL(0, output.req.m_end); - CPPUNIT_ASSERT(memcmp("\t", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1)) == 0); - CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start); - CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end); - CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start); - CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end); - CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj); - CPPUNIT_ASSERT_EQUAL(0, output.req.v_min); - input.reset(); + { + // 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"); + output.reset(input.content(), input.contentSize()); + CPPUNIT_ASSERT_EQUAL(-1, HttpParserParseReqLine(&output)); + CPPUNIT_ASSERT_EQUAL(Http::scBadRequest, output.request_parse_status); + CPPUNIT_ASSERT_EQUAL(0, output.req.start); + CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req.end); + CPPUNIT_ASSERT_EQUAL(0, memcmp("\t \t \t\n", &output.buf[output.req.start],(output.req.end-output.req.start+1))); + CPPUNIT_ASSERT_EQUAL(0, output.req.m_start); + CPPUNIT_ASSERT_EQUAL(0, output.req.m_end); + CPPUNIT_ASSERT_EQUAL(0, memcmp("\t", &output.buf[output.req.m_start],(output.req.m_end-output.req.m_start+1))); + CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start); + CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end); + CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start); + CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end); + CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj); + CPPUNIT_ASSERT_EQUAL(0, output.req.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"); - output.reset(input.content(), input.contentSize()); - CPPUNIT_ASSERT_EQUAL(-1, HttpParserParseReqLine(&output)); - CPPUNIT_ASSERT_EQUAL(Http::scBadRequest, output.request_parse_status); - CPPUNIT_ASSERT_EQUAL(0, output.req.start); - CPPUNIT_ASSERT_EQUAL(-1, output.req.end); - CPPUNIT_ASSERT_EQUAL(-1, output.req.m_start); - CPPUNIT_ASSERT_EQUAL(-1, output.req.m_end); - CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start); - CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end); - CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start); - CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end); - CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj); - CPPUNIT_ASSERT_EQUAL(0, output.req.v_min); - input.reset(); + { + // 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"); + output.reset(input.content(), input.contentSize()); + CPPUNIT_ASSERT_EQUAL(-1, HttpParserParseReqLine(&output)); + CPPUNIT_ASSERT_EQUAL(Http::scBadRequest, output.request_parse_status); + CPPUNIT_ASSERT_EQUAL(0, output.req.start); + CPPUNIT_ASSERT_EQUAL(-1, output.req.end); + CPPUNIT_ASSERT_EQUAL(-1, output.req.m_start); + CPPUNIT_ASSERT_EQUAL(-1, output.req.m_end); + CPPUNIT_ASSERT_EQUAL(-1, output.req.u_start); + CPPUNIT_ASSERT_EQUAL(-1, output.req.u_end); + CPPUNIT_ASSERT_EQUAL(-1, output.req.v_start); + CPPUNIT_ASSERT_EQUAL(-1, output.req.v_end); + CPPUNIT_ASSERT_EQUAL(0, output.req.v_maj); + CPPUNIT_ASSERT_EQUAL(0, output.req.v_min); + input.reset(); + } } + +void +testHttpParser::testDripFeed() +{ + // Simulate a client drip-feeding Squid a few bytes at a time. + // extend the size of the buffer from 0 bytes to full request length + // calling the parser repeatedly as visible data grows. + + MemBuf mb; + mb.init(1024, 1024); + mb.append(" ", 12); + int garbageEnd = mb.contentSize(); + mb.append("GET http://example.com/ HTTP/1.1\r\n", 34); + int reqLineEnd = mb.contentSize(); + mb.append("\n", 1); + + HttpParser hp(mb.content(), 0); + + // only relaxed parser accepts the garbage whitespace + Config.onoff.relaxed_header_parser = 1; + + for (; hp.bufsiz < mb.contentSize(); ++hp.bufsiz) { + int parseResult = hp.parseRequestFirstLine(); + +#if WHEN_TEST_DEBUG_IS_NEEDED + printf("%d/%d :: %d, %d, %d '%c'\n", hp.bufsiz, mb.contentSize(), + garbageEnd, reqLineEnd, parseResult, + mb.content()[hp.bufsiz]); +#endif + + // before end of garbage found its a moving offset. + if (hp.bufsiz < garbageEnd) { + CPPUNIT_ASSERT_EQUAL(hp.bufsiz, (int)hp.parseOffset_); + continue; + } + + // before request line found, parse announces incomplete + if (hp.bufsiz < reqLineEnd) { + CPPUNIT_ASSERT_EQUAL(garbageEnd, (int)hp.parseOffset_); + CPPUNIT_ASSERT_EQUAL(0, parseResult); + continue; + } + + // once request line is found (AND the following \n) current parser announces success + CPPUNIT_ASSERT_EQUAL(reqLineEnd, (int)hp.parseOffset_); + CPPUNIT_ASSERT_EQUAL(1, parseResult); + } +}