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