2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
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)
7 // Official repository: https://github.com/boostorg/beast
10 #ifndef BOOST_BEAST_HTTP_TEST_MESSAGE_FUZZ_HPP
11 #define BOOST_BEAST_HTTP_TEST_MESSAGE_FUZZ_HPP
13 #include <boost/beast/core/ostream.hpp>
14 #include <boost/beast/http/detail/rfc7230.hpp>
23 template<class = void>
25 escaped_string(string_view s)
28 out.reserve(s.size());
43 // Produces random HTTP messages
45 template<class = void>
60 "0123456789abcdef"[v&0xf]);
67 template<class UInt = std::size_t>
71 return static_cast<UInt>(
72 std::uniform_int_distribution<
73 std::size_t>{0, n-1}(rng_));
80 // All IANA registered methods
81 static char const* const list[39] = {
82 "ACL", "BASELINE-CONTROL", "BIND", "CHECKIN", "CHECKOUT", "CONNECT",
83 "COPY", "DELETE", "GET", "HEAD", "LABEL", "LINK", "LOCK", "MERGE",
84 "MKACTIVITY", "MKCALENDAR", "MKCOL", "MKREDIRECTREF", "MKWORKSPACE",
85 "MOVE", "OPTIONS", "ORDERPATCH", "PATCH", "POST", "PRI", "PROPFIND",
86 "PROPPATCH", "PUT", "REBIND", "REPORT", "SEARCH", "TRACE", "UNBIND",
87 "UNCHECKOUT", "UNLINK", "UNLOCK", "UPDATE", "UPDATEREDIRECTREF",
90 return list[rand(39)];
92 // methods parsed by nodejs-http-parser
93 static char const* const list[33] = {
94 "ACL", "BIND", "CHECKOUT", "CONNECT", "COPY", "DELETE", "HEAD", "GET",
95 "LINK", "LOCK", "MERGE", "MKCOL", "MKCALENDAR", "MKACTIVITY", "M-SEARCH",
96 "MOVE", "NOTIFY", "OPTIONS", "PATCH", "POST", "PROPFIND", "PROPPATCH",
97 "PURGE", "PUT", "REBIND", "REPORT", "SEARCH", "SUBSCRIBE", "TRACE",
98 "UNBIND", "UNLINK", "UNLOCK", "UNSUBSCRIBE"
100 return list[rand(33)];
107 static char const* const list[241] = {
108 "aaa", "aaas", "about", "acap", "acct", "acr", "adiumxtra", "afp", "afs",
109 "aim", "appdata", "apt", "attachment", "aw", "barion", "beshare", "bitcoin",
110 "blob", "bolo", "callto", "cap", "chrome", "chrome-extension", "cid",
111 "coap", "coaps", "com-eventbrite-attendee", "content", "crid", "cvs",
112 "data", "dav", "dict", "dis", "dlna-playcontainer", "dlna-playsingle",
113 "dns", "dntp", "dtn", "dvb", "ed2k", "example", "facetime", "fax", "feed",
114 "feedready", "file", "filesystem", "finger", "fish", "ftp", "geo", "gg",
115 "git", "gizmoproject", "go", "gopher", "gtalk", "h323", "ham", "hcp",
116 "http", "https", "iax", "icap", "icon", "im", "imap", "info", "iotdisco",
117 "ipn", "ipp", "ipps", "irc", "irc6", "ircs", "iris", "iris.beep",
118 "iris.lwz", "iris.xpc", "iris.xpcs", "isostore", "itms", "jabber", "jar",
119 "jms", "keyparc", "lastfm", "ldap", "ldaps", "magnet", "mailserver",
120 "mailto", "maps", "market", "message", "mid", "mms",
121 "modem", "ms-access", "ms-drive-to", "ms-enrollment", "ms-excel",
122 "ms-getoffice", "ms-help", "ms-infopath", "ms-media-stream-id", "ms-project",
123 "ms-powerpoint", "ms-publisher", "ms-search-repair",
124 "ms-secondary-screen-controller", "ms-secondary-screen-setup",
125 "ms-settings", "ms-settings-airplanemode", "ms-settings-bluetooth",
126 "ms-settings-camera", "ms-settings-cellular", "ms-settings-cloudstorage",
127 "ms-settings-emailandaccounts", "ms-settings-language", "ms-settings-location",
128 "ms-settings-lock", "ms-settings-nfctransactions", "ms-settings-notifications",
129 "ms-settings-power", "ms-settings-privacy", "ms-settings-proximity",
130 "ms-settings-screenrotation", "ms-settings-wifi", "ms-settings-workplace",
131 "ms-spd", "ms-transit-to", "ms-visio", "ms-walk-to", "ms-word", "msnim",
132 "msrp", "msrps", "mtqp", "mumble", "mupdate", "mvn", "news", "nfs", "ni",
133 "nih", "nntp", "notes", "oid", "opaquelocktoken", "pack", "palm", "paparazzi",
134 "pkcs11", "platform", "pop", "pres", "prospero", "proxy", "psyc", "query",
135 "redis", "rediss", "reload", "res", "target", "rmi", "rsync", "rtmfp",
136 "rtmp", "rtsp", "rtsps", "rtspu", "secondlife", "service", "session", "sftp",
137 "sgn", "shttp", "sieve", "sip", "sips", "skype", "smb", "sms", "smtp",
138 "snews", "snmp", "soap.beep", "soap.beeps", "soldat", "spotify", "ssh",
139 "steam", "stun", "stuns", "submit", "svn", "tag", "teamspeak", "tel",
140 "teliaeid", "telnet", "tftp", "things", "thismessage", "tip", "tn3270",
141 "tool", "turn", "turns", "tv", "udp", "unreal", "urn", "ut2004", "v-event",
142 "vemmi", "ventrilo", "videotex", "vnc", "view-source", "wais", "webcal",
143 "wpid", "ws", "wss", "wtai", "wyciwyg", "xcon", "xcon-userid", "xfire",
144 "xmlrpc.beep", "xmlrpc.beeps", "xmpp", "xri", "ymsgr", "z39.50", "z39.50r",
147 return list[rand(241)];
154 return std::string(1,
156 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
157 "abcdefghijklmnopqrstuvwxyz"
158 ":@&=+$,"[rand(69)]);
160 s += "0123456789abcdef"[rand(16)];
161 s += "0123456789abcdef"[rand(16)];
204 /* authority = server | reg_name
206 reg_name = 1*( unreserved | escaped | "$" | "," |
207 ";" | ":" | "@" | "&" | "=" | "+" )
209 server = [ [ userinfo "@" ] hostport ]
210 userinfo = *( unreserved | escaped |
211 ";" | ":" | "&" | "=" | "+" | "$" | "," )
213 hostport = host [ ":" port ]
214 host = hostname | IPv4address
215 hostname = *( domainlabel "." ) toplabel [ "." ]
216 domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
217 toplabel = alpha | alpha *( alphanum | "-" ) alphanum
218 IPv4address = 1*digit "." 1*digit "." 1*digit "." 1*digit
226 s += userinfo() + "@";
252 s += uric_no_slash();
258 /* abs_path = "/" path_segments
259 path_segments = segment *( "/" segment )
260 segment = *pchar *( ";" param )
262 pchar = unreserved | escaped |
263 ":" | "@" | "&" | "=" | "+" | "$" | ","
282 /* net_path = "//" authority [ abs_path ]
287 std::string s = "//";
294 /* absoluteURI = scheme ":" ( hier_part | opaque_part )
295 scheme = alpha *( alpha | digit | "+" | "-" | "." )
296 hier_part = ( net_path | abs_path ) [ "?" query ]
297 abs_path = "/" path_segments
299 opaque_part = uric_no_slash *uric
328 case 0: return abs_uri();
329 case 1: return abs_path();
330 case 2: return authority();
340 static char constexpr valid[78] =
341 "!#$%&\'*+-." "0123456789" "ABCDEFGHIJ" "KLMNOPQRST"
342 "UVWXYZ^_`a" "bcdefghijk" "lmnopqrstu" "vwxyz|~";
344 s.append(1, valid[rand(77)]);
346 s.append(1, valid[rand(77)]);
354 static char constexpr alpha[63] =
355 "0123456789" "ABCDEFGHIJ" "KLMNOPQRST"
356 "UVWXYZabcd" "efghijklmn" "opqrstuvwx" "yz";
360 s.append(1, alpha[rand(62)]);
367 { static char const* const list[289] =
370 "Accept", "Accept-Additions", "Accept-Charset", "Accept-Datetime", "Accept-Encoding",
371 "Accept-Features", "Accept-Language", "Accept-Patch", "Accept-Ranges", "Age", "Allow",
372 "ALPN", "Also-Control", "Alt-Svc", "Alt-Used", "Alternate-Recipient", "Alternates",
373 "Apply-To-Redirect-Ref", "Approved", "Archive", "Archived-At", "Article-Names",
374 "Article-Updates", "Authentication-Info", "Authentication-Results", "Authorization",
375 "Auto-Submitted", "Autoforwarded", "Autosubmitted", "Base", "Bcc", "Body", "C-Ext",
376 "C-Man", "C-Opt", "C-PEP", "C-PEP-Info", "Cache-Control",
377 "CalDAV-Timezones", "Cc", "Close", "Comments", /*"Connection",*/ "Content-Alternative",
378 "Content-Base", "Content-Description", "Content-Disposition", "Content-Duration",
379 "Content-Encoding", "Content-features", "Content-ID", "Content-Identifier",
380 "Content-Language", /*"Content-Length",*/ "Content-Location", "Content-MD5",
381 "Content-Range", "Content-Return", "Content-Script-Type", "Content-Style-Type",
382 "Content-Transfer-Encoding", "Content-Type", "Content-Version", "Control", "Conversion",
383 "Conversion-With-Loss", "Cookie", "Cookie2", "DASL", "DAV", "DL-Expansion-History", "Date",
384 "Date-Received", "Default-Style", "Deferred-Delivery", "Delivery-Date", "Delta-Base",
385 "Depth", "Derived-From", "Destination", "Differential-ID", "Digest",
386 "Discarded-X400-IPMS-Extensions", "Discarded-X400-MTS-Extensions", "Disclose-Recipients",
387 "Disposition-Notification-Options", "Disposition-Notification-To", "Distribution",
388 "DKIM-Signature", "Downgraded-Bcc", "Downgraded-Cc", "Downgraded-Disposition-Notification-To",
389 "Downgraded-Final-Recipient", "Downgraded-From", "Downgraded-In-Reply-To",
390 "Downgraded-Mail-From", "Downgraded-Message-Id", "Downgraded-Original-Recipient",
391 "Downgraded-Rcpt-To", "Downgraded-References", "Downgraded-Reply-To", "Downgraded-Resent-Bcc",
392 "Downgraded-Resent-Cc", "Downgraded-Resent-From", "Downgraded-Resent-Reply-To",
393 "Downgraded-Resent-Sender", "Downgraded-Resent-To", "Downgraded-Return-Path",
394 "Downgraded-Sender", "Downgraded-To", "Encoding", "Encrypted", "ETag", "Expect",
395 "Expires", "Expiry-Date", "Ext", "Followup-To", "Forwarded", "From",
396 "Generate-Delivery-Report", "GetProfile", "Hobareg", "Host", "HTTP2-Settings", "IM", "If",
397 "If-Match", "If-Modified-Since", "If-None-Match", "If-Range", "If-Schedule-Tag-Match",
398 "If-Unmodified-Since", "Importance", "In-Reply-To", "Incomplete-Copy", "Injection-Date",
399 "Injection-Info", "Keep-Alive", "Keywords", "Label", "Language", "Last-Modified",
400 "Latest-Delivery-Time", "Lines", "Link", "List-Archive", "List-Help", "List-ID",
401 "List-Owner", "List-Post", "List-Subscribe", "List-Unsubscribe", "Location", "Lock-Token",
402 "Man", "Max-Forwards", "Memento-Datetime", "Message-Context", "Message-ID", "Message-Type",
403 "Meter", "MIME-Version", "MMHS-Exempted-Address", "MMHS-Extended-Authorisation-Info",
404 "MMHS-Subject-Indicator-Codes", "MMHS-Handling-Instructions", "MMHS-Message-Instructions",
405 "MMHS-Codress-Message-Indicator", "MMHS-Originator-Reference", "MMHS-Primary-Precedence",
406 "MMHS-Copy-Precedence", "MMHS-Message-Type", "MMHS-Other-Recipients-Indicator-To",
407 "MMHS-Other-Recipients-Indicator-CC", "MMHS-Acp127-Message-Identifier", "MMHS-Originator-PLAD",
408 "MT-Priority", "Negotiate", "Newsgroups", "NNTP-Posting-Date", "NNTP-Posting-Host",
409 "Obsoletes", "Opt", "Ordering-Type", "Organization", "Origin",
410 "Original-Encoded-Information-Types", "Original-From", "Original-Message-ID",
411 "Original-Recipient", "Original-Sender", "Originator-Return-Address", "Original-Subject",
412 "Overwrite", "P3P", "Path", "PEP", "PICS-Label", "Pep-Info", "Position", "Posting-Version",
413 "Pragma", "Prefer", "Preference-Applied", "Prevent-NonDelivery-Report", "Priority",
414 "ProfileObject", "Protocol", "Protocol-Info", "Protocol-Query", "Protocol-Request",
415 "Proxy-Authenticate", "Proxy-Authentication-Info", "Proxy-Authorization", "Proxy-Features",
416 "Proxy-Instruction", "Public", "Public-Key-Pins", "Public-Key-Pins-Report-Only", "Range",
417 "Received", "Received-SPF", "Redirect-Ref", "References", "Referer", "Relay-Version",
418 "Reply-By", "Reply-To", "Require-Recipient-Valid-Since", "Resent-Bcc", "Resent-Cc",
419 "Resent-Date", "Resent-From", "Resent-Message-ID", "Resent-Reply-To", "Resent-Sender",
420 "Resent-To", "Retry-After", "Return-Path", "Safe", "Schedule-Reply", "Schedule-Tag",
421 "Sec-WebSocket-Accept", "Sec-WebSocket-Extensions", "Sec-WebSocket-Key",
422 "Sec-WebSocket-Protocol", "Sec-WebSocket-Version", "Security-Scheme", "See-Also", "Sender",
423 "Sensitivity", "Server", "Set-Cookie", "Set-Cookie2",
424 "SetProfile", "SLUG", "SoapAction", "Solicitation", "Status-URI", "Strict-Transport-Security",
425 "Subject", "Summary", "Supersedes", "Surrogate-Capability", "Surrogate-Control", "TCN",
426 "TE", "Timeout", "To", "Trailer", /*"Transfer-Encoding",*/ "URI", /*"Upgrade",*/ "User-Agent",
427 "Variant-Vary", "Vary", "VBR-Info", "Via", "WWW-Authenticate", "Want-Digest", "Warning",
428 "X400-Content-Identifier", "X400-Content-Return", "X400-Content-Type", "X400-MTS-Identifier",
429 "X400-Originator", "X400-Received", "X400-Recipients", "X400-Trace", "X-Frame-Options", "Xref"
431 return list[rand(289)];
442 char c = rand<char>(256);
443 if(detail::is_text(c))
468 s.append(1, rand(2) ? ' ' : '\t');
470 s.append(1, rand(2) ? ' ' : '\t');
476 template<class DynamicBuffer>
478 fields(DynamicBuffer& db)
480 auto os = ostream(db);
484 (rand(4) ? ": " : ":") <<
489 template<class DynamicBuffer>
491 body(DynamicBuffer& db)
496 "Content-Length: 0\r\n\r\n";
501 auto const len = rand(500);
503 "Content-Length: " << len << "\r\n\r\n";
504 auto mb = db.prepare(len);
505 for(auto it = net::buffer_sequence_begin(mb);
506 it != net::buffer_sequence_end(mb);
509 net::mutable_buffer b = *it;
510 auto p = static_cast<char*>(b.data());
513 *p++ = static_cast<char>(32 + rand(26+26+10+6));
519 auto len = rand(500);
521 "Transfer-Encoding: chunked\r\n\r\n";
524 auto n = (std::min)(1 + rand(300), len);
528 auto mb = db.prepare(n);
529 for(auto it = net::buffer_sequence_begin(mb);
530 it != net::buffer_sequence_end(mb);
533 net::mutable_buffer b = *it;
534 auto p = static_cast<char*>(b.data());
537 *p++ = static_cast<char>(32 + rand(26+26+10+6));
540 ostream(db) << "\r\n";
542 ostream(db) << "0\r\n\r\n";
546 template<class DynamicBuffer>
548 request(DynamicBuffer& db)
551 method() << " " << target() << " HTTP/1.1\r\n";
556 template<class DynamicBuffer>
558 response(DynamicBuffer& db)
562 (rand(2) ? "0" : "1") << " " <<
563 (100 + rand(401)) << " " <<
568 ostream(db) << "\r\n";
572 using message_fuzz = message_fuzz_t<>;
574 template<class Good, class Bad>
577 Good const& good, Bad const& bad)
596 good(R"(;x;y=z;z="\"";p="\\";q="1\"2\\")");