]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/boost/libs/beast/test/beast/http/basic_parser.cpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / beast / test / beast / http / basic_parser.cpp
index f1f2d538e9cae217d50985067cfedc6e3d312916..2cfa7b9d450c17f6652688e7718fa98169998f5e 100644 (file)
@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -13,6 +13,7 @@
 #include "message_fuzz.hpp"
 #include "test_parser.hpp"
 
+#include <boost/beast/core/buffer_traits.hpp>
 #include <boost/beast/core/buffers_cat.hpp>
 #include <boost/beast/core/buffers_prefix.hpp>
 #include <boost/beast/core/buffers_suffix.hpp>
@@ -21,7 +22,7 @@
 #include <boost/beast/http/parser.hpp>
 #include <boost/beast/http/string_body.hpp>
 #include <boost/beast/test/fuzz.hpp>
-#include <boost/beast/unit_test/suite.hpp>
+#include <boost/beast/_experimental/unit_test/suite.hpp>
 
 namespace boost {
 namespace beast {
@@ -152,11 +153,11 @@ public:
 
     template<class Parser, class ConstBufferSequence, class Test>
     typename std::enable_if<
-        boost::asio::is_const_buffer_sequence<ConstBufferSequence>::value>::type
+        net::is_const_buffer_sequence<ConstBufferSequence>::value>::type
     parsegrind(ConstBufferSequence const& buffers,
         Test const& test, bool skip = false)
     {
-        auto const size = boost::asio::buffer_size(buffers);
+        auto const size = buffer_bytes(buffers);
         for(std::size_t i = 1; i < size - 1; ++i)
         {
             Parser p;
@@ -174,7 +175,7 @@ public:
             n = p.put(cb, ec);
             if(! BEAST_EXPECTS(! ec, ec.message()))
                 continue;
-            if(! BEAST_EXPECT(n == boost::asio::buffer_size(cb)))
+            if(! BEAST_EXPECT(n == buffer_bytes(cb)))
                 continue;
             if(p.need_eof())
             {
@@ -213,13 +214,13 @@ public:
     void
     parsegrind(string_view msg, Test const& test, bool skip = false)
     {
-        parsegrind<Parser>(boost::asio::const_buffer{
+        parsegrind<Parser>(net::const_buffer{
             msg.data(), msg.size()}, test, skip);
     }
 
     template<class Parser, class ConstBufferSequence>
     typename std::enable_if<
-        boost::asio::is_const_buffer_sequence<ConstBufferSequence>::value>::type
+        net::is_const_buffer_sequence<ConstBufferSequence>::value>::type
     parsegrind(ConstBufferSequence const& buffers)
     {
         parsegrind<Parser>(buffers, [](Parser const&){});
@@ -241,7 +242,7 @@ public:
             Parser p;
             p.eager(true);
             error_code ec;
-            buffers_suffix<boost::asio::const_buffer> cb{
+            buffers_suffix<net::const_buffer> cb{
                 boost::in_place_init, msg.data(), msg.size()};
             auto n = p.put(buffers_prefix(i, cb), ec);
             if(ec == result)
@@ -266,8 +267,8 @@ public:
             p.eager(true);
             error_code ec;
             p.put(buffers_cat(
-                boost::asio::const_buffer{msg.data(), i},
-                boost::asio::const_buffer{
+                net::const_buffer{msg.data(), i},
+                net::const_buffer{
                     msg.data() + i, msg.size() - i}), ec);
             if(! ec)
                 p.put_eof(ec);
@@ -827,7 +828,7 @@ public:
     {
         {
             multi_buffer b;
-            ostream(b) << 
+            ostream(b) <<
                 "POST / HTTP/1.1\r\n"
                 "Content-Length: 2\r\n"
                 "\r\n"
@@ -841,7 +842,7 @@ public:
         }
         {
             multi_buffer b;
-            ostream(b) << 
+            ostream(b) <<
                 "POST / HTTP/1.1\r\n"
                 "Content-Length: 2\r\n"
                 "\r\n"
@@ -855,7 +856,7 @@ public:
         }
         {
             multi_buffer b;
-            ostream(b) << 
+            ostream(b) <<
                 "HTTP/1.1 200 OK\r\n"
                 "\r\n"
                 "**";
@@ -868,7 +869,7 @@ public:
         }
         {
             multi_buffer b;
-            ostream(b) << 
+            ostream(b) <<
                 "POST / HTTP/1.1\r\n"
                 "Transfer-Encoding: chunked\r\n"
                 "\r\n"
@@ -887,16 +888,16 @@ public:
     //--------------------------------------------------------------------------
 
     static
-    boost::asio::const_buffer
+    net::const_buffer
     buf(string_view s)
     {
         return {s.data(), s.size()};
     }
 
-    template<class ConstBufferSequence, bool isRequest, class Derived>
+    template<class ConstBufferSequence, bool isRequest>
     std::size_t
     feed(ConstBufferSequence const& buffers,
-        basic_parser<isRequest, Derived>& p, error_code& ec)
+        basic_parser<isRequest>& p, error_code& ec)
     {
         p.eager(true);
         return p.put(buffers, ec);
@@ -1080,7 +1081,7 @@ public:
             "GET / HTTP/1.1\r\n"
             "\r\n"
             "die!";
-        p.put(boost::asio::buffer(
+        p.put(net::buffer(
             s.data(), s.size()), ec);
         if(! BEAST_EXPECTS(! ec, ec.message()))
             return;
@@ -1117,7 +1118,7 @@ public:
             "HTTP/1.1 101 Switching Protocols\r\n"
             "Content-Length: 2147483648\r\n"
             "\r\n";
-        p.put(boost::asio::buffer(
+        p.put(net::buffer(
             s.data(), s.size()), ec);
         if(! BEAST_EXPECTS(! ec, ec.message()))
             return;
@@ -1140,7 +1141,7 @@ public:
                 error_code ec;
                 test_parser<false> p;
                 p.eager(true);
-                p.put(boost::asio::const_buffer{
+                p.put(net::const_buffer{
                     s.data(), s.size()}, ec);
             });
         };
@@ -1151,12 +1152,12 @@ public:
                 "HTTP/1.1 200 OK\r\n"
                 "Transfer-Encoding: chunked\r\n"
                 "\r\n"
-                "0" + s.to_string() + "\r\n"
+                "0" + std::string(s) + "\r\n"
                 "\r\n";
             error_code ec;
             test_parser<false> p;
             p.eager(true);
-            p.put(boost::asio::const_buffer{
+            p.put(net::const_buffer{
                 msg.data(), msg.size()}, ec);
             BEAST_EXPECTS(! ec, ec.message());
             grind(msg);
@@ -1168,12 +1169,12 @@ public:
                 "HTTP/1.1 200 OK\r\n"
                 "Transfer-Encoding: chunked\r\n"
                 "\r\n"
-                "0" + s.to_string() + "\r\n"
+                "0" + std::string(s) + "\r\n"
                 "\r\n";
             error_code ec;
             test_parser<false> p;
             p.eager(true);
-            p.put(boost::asio::const_buffer{
+            p.put(net::const_buffer{
                 msg.data(), msg.size()}, ec);
             BEAST_EXPECT(ec);
             grind(msg);
@@ -1209,10 +1210,172 @@ public:
 
         error_code ec;
         test_parser<true> p;
-        feed(boost::asio::buffer(buf, sizeof(buf)), p, ec);
+        feed(net::buffer(buf, sizeof(buf)), p, ec);
         BEAST_EXPECT(ec);
     }
 
+    void
+    testIssue1211()
+    {
+        using base = detail::basic_parser_base;
+        auto const good =
+            [&](string_view s, std::uint32_t v0)
+            {
+                std::uint64_t v;
+                auto const result =
+                    base::parse_dec(s, v);
+                if(BEAST_EXPECTS(result, s))
+                    BEAST_EXPECTS(v == v0, s);
+            };
+        auto const bad =
+            [&](string_view s)
+            {
+                std::uint64_t v;
+                auto const result =
+                    base::parse_dec(s, v);
+                BEAST_EXPECTS(! result, s);
+            };
+        good("0",           0);
+        good("00",          0);
+        good("001",         1);
+        good("255",         255);
+        good("65535",       65535);
+        good("65536",       65536);
+        good("4294967295",  4294967295);
+        bad ("");
+        bad (" ");
+        bad (" 0");
+        bad ("0 ");
+        bad ("-1");
+        bad ("18446744073709551616"); // max(uint64) + 1
+    }
+
+    void
+    testIssue1267()
+    {
+        using base = detail::basic_parser_base;
+        auto const good =
+            [&](string_view s, std::uint64_t v0)
+            {
+                std::uint64_t v;
+                auto it = s.data();
+                auto const result =
+                    base::parse_hex(it, v);
+                if(BEAST_EXPECTS(result, s))
+                    BEAST_EXPECTS(v == v0, s);
+            };
+        auto const bad =
+            [&](string_view s)
+            {
+                std::uint64_t v;
+                auto it = s.data();
+                auto const result =
+                    base::parse_hex(it, v);
+                BEAST_EXPECTS(! result, s);
+            };
+        good("f\r\n",               15);
+        good("ff\r\n",              255);
+        good("ffff\r\n",            65535);
+        good("ffffffffr\n",         4294967295);
+        good("ffffffffffffffff\r\n", 18446744073709551615ULL);
+        bad ("\r\n");
+        bad ("g\r\n");
+        bad ("10000000000000000\r\n");
+        bad ("ffffffffffffffffffffff\r\n");
+    }
+
+    //--------------------------------------------------------------------------
+
+    // https://github.com/boostorg/beast/issues/1734
+
+    void
+    testIssue1734()
+    {
+        // Ensure more than one buffer, this is to avoid an optimized path in
+        // basic_parser::put(ConstBufferSequence const&,...) which avoids
+        // buffer flattening.
+        auto multibufs = [](multi_buffer::const_buffers_type buffers) {
+            std::vector<net::const_buffer> bs;
+            for (auto b : buffers_range(buffers))
+                bs.push_back(b);
+            while (std::distance(bs.begin(), bs.end()) < 2) {
+                bs.push_back({});
+            }
+            return bs;
+        };
+
+        // Buffers must be bigger than max_stack_buffer to force flattening
+        // in basic_parser::put(ConstBufferSequence const&,...)
+        std::string first_chunk_data(
+            2 * basic_parser<false>::max_stack_buffer + 1, 'x');
+
+        std::string second_chunk_data_part1(
+            basic_parser<false>::max_stack_buffer + 2, 'x');
+        std::string second_chunk_data_part2(
+            basic_parser<false>::max_stack_buffer + 1, 'x');
+
+        multi_buffer b;
+        parser<false, string_body> p;
+        p.eager(true);
+        error_code ec;
+        std::size_t used;
+
+        ostream(b) <<
+            "HTTP/1.1 200 OK\r\n"
+            "Server: test\r\n"
+            "Transfer-Encoding: chunked\r\n"
+            "\r\n";
+
+        used = p.put(b.data(), ec);
+        b.consume(used);
+
+        BEAST_EXPECT(net::buffer_size(b.data()) == 0);
+        BEAST_EXPECTS(!ec, ec.message());
+        BEAST_EXPECT(!p.is_done());
+        BEAST_EXPECT(p.is_header_done());
+
+        ostream(b) <<
+            std::hex <<
+            first_chunk_data.size() << "\r\n" <<
+            first_chunk_data << "\r\n";
+
+        // First chunk
+        used = p.put(multibufs(b.data()), ec);
+        b.consume(used);
+
+        BEAST_EXPECTS(ec == error::need_more, ec.message());
+        BEAST_EXPECT(!p.is_done());
+
+        ostream(b) <<
+            std::hex <<
+            (second_chunk_data_part1.size() +
+             second_chunk_data_part2.size() ) << "\r\n" <<
+            second_chunk_data_part1;
+
+        // Second chunk, part 1
+        used = p.put(multibufs(b.data()), ec);
+        b.consume(used);
+
+        BEAST_EXPECTS(!ec, ec.message());
+        BEAST_EXPECT(!p.is_done());
+
+        ostream(b) <<
+            second_chunk_data_part2 << "\r\n"
+            << "0\r\n\r\n";
+
+        // Second chunk, part 2
+        used = p.put(multibufs(b.data()), ec);
+        b.consume(used);
+
+        BEAST_EXPECTS(!ec, ec.message()); // <-- Error: bad chunk
+        if(p.need_eof())
+        {
+            p.put_eof(ec);
+            BEAST_EXPECTS(! ec, ec.message());
+        }
+        BEAST_EXPECT(p.is_done());
+    }
+
     //--------------------------------------------------------------------------
 
     void
@@ -1237,6 +1400,8 @@ public:
         testIssue692();
         testFuzz();
         testRegression1();
+        testIssue1211();
+        testIssue1267();
     }
 };