1 // 2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) 3 // 4 // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 // 7 // Official repository: https://github.com/boostorg/beast 8 // 9 10 // Test that header file is self-contained. 11 #include <boost/beast/http/basic_parser.hpp> 12 13 #include "message_fuzz.hpp" 14 #include "test_parser.hpp" 15 16 #include <boost/beast/core/buffer_traits.hpp> 17 #include <boost/beast/core/buffers_cat.hpp> 18 #include <boost/beast/core/buffers_prefix.hpp> 19 #include <boost/beast/core/buffers_suffix.hpp> 20 #include <boost/beast/core/flat_buffer.hpp> 21 #include <boost/beast/core/multi_buffer.hpp> 22 #include <boost/beast/core/ostream.hpp> 23 #include <boost/beast/http/parser.hpp> 24 #include <boost/beast/http/string_body.hpp> 25 #include <boost/beast/test/fuzz.hpp> 26 #include <boost/beast/_experimental/unit_test/suite.hpp> 27 28 namespace boost { 29 namespace beast { 30 namespace http { 31 32 class basic_parser_test : public beast::unit_test::suite 33 { 34 public: 35 enum parse_flag 36 { 37 chunked = 1, 38 connection_keep_alive = 2, 39 connection_close = 4, 40 connection_upgrade = 8, 41 upgrade = 16, 42 }; 43 44 class expect_version 45 { 46 suite& s_; 47 int version_; 48 49 public: expect_version(suite & s,int version)50 expect_version(suite& s, int version) 51 : s_(s) 52 , version_(version) 53 { 54 } 55 56 template<class Parser> 57 void operator ()(Parser const & p) const58 operator()(Parser const& p) const 59 { 60 s_.BEAST_EXPECT(p.version == version_); 61 } 62 }; 63 64 class expect_status 65 { 66 suite& s_; 67 int status_; 68 69 public: expect_status(suite & s,int status)70 expect_status(suite& s, int status) 71 : s_(s) 72 , status_(status) 73 { 74 } 75 76 template<class Parser> 77 void operator ()(Parser const & p) const78 operator()(Parser const& p) const 79 { 80 s_.BEAST_EXPECT(p.status == status_); 81 } 82 }; 83 84 class expect_flags 85 { 86 suite& s_; 87 unsigned flags_; 88 89 public: expect_flags(suite & s,unsigned flags)90 expect_flags(suite& s, unsigned flags) 91 : s_(s) 92 , flags_(flags) 93 { 94 } 95 96 template<class Parser> 97 void operator ()(Parser const & p) const98 operator()(Parser const& p) const 99 { 100 if(flags_ & parse_flag::chunked) 101 s_.BEAST_EXPECT(p.chunked()); 102 if(flags_ & parse_flag::connection_keep_alive) 103 s_.BEAST_EXPECT(p.keep_alive()); 104 if(flags_ & parse_flag::connection_close) 105 s_.BEAST_EXPECT(! p.keep_alive()); 106 if(flags_ & parse_flag::upgrade) 107 s_.BEAST_EXPECT(! p.upgrade()); 108 } 109 }; 110 111 class expect_keepalive 112 { 113 suite& s_; 114 bool v_; 115 116 public: expect_keepalive(suite & s,bool v)117 expect_keepalive(suite& s, bool v) 118 : s_(s) 119 , v_(v) 120 { 121 } 122 123 template<class Parser> 124 void operator ()(Parser const & p) const125 operator()(Parser const& p) const 126 { 127 s_.BEAST_EXPECT(p.keep_alive() == v_); 128 } 129 }; 130 131 class expect_body 132 { 133 suite& s_; 134 std::string const& body_; 135 136 public: 137 expect_body(expect_body&&) = default; 138 expect_body(suite & s,std::string const & v)139 expect_body(suite& s, std::string const& v) 140 : s_(s) 141 , body_(v) 142 { 143 } 144 145 template<class Parser> 146 void operator ()(Parser const & p) const147 operator()(Parser const& p) const 148 { 149 s_.BEAST_EXPECT(p.body == body_); 150 } 151 }; 152 153 //-------------------------------------------------------------------------- 154 155 template<class Parser, class ConstBufferSequence, class Test> 156 typename std::enable_if< 157 net::is_const_buffer_sequence<ConstBufferSequence>::value>::type parsegrind(ConstBufferSequence const & buffers,Test const & test,bool skip=false)158 parsegrind(ConstBufferSequence const& buffers, 159 Test const& test, bool skip = false) 160 { 161 auto const size = buffer_bytes(buffers); 162 for(std::size_t i = 1; i < size - 1; ++i) 163 { 164 Parser p; 165 p.eager(true); 166 p.skip(skip); 167 error_code ec; 168 buffers_suffix<ConstBufferSequence> cb{buffers}; 169 auto n = p.put(buffers_prefix(i, cb), ec); 170 if(! BEAST_EXPECTS(! ec || 171 ec == error::need_more, ec.message())) 172 continue; 173 if(! BEAST_EXPECT(! p.is_done())) 174 continue; 175 cb.consume(n); 176 n = p.put(cb, ec); 177 if(! BEAST_EXPECTS(! ec, ec.message())) 178 continue; 179 if(! BEAST_EXPECT(n == buffer_bytes(cb))) 180 continue; 181 if(p.need_eof()) 182 { 183 p.put_eof(ec); 184 if(! BEAST_EXPECTS(! ec, ec.message())) 185 continue; 186 } 187 if(! BEAST_EXPECT(p.is_done())) 188 continue; 189 test(p); 190 } 191 for(std::size_t i = 1; i < size - 1; ++i) 192 { 193 Parser p; 194 p.eager(true); 195 error_code ec; 196 buffers_suffix<ConstBufferSequence> cb{buffers}; 197 cb.consume(i); 198 auto n = p.put(buffers_cat( 199 buffers_prefix(i, buffers), cb), ec); 200 if(! BEAST_EXPECTS(! ec, ec.message())) 201 continue; 202 if(! BEAST_EXPECT(n == size)) 203 continue; 204 if(p.need_eof()) 205 { 206 p.put_eof(ec); 207 if(! BEAST_EXPECTS(! ec, ec.message())) 208 continue; 209 } 210 test(p); 211 } 212 } 213 214 template<class Parser, class Test> 215 void parsegrind(string_view msg,Test const & test,bool skip=false)216 parsegrind(string_view msg, Test const& test, bool skip = false) 217 { 218 parsegrind<Parser>(net::const_buffer{ 219 msg.data(), msg.size()}, test, skip); 220 } 221 222 template<class Parser, class ConstBufferSequence> 223 typename std::enable_if< 224 net::is_const_buffer_sequence<ConstBufferSequence>::value>::type parsegrind(ConstBufferSequence const & buffers)225 parsegrind(ConstBufferSequence const& buffers) 226 { 227 parsegrind<Parser>(buffers, [](Parser const&){}); 228 } 229 230 template<class Parser> 231 void parsegrind(string_view msg)232 parsegrind(string_view msg) 233 { 234 parsegrind<Parser>(msg, [](Parser const&){}); 235 } 236 237 template<class Parser> 238 void failgrind(string_view msg,error_code const & result)239 failgrind(string_view msg, error_code const& result) 240 { 241 for(std::size_t i = 1; i < msg.size() - 1; ++i) 242 { 243 Parser p; 244 p.eager(true); 245 error_code ec; 246 buffers_suffix<net::const_buffer> cb{ 247 boost::in_place_init, msg.data(), msg.size()}; 248 auto n = p.put(buffers_prefix(i, cb), ec); 249 if(ec == result) 250 { 251 pass(); 252 continue; 253 } 254 if(! BEAST_EXPECTS( 255 ec == error::need_more, ec.message())) 256 continue; 257 if(! BEAST_EXPECT(! p.is_done())) 258 continue; 259 cb.consume(n); 260 n = p.put(cb, ec); 261 if(! ec) 262 p.put_eof(ec); 263 BEAST_EXPECTS(ec == result, ec.message()); 264 } 265 for(std::size_t i = 1; i < msg.size() - 1; ++i) 266 { 267 Parser p; 268 p.eager(true); 269 error_code ec; 270 p.put(buffers_cat( 271 net::const_buffer{msg.data(), i}, 272 net::const_buffer{ 273 msg.data() + i, msg.size() - i}), ec); 274 if(! ec) 275 p.put_eof(ec); 276 BEAST_EXPECTS(ec == result, ec.message()); 277 } 278 } 279 280 //-------------------------------------------------------------------------- 281 282 void testFlatten()283 testFlatten() 284 { 285 parsegrind<test_parser<true>>( 286 "GET / HTTP/1.1\r\n" 287 "\r\n" 288 ); 289 parsegrind<test_parser<true>>( 290 "POST / HTTP/1.1\r\n" 291 "Content-Length: 5\r\n" 292 "\r\n" 293 "*****" 294 ); 295 parsegrind<test_parser<false>>( 296 "HTTP/1.1 403 Not Found\r\n" 297 "\r\n" 298 ); 299 parsegrind<test_parser<false>>( 300 "HTTP/1.1 200 OK\r\n" 301 "Content-Length: 5\r\n" 302 "\r\n" 303 "*****" 304 ); 305 parsegrind<test_parser<false>>( 306 "HTTP/1.1 200 OK\r\n" 307 "Transfer-Encoding: chunked\r\n" 308 "\r\n" 309 "5;x\r\n*****\r\n" 310 "0\r\nMD5: 0xff30\r\n" 311 "\r\n" 312 ); 313 parsegrind<test_parser<false>>( 314 "HTTP/1.1 200 OK\r\n" 315 "\r\n" 316 "*****" 317 ); 318 } 319 320 void testObsFold()321 testObsFold() 322 { 323 auto const check = 324 [&](std::string const& s, string_view value) 325 { 326 std::string m = 327 "GET / HTTP/1.1\r\n" 328 "f: " + s + "\r\n" 329 "\r\n"; 330 parsegrind<request_parser<string_body>>(m, 331 [&](request_parser<string_body> const& p) 332 { 333 BEAST_EXPECT(p.get()["f"] == value); 334 }); 335 }; 336 check("x", "x"); 337 check(" x", "x"); 338 check("\tx", "x"); 339 check(" \tx", "x"); 340 check("\t x", "x"); 341 check("x ", "x"); 342 check(" x\t", "x"); 343 check("\tx \t", "x"); 344 check(" \tx\t ", "x"); 345 check("\t x \t ", "x"); 346 check("\r\n x", "x"); 347 check(" \r\n x", "x"); 348 check(" \r\n\tx", "x"); 349 check(" \r\n\t x", "x"); 350 check(" \r\n \tx", "x"); 351 check(" \r\n \r\n \r\n x \t", "x"); 352 check("xy", "xy"); 353 check("\r\n x", "x"); 354 check("\r\n x", "x"); 355 check("\r\n xy", "xy"); 356 check("\r\n \r\n \r\n x", "x"); 357 check("\r\n \r\n \r\n xy", "xy"); 358 check("x\r\n y", "x y"); 359 check("x\r\n y\r\n z ", "x y z"); 360 } 361 362 // Check that all callbacks are invoked 363 void testCallbacks()364 testCallbacks() 365 { 366 parsegrind<test_parser<true>>( 367 "GET / HTTP/1.1\r\n" 368 "User-Agent: test\r\n" 369 "Content-Length: 1\r\n" 370 "\r\n" 371 "*", 372 [&](test_parser<true> const& p) 373 { 374 BEAST_EXPECT(p.got_on_begin == 1); 375 BEAST_EXPECT(p.got_on_field == 2); 376 BEAST_EXPECT(p.got_on_header == 1); 377 BEAST_EXPECT(p.got_on_body == 1); 378 BEAST_EXPECT(p.got_on_chunk == 0); 379 BEAST_EXPECT(p.got_on_complete == 1); 380 }); 381 parsegrind<test_parser<false>>( 382 "HTTP/1.1 200 OK\r\n" 383 "Server: test\r\n" 384 "Content-Length: 1\r\n" 385 "\r\n" 386 "*", 387 [&](test_parser<false> const& p) 388 { 389 BEAST_EXPECT(p.got_on_begin == 1); 390 BEAST_EXPECT(p.got_on_field == 2); 391 BEAST_EXPECT(p.got_on_header == 1); 392 BEAST_EXPECT(p.got_on_body == 1); 393 BEAST_EXPECT(p.got_on_chunk == 0); 394 BEAST_EXPECT(p.got_on_complete == 1); 395 }); 396 parsegrind<test_parser<false>>( 397 "HTTP/1.1 200 OK\r\n" 398 "Server: test\r\n" 399 "Transfer-Encoding: chunked\r\n" 400 "\r\n" 401 "1\r\n*\r\n" 402 "0\r\n\r\n", 403 [&](test_parser<false> const& p) 404 { 405 BEAST_EXPECT(p.got_on_begin == 1); 406 BEAST_EXPECT(p.got_on_field == 2); 407 BEAST_EXPECT(p.got_on_header == 1); 408 BEAST_EXPECT(p.got_on_body == 1); 409 BEAST_EXPECT(p.got_on_chunk == 2); 410 BEAST_EXPECT(p.got_on_complete == 1); 411 }); 412 parsegrind<test_parser<false>>( 413 "HTTP/1.1 200 OK\r\n" 414 "Server: test\r\n" 415 "Transfer-Encoding: chunked\r\n" 416 "\r\n" 417 "1;x\r\n*\r\n" 418 "0\r\n\r\n", 419 [&](test_parser<false> const& p) 420 { 421 BEAST_EXPECT(p.got_on_begin == 1); 422 BEAST_EXPECT(p.got_on_field == 2); 423 BEAST_EXPECT(p.got_on_header == 1); 424 BEAST_EXPECT(p.got_on_body == 1); 425 BEAST_EXPECT(p.got_on_chunk == 2); 426 BEAST_EXPECT(p.got_on_complete == 1); 427 }); 428 } 429 430 void testRequestLine()431 testRequestLine() 432 { 433 using P = test_parser<true>; 434 435 parsegrind<P>("GET /x HTTP/1.0\r\n\r\n"); 436 parsegrind<P>("!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz / HTTP/1.0\r\n\r\n"); 437 parsegrind<P>("GET / HTTP/1.0\r\n\r\n", expect_version{*this, 10}); 438 parsegrind<P>("G / HTTP/1.1\r\n\r\n", expect_version{*this, 11}); 439 // VFALCO TODO various forms of good request-target (uri) 440 441 failgrind<P>("\tGET / HTTP/1.0\r\n" "\r\n", error::bad_method); 442 failgrind<P>("GET\x01 / HTTP/1.0\r\n" "\r\n", error::bad_method); 443 failgrind<P>("GET / HTTP/1.0\r\n" "\r\n", error::bad_target); 444 failgrind<P>("GET \x01 HTTP/1.0\r\n" "\r\n", error::bad_target); 445 failgrind<P>("GET /\x01 HTTP/1.0\r\n" "\r\n", error::bad_target); 446 // VFALCO TODO various forms of bad request-target (uri) 447 failgrind<P>("GET / HTTP/1.0\r\n" "\r\n", error::bad_version); 448 failgrind<P>("GET / _TTP/1.0\r\n" "\r\n", error::bad_version); 449 failgrind<P>("GET / H_TP/1.0\r\n" "\r\n", error::bad_version); 450 failgrind<P>("GET / HT_P/1.0\r\n" "\r\n", error::bad_version); 451 failgrind<P>("GET / HTT_/1.0\r\n" "\r\n", error::bad_version); 452 failgrind<P>("GET / HTTP_1.0\r\n" "\r\n", error::bad_version); 453 failgrind<P>("GET / HTTP/01.2\r\n" "\r\n", error::bad_version); 454 failgrind<P>("GET / HTTP/3.45\r\n" "\r\n", error::bad_version); 455 failgrind<P>("GET / HTTP/67.89\r\n" "\r\n", error::bad_version); 456 failgrind<P>("GET / HTTP/x.0\r\n" "\r\n", error::bad_version); 457 failgrind<P>("GET / HTTP/1.x\r\n" "\r\n", error::bad_version); 458 failgrind<P>("GET / HTTP/1.0 \r\n" "\r\n", error::bad_version); 459 failgrind<P>("GET / HTTP/1_0\r\n" "\r\n", error::bad_version); 460 failgrind<P>("GET / HTTP/1.0\n\r\n" "\r\n", error::bad_version); 461 failgrind<P>("GET / HTTP/1.0\n\r\r\n" "\r\n", error::bad_version); 462 failgrind<P>("GET / HTTP/1.0\r\r\n" "\r\n", error::bad_version); 463 } 464 465 void testStatusLine()466 testStatusLine() 467 { 468 using P = test_parser<false>; 469 470 parsegrind<P>("HTTP/1.0 000 OK\r\n" "\r\n", expect_status{*this, 0}); 471 parsegrind<P>("HTTP/1.1 012 OK\r\n" "\r\n", expect_status{*this, 12}); 472 parsegrind<P>("HTTP/1.0 345 OK\r\n" "\r\n", expect_status{*this, 345}); 473 parsegrind<P>("HTTP/1.0 678 OK\r\n" "\r\n", expect_status{*this, 678}); 474 parsegrind<P>("HTTP/1.0 999 OK\r\n" "\r\n", expect_status{*this, 999}); 475 parsegrind<P>("HTTP/1.0 200 \tX\r\n" "\r\n", expect_version{*this, 10}); 476 parsegrind<P>("HTTP/1.1 200 X\r\n" "\r\n", expect_version{*this, 11}); 477 parsegrind<P>("HTTP/1.0 200 \r\n" "\r\n"); 478 parsegrind<P>("HTTP/1.1 200 X \r\n" "\r\n"); 479 parsegrind<P>("HTTP/1.1 200 X\t\r\n" "\r\n"); 480 parsegrind<P>("HTTP/1.1 200 \x80\x81...\xfe\xff\r\n\r\n"); 481 parsegrind<P>("HTTP/1.1 200 !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\r\n\r\n"); 482 483 failgrind<P>("\rHTTP/1.0 200 OK\r\n" "\r\n", error::bad_version); 484 failgrind<P>("\nHTTP/1.0 200 OK\r\n" "\r\n", error::bad_version); 485 failgrind<P>(" HTTP/1.0 200 OK\r\n" "\r\n", error::bad_version); 486 failgrind<P>("_TTP/1.0 200 OK\r\n" "\r\n", error::bad_version); 487 failgrind<P>("H_TP/1.0 200 OK\r\n" "\r\n", error::bad_version); 488 failgrind<P>("HT_P/1.0 200 OK\r\n" "\r\n", error::bad_version); 489 failgrind<P>("HTT_/1.0 200 OK\r\n" "\r\n", error::bad_version); 490 failgrind<P>("HTTP_1.0 200 OK\r\n" "\r\n", error::bad_version); 491 failgrind<P>("HTTP/01.2 200 OK\r\n" "\r\n", error::bad_version); 492 failgrind<P>("HTTP/3.45 200 OK\r\n" "\r\n", error::bad_version); 493 failgrind<P>("HTTP/67.89 200 OK\r\n" "\r\n", error::bad_version); 494 failgrind<P>("HTTP/x.0 200 OK\r\n" "\r\n", error::bad_version); 495 failgrind<P>("HTTP/1.x 200 OK\r\n" "\r\n", error::bad_version); 496 failgrind<P>("HTTP/1_0 200 OK\r\n" "\r\n", error::bad_version); 497 failgrind<P>("HTTP/1.0 200 OK\r\n" "\r\n", error::bad_status); 498 failgrind<P>("HTTP/1.0 0 OK\r\n" "\r\n", error::bad_status); 499 failgrind<P>("HTTP/1.0 12 OK\r\n" "\r\n", error::bad_status); 500 failgrind<P>("HTTP/1.0 3456 OK\r\n" "\r\n", error::bad_status); 501 failgrind<P>("HTTP/1.0 200\r\n" "\r\n", error::bad_status); 502 failgrind<P>("HTTP/1.0 200 \n\r\n" "\r\n", error::bad_reason); 503 failgrind<P>("HTTP/1.0 200 \x01\r\n" "\r\n", error::bad_reason); 504 failgrind<P>("HTTP/1.0 200 \x7f\r\n" "\r\n", error::bad_reason); 505 failgrind<P>("HTTP/1.0 200 OK\n\r\n" "\r\n", error::bad_reason); 506 failgrind<P>("HTTP/1.0 200 OK\r\r\n" "\r\n", error::bad_line_ending); 507 } 508 509 void testFields()510 testFields() 511 { 512 auto const m = 513 [](std::string const& s) 514 { 515 return "GET / HTTP/1.1\r\n" + s + "\r\n"; 516 }; 517 518 using P = test_parser<true>; 519 520 parsegrind<P>(m("f:\r\n")); 521 parsegrind<P>(m("f: \r\n")); 522 parsegrind<P>(m("f:\t\r\n")); 523 parsegrind<P>(m("f: \t\r\n")); 524 parsegrind<P>(m("f: v\r\n")); 525 parsegrind<P>(m("f:\tv\r\n")); 526 parsegrind<P>(m("f:\tv \r\n")); 527 parsegrind<P>(m("f:\tv\t\r\n")); 528 parsegrind<P>(m("f:\tv\t \r\n")); 529 parsegrind<P>(m("f:\r\n \r\n")); 530 parsegrind<P>(m("f:v\r\n")); 531 parsegrind<P>(m("f: v\r\n u\r\n")); 532 parsegrind<P>(m("!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz: v\r\n")); 533 parsegrind<P>(m("f: !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x80\x81...\xfe\xff\r\n")); 534 535 failgrind<P>(m(" f: v\r\n"), error::bad_field); 536 failgrind<P>(m("\tf: v\r\n"), error::bad_field); 537 failgrind<P>(m("f : v\r\n"), error::bad_field); 538 failgrind<P>(m("f\t: v\r\n"), error::bad_field); 539 failgrind<P>(m("f: \n\r\n"), error::bad_value); 540 failgrind<P>(m("f: v\r \r\n"), error::bad_line_ending); 541 failgrind<P>(m("f: \r v\r\n"), error::bad_line_ending); 542 failgrind<P>( 543 "GET / HTTP/1.1\r\n" 544 "\r \n\r\n" 545 "\r\n", error::bad_line_ending); 546 } 547 548 void testConnectionField()549 testConnectionField() 550 { 551 auto const m = [](std::string const& s) 552 { return "GET / HTTP/1.1\r\n" + s + "\r\n"; }; 553 auto const cn = [](std::string const& s) 554 { return "GET / HTTP/1.1\r\nConnection: " + s + "\r\n"; }; 555 #if 0 556 auto const keepalive = [&](bool v) 557 { //return keepalive_f{*this, v}; return true; }; 558 #endif 559 560 using P = test_parser<true>; 561 562 parsegrind<P>(cn("close\r\n"), expect_flags{*this, parse_flag::connection_close}); 563 parsegrind<P>(cn(",close\r\n"), expect_flags{*this, parse_flag::connection_close}); 564 parsegrind<P>(cn(" close\r\n"), expect_flags{*this, parse_flag::connection_close}); 565 parsegrind<P>(cn("\tclose\r\n"), expect_flags{*this, parse_flag::connection_close}); 566 parsegrind<P>(cn("close,\r\n"), expect_flags{*this, parse_flag::connection_close}); 567 parsegrind<P>(cn("close\t\r\n"), expect_flags{*this, parse_flag::connection_close}); 568 parsegrind<P>(cn("close\r\n"), expect_flags{*this, parse_flag::connection_close}); 569 parsegrind<P>(cn(" ,\t,,close,, ,\t,,\r\n"), expect_flags{*this, parse_flag::connection_close}); 570 parsegrind<P>(cn("\r\n close\r\n"), expect_flags{*this, parse_flag::connection_close}); 571 parsegrind<P>(cn("close\r\n \r\n"), expect_flags{*this, parse_flag::connection_close}); 572 parsegrind<P>(cn("any,close\r\n"), expect_flags{*this, parse_flag::connection_close}); 573 parsegrind<P>(cn("close,any\r\n"), expect_flags{*this, parse_flag::connection_close}); 574 parsegrind<P>(cn("any\r\n ,close\r\n"), expect_flags{*this, parse_flag::connection_close}); 575 parsegrind<P>(cn("close\r\n ,any\r\n"), expect_flags{*this, parse_flag::connection_close}); 576 parsegrind<P>(cn("close,close\r\n"), expect_flags{*this, parse_flag::connection_close}); // weird but allowed 577 578 parsegrind<P>(cn("keep-alive\r\n"), expect_flags{*this, parse_flag::connection_keep_alive}); 579 parsegrind<P>(cn("keep-alive \r\n"), expect_flags{*this, parse_flag::connection_keep_alive}); 580 parsegrind<P>(cn("keep-alive\t \r\n"), expect_flags{*this, parse_flag::connection_keep_alive}); 581 parsegrind<P>(cn("keep-alive\t ,x\r\n"), expect_flags{*this, parse_flag::connection_keep_alive}); 582 parsegrind<P>(cn("\r\n keep-alive \t\r\n"), expect_flags{*this, parse_flag::connection_keep_alive}); 583 parsegrind<P>(cn("keep-alive \r\n \t \r\n"), expect_flags{*this, parse_flag::connection_keep_alive}); 584 parsegrind<P>(cn("keep-alive\r\n \r\n"), expect_flags{*this, parse_flag::connection_keep_alive}); 585 586 parsegrind<P>(cn("upgrade\r\n"), expect_flags{*this, parse_flag::connection_upgrade}); 587 parsegrind<P>(cn("upgrade \r\n"), expect_flags{*this, parse_flag::connection_upgrade}); 588 parsegrind<P>(cn("upgrade\t \r\n"), expect_flags{*this, parse_flag::connection_upgrade}); 589 parsegrind<P>(cn("upgrade\t ,x\r\n"), expect_flags{*this, parse_flag::connection_upgrade}); 590 parsegrind<P>(cn("\r\n upgrade \t\r\n"), expect_flags{*this, parse_flag::connection_upgrade}); 591 parsegrind<P>(cn("upgrade \r\n \t \r\n"), expect_flags{*this, parse_flag::connection_upgrade}); 592 parsegrind<P>(cn("upgrade\r\n \r\n"), expect_flags{*this, parse_flag::connection_upgrade}); 593 594 // VFALCO What's up with these? 595 //parsegrind<P>(cn("close,keep-alive\r\n"), expect_flags{*this, parse_flag::connection_close | parse_flag::connection_keep_alive}); 596 parsegrind<P>(cn("upgrade,keep-alive\r\n"), expect_flags{*this, parse_flag::connection_upgrade | parse_flag::connection_keep_alive}); 597 parsegrind<P>(cn("upgrade,\r\n keep-alive\r\n"), expect_flags{*this, parse_flag::connection_upgrade | parse_flag::connection_keep_alive}); 598 //parsegrind<P>(cn("close,keep-alive,upgrade\r\n"), expect_flags{*this, parse_flag::connection_close | parse_flag::connection_keep_alive | parse_flag::connection_upgrade}); 599 600 parsegrind<P>("GET / HTTP/1.1\r\n\r\n", expect_keepalive(*this, true)); 601 parsegrind<P>("GET / HTTP/1.0\r\n\r\n", expect_keepalive(*this, false)); 602 parsegrind<P>("GET / HTTP/1.0\r\n" 603 "Connection: keep-alive\r\n\r\n", expect_keepalive(*this, true)); 604 parsegrind<P>("GET / HTTP/1.1\r\n" 605 "Connection: close\r\n\r\n", expect_keepalive(*this, false)); 606 607 parsegrind<P>(cn("x\r\n"), expect_flags{*this, 0}); 608 parsegrind<P>(cn("x,y\r\n"), expect_flags{*this, 0}); 609 parsegrind<P>(cn("x ,y\r\n"), expect_flags{*this, 0}); 610 parsegrind<P>(cn("x\t,y\r\n"), expect_flags{*this, 0}); 611 parsegrind<P>(cn("keep\r\n"), expect_flags{*this, 0}); 612 parsegrind<P>(cn(",keep\r\n"), expect_flags{*this, 0}); 613 parsegrind<P>(cn(" keep\r\n"), expect_flags{*this, 0}); 614 parsegrind<P>(cn("\tnone\r\n"), expect_flags{*this, 0}); 615 parsegrind<P>(cn("keep,\r\n"), expect_flags{*this, 0}); 616 parsegrind<P>(cn("keep\t\r\n"), expect_flags{*this, 0}); 617 parsegrind<P>(cn("keep\r\n"), expect_flags{*this, 0}); 618 parsegrind<P>(cn(" ,\t,,keep,, ,\t,,\r\n"), expect_flags{*this, 0}); 619 parsegrind<P>(cn("\r\n keep\r\n"), expect_flags{*this, 0}); 620 parsegrind<P>(cn("keep\r\n \r\n"), expect_flags{*this, 0}); 621 parsegrind<P>(cn("closet\r\n"), expect_flags{*this, 0}); 622 parsegrind<P>(cn(",closet\r\n"), expect_flags{*this, 0}); 623 parsegrind<P>(cn(" closet\r\n"), expect_flags{*this, 0}); 624 parsegrind<P>(cn("\tcloset\r\n"), expect_flags{*this, 0}); 625 parsegrind<P>(cn("closet,\r\n"), expect_flags{*this, 0}); 626 parsegrind<P>(cn("closet\t\r\n"), expect_flags{*this, 0}); 627 parsegrind<P>(cn("closet\r\n"), expect_flags{*this, 0}); 628 parsegrind<P>(cn(" ,\t,,closet,, ,\t,,\r\n"), expect_flags{*this, 0}); 629 parsegrind<P>(cn("\r\n closet\r\n"), expect_flags{*this, 0}); 630 parsegrind<P>(cn("closet\r\n \r\n"), expect_flags{*this, 0}); 631 parsegrind<P>(cn("clog\r\n"), expect_flags{*this, 0}); 632 parsegrind<P>(cn("key\r\n"), expect_flags{*this, 0}); 633 parsegrind<P>(cn("uptown\r\n"), expect_flags{*this, 0}); 634 parsegrind<P>(cn("keeper\r\n \r\n"), expect_flags{*this, 0}); 635 parsegrind<P>(cn("keep-alively\r\n \r\n"), expect_flags{*this, 0}); 636 parsegrind<P>(cn("up\r\n \r\n"), expect_flags{*this, 0}); 637 parsegrind<P>(cn("upgrader\r\n \r\n"), expect_flags{*this, 0}); 638 parsegrind<P>(cn("none\r\n"), expect_flags{*this, 0}); 639 parsegrind<P>(cn("\r\n none\r\n"), expect_flags{*this, 0}); 640 641 parsegrind<P>(m("ConnectioX: close\r\n"), expect_flags{*this, 0}); 642 parsegrind<P>(m("Condor: close\r\n"), expect_flags{*this, 0}); 643 parsegrind<P>(m("Connect: close\r\n"), expect_flags{*this, 0}); 644 parsegrind<P>(m("Connections: close\r\n"), expect_flags{*this, 0}); 645 646 parsegrind<P>(m("Proxy-Connection: close\r\n"), expect_flags{*this, parse_flag::connection_close}); 647 parsegrind<P>(m("Proxy-Connection: keep-alive\r\n"), expect_flags{*this, parse_flag::connection_keep_alive}); 648 parsegrind<P>(m("Proxy-Connection: upgrade\r\n"), expect_flags{*this, parse_flag::connection_upgrade}); 649 parsegrind<P>(m("Proxy-ConnectioX: none\r\n"), expect_flags{*this, 0}); 650 parsegrind<P>(m("Proxy-Connections: 1\r\n"), expect_flags{*this, 0}); 651 parsegrind<P>(m("Proxy-Connotes: see-also\r\n"), expect_flags{*this, 0}); 652 653 failgrind<P>(cn("[\r\n"), error::bad_value); 654 failgrind<P>(cn("close[\r\n"), error::bad_value); 655 failgrind<P>(cn("close [\r\n"), error::bad_value); 656 failgrind<P>(cn("close, upgrade [\r\n"), error::bad_value); 657 failgrind<P>(cn("upgrade[]\r\n"), error::bad_value); 658 failgrind<P>(cn("keep\r\n -alive\r\n"), error::bad_value); 659 failgrind<P>(cn("keep-alive[\r\n"), error::bad_value); 660 failgrind<P>(cn("keep-alive []\r\n"), error::bad_value); 661 failgrind<P>(cn("no[ne]\r\n"), error::bad_value); 662 } 663 664 void 665 testContentLengthField() 666 { 667 using P = test_parser<true>; 668 auto const c = [](std::string const& s) 669 { return "GET / HTTP/1.1\r\nContent-Length: " + s + "\r\n"; }; 670 auto const m = [](std::string const& s) 671 { return "GET / HTTP/1.1\r\n" + s + "\r\n"; }; 672 auto const check = 673 [&](std::string const& s, std::uint64_t v) 674 { 675 parsegrind<P>(c(s), 676 [&](P const& p) 677 { 678 BEAST_EXPECT(p.content_length()); 679 BEAST_EXPECT(p.content_length() && *p.content_length() == v); 680 }, true); 681 }; 682 683 check("0\r\n", 0); 684 check("00\r\n", 0); 685 check("1\r\n", 1); 686 check("01\r\n", 1); 687 check("9\r\n", 9); 688 check("42 \r\n", 42); 689 check("42\t\r\n", 42); 690 check("42 \t \r\n", 42); 691 check("42\r\n \t \r\n", 42); 692 693 parsegrind<P>(m("Content-LengtX: 0\r\n"), expect_flags{*this, 0}); 694 parsegrind<P>(m("Content-Lengths: many\r\n"), expect_flags{*this, 0}); 695 parsegrind<P>(m("Content: full\r\n"), expect_flags{*this, 0}); 696 parsegrind<P>(m("Content-Length: 0\r\n" 697 "Content-Length: 0\r\n"), expect_flags{*this, 0}); 698 699 failgrind<P>(c("\r\n"), error::bad_content_length); 700 failgrind<P>(c("18446744073709551616\r\n"), error::bad_content_length); 701 failgrind<P>(c("0 0\r\n"), error::bad_content_length); 702 failgrind<P>(c("0 1\r\n"), error::bad_content_length); 703 failgrind<P>(c(",\r\n"), error::bad_content_length); 704 failgrind<P>(c("0,\r\n"), error::bad_content_length); 705 failgrind<P>(m("Content-Length: 0\r\n" 706 "Content-Length: 100\r\n"), error::bad_content_length); 707 } 708 709 void 710 testTransferEncodingField() 711 { 712 auto const m = [](std::string const& s) 713 { return "GET / HTTP/1.1\r\n" + s + "\r\n"; }; 714 auto const ce = [](std::string const& s) 715 { return "GET / HTTP/1.1\r\nTransfer-Encoding: " + s + "\r\n0\r\n\r\n"; }; 716 auto const te = [](std::string const& s) 717 { return "GET / HTTP/1.1\r\nTransfer-Encoding: " + s + "\r\n"; }; 718 719 using P = test_parser<true>; 720 721 parsegrind<P>(ce("chunked\r\n"), expect_flags{*this, parse_flag::chunked}); 722 parsegrind<P>(ce("chunked \r\n"), expect_flags{*this, parse_flag::chunked}); 723 parsegrind<P>(ce("chunked\t\r\n"), expect_flags{*this, parse_flag::chunked}); 724 parsegrind<P>(ce("chunked \t\r\n"), expect_flags{*this, parse_flag::chunked}); 725 parsegrind<P>(ce(" chunked\r\n"), expect_flags{*this, parse_flag::chunked}); 726 parsegrind<P>(ce("\tchunked\r\n"), expect_flags{*this, parse_flag::chunked}); 727 parsegrind<P>(ce("chunked,\r\n"), expect_flags{*this, parse_flag::chunked}); 728 parsegrind<P>(ce("chunked ,\r\n"), expect_flags{*this, parse_flag::chunked}); 729 parsegrind<P>(ce("chunked, \r\n"), expect_flags{*this, parse_flag::chunked}); 730 parsegrind<P>(ce(",chunked\r\n"), expect_flags{*this, parse_flag::chunked}); 731 parsegrind<P>(ce(", chunked\r\n"), expect_flags{*this, parse_flag::chunked}); 732 parsegrind<P>(ce(" ,chunked\r\n"), expect_flags{*this, parse_flag::chunked}); 733 parsegrind<P>(ce("chunked\r\n \r\n"), expect_flags{*this, parse_flag::chunked}); 734 parsegrind<P>(ce("\r\n chunked\r\n"), expect_flags{*this, parse_flag::chunked}); 735 parsegrind<P>(ce(",\r\n chunked\r\n"), expect_flags{*this, parse_flag::chunked}); 736 parsegrind<P>(ce("\r\n ,chunked\r\n"), expect_flags{*this, parse_flag::chunked}); 737 parsegrind<P>(ce(",\r\n chunked\r\n"), expect_flags{*this, parse_flag::chunked}); 738 parsegrind<P>(ce("gzip, chunked\r\n"), expect_flags{*this, parse_flag::chunked}); 739 parsegrind<P>(ce("gzip, chunked \r\n"), expect_flags{*this, parse_flag::chunked}); 740 parsegrind<P>(ce("gzip, \r\n chunked\r\n"), expect_flags{*this, parse_flag::chunked}); 741 742 // Technically invalid but beyond the parser's scope to detect 743 // VFALCO Look into this 744 //parsegrind<P>(ce("custom;key=\",chunked\r\n"), expect_flags{*this, parse_flag::chunked}); 745 746 parsegrind<P>(te("gzip\r\n"), expect_flags{*this, 0}); 747 parsegrind<P>(te("chunked, gzip\r\n"), expect_flags{*this, 0}); 748 parsegrind<P>(te("chunked\r\n , gzip\r\n"), expect_flags{*this, 0}); 749 parsegrind<P>(te("chunked,\r\n gzip\r\n"), expect_flags{*this, 0}); 750 parsegrind<P>(te("chunked,\r\n ,gzip\r\n"), expect_flags{*this, 0}); 751 parsegrind<P>(te("bigchunked\r\n"), expect_flags{*this, 0}); 752 parsegrind<P>(te("chunk\r\n ked\r\n"), expect_flags{*this, 0}); 753 parsegrind<P>(te("bar\r\n ley chunked\r\n"), expect_flags{*this, 0}); 754 parsegrind<P>(te("barley\r\n chunked\r\n"), expect_flags{*this, 0}); 755 756 parsegrind<P>(m("Transfer-EncodinX: none\r\n"), expect_flags{*this, 0}); 757 parsegrind<P>(m("Transfer-Encodings: 2\r\n"), expect_flags{*this, 0}); 758 parsegrind<P>(m("Transfer-Encoded: false\r\n"), expect_flags{*this, 0}); 759 760 failgrind<test_parser<false>>( 761 "HTTP/1.1 200 OK\r\n" 762 "Content-Length: 1\r\n" 763 "Transfer-Encoding: chunked\r\n" 764 "\r\n", error::bad_transfer_encoding); 765 } 766 767 void 768 testUpgradeField() 769 { 770 auto const m = [](std::string const& s) 771 { return "GET / HTTP/1.1\r\n" + s + "\r\n"; }; 772 773 using P = test_parser<true>; 774 775 parsegrind<P>(m("Upgrade:\r\n"), expect_flags{*this, parse_flag::upgrade}); 776 parsegrind<P>(m("Upgrade: \r\n"), expect_flags{*this, parse_flag::upgrade}); 777 parsegrind<P>(m("Upgrade: yes\r\n"), expect_flags{*this, parse_flag::upgrade}); 778 779 parsegrind<P>(m("Up: yes\r\n"), expect_flags{*this, 0}); 780 parsegrind<P>(m("UpgradX: none\r\n"), expect_flags{*this, 0}); 781 parsegrind<P>(m("Upgrades: 2\r\n"), expect_flags{*this, 0}); 782 parsegrind<P>(m("Upsample: 4x\r\n"), expect_flags{*this, 0}); 783 784 parsegrind<P>( 785 "GET / HTTP/1.1\r\n" 786 "Connection: upgrade\r\n" 787 "Upgrade: WebSocket\r\n" 788 "\r\n", 789 [&](P const& p) 790 { 791 BEAST_EXPECT(p.upgrade()); 792 }); 793 } 794 795 void 796 testPartial() 797 { 798 // Make sure the slow-loris defense works and that 799 // we don't get duplicate or missing fields on a split. 800 parsegrind<test_parser<true>>( 801 "GET / HTTP/1.1\r\n" 802 "a: 0\r\n" 803 "b: 1\r\n" 804 "c: 2\r\n" 805 "d: 3\r\n" 806 "e: 4\r\n" 807 "f: 5\r\n" 808 "g: 6\r\n" 809 "h: 7\r\n" 810 "i: 8\r\n" 811 "j: 9\r\n" 812 "\r\n", 813 [&](test_parser<true> const& p) 814 { 815 BEAST_EXPECT(p.fields.size() == 10); 816 BEAST_EXPECT(p.fields.at("a") == "0"); 817 BEAST_EXPECT(p.fields.at("b") == "1"); 818 BEAST_EXPECT(p.fields.at("c") == "2"); 819 BEAST_EXPECT(p.fields.at("d") == "3"); 820 BEAST_EXPECT(p.fields.at("e") == "4"); 821 BEAST_EXPECT(p.fields.at("f") == "5"); 822 BEAST_EXPECT(p.fields.at("g") == "6"); 823 BEAST_EXPECT(p.fields.at("h") == "7"); 824 BEAST_EXPECT(p.fields.at("i") == "8"); 825 BEAST_EXPECT(p.fields.at("j") == "9"); 826 }); 827 } 828 829 void 830 testLimits() 831 { 832 { 833 multi_buffer b; 834 ostream(b) << 835 "POST / HTTP/1.1\r\n" 836 "Content-Length: 2\r\n" 837 "\r\n" 838 "**"; 839 error_code ec; 840 test_parser<true> p; 841 p.header_limit(10); 842 p.eager(true); 843 p.put(b.data(), ec); 844 BEAST_EXPECTS(ec == error::header_limit, ec.message()); 845 } 846 { 847 multi_buffer b; 848 ostream(b) << 849 "POST / HTTP/1.1\r\n" 850 "Content-Length: 2\r\n" 851 "\r\n" 852 "**"; 853 error_code ec; 854 test_parser<true> p; 855 p.body_limit(1); 856 p.eager(true); 857 p.put(b.data(), ec); 858 BEAST_EXPECTS(ec == error::body_limit, ec.message()); 859 } 860 { 861 multi_buffer b; 862 ostream(b) << 863 "HTTP/1.1 200 OK\r\n" 864 "\r\n" 865 "**"; 866 error_code ec; 867 test_parser<false> p; 868 p.body_limit(1); 869 p.eager(true); 870 p.put(b.data(), ec); 871 BEAST_EXPECTS(ec == error::body_limit, ec.message()); 872 } 873 { 874 multi_buffer b; 875 ostream(b) << 876 "POST / HTTP/1.1\r\n" 877 "Transfer-Encoding: chunked\r\n" 878 "\r\n" 879 "2\r\n" 880 "**\r\n" 881 "0\r\n\r\n"; 882 error_code ec; 883 test_parser<true> p; 884 p.body_limit(1); 885 p.eager(true); 886 p.put(b.data(), ec); 887 BEAST_EXPECTS(ec == error::body_limit, ec.message()); 888 } 889 } 890 891 //-------------------------------------------------------------------------- 892 893 static 894 net::const_buffer 895 buf(string_view s) 896 { 897 return {s.data(), s.size()}; 898 } 899 900 template<class ConstBufferSequence, bool isRequest> 901 std::size_t 902 feed(ConstBufferSequence const& buffers, 903 basic_parser<isRequest>& p, error_code& ec) 904 { 905 p.eager(true); 906 return p.put(buffers, ec); 907 } 908 909 void 910 testBody() 911 { 912 parsegrind<test_parser<false>>( 913 "HTTP/1.1 200 OK\r\n" 914 "Transfer-Encoding: chunked\r\n" 915 "Content-Type: application/octet-stream\r\n" 916 "\r\n" 917 "4\r\nabcd\r\n" 918 "0\r\n\r\n" 919 ,[&](test_parser<false> const& p) 920 { 921 BEAST_EXPECT(p.body == "abcd"); 922 }); 923 parsegrind<test_parser<false>>( 924 "HTTP/1.1 200 OK\r\n" 925 "Server: test\r\n" 926 "Expect: Expires, MD5-Fingerprint\r\n" 927 "Transfer-Encoding: chunked\r\n" 928 "\r\n" 929 "5\r\n" 930 "*****\r\n" 931 "2;a;b=1;c=\"2\"\r\n" 932 "--\r\n" 933 "0;d;e=3;f=\"4\"\r\n" 934 "Expires: never\r\n" 935 "MD5-Fingerprint: -\r\n" 936 "\r\n" 937 ,[&](test_parser<false> const& p) 938 { 939 BEAST_EXPECT(p.body == "*****--"); 940 }); 941 942 parsegrind<test_parser<true>>( 943 "GET / HTTP/1.1\r\n" 944 "Content-Length: 1\r\n" 945 "\r\n" 946 "1", 947 expect_body(*this, "1")); 948 949 parsegrind<test_parser<false>>( 950 "HTTP/1.0 200 OK\r\n" 951 "\r\n" 952 "hello", 953 expect_body(*this, "hello")); 954 955 parsegrind<test_parser<true>>(buffers_cat( 956 buf("GET / HTTP/1.1\r\n" 957 "Content-Length: 10\r\n" 958 "\r\n"), 959 buf("12"), 960 buf("345"), 961 buf("67890"))); 962 963 // request without Content-Length or 964 // Transfer-Encoding: chunked has no body. 965 { 966 error_code ec; 967 test_parser<true> p; 968 feed(buf( 969 "GET / HTTP/1.0\r\n" 970 "\r\n" 971 ), p, ec); 972 BEAST_EXPECTS(! ec, ec.message()); 973 BEAST_EXPECT(p.is_done()); 974 } 975 { 976 error_code ec; 977 test_parser<true> p; 978 feed(buf( 979 "GET / HTTP/1.1\r\n" 980 "\r\n" 981 ), p, ec); 982 BEAST_EXPECTS(! ec, ec.message()); 983 BEAST_EXPECT(p.is_done()); 984 } 985 986 // response without Content-Length or 987 // Transfer-Encoding: chunked requires eof. 988 { 989 error_code ec; 990 test_parser<false> p; 991 feed(buf( 992 "HTTP/1.0 200 OK\r\n" 993 "\r\n" 994 ), p, ec); 995 BEAST_EXPECTS(! ec, ec.message()); 996 BEAST_EXPECT(! p.is_done()); 997 BEAST_EXPECT(p.need_eof()); 998 } 999 1000 // 304 "Not Modified" response does not require eof 1001 { 1002 error_code ec; 1003 test_parser<false> p; 1004 feed(buf( 1005 "HTTP/1.0 304 Not Modified\r\n" 1006 "\r\n" 1007 ), p, ec); 1008 BEAST_EXPECTS(! ec, ec.message()); 1009 BEAST_EXPECT(p.is_done()); 1010 } 1011 1012 // Chunked response does not require eof 1013 { 1014 error_code ec; 1015 test_parser<false> p; 1016 feed(buf( 1017 "HTTP/1.1 200 OK\r\n" 1018 "Transfer-Encoding: chunked\r\n" 1019 "\r\n" 1020 ), p, ec); 1021 BEAST_EXPECTS(! ec, ec.message()); 1022 BEAST_EXPECT(! p.is_done()); 1023 feed(buf( 1024 "0\r\n\r\n" 1025 ), p, ec); 1026 BEAST_EXPECTS(! ec, ec.message()); 1027 BEAST_EXPECT(p.is_done()); 1028 } 1029 1030 // restart: 1.0 assumes Connection: close 1031 { 1032 error_code ec; 1033 test_parser<true> p; 1034 feed(buf( 1035 "GET / HTTP/1.0\r\n" 1036 "\r\n" 1037 ), p, ec); 1038 BEAST_EXPECTS(! ec, ec.message()); 1039 BEAST_EXPECT(p.is_done()); 1040 } 1041 1042 // restart: 1.1 assumes Connection: keep-alive 1043 { 1044 error_code ec; 1045 test_parser<true> p; 1046 feed(buf( 1047 "GET / HTTP/1.1\r\n" 1048 "\r\n" 1049 ), p, ec); 1050 BEAST_EXPECTS(! ec, ec.message()); 1051 BEAST_EXPECT(p.is_done()); 1052 } 1053 1054 failgrind<test_parser<true>>( 1055 "GET / HTTP/1.1\r\n" 1056 "Content-Length: 1\r\n" 1057 "\r\n", 1058 error::partial_message); 1059 } 1060 1061 //-------------------------------------------------------------------------- 1062 1063 // https://github.com/boostorg/beast/issues/430 1064 void 1065 testIssue430() 1066 { 1067 parsegrind<test_parser<false>>( 1068 "HTTP/1.1 200 OK\r\n" 1069 "Transfer-Encoding: chunked\r\n" 1070 "Content-Type: application/octet-stream\r\n" 1071 "\r\n" 1072 "4\r\nabcd\r\n" 1073 "0\r\n\r\n"); 1074 } 1075 1076 // https://github.com/boostorg/beast/issues/452 1077 void 1078 testIssue452() 1079 { 1080 error_code ec; 1081 test_parser<true> p; 1082 p.eager(true); 1083 string_view s = 1084 "GET / HTTP/1.1\r\n" 1085 "\r\n" 1086 "die!"; 1087 p.put(net::buffer( 1088 s.data(), s.size()), ec); 1089 if(! BEAST_EXPECTS(! ec, ec.message())) 1090 return; 1091 BEAST_EXPECT(p.is_done()); 1092 } 1093 1094 // https://github.com/boostorg/beast/issues/496 1095 void 1096 testIssue496() 1097 { 1098 // The bug affected hex parsing with leading zeroes 1099 using P = test_parser<false>; 1100 parsegrind<P>( 1101 "HTTP/1.1 200 OK\r\n" 1102 "Transfer-Encoding: chunked\r\n" 1103 "Content-Type: application/octet-stream\r\n" 1104 "\r\n" 1105 "0004\r\nabcd\r\n" 1106 "0\r\n\r\n" 1107 ,[&](P const& p) 1108 { 1109 BEAST_EXPECT(p.body == "abcd"); 1110 }); 1111 } 1112 1113 // https://github.com/boostorg/beast/issues/692 1114 void 1115 testIssue692() 1116 { 1117 error_code ec; 1118 test_parser<false> p; 1119 p.eager(true); 1120 string_view s = 1121 "HTTP/1.1 101 Switching Protocols\r\n" 1122 "Content-Length: 2147483648\r\n" 1123 "\r\n"; 1124 p.put(net::buffer( 1125 s.data(), s.size()), ec); 1126 if(! BEAST_EXPECTS(! ec, ec.message())) 1127 return; 1128 BEAST_EXPECT(p.is_done()); 1129 } 1130 1131 //-------------------------------------------------------------------------- 1132 1133 void 1134 testFuzz() 1135 { 1136 auto const grind = 1137 [&](string_view s) 1138 { 1139 static_string<100> ss{s}; 1140 test::fuzz_rand r; 1141 test::fuzz(ss, 4, 5, r, 1142 [&](string_view s) 1143 { 1144 error_code ec; 1145 test_parser<false> p; 1146 p.eager(true); 1147 p.put(net::const_buffer{ 1148 s.data(), s.size()}, ec); 1149 }); 1150 }; 1151 auto const good = 1152 [&](string_view s) 1153 { 1154 std::string msg = 1155 "HTTP/1.1 200 OK\r\n" 1156 "Transfer-Encoding: chunked\r\n" 1157 "\r\n" 1158 "0" + std::string(s) + "\r\n" 1159 "\r\n"; 1160 error_code ec; 1161 test_parser<false> p; 1162 p.eager(true); 1163 p.put(net::const_buffer{ 1164 msg.data(), msg.size()}, ec); 1165 BEAST_EXPECTS(! ec, ec.message()); 1166 grind(msg); 1167 }; 1168 auto const bad = 1169 [&](string_view s) 1170 { 1171 std::string msg = 1172 "HTTP/1.1 200 OK\r\n" 1173 "Transfer-Encoding: chunked\r\n" 1174 "\r\n" 1175 "0" + std::string(s) + "\r\n" 1176 "\r\n"; 1177 error_code ec; 1178 test_parser<false> p; 1179 p.eager(true); 1180 p.put(net::const_buffer{ 1181 msg.data(), msg.size()}, ec); 1182 BEAST_EXPECT(ec); 1183 grind(msg); 1184 }; 1185 chunkExtensionsTest(good, bad); 1186 } 1187 1188 //-------------------------------------------------------------------------- 1189 1190 void 1191 testRegression1() 1192 { 1193 // crash_00cda0b02d5166bd1039ddb3b12618cd80da75f3 1194 unsigned char buf[] ={ 1195 0x4C,0x4F,0x43,0x4B,0x20,0x2F,0x25,0x65,0x37,0x6C,0x59,0x3B,0x2F,0x3B,0x3B,0x25,0x30,0x62,0x38,0x3D,0x70,0x2F,0x72,0x20, 1196 0x48,0x54,0x54,0x50,0x2F,0x31,0x2E,0x31,0x0D,0x0A,0x41,0x63,0x63,0x65,0x70,0x74,0x2D,0x45,0x6E,0x63,0x6F,0x64,0x69,0x6E, 1197 0x67,0x3A,0x0D,0x0A,0x09,0x20,0xEE,0x0D,0x0A,0x4F,0x72,0x69,0x67,0x69,0x6E,0x61,0x6C,0x2D,0x4D,0x65,0x73,0x73,0x61,0x67, 1198 0x65,0x2D,0x49,0x44,0x3A,0xEB,0x09,0x09,0x09,0x09,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3A,0x20,0x0D,0x0A,0x09,0x20, 1199 0xF7,0x44,0x9B,0xA5,0x06,0x9F,0x0D,0x0A,0x52,0x65,0x73,0x65,0x6E,0x74,0x2D,0x44,0x61,0x74,0x65,0x3A,0xF4,0x0D,0x0A,0x41, 1200 0x6C,0x74,0x2D,0x53,0x76,0x63,0x3A,0x20,0x0D,0x0A,0x54,0x72,0x61,0x69,0x6C,0x65,0x72,0x3A,0x20,0x20,0x09,0x20,0x20,0x20, 1201 0x0D,0x0A,0x4C,0x69,0x73,0x74,0x2D,0x49,0x44,0x3A,0xA6,0x6B,0x86,0x09,0x09,0x20,0x09,0x0D,0x0A,0x41,0x6C,0x74,0x65,0x72, 1202 0x6E,0x61,0x74,0x65,0x2D,0x52,0x65,0x63,0x69,0x70,0x69,0x65,0x6E,0x74,0x3A,0xF3,0x13,0xE3,0x22,0x9D,0xEF,0xFB,0x84,0x71, 1203 0x4A,0xCC,0xBC,0x96,0xF7,0x5B,0x72,0xF1,0xF2,0x0D,0x0A,0x4C,0x6F,0x63,0x61,0x74,0x69,0x6F,0x6E,0x3A,0x20,0x0D,0x0A,0x41, 1204 0x63,0x63,0x65,0x70,0x74,0x2D,0x41,0x64,0x64,0x69,0x74,0x69,0x6F,0x6E,0x73,0x3A,0x20,0x0D,0x0A,0x4D,0x4D,0x48,0x53,0x2D, 1205 0x4F,0x72,0x69,0x67,0x69,0x6E,0x61,0x74,0x6F,0x72,0x2D,0x50,0x4C,0x41,0x44,0x3A,0x20,0x0D,0x0A,0x4F,0x72,0x69,0x67,0x69, 1206 0x6E,0x61,0x6C,0x2D,0x53,0x65,0x6E,0x64,0x65,0x72,0x3A,0x20,0x0D,0x0A,0x4F,0x72,0x69,0x67,0x69,0x6E,0x61,0x6C,0x2D,0x53, 1207 0x65,0x6E,0x64,0x65,0x72,0x3A,0x0D,0x0A,0x50,0x49,0x43,0x53,0x2D,0x4C,0x61,0x62,0x65,0x6C,0x3A,0x0D,0x0A,0x20,0x09,0x0D, 1208 0x0A,0x49,0x66,0x3A,0x20,0x40,0xC1,0x50,0x5C,0xD6,0xC3,0x86,0xFC,0x8D,0x5C,0x7C,0x96,0x45,0x0D,0x0A,0x4D,0x4D,0x48,0x53, 1209 0x2D,0x45,0x78,0x65,0x6D,0x70,0x74,0x65,0x64,0x2D,0x41,0x64,0x64,0x72,0x65,0x73,0x73,0x3A,0x0D,0x0A,0x49,0x6E,0x6A,0x65, 1210 0x63,0x74,0x69,0x6F,0x6E,0x2D,0x49,0x6E,0x66,0x6F,0x3A,0x20,0x0D,0x0A,0x43,0x6F,0x6E,0x74,0x65,0x74,0x6E,0x2D,0x4C,0x65, 1211 0x6E,0x67,0x74,0x68,0x3A,0x20,0x30,0x0D,0x0A,0x0D,0x0A 1212 }; 1213 1214 error_code ec; 1215 test_parser<true> p; 1216 feed(net::buffer(buf, sizeof(buf)), p, ec); 1217 BEAST_EXPECT(ec); 1218 } 1219 1220 void 1221 testIssue1211() 1222 { 1223 using base = detail::basic_parser_base; 1224 auto const good = 1225 [&](string_view s, std::uint32_t v0) 1226 { 1227 std::uint64_t v; 1228 auto const result = 1229 base::parse_dec(s, v); 1230 if(BEAST_EXPECTS(result, s)) 1231 BEAST_EXPECTS(v == v0, s); 1232 }; 1233 auto const bad = 1234 [&](string_view s) 1235 { 1236 std::uint64_t v; 1237 auto const result = 1238 base::parse_dec(s, v); 1239 BEAST_EXPECTS(! result, s); 1240 }; 1241 good("0", 0); 1242 good("00", 0); 1243 good("001", 1); 1244 good("255", 255); 1245 good("65535", 65535); 1246 good("65536", 65536); 1247 good("4294967295", 4294967295); 1248 bad (""); 1249 bad (" "); 1250 bad (" 0"); 1251 bad ("0 "); 1252 bad ("-1"); 1253 bad ("18446744073709551616"); // max(uint64) + 1 1254 } 1255 1256 void 1257 testIssue1267() 1258 { 1259 using base = detail::basic_parser_base; 1260 auto const good = 1261 [&](string_view s, std::uint64_t v0) 1262 { 1263 std::uint64_t v; 1264 auto it = s.data(); 1265 auto const result = 1266 base::parse_hex(it, v); 1267 if(BEAST_EXPECTS(result, s)) 1268 BEAST_EXPECTS(v == v0, s); 1269 }; 1270 auto const bad = 1271 [&](string_view s) 1272 { 1273 std::uint64_t v; 1274 auto it = s.data(); 1275 auto const result = 1276 base::parse_hex(it, v); 1277 BEAST_EXPECTS(! result, s); 1278 }; 1279 good("f\r\n", 15); 1280 good("ff\r\n", 255); 1281 good("ffff\r\n", 65535); 1282 good("ffffffffr\n", 4294967295); 1283 good("ffffffffffffffff\r\n", 18446744073709551615ULL); 1284 bad ("\r\n"); 1285 bad ("g\r\n"); 1286 bad ("10000000000000000\r\n"); 1287 bad ("ffffffffffffffffffffff\r\n"); 1288 } 1289 1290 //-------------------------------------------------------------------------- 1291 1292 // https://github.com/boostorg/beast/issues/1734 1293 1294 void 1295 testIssue1734() 1296 { 1297 // Ensure more than one buffer, this is to avoid an optimized path in 1298 // basic_parser::put(ConstBufferSequence const&,...) which avoids 1299 // buffer flattening. 1300 auto multibufs = [](multi_buffer::const_buffers_type buffers) { 1301 std::vector<net::const_buffer> bs; 1302 for (auto b : buffers_range(buffers)) 1303 bs.push_back(b); 1304 while (std::distance(bs.begin(), bs.end()) < 2) { 1305 bs.push_back({}); 1306 } 1307 return bs; 1308 }; 1309 1310 // Buffers must be bigger than max_stack_buffer to force flattening 1311 // in basic_parser::put(ConstBufferSequence const&,...) 1312 std::string first_chunk_data( 1313 2 * basic_parser<false>::max_stack_buffer + 1, 'x'); 1314 1315 std::string second_chunk_data_part1( 1316 basic_parser<false>::max_stack_buffer + 2, 'x'); 1317 std::string second_chunk_data_part2( 1318 basic_parser<false>::max_stack_buffer + 1, 'x'); 1319 1320 multi_buffer b; 1321 parser<false, string_body> p; 1322 p.eager(true); 1323 error_code ec; 1324 std::size_t used; 1325 1326 ostream(b) << 1327 "HTTP/1.1 200 OK\r\n" 1328 "Server: test\r\n" 1329 "Transfer-Encoding: chunked\r\n" 1330 "\r\n"; 1331 1332 used = p.put(b.data(), ec); 1333 b.consume(used); 1334 1335 BEAST_EXPECT(net::buffer_size(b.data()) == 0); 1336 BEAST_EXPECTS(!ec, ec.message()); 1337 BEAST_EXPECT(!p.is_done()); 1338 BEAST_EXPECT(p.is_header_done()); 1339 1340 ostream(b) << 1341 std::hex << 1342 first_chunk_data.size() << "\r\n" << 1343 first_chunk_data << "\r\n"; 1344 1345 // First chunk 1346 used = p.put(multibufs(b.data()), ec); 1347 b.consume(used); 1348 1349 BEAST_EXPECTS(ec == error::need_more, ec.message()); 1350 BEAST_EXPECT(!p.is_done()); 1351 1352 ostream(b) << 1353 std::hex << 1354 (second_chunk_data_part1.size() + 1355 second_chunk_data_part2.size() ) << "\r\n" << 1356 second_chunk_data_part1; 1357 1358 // Second chunk, part 1 1359 used = p.put(multibufs(b.data()), ec); 1360 b.consume(used); 1361 1362 BEAST_EXPECTS(!ec, ec.message()); 1363 BEAST_EXPECT(!p.is_done()); 1364 1365 ostream(b) << 1366 second_chunk_data_part2 << "\r\n" 1367 << "0\r\n\r\n"; 1368 1369 // Second chunk, part 2 1370 used = p.put(multibufs(b.data()), ec); 1371 b.consume(used); 1372 1373 BEAST_EXPECTS(!ec, ec.message()); // <-- Error: bad chunk 1374 if(p.need_eof()) 1375 { 1376 p.put_eof(ec); 1377 BEAST_EXPECTS(! ec, ec.message()); 1378 } 1379 BEAST_EXPECT(p.is_done()); 1380 } 1381 1382 void 1383 testChunkedOverflow() 1384 { 1385 { 1386 const std::string hdr = 1387 "HTTP/1.1 200 OK" "\r\n" 1388 "Server: test" "\r\n" 1389 "Transfer-Encoding: chunked" "\r\n" 1390 "\r\n"; 1391 const std::string chunk1 = 1392 "10000000000000000" "\r\n" 1393 "data..."; 1394 test_parser<false> p; 1395 error_code ec; 1396 p.put(net::buffer(hdr), ec); 1397 BEAST_EXPECT(!ec); 1398 BEAST_EXPECT(p.is_header_done()); 1399 auto bt = p.put(net::buffer(chunk1), ec); 1400 BEAST_EXPECT(bt == 0); 1401 BEAST_EXPECT(ec == error::bad_chunk); 1402 } 1403 { 1404 const std::string hdr = 1405 "HTTP/1.1 200 OK" "\r\n" 1406 "Server: test" "\r\n" 1407 "Transfer-Encoding: chunked" "\r\n" 1408 "\r\n" 1409 "1" "\r\n" 1410 "x" "\r\n"; 1411 const std::string chunk2 = 1412 "FFFFFFFFFFFFFFFF" "\r\n" 1413 "data..."; 1414 test_parser<false> p; 1415 p.eager(true); 1416 error_code ec; 1417 flat_buffer fb; 1418 fb.commit(net::buffer_copy(fb.prepare(10000), net::buffer(hdr))); 1419 fb.consume(p.put(fb.data(), ec)); 1420 BEAST_EXPECT(p.is_header_done()); 1421 BEAST_EXPECT(ec = error::need_more); 1422 fb.commit(net::buffer_copy(fb.prepare(10000), net::buffer(chunk2))); 1423 auto bt = p.put(fb.data(), ec); 1424 BEAST_EXPECT(bt == 0); 1425 BEAST_EXPECT(ec == error::body_limit); 1426 } 1427 { 1428 const std::string hdr = 1429 "HTTP/1.1 200 OK" "\r\n" 1430 "Server: test" "\r\n" 1431 "Transfer-Encoding: chunked" "\r\n" 1432 "\r\n" 1433 "1" "\r\n" 1434 "x" "\r\n"; 1435 const std::string chunk2 = 1436 "FFFFFFFFFFFFFFFF" "\r\n" 1437 "data..."; 1438 test_parser<false> p; 1439 p.eager(true); 1440 p.body_limit(boost::none); 1441 error_code ec; 1442 flat_buffer fb; 1443 fb.commit(net::buffer_copy(fb.prepare(10000), net::buffer(hdr))); 1444 fb.consume(p.put(fb.data(), ec)); 1445 BEAST_EXPECT(p.is_header_done()); 1446 BEAST_EXPECTS(ec = error::need_more, ec.message()); 1447 fb.commit(net::buffer_copy(fb.prepare(10000), net::buffer(chunk2))); 1448 auto bt = p.put(fb.data(), ec); 1449 BEAST_EXPECT(bt == 27); 1450 BEAST_EXPECT(!ec); 1451 } 1452 } 1453 1454 void testChunkedBodySize() 1455 { 1456 string_view resp = 1457 "HTTP/1.1 200 OK\r\n" 1458 "Server: test\r\n" 1459 "Transfer-Encoding: chunked\r\n" 1460 "\r\n" 1461 1462 // chunk 1 1463 "4\r\n" 1464 "Wiki\r\n" 1465 1466 // chunk 2 1467 "5\r\n" 1468 "pedia\r\n" 1469 1470 // chunk 3 1471 "E\r\n" 1472 " in\r\n" 1473 "\r\n" 1474 "chunks.\r\n" 1475 1476 // end 1477 "0\r\n" 1478 "\r\n"; 1479 1480 { // body limit not exceeded 1481 test_parser<false> p; 1482 p.eager(true); 1483 p.body_limit(23); 1484 error_code ec; 1485 p.put(net::buffer(resp.data(), resp.size()), ec); 1486 BEAST_EXPECT(!ec); 1487 p.put_eof(ec); 1488 BEAST_EXPECT(!ec); 1489 } 1490 1491 { // body limit exceeded 1492 test_parser<false> p; 1493 p.eager(true); 1494 p.body_limit(22); 1495 error_code ec; 1496 p.put(net::buffer(resp.data(), resp.size()), ec); 1497 BEAST_EXPECT(ec == error::body_limit); 1498 p.put_eof(ec); 1499 BEAST_EXPECT(ec == error::partial_message); 1500 } 1501 } 1502 1503 //-------------------------------------------------------------------------- 1504 1505 void 1506 run() override 1507 { 1508 testFlatten(); 1509 testObsFold(); 1510 testCallbacks(); 1511 testRequestLine(); 1512 testStatusLine(); 1513 testFields(); 1514 testConnectionField(); 1515 testContentLengthField(); 1516 testTransferEncodingField(); 1517 testUpgradeField(); 1518 testPartial(); 1519 testLimits(); 1520 testBody(); 1521 testIssue430(); 1522 testIssue452(); 1523 testIssue496(); 1524 testIssue692(); 1525 testFuzz(); 1526 testRegression1(); 1527 testIssue1211(); 1528 testIssue1267(); 1529 testChunkedOverflow(); 1530 testChunkedBodySize(); 1531 } 1532 }; 1533 1534 BEAST_DEFINE_TESTSUITE(beast,http,basic_parser); 1535 1536 } // http 1537 } // beast 1538 } // boost 1539