• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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