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