1 // Copyright 2022 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "quiche/balsa/balsa_frame.h"
6
7 #include <stdlib.h>
8
9 #include <cstdint>
10 #include <limits>
11 #include <map>
12 #include <memory>
13 #include <random>
14 #include <sstream>
15 #include <string>
16 #include <utility>
17 #include <vector>
18
19 #include "absl/strings/escaping.h"
20 #include "absl/strings/numbers.h"
21 #include "absl/strings/str_cat.h"
22 #include "absl/strings/str_format.h"
23 #include "absl/strings/str_replace.h"
24 #include "absl/strings/string_view.h"
25 #include "quiche/balsa/balsa_enums.h"
26 #include "quiche/balsa/balsa_headers.h"
27 #include "quiche/balsa/balsa_visitor_interface.h"
28 #include "quiche/balsa/http_validation_policy.h"
29 #include "quiche/balsa/noop_balsa_visitor.h"
30 #include "quiche/balsa/simple_buffer.h"
31 #include "quiche/common/platform/api/quiche_command_line_flags.h"
32 #include "quiche/common/platform/api/quiche_expect_bug.h"
33 #include "quiche/common/platform/api/quiche_flags.h"
34 #include "quiche/common/platform/api/quiche_logging.h"
35 #include "quiche/common/platform/api/quiche_test.h"
36
37 using ::testing::_;
38 using ::testing::AnyNumber;
39 using ::testing::AtLeast;
40 using ::testing::InSequence;
41 using ::testing::IsEmpty;
42 using ::testing::Mock;
43 using ::testing::NiceMock;
44 using ::testing::Pointee;
45 using ::testing::Property;
46 using ::testing::Range;
47 using ::testing::StrEq;
48 using ::testing::StrictMock;
49
50 DEFINE_QUICHE_COMMAND_LINE_FLAG(
51 std::string, randseed, "",
52 "This is the seed for Pseudo-random number"
53 " generator used when generating random messages for unittests");
54
55 namespace quiche {
56
57 namespace test {
58
59 // This random engine from the standard library supports initialization with a
60 // seed, which is helpful for reproducing any unit test failures that are due to
61 // random sequence variation.
62 using RandomEngine = std::mt19937;
63
64 class BalsaFrameTestPeer {
65 public:
HeaderFramingFound(BalsaFrame * balsa_frame,char c)66 static int32_t HeaderFramingFound(BalsaFrame* balsa_frame, char c) {
67 return balsa_frame->HeaderFramingFound(c);
68 }
69
FindColonsAndParseIntoKeyValue(BalsaFrame * balsa_frame,const BalsaFrame::Lines & lines,bool is_trailer,BalsaHeaders * headers)70 static void FindColonsAndParseIntoKeyValue(BalsaFrame* balsa_frame,
71 const BalsaFrame::Lines& lines,
72 bool is_trailer,
73 BalsaHeaders* headers) {
74 balsa_frame->FindColonsAndParseIntoKeyValue(lines, is_trailer, headers);
75 }
76 };
77
78 class BalsaHeadersTestPeer {
79 public:
WriteFromFramer(BalsaHeaders * headers,const char * ptr,size_t size)80 static void WriteFromFramer(BalsaHeaders* headers, const char* ptr,
81 size_t size) {
82 headers->WriteFromFramer(ptr, size);
83 }
84 };
85
86 namespace {
87
88 // This class encapsulates the policy of seed selection. If user supplies a
89 // valid use via the --randseed flag, GetSeed will only return the user
90 // supplied seed value. This is useful in reproducing bugs reported by the
91 // test. If an invalid seed value is supplied (likely due to bad numeric
92 // format), the test will abort (since this mode tend to be used for debugging,
93 // it is better to die early so the user knows a bad value is supplied). If no
94 // seed is supplied, the value supplied by ACMRandom::HostnamePidTimeSeed() is
95 // used. This class is supposed to be a singleton, but there is no ill-effect if
96 // multiple instances are created (although that tends not to be what the user
97 // wants).
98 class TestSeed {
99 public:
TestSeed()100 TestSeed() : test_seed_(0), user_supplied_seed_(false) {}
101
Initialize(const std::string & seed_flag)102 void Initialize(const std::string& seed_flag) {
103 if (!seed_flag.empty()) {
104 ASSERT_TRUE(absl::SimpleAtoi(seed_flag, &test_seed_));
105 user_supplied_seed_ = true;
106 }
107 }
108
GetSeed() const109 int GetSeed() const {
110 int seed =
111 (user_supplied_seed_ ? test_seed_
112 : testing::UnitTest::GetInstance()->random_seed());
113 QUICHE_LOG(INFO) << "**** The current seed is " << seed << " ****";
114 return seed;
115 }
116
117 private:
118 int test_seed_;
119 bool user_supplied_seed_;
120 };
121
RandomBool(RandomEngine & rng)122 static bool RandomBool(RandomEngine& rng) { return rng() % 2 != 0; }
123
EscapeString(absl::string_view message)124 std::string EscapeString(absl::string_view message) {
125 return absl::StrReplaceAll(
126 message, {{"\n", "\\\\n\n"}, {"\\r", "\\\\r"}, {"\\t", "\\\\t"}});
127 }
128
random_lws(RandomEngine & rng)129 char random_lws(RandomEngine& rng) {
130 if (RandomBool(rng)) {
131 return '\t';
132 }
133 return ' ';
134 }
135
random_line_term(RandomEngine & rng)136 const char* random_line_term(RandomEngine& rng) {
137 if (RandomBool(rng)) {
138 return "\r\n";
139 }
140 return "\n";
141 }
142
AppendRandomWhitespace(RandomEngine & rng,std::stringstream * s)143 void AppendRandomWhitespace(RandomEngine& rng, std::stringstream* s) {
144 // Appending a random amount of whitespace to the unparsed value. There is a
145 // max of 1000 pieces of whitespace that will be attached, however, it is
146 // extremely unlikely (1 in 2^1000) that we'll hit this limit, as we have a
147 // 50% probability of exiting the loop at any point in time.
148 for (int i = 0; i < 1000 && RandomBool(rng); ++i) {
149 *s << random_lws(rng);
150 }
151 }
152
153 // Creates an HTTP message firstline from the given inputs.
154 //
155 // tokens - The list of nonwhitespace tokens (which should later be parsed out
156 // from the firstline).
157 // whitespace - the whitespace that occurs before, between, and
158 // after the tokens. Note that the last whitespace
159 // character should -not- include any '\n'.
160 // line_ending - one of "\n" or "\r\n"
161 //
162 // whitespace[0] occurs before the first token.
163 // whitespace[1] occurs between the first and second token
164 // whitespace[2] occurs between the second and third token
165 // whitespace[3] occurs between the third token and the line_ending.
166 //
167 // This code:
168 // const char tokens[3] = {"GET", "/", "HTTP/1.0"};
169 // const char whitespace[4] = { "\n\n", " ", "\t", "\t"};
170 // const char line_ending = "\r\n";
171 // CreateFirstLine(tokens, whitespace, line_ending) ->
172 // Would yield the following string:
173 // string(
174 // "\n"
175 // "\n"
176 // "GET /\tHTTP/1.0\t\r\n"
177 // );
178 //
CreateFirstLine(const char * tokens[3],const char * whitespace[4],const char * line_ending)179 std::string CreateFirstLine(const char* tokens[3], const char* whitespace[4],
180 const char* line_ending) {
181 QUICHE_CHECK(tokens != nullptr);
182 QUICHE_CHECK(whitespace != nullptr);
183 QUICHE_CHECK(line_ending != nullptr);
184 QUICHE_CHECK(std::string(line_ending) == "\n" ||
185 std::string(line_ending) == "\r\n")
186 << "line_ending: " << EscapeString(line_ending);
187 SimpleBuffer firstline_buffer;
188 firstline_buffer.WriteString(whitespace[0]);
189 for (int i = 0; i < 3; ++i) {
190 firstline_buffer.WriteString(tokens[i]);
191 firstline_buffer.WriteString(whitespace[i + 1]);
192 }
193 firstline_buffer.WriteString(line_ending);
194 return std::string(firstline_buffer.GetReadableRegion());
195 }
196
197 // Creates a string (ostensibly an entire HTTP message) from the given input
198 // arguments.
199 //
200 // firstline - the first line of the request or response.
201 // The firstline should already have a line-ending on it. If you use the
202 // CreateFirstLine function, you'll get a valid firstline string for this
203 // function. This may include 'extraneous' whitespace before the first
204 // nonwhitespace character, including '\n's
205 // headers - a list of the -interpreted- key, value pairs.
206 // In other words, the value should be what you expect to get out of the
207 // headers after framing has occurred (and should include no whitespace
208 // before or after the first and list nonwhitespace characters,
209 // respectively). While this function will succeed if you don't follow
210 // these guidelines, the VerifyHeaderLines function will likely not agree
211 // with that input.
212 // headers_len - the number of key value pairs
213 // colon - the string that exists between the key and value pairs.
214 // It MUST include EXACTLY one colon, and may include any amount of either
215 // ' ' or '\t'. Note that for certain key strings, this value will be
216 // modified to exclude any leading whitespace. See the body of the function
217 // for more details.
218 // line_ending - one of "\r\n", or "\n\n"
219 // body - the appropriate body.
220 // The CreateMessage function does not do any checking that the headers
221 // agree with the present of any body, so the input must be correct given
222 // the set of headers.
CreateMessage(const char * firstline,const std::pair<std::string,std::string> * headers,size_t headers_len,const char * colon,const char * line_ending,const char * body)223 std::string CreateMessage(const char* firstline,
224 const std::pair<std::string, std::string>* headers,
225 size_t headers_len, const char* colon,
226 const char* line_ending, const char* body) {
227 SimpleBuffer request_buffer;
228 request_buffer.WriteString(firstline);
229 if (headers_len > 0) {
230 QUICHE_CHECK(headers != nullptr);
231 QUICHE_CHECK(colon != nullptr);
232 }
233 QUICHE_CHECK(line_ending != nullptr);
234 QUICHE_CHECK(std::string(line_ending) == "\n" ||
235 std::string(line_ending) == "\r\n")
236 << "line_ending: " << EscapeString(line_ending);
237 QUICHE_CHECK(body != nullptr);
238 for (size_t i = 0; i < headers_len; ++i) {
239 bool only_whitespace_in_key = true;
240 {
241 // If the 'key' part includes no non-whitespace characters, then we need
242 // to be sure that the 'colon' part includes no whitespace before the
243 // ':'. If it did, then the line would be (correctly!) interpreted as a
244 // continuation, and the test would not work properly.
245 const char* tmp_key = headers[i].first.c_str();
246 while (*tmp_key != '\0') {
247 if (*tmp_key > ' ') {
248 only_whitespace_in_key = false;
249 break;
250 }
251 ++tmp_key;
252 }
253 }
254 const char* tmp_colon = colon;
255 if (only_whitespace_in_key) {
256 while (*tmp_colon != ':') {
257 ++tmp_colon;
258 }
259 }
260 request_buffer.WriteString(headers[i].first);
261 request_buffer.WriteString(tmp_colon);
262 request_buffer.WriteString(headers[i].second);
263 request_buffer.WriteString(line_ending);
264 }
265 request_buffer.WriteString(line_ending);
266 request_buffer.WriteString(body);
267 return std::string(request_buffer.GetReadableRegion());
268 }
269
VerifyRequestFirstLine(const char * tokens[3],const BalsaHeaders & headers)270 void VerifyRequestFirstLine(const char* tokens[3],
271 const BalsaHeaders& headers) {
272 EXPECT_EQ(tokens[0], headers.request_method());
273 EXPECT_EQ(tokens[1], headers.request_uri());
274 EXPECT_EQ(0u, headers.parsed_response_code());
275 EXPECT_EQ(tokens[2], headers.request_version());
276 }
277
VerifyResponseFirstLine(const char * tokens[3],size_t expected_response_code,const BalsaHeaders & headers)278 void VerifyResponseFirstLine(const char* tokens[3],
279 size_t expected_response_code,
280 const BalsaHeaders& headers) {
281 EXPECT_EQ(tokens[0], headers.response_version());
282 EXPECT_EQ(tokens[1], headers.response_code());
283 EXPECT_EQ(expected_response_code, headers.parsed_response_code());
284 EXPECT_EQ(tokens[2], headers.response_reason_phrase());
285 }
286
287 // This function verifies that the expected_headers key and values
288 // are exactly equal to that returned by an iterator to a BalsaHeader
289 // object.
290 //
291 // expected_headers - key, value pairs, in the order in which they're
292 // expected to be returned from the iterator.
293 // headers_len - as expected, the number of expected key-value pairs.
294 // headers - the BalsaHeaders from which we'll examine the actual
295 // headers.
VerifyHeaderLines(const std::pair<std::string,std::string> * expected_headers,size_t headers_len,const BalsaHeaders & headers)296 void VerifyHeaderLines(
297 const std::pair<std::string, std::string>* expected_headers,
298 size_t headers_len, const BalsaHeaders& headers) {
299 BalsaHeaders::const_header_lines_iterator it = headers.lines().begin();
300 for (size_t i = 0; it != headers.lines().end(); ++it, ++i) {
301 ASSERT_GT(headers_len, i);
302 std::string actual_key;
303 std::string actual_value;
304 if (!it->first.empty()) {
305 actual_key = std::string(it->first);
306 }
307 if (!it->second.empty()) {
308 actual_value = std::string(it->second);
309 }
310 EXPECT_THAT(actual_key, StrEq(expected_headers[i].first));
311 EXPECT_THAT(actual_value, StrEq(expected_headers[i].second));
312 }
313 EXPECT_TRUE(headers.lines().end() == it);
314 }
315
FirstLineParsedCorrectlyHelper(const char * tokens[3],size_t expected_response_code,bool is_request,const char * whitespace)316 void FirstLineParsedCorrectlyHelper(const char* tokens[3],
317 size_t expected_response_code,
318 bool is_request, const char* whitespace) {
319 BalsaHeaders headers;
320 BalsaFrame framer;
321 framer.set_is_request(is_request);
322 framer.set_balsa_headers(&headers);
323 const char* tmp_tokens[3] = {tokens[0], tokens[1], tokens[2]};
324 const char* tmp_whitespace[4] = {"", whitespace, whitespace, ""};
325 for (int j = 2; j >= 0; --j) {
326 framer.Reset();
327 std::string firstline = CreateFirstLine(tmp_tokens, tmp_whitespace, "\n");
328 std::string message =
329 CreateMessage(firstline.c_str(), nullptr, 0, nullptr, "\n", "");
330 SCOPED_TRACE(absl::StrFormat("input: \n%s", EscapeString(message)));
331 EXPECT_GE(message.size(),
332 framer.ProcessInput(message.data(), message.size()));
333 // If this is a request then we don't expect a framer error (as we'll be
334 // getting back warnings that fields are missing). If, however, this is
335 // a response, and it is missing anything other than the reason phrase,
336 // the framer will signal an error instead.
337 if (is_request || j >= 1) {
338 EXPECT_FALSE(framer.Error());
339 if (is_request) {
340 EXPECT_TRUE(framer.MessageFullyRead());
341 }
342 if (j == 0) {
343 expected_response_code = 0;
344 }
345 if (is_request) {
346 VerifyRequestFirstLine(tmp_tokens, *framer.headers());
347 } else {
348 VerifyResponseFirstLine(tmp_tokens, expected_response_code,
349 *framer.headers());
350 }
351 } else {
352 EXPECT_TRUE(framer.Error());
353 }
354 tmp_tokens[j] = "";
355 tmp_whitespace[j] = "";
356 }
357 }
358
TEST(HTTPBalsaFrame,ParseStateToString)359 TEST(HTTPBalsaFrame, ParseStateToString) {
360 EXPECT_STREQ("ERROR",
361 BalsaFrameEnums::ParseStateToString(BalsaFrameEnums::ERROR));
362 EXPECT_STREQ("READING_HEADER_AND_FIRSTLINE",
363 BalsaFrameEnums::ParseStateToString(
364 BalsaFrameEnums::READING_HEADER_AND_FIRSTLINE));
365 EXPECT_STREQ("READING_CHUNK_LENGTH",
366 BalsaFrameEnums::ParseStateToString(
367 BalsaFrameEnums::READING_CHUNK_LENGTH));
368 EXPECT_STREQ("READING_CHUNK_EXTENSION",
369 BalsaFrameEnums::ParseStateToString(
370 BalsaFrameEnums::READING_CHUNK_EXTENSION));
371 EXPECT_STREQ("READING_CHUNK_DATA", BalsaFrameEnums::ParseStateToString(
372 BalsaFrameEnums::READING_CHUNK_DATA));
373 EXPECT_STREQ("READING_CHUNK_TERM", BalsaFrameEnums::ParseStateToString(
374 BalsaFrameEnums::READING_CHUNK_TERM));
375 EXPECT_STREQ("READING_LAST_CHUNK_TERM",
376 BalsaFrameEnums::ParseStateToString(
377 BalsaFrameEnums::READING_LAST_CHUNK_TERM));
378 EXPECT_STREQ("READING_TRAILER", BalsaFrameEnums::ParseStateToString(
379 BalsaFrameEnums::READING_TRAILER));
380 EXPECT_STREQ("READING_UNTIL_CLOSE",
381 BalsaFrameEnums::ParseStateToString(
382 BalsaFrameEnums::READING_UNTIL_CLOSE));
383 EXPECT_STREQ("READING_CONTENT", BalsaFrameEnums::ParseStateToString(
384 BalsaFrameEnums::READING_CONTENT));
385 EXPECT_STREQ("MESSAGE_FULLY_READ", BalsaFrameEnums::ParseStateToString(
386 BalsaFrameEnums::MESSAGE_FULLY_READ));
387
388 EXPECT_STREQ("UNKNOWN_STATE", BalsaFrameEnums::ParseStateToString(
389 BalsaFrameEnums::NUM_STATES));
390 EXPECT_STREQ("UNKNOWN_STATE",
391 BalsaFrameEnums::ParseStateToString(
392 static_cast<BalsaFrameEnums::ParseState>(-1)));
393
394 for (int i = 0; i < BalsaFrameEnums::NUM_STATES; ++i) {
395 EXPECT_STRNE("UNKNOWN_STATE",
396 BalsaFrameEnums::ParseStateToString(
397 static_cast<BalsaFrameEnums::ParseState>(i)));
398 }
399 }
400
TEST(HTTPBalsaFrame,ErrorCodeToString)401 TEST(HTTPBalsaFrame, ErrorCodeToString) {
402 EXPECT_STREQ("NO_STATUS_LINE_IN_RESPONSE",
403 BalsaFrameEnums::ErrorCodeToString(
404 BalsaFrameEnums::NO_STATUS_LINE_IN_RESPONSE));
405 EXPECT_STREQ("NO_REQUEST_LINE_IN_REQUEST",
406 BalsaFrameEnums::ErrorCodeToString(
407 BalsaFrameEnums::NO_REQUEST_LINE_IN_REQUEST));
408 EXPECT_STREQ("FAILED_TO_FIND_WS_AFTER_RESPONSE_VERSION",
409 BalsaFrameEnums::ErrorCodeToString(
410 BalsaFrameEnums::FAILED_TO_FIND_WS_AFTER_RESPONSE_VERSION));
411 EXPECT_STREQ("FAILED_TO_FIND_WS_AFTER_REQUEST_METHOD",
412 BalsaFrameEnums::ErrorCodeToString(
413 BalsaFrameEnums::FAILED_TO_FIND_WS_AFTER_REQUEST_METHOD));
414 EXPECT_STREQ(
415 "FAILED_TO_FIND_WS_AFTER_RESPONSE_STATUSCODE",
416 BalsaFrameEnums::ErrorCodeToString(
417 BalsaFrameEnums::FAILED_TO_FIND_WS_AFTER_RESPONSE_STATUSCODE));
418 EXPECT_STREQ(
419 "FAILED_TO_FIND_WS_AFTER_REQUEST_REQUEST_URI",
420 BalsaFrameEnums::ErrorCodeToString(
421 BalsaFrameEnums::FAILED_TO_FIND_WS_AFTER_REQUEST_REQUEST_URI));
422 EXPECT_STREQ(
423 "FAILED_TO_FIND_NL_AFTER_RESPONSE_REASON_PHRASE",
424 BalsaFrameEnums::ErrorCodeToString(
425 BalsaFrameEnums::FAILED_TO_FIND_NL_AFTER_RESPONSE_REASON_PHRASE));
426 EXPECT_STREQ(
427 "FAILED_TO_FIND_NL_AFTER_REQUEST_HTTP_VERSION",
428 BalsaFrameEnums::ErrorCodeToString(
429 BalsaFrameEnums::FAILED_TO_FIND_NL_AFTER_REQUEST_HTTP_VERSION));
430 EXPECT_STREQ("FAILED_CONVERTING_STATUS_CODE_TO_INT",
431 BalsaFrameEnums::ErrorCodeToString(
432 BalsaFrameEnums::FAILED_CONVERTING_STATUS_CODE_TO_INT));
433 EXPECT_STREQ("HEADERS_TOO_LONG", BalsaFrameEnums::ErrorCodeToString(
434 BalsaFrameEnums::HEADERS_TOO_LONG));
435 EXPECT_STREQ("UNPARSABLE_CONTENT_LENGTH",
436 BalsaFrameEnums::ErrorCodeToString(
437 BalsaFrameEnums::UNPARSABLE_CONTENT_LENGTH));
438 EXPECT_STREQ("MAYBE_BODY_BUT_NO_CONTENT_LENGTH",
439 BalsaFrameEnums::ErrorCodeToString(
440 BalsaFrameEnums::MAYBE_BODY_BUT_NO_CONTENT_LENGTH));
441 EXPECT_STREQ("HEADER_MISSING_COLON",
442 BalsaFrameEnums::ErrorCodeToString(
443 BalsaFrameEnums::HEADER_MISSING_COLON));
444 EXPECT_STREQ("INVALID_CHUNK_LENGTH",
445 BalsaFrameEnums::ErrorCodeToString(
446 BalsaFrameEnums::INVALID_CHUNK_LENGTH));
447 EXPECT_STREQ("CHUNK_LENGTH_OVERFLOW",
448 BalsaFrameEnums::ErrorCodeToString(
449 BalsaFrameEnums::CHUNK_LENGTH_OVERFLOW));
450 EXPECT_STREQ("CALLED_BYTES_SPLICED_WHEN_UNSAFE_TO_DO_SO",
451 BalsaFrameEnums::ErrorCodeToString(
452 BalsaFrameEnums::CALLED_BYTES_SPLICED_WHEN_UNSAFE_TO_DO_SO));
453 EXPECT_STREQ("CALLED_BYTES_SPLICED_AND_EXCEEDED_SAFE_SPLICE_AMOUNT",
454 BalsaFrameEnums::ErrorCodeToString(
455 BalsaFrameEnums::
456 CALLED_BYTES_SPLICED_AND_EXCEEDED_SAFE_SPLICE_AMOUNT));
457 EXPECT_STREQ("MULTIPLE_CONTENT_LENGTH_KEYS",
458 BalsaFrameEnums::ErrorCodeToString(
459 BalsaFrameEnums::MULTIPLE_CONTENT_LENGTH_KEYS));
460 EXPECT_STREQ("MULTIPLE_TRANSFER_ENCODING_KEYS",
461 BalsaFrameEnums::ErrorCodeToString(
462 BalsaFrameEnums::MULTIPLE_TRANSFER_ENCODING_KEYS));
463 EXPECT_STREQ("INVALID_HEADER_FORMAT",
464 BalsaFrameEnums::ErrorCodeToString(
465 BalsaFrameEnums::INVALID_HEADER_FORMAT));
466 EXPECT_STREQ("INVALID_TRAILER_FORMAT",
467 BalsaFrameEnums::ErrorCodeToString(
468 BalsaFrameEnums::INVALID_TRAILER_FORMAT));
469 EXPECT_STREQ("TRAILER_TOO_LONG", BalsaFrameEnums::ErrorCodeToString(
470 BalsaFrameEnums::TRAILER_TOO_LONG));
471 EXPECT_STREQ("TRAILER_MISSING_COLON",
472 BalsaFrameEnums::ErrorCodeToString(
473 BalsaFrameEnums::TRAILER_MISSING_COLON));
474 EXPECT_STREQ("INTERNAL_LOGIC_ERROR",
475 BalsaFrameEnums::ErrorCodeToString(
476 BalsaFrameEnums::INTERNAL_LOGIC_ERROR));
477 EXPECT_STREQ("INVALID_HEADER_CHARACTER",
478 BalsaFrameEnums::ErrorCodeToString(
479 BalsaFrameEnums::INVALID_HEADER_CHARACTER));
480
481 EXPECT_STREQ("UNKNOWN_ERROR", BalsaFrameEnums::ErrorCodeToString(
482 BalsaFrameEnums::NUM_ERROR_CODES));
483 EXPECT_STREQ("UNKNOWN_ERROR",
484 BalsaFrameEnums::ErrorCodeToString(
485 static_cast<BalsaFrameEnums::ErrorCode>(-1)));
486
487 for (int i = 0; i < BalsaFrameEnums::NUM_ERROR_CODES; ++i) {
488 EXPECT_STRNE("UNKNOWN_ERROR",
489 BalsaFrameEnums::ErrorCodeToString(
490 static_cast<BalsaFrameEnums::ErrorCode>(i)));
491 }
492 }
493
494 class FakeHeaders {
495 public:
496 struct KeyValuePair {
KeyValuePairquiche::test::__anona5a5d6350111::FakeHeaders::KeyValuePair497 KeyValuePair(const std::string& key, const std::string& value)
498 : key(key), value(value) {}
KeyValuePairquiche::test::__anona5a5d6350111::FakeHeaders::KeyValuePair499 KeyValuePair() {}
500
501 std::string key;
502 std::string value;
503 };
504 typedef std::vector<KeyValuePair> KeyValuePairs;
505 KeyValuePairs key_value_pairs_;
506
operator ==(const FakeHeaders & other) const507 bool operator==(const FakeHeaders& other) const {
508 if (key_value_pairs_.size() != other.key_value_pairs_.size()) {
509 return false;
510 }
511 for (KeyValuePairs::size_type i = 0; i < key_value_pairs_.size(); ++i) {
512 if (key_value_pairs_[i].key != other.key_value_pairs_[i].key) {
513 return false;
514 }
515 if (key_value_pairs_[i].value != other.key_value_pairs_[i].value) {
516 return false;
517 }
518 }
519 return true;
520 }
521
AddKeyValue(const std::string & key,const std::string & value)522 void AddKeyValue(const std::string& key, const std::string& value) {
523 key_value_pairs_.push_back(KeyValuePair(key, value));
524 }
525 };
526
527 class BalsaVisitorMock : public BalsaVisitorInterface {
528 public:
529 ~BalsaVisitorMock() override = default;
530
ProcessHeaders(const BalsaHeaders & headers)531 void ProcessHeaders(const BalsaHeaders& headers) override {
532 FakeHeaders fake_headers;
533 GenerateFakeHeaders(headers, &fake_headers);
534 ProcessHeaders(fake_headers);
535 }
OnTrailers(std::unique_ptr<BalsaHeaders> trailers)536 void OnTrailers(std::unique_ptr<BalsaHeaders> trailers) override {
537 FakeHeaders fake_trailers;
538 GenerateFakeHeaders(*trailers, &fake_trailers);
539 OnTrailers(fake_trailers);
540 }
541
542 MOCK_METHOD(void, OnRawBodyInput, (absl::string_view input), (override));
543 MOCK_METHOD(void, OnBodyChunkInput, (absl::string_view input), (override));
544 MOCK_METHOD(void, OnHeaderInput, (absl::string_view input), (override));
545 MOCK_METHOD(void, OnTrailerInput, (absl::string_view input), (override));
546 MOCK_METHOD(void, ProcessHeaders, (const FakeHeaders& headers));
547 MOCK_METHOD(void, OnTrailers, (const FakeHeaders& trailers));
548 MOCK_METHOD(void, OnRequestFirstLineInput,
549 (absl::string_view line_input, absl::string_view method_input,
550 absl::string_view request_uri, absl::string_view version_input),
551 (override));
552 MOCK_METHOD(void, OnResponseFirstLineInput,
553 (absl::string_view line_input, absl::string_view version_input,
554 absl::string_view status_input, absl::string_view reason_input),
555 (override));
556 MOCK_METHOD(void, OnChunkLength, (size_t length), (override));
557 MOCK_METHOD(void, OnChunkExtensionInput, (absl::string_view input),
558 (override));
559 MOCK_METHOD(void, OnInterimHeaders, (std::unique_ptr<BalsaHeaders> headers),
560 (override));
561 MOCK_METHOD(void, ContinueHeaderDone, (), (override));
562 MOCK_METHOD(void, HeaderDone, (), (override));
563 MOCK_METHOD(void, MessageDone, (), (override));
564 MOCK_METHOD(void, HandleError, (BalsaFrameEnums::ErrorCode error_code),
565 (override));
566 MOCK_METHOD(void, HandleWarning, (BalsaFrameEnums::ErrorCode error_code),
567 (override));
568
569 private:
GenerateFakeHeaders(const BalsaHeaders & headers,FakeHeaders * fake_headers)570 static void GenerateFakeHeaders(const BalsaHeaders& headers,
571 FakeHeaders* fake_headers) {
572 for (const auto& line : headers.lines()) {
573 fake_headers->AddKeyValue(std::string(line.first),
574 std::string(line.second));
575 }
576 }
577 };
578
579 class HTTPBalsaFrameTest : public QuicheTest {
580 protected:
SetUp()581 void SetUp() override {
582 balsa_frame_.set_balsa_headers(&headers_);
583 balsa_frame_.set_balsa_visitor(&visitor_mock_);
584 balsa_frame_.set_is_request(true);
585 balsa_frame_.EnableTrailers();
586 }
587
VerifyFirstLineParsing(const std::string & firstline,BalsaFrameEnums::ErrorCode error_code)588 void VerifyFirstLineParsing(const std::string& firstline,
589 BalsaFrameEnums::ErrorCode error_code) {
590 balsa_frame_.ProcessInput(firstline.data(), firstline.size());
591 EXPECT_EQ(error_code, balsa_frame_.ErrorCode());
592 }
593
594 BalsaHeaders headers_;
595 BalsaFrame balsa_frame_;
596 NiceMock<BalsaVisitorMock> visitor_mock_;
597 };
598
599 // Test correct return value for HeaderFramingFound.
TEST_F(HTTPBalsaFrameTest,TestHeaderFramingFound)600 TEST_F(HTTPBalsaFrameTest, TestHeaderFramingFound) {
601 // Pattern \r\n\r\n should match kValidTerm1.
602 EXPECT_EQ(0, BalsaFrameTestPeer::HeaderFramingFound(&balsa_frame_, ' '));
603 EXPECT_EQ(0, BalsaFrameTestPeer::HeaderFramingFound(&balsa_frame_, '\r'));
604 EXPECT_EQ(0, BalsaFrameTestPeer::HeaderFramingFound(&balsa_frame_, '\n'));
605 EXPECT_EQ(0, BalsaFrameTestPeer::HeaderFramingFound(&balsa_frame_, '\r'));
606 EXPECT_EQ(BalsaFrame::kValidTerm1,
607 BalsaFrameTestPeer::HeaderFramingFound(&balsa_frame_, '\n'));
608
609 // Pattern \n\r\n should match kValidTerm1.
610 EXPECT_EQ(0, BalsaFrameTestPeer::HeaderFramingFound(&balsa_frame_, '\t'));
611 EXPECT_EQ(0, BalsaFrameTestPeer::HeaderFramingFound(&balsa_frame_, '\n'));
612 EXPECT_EQ(0, BalsaFrameTestPeer::HeaderFramingFound(&balsa_frame_, '\r'));
613 EXPECT_EQ(BalsaFrame::kValidTerm1,
614 BalsaFrameTestPeer::HeaderFramingFound(&balsa_frame_, '\n'));
615
616 // Pattern \r\n\n should match kValidTerm2.
617 EXPECT_EQ(0, BalsaFrameTestPeer::HeaderFramingFound(&balsa_frame_, 'a'));
618 EXPECT_EQ(0, BalsaFrameTestPeer::HeaderFramingFound(&balsa_frame_, '\r'));
619 EXPECT_EQ(0, BalsaFrameTestPeer::HeaderFramingFound(&balsa_frame_, '\n'));
620 EXPECT_EQ(BalsaFrame::kValidTerm2,
621 BalsaFrameTestPeer::HeaderFramingFound(&balsa_frame_, '\n'));
622
623 // Pattern \n\n should match kValidTerm2.
624 EXPECT_EQ(0, BalsaFrameTestPeer::HeaderFramingFound(&balsa_frame_, '1'));
625 EXPECT_EQ(0, BalsaFrameTestPeer::HeaderFramingFound(&balsa_frame_, '\n'));
626 EXPECT_EQ(BalsaFrame::kValidTerm2,
627 BalsaFrameTestPeer::HeaderFramingFound(&balsa_frame_, '\n'));
628
629 // Other patterns should not match.
630 EXPECT_EQ(0, BalsaFrameTestPeer::HeaderFramingFound(&balsa_frame_, ':'));
631 EXPECT_EQ(0, BalsaFrameTestPeer::HeaderFramingFound(&balsa_frame_, '\r'));
632 EXPECT_EQ(0, BalsaFrameTestPeer::HeaderFramingFound(&balsa_frame_, '\r'));
633 EXPECT_EQ(0, BalsaFrameTestPeer::HeaderFramingFound(&balsa_frame_, '\n'));
634 }
635
TEST_F(HTTPBalsaFrameTest,MissingColonInTrailer)636 TEST_F(HTTPBalsaFrameTest, MissingColonInTrailer) {
637 const absl::string_view trailer = "kv\r\n\r\n";
638
639 BalsaFrame::Lines lines;
640 lines.push_back({0, 4});
641 lines.push_back({4, trailer.length()});
642 BalsaHeaders trailers;
643 BalsaHeadersTestPeer::WriteFromFramer(&trailers, trailer.data(),
644 trailer.length());
645 BalsaFrameTestPeer::FindColonsAndParseIntoKeyValue(
646 &balsa_frame_, lines, true /*is_trailer*/, &trailers);
647 // Note missing colon is not an error, just a warning.
648 EXPECT_FALSE(balsa_frame_.Error());
649 EXPECT_EQ(BalsaFrameEnums::TRAILER_MISSING_COLON, balsa_frame_.ErrorCode());
650 }
651
652 // Correctness of FindColonsAndParseIntoKeyValue is already verified for
653 // headers, so trailer related test is light.
TEST_F(HTTPBalsaFrameTest,FindColonsAndParseIntoKeyValueInTrailer)654 TEST_F(HTTPBalsaFrameTest, FindColonsAndParseIntoKeyValueInTrailer) {
655 const absl::string_view trailer_line1 = "Fraction: 0.23\r\n";
656 const absl::string_view trailer_line2 = "Some:junk \r\n";
657 const absl::string_view trailer_line3 = "\r\n";
658 const std::string trailer =
659 absl::StrCat(trailer_line1, trailer_line2, trailer_line3);
660
661 BalsaFrame::Lines lines;
662 lines.push_back({0, trailer_line1.length()});
663 lines.push_back({trailer_line1.length(),
664 trailer_line1.length() + trailer_line2.length()});
665 lines.push_back(
666 {trailer_line1.length() + trailer_line2.length(), trailer.length()});
667 BalsaHeaders trailers;
668 BalsaHeadersTestPeer::WriteFromFramer(&trailers, trailer.data(),
669 trailer.length());
670 BalsaFrameTestPeer::FindColonsAndParseIntoKeyValue(
671 &balsa_frame_, lines, true /*is_trailer*/, &trailers);
672 EXPECT_FALSE(balsa_frame_.Error());
673 absl::string_view fraction = trailers.GetHeader("Fraction");
674 EXPECT_EQ("0.23", fraction);
675 absl::string_view some = trailers.GetHeader("Some");
676 EXPECT_EQ("junk", some);
677 }
678
TEST_F(HTTPBalsaFrameTest,InvalidTrailer)679 TEST_F(HTTPBalsaFrameTest, InvalidTrailer) {
680 const absl::string_view trailer_line1 = "Fraction : 0.23\r\n";
681 const absl::string_view trailer_line2 = "Some\t :junk \r\n";
682 const absl::string_view trailer_line3 = "\r\n";
683 const std::string trailer =
684 absl::StrCat(trailer_line1, trailer_line2, trailer_line3);
685
686 BalsaFrame::Lines lines;
687 lines.push_back({0, trailer_line1.length()});
688 lines.push_back({trailer_line1.length(),
689 trailer_line1.length() + trailer_line2.length()});
690 lines.push_back(
691 {trailer_line1.length() + trailer_line2.length(), trailer.length()});
692 BalsaHeaders trailers;
693 BalsaHeadersTestPeer::WriteFromFramer(&trailers, trailer.data(),
694 trailer.length());
695 BalsaFrameTestPeer::FindColonsAndParseIntoKeyValue(
696 &balsa_frame_, lines, true /*is_trailer*/, &trailers);
697 EXPECT_TRUE(balsa_frame_.Error());
698 EXPECT_EQ(BalsaFrameEnums::INVALID_TRAILER_NAME_CHARACTER,
699 balsa_frame_.ErrorCode());
700 }
701
TEST_F(HTTPBalsaFrameTest,OneCharacterFirstLineParsedAsExpected)702 TEST_F(HTTPBalsaFrameTest, OneCharacterFirstLineParsedAsExpected) {
703 VerifyFirstLineParsing(
704 "a\r\n\r\n", BalsaFrameEnums::FAILED_TO_FIND_WS_AFTER_REQUEST_METHOD);
705 }
706
TEST_F(HTTPBalsaFrameTest,OneCharacterFirstLineWithWhitespaceParsedAsExpected)707 TEST_F(HTTPBalsaFrameTest,
708 OneCharacterFirstLineWithWhitespaceParsedAsExpected) {
709 VerifyFirstLineParsing(
710 "a \r\n\r\n", BalsaFrameEnums::FAILED_TO_FIND_WS_AFTER_REQUEST_METHOD);
711 }
712
TEST_F(HTTPBalsaFrameTest,WhitespaceOnlyFirstLineIsNotACompleteHeader)713 TEST_F(HTTPBalsaFrameTest, WhitespaceOnlyFirstLineIsNotACompleteHeader) {
714 VerifyFirstLineParsing(" \n\n", BalsaFrameEnums::NO_REQUEST_LINE_IN_REQUEST);
715 }
716
TEST(HTTPBalsaFrame,RequestFirstLineParsedCorrectly)717 TEST(HTTPBalsaFrame, RequestFirstLineParsedCorrectly) {
718 const char* request_tokens[3] = {"GET", "/jjsdjrqk", "HTTP/1.0"};
719 FirstLineParsedCorrectlyHelper(request_tokens, 0, true, " ");
720 FirstLineParsedCorrectlyHelper(request_tokens, 0, true, "\t");
721 FirstLineParsedCorrectlyHelper(request_tokens, 0, true, "\t ");
722 FirstLineParsedCorrectlyHelper(request_tokens, 0, true, " \t");
723 FirstLineParsedCorrectlyHelper(request_tokens, 0, true, " \t \t ");
724 }
725
TEST_F(HTTPBalsaFrameTest,NonnumericResponseCode)726 TEST_F(HTTPBalsaFrameTest, NonnumericResponseCode) {
727 balsa_frame_.set_is_request(false);
728
729 VerifyFirstLineParsing("HTTP/1.1 0x3 Digits only\r\n\r\n",
730 BalsaFrameEnums::FAILED_CONVERTING_STATUS_CODE_TO_INT);
731
732 EXPECT_EQ("HTTP/1.1 0x3 Digits only", headers_.first_line());
733 }
734
TEST_F(HTTPBalsaFrameTest,NegativeResponseCode)735 TEST_F(HTTPBalsaFrameTest, NegativeResponseCode) {
736 balsa_frame_.set_is_request(false);
737
738 VerifyFirstLineParsing("HTTP/1.1 -11 No sign allowed\r\n\r\n",
739 BalsaFrameEnums::FAILED_CONVERTING_STATUS_CODE_TO_INT);
740
741 EXPECT_EQ("HTTP/1.1 -11 No sign allowed", headers_.first_line());
742 }
743
TEST_F(HTTPBalsaFrameTest,WithoutTrailingWhitespace)744 TEST_F(HTTPBalsaFrameTest, WithoutTrailingWhitespace) {
745 balsa_frame_.set_is_request(false);
746
747 VerifyFirstLineParsing(
748 "HTTP/1.1 101\r\n\r\n",
749 BalsaFrameEnums::FAILED_TO_FIND_WS_AFTER_RESPONSE_STATUSCODE);
750
751 EXPECT_EQ("HTTP/1.1 101", headers_.first_line());
752 }
753
TEST_F(HTTPBalsaFrameTest,TrailingWhitespace)754 TEST_F(HTTPBalsaFrameTest, TrailingWhitespace) {
755 balsa_frame_.set_is_request(false);
756
757 // b/69446061
758 std::string firstline = "HTTP/1.1 101 \r\n\r\n";
759 balsa_frame_.ProcessInput(firstline.data(), firstline.size());
760
761 EXPECT_EQ("HTTP/1.1 101 ", headers_.first_line());
762 }
763
TEST(HTTPBalsaFrame,ResponseFirstLineParsedCorrectly)764 TEST(HTTPBalsaFrame, ResponseFirstLineParsedCorrectly) {
765 const char* response_tokens[3] = {"HTTP/1.1", "200", "A reason\tphrase"};
766 FirstLineParsedCorrectlyHelper(response_tokens, 200, false, " ");
767 FirstLineParsedCorrectlyHelper(response_tokens, 200, false, "\t");
768 FirstLineParsedCorrectlyHelper(response_tokens, 200, false, "\t ");
769 FirstLineParsedCorrectlyHelper(response_tokens, 200, false, " \t");
770 FirstLineParsedCorrectlyHelper(response_tokens, 200, false, " \t \t ");
771
772 response_tokens[1] = "312";
773 FirstLineParsedCorrectlyHelper(response_tokens, 312, false, " ");
774 FirstLineParsedCorrectlyHelper(response_tokens, 312, false, "\t");
775 FirstLineParsedCorrectlyHelper(response_tokens, 312, false, "\t ");
776 FirstLineParsedCorrectlyHelper(response_tokens, 312, false, " \t");
777 FirstLineParsedCorrectlyHelper(response_tokens, 312, false, " \t \t ");
778
779 // Who knows what the future may hold w.r.t. response codes?!
780 response_tokens[1] = "4242";
781 FirstLineParsedCorrectlyHelper(response_tokens, 4242, false, " ");
782 FirstLineParsedCorrectlyHelper(response_tokens, 4242, false, "\t");
783 FirstLineParsedCorrectlyHelper(response_tokens, 4242, false, "\t ");
784 FirstLineParsedCorrectlyHelper(response_tokens, 4242, false, " \t");
785 FirstLineParsedCorrectlyHelper(response_tokens, 4242, false, " \t \t ");
786 }
787
HeaderLineTestHelper(const char * firstline,bool is_request,const std::pair<std::string,std::string> * headers,size_t headers_len,const char * colon,const char * line_ending)788 void HeaderLineTestHelper(const char* firstline, bool is_request,
789 const std::pair<std::string, std::string>* headers,
790 size_t headers_len, const char* colon,
791 const char* line_ending) {
792 BalsaHeaders balsa_headers;
793 BalsaFrame framer;
794 framer.set_is_request(is_request);
795 framer.set_balsa_headers(&balsa_headers);
796 std::string message =
797 CreateMessage(firstline, headers, headers_len, colon, line_ending, "");
798 SCOPED_TRACE(EscapeString(message));
799 size_t bytes_consumed = framer.ProcessInput(message.data(), message.size());
800 EXPECT_EQ(message.size(), bytes_consumed);
801 VerifyHeaderLines(headers, headers_len, *framer.headers());
802 }
803
TEST(HTTPBalsaFrame,RequestLinesParsedProperly)804 TEST(HTTPBalsaFrame, RequestLinesParsedProperly) {
805 SCOPED_TRACE("Testing that lines are properly parsed.");
806 const char firstline[] = "GET / \rHTTP/1.1\r\n";
807 const std::pair<std::string, std::string> headers[] = {
808 std::pair<std::string, std::string>("foo", "bar"),
809 std::pair<std::string, std::string>("duck", "water"),
810 std::pair<std::string, std::string>("goose", "neck"),
811 std::pair<std::string, std::string>("key_is_fine",
812 "value:includes:colons"),
813 std::pair<std::string, std::string>("trucks",
814 "along\rvalue\rincluding\rslash\rrs"),
815 std::pair<std::string, std::string>("monster", "truck"),
816 std::pair<std::string, std::string>("another_key", ":colons in value"),
817 std::pair<std::string, std::string>("another_key", "colons in value:"),
818 std::pair<std::string, std::string>("another_key",
819 "value includes\r\n continuation"),
820 std::pair<std::string, std::string>("key_without_continuations",
821 "multiple\n in\r\n the\n value"),
822 std::pair<std::string, std::string>("key_without_value",
823 ""), // empty value
824 std::pair<std::string, std::string>("",
825 "value without key"), // empty key
826 std::pair<std::string, std::string>("", ""), // both key and value empty
827 std::pair<std::string, std::string>("normal_key", "normal_value"),
828 };
829 const size_t headers_len = ABSL_ARRAYSIZE(headers);
830 HeaderLineTestHelper(firstline, true, headers, headers_len, ":", "\n");
831 HeaderLineTestHelper(firstline, true, headers, headers_len, ": ", "\n");
832 HeaderLineTestHelper(firstline, true, headers, headers_len, ": ", "\r\n");
833 HeaderLineTestHelper(firstline, true, headers, headers_len, ":\t", "\n");
834 HeaderLineTestHelper(firstline, true, headers, headers_len, ":\t", "\r\n");
835 HeaderLineTestHelper(firstline, true, headers, headers_len, ":\t ", "\n");
836 HeaderLineTestHelper(firstline, true, headers, headers_len, ":\t ", "\r\n");
837 HeaderLineTestHelper(firstline, true, headers, headers_len, ":\t\t", "\n");
838 HeaderLineTestHelper(firstline, true, headers, headers_len, ":\t\t", "\r\n");
839 HeaderLineTestHelper(firstline, true, headers, headers_len, ":\t \t", "\n");
840 HeaderLineTestHelper(firstline, true, headers, headers_len, ":\t \t", "\r\n");
841 }
842
TEST(HTTPBalsaFrame,CarriageReturnIllegalInHeaders)843 TEST(HTTPBalsaFrame, CarriageReturnIllegalInHeaders) {
844 HttpValidationPolicy policy{.disallow_lone_cr_in_request_headers = true};
845 BalsaHeaders balsa_headers;
846 BalsaFrame framer;
847 framer.set_is_request(true);
848 framer.set_balsa_headers(&balsa_headers);
849 framer.set_http_validation_policy(policy);
850 framer.set_invalid_chars_level(BalsaFrame::InvalidCharsLevel::kError);
851 const std::pair<std::string, std::string> headers[] = {
852 std::pair<std::string, std::string>("foo", "bar"),
853 std::pair<std::string, std::string>("trucks", "value-has-solo-\r-in it"),
854 };
855 std::string message =
856 CreateMessage("GET / \rHTTP/1.1\r\n", headers, 2, ":", "\r\n", "");
857 framer.ProcessInput(message.data(), message.size());
858 EXPECT_EQ(framer.ErrorCode(), BalsaFrameEnums::INVALID_HEADER_CHARACTER);
859 // One carriage return in firstline, 1 in header value.
860 EXPECT_EQ(framer.get_invalid_chars().at('\r'), 2);
861 }
862
TEST(HTTPBalsaFrame,CarriageReturnIllegalInHeaderKey)863 TEST(HTTPBalsaFrame, CarriageReturnIllegalInHeaderKey) {
864 BalsaHeaders balsa_headers;
865 BalsaFrame framer;
866 framer.set_is_request(true);
867 framer.set_balsa_headers(&balsa_headers);
868 framer.set_invalid_chars_level(BalsaFrame::InvalidCharsLevel::kError);
869 const std::pair<std::string, std::string> headers[] = {
870 std::pair<std::string, std::string>("tru\rcks", "along"),
871 };
872 std::string message =
873 CreateMessage("GET / HTTP/1.1\r\n", headers, 1, ":", "\r\n", "");
874 framer.ProcessInput(message.data(), message.size());
875 EXPECT_EQ(framer.ErrorCode(), BalsaFrameEnums::INVALID_HEADER_NAME_CHARACTER);
876 }
877
TEST(HTTPBalsaFrame,ResponseLinesParsedProperly)878 TEST(HTTPBalsaFrame, ResponseLinesParsedProperly) {
879 SCOPED_TRACE("ResponseLineParsedProperly");
880 const char firstline[] = "HTTP/1.0 200 A reason\tphrase\r\n";
881 const std::pair<std::string, std::string> headers[] = {
882 std::pair<std::string, std::string>("foo", "bar"),
883 std::pair<std::string, std::string>("duck", "water"),
884 std::pair<std::string, std::string>("goose", "neck"),
885 std::pair<std::string, std::string>("key_is_fine",
886 "value:includes:colons"),
887 std::pair<std::string, std::string>("trucks",
888 "along\rvalue\rincluding\rslash\rrs"),
889 std::pair<std::string, std::string>("monster", "truck"),
890 std::pair<std::string, std::string>("another_key", ":colons in value"),
891 std::pair<std::string, std::string>("another_key", "colons in value:"),
892 std::pair<std::string, std::string>("another_key",
893 "value includes\r\n continuation"),
894 std::pair<std::string, std::string>("key_includes_no_continuations",
895 "multiple\n in\r\n the\n value"),
896 std::pair<std::string, std::string>("key_without_value",
897 ""), // empty value
898 std::pair<std::string, std::string>("",
899 "value without key"), // empty key
900 std::pair<std::string, std::string>("", ""), // both key and value empty
901 std::pair<std::string, std::string>("normal_key", "normal_value"),
902 };
903 const size_t headers_len = ABSL_ARRAYSIZE(headers);
904 HeaderLineTestHelper(firstline, false, headers, headers_len, ":", "\n");
905 HeaderLineTestHelper(firstline, false, headers, headers_len, ": ", "\n");
906 HeaderLineTestHelper(firstline, false, headers, headers_len, ": ", "\r\n");
907 HeaderLineTestHelper(firstline, false, headers, headers_len, ":\t", "\n");
908 HeaderLineTestHelper(firstline, false, headers, headers_len, ":\t", "\r\n");
909 HeaderLineTestHelper(firstline, false, headers, headers_len, ":\t ", "\n");
910 HeaderLineTestHelper(firstline, false, headers, headers_len, ":\t ", "\r\n");
911 HeaderLineTestHelper(firstline, false, headers, headers_len, ":\t\t", "\n");
912 HeaderLineTestHelper(firstline, false, headers, headers_len, ":\t\t", "\r\n");
913 HeaderLineTestHelper(firstline, false, headers, headers_len, ":\t \t", "\n");
914 HeaderLineTestHelper(firstline, false, headers, headers_len, ":\t \t",
915 "\r\n");
916 }
917
WhitespaceHeaderTestHelper(const std::string & message,bool is_request,BalsaFrameEnums::ErrorCode expected_error_code)918 void WhitespaceHeaderTestHelper(
919 const std::string& message, bool is_request,
920 BalsaFrameEnums::ErrorCode expected_error_code) {
921 BalsaHeaders balsa_headers;
922 BalsaFrame framer;
923 framer.set_is_request(is_request);
924 framer.set_balsa_headers(&balsa_headers);
925 SCOPED_TRACE(EscapeString(message));
926 size_t bytes_consumed = framer.ProcessInput(message.data(), message.size());
927 EXPECT_EQ(message.size(), bytes_consumed);
928 if (expected_error_code == BalsaFrameEnums::BALSA_NO_ERROR) {
929 EXPECT_EQ(false, framer.Error());
930 } else {
931 EXPECT_EQ(true, framer.Error());
932 }
933 EXPECT_EQ(expected_error_code, framer.ErrorCode());
934 }
935
TEST(HTTPBalsaFrame,WhitespaceInRequestsProcessedProperly)936 TEST(HTTPBalsaFrame, WhitespaceInRequestsProcessedProperly) {
937 SCOPED_TRACE(
938 "Test that a request header with a line with spaces and no "
939 "data generates an error.");
940 WhitespaceHeaderTestHelper(
941 "GET / HTTP/1.1\r\n"
942 " \r\n"
943 "\r\n",
944 true, BalsaFrameEnums::INVALID_HEADER_NAME_CHARACTER);
945 WhitespaceHeaderTestHelper(
946 "GET / HTTP/1.1\r\n"
947 " \r\n"
948 "test: test\r\n"
949 "\r\n",
950 true, BalsaFrameEnums::INVALID_HEADER_NAME_CHARACTER);
951
952 SCOPED_TRACE("Test proper handling for line continuation in requests.");
953 WhitespaceHeaderTestHelper(
954 "GET / HTTP/1.1\r\n"
955 "test: test\r\n"
956 " continued\r\n"
957 "\r\n",
958 true, BalsaFrameEnums::BALSA_NO_ERROR);
959 WhitespaceHeaderTestHelper(
960 "GET / HTTP/1.1\r\n"
961 "test: test\r\n"
962 " \r\n"
963 "\r\n",
964 true, BalsaFrameEnums::BALSA_NO_ERROR);
965 SCOPED_TRACE(
966 "Test a confusing and ambiguous case: is it a line continuation or a new "
967 "header field?");
968 WhitespaceHeaderTestHelper(
969 "GET / HTTP/1.1\r\n"
970 "test: test\r\n"
971 " confusing:continued\r\n"
972 "\r\n",
973 true, BalsaFrameEnums::BALSA_NO_ERROR);
974 }
975
TEST(HTTPBalsaFrame,WhitespaceInResponsesProcessedProperly)976 TEST(HTTPBalsaFrame, WhitespaceInResponsesProcessedProperly) {
977 SCOPED_TRACE(
978 "Test that a response header with a line with spaces and no "
979 "data generates an error.");
980 WhitespaceHeaderTestHelper(
981 "HTTP/1.0 200 Reason\r\n"
982 " \r\nContent-Length: 0\r\n"
983 "\r\n",
984 false, BalsaFrameEnums::INVALID_HEADER_NAME_CHARACTER);
985
986 SCOPED_TRACE("Test proper handling for line continuation in responses.");
987 WhitespaceHeaderTestHelper(
988 "HTTP/1.0 200 Reason\r\n"
989 "test: test\r\n"
990 " continued\r\n"
991 "Content-Length: 0\r\n"
992 "\r\n",
993 false, BalsaFrameEnums::BALSA_NO_ERROR);
994 WhitespaceHeaderTestHelper(
995 "HTTP/1.0 200 Reason\r\n"
996 "test: test\r\n"
997 " \r\n"
998 "Content-Length: 0\r\n"
999 "\r\n",
1000 false, BalsaFrameEnums::BALSA_NO_ERROR);
1001 SCOPED_TRACE(
1002 "Test a confusing and ambiguous case: is it a line continuation or a new "
1003 "header field?");
1004 WhitespaceHeaderTestHelper(
1005 "HTTP/1.0 200 Reason\r\n"
1006 "test: test\r\n"
1007 " confusing:continued\r\n"
1008 "Content-Length: 0\r\n"
1009 "\r\n",
1010 false, BalsaFrameEnums::BALSA_NO_ERROR);
1011 }
1012
TEST_F(HTTPBalsaFrameTest,VisitorInvokedProperlyForTrivialRequest)1013 TEST_F(HTTPBalsaFrameTest, VisitorInvokedProperlyForTrivialRequest) {
1014 std::string message = "GET /foobar HTTP/1.0\r\n\n";
1015
1016 FakeHeaders fake_headers;
1017
1018 {
1019 InSequence s;
1020
1021 EXPECT_CALL(visitor_mock_,
1022 OnRequestFirstLineInput("GET /foobar HTTP/1.0", "GET",
1023 "/foobar", "HTTP/1.0"));
1024 EXPECT_CALL(visitor_mock_, ProcessHeaders(fake_headers));
1025 EXPECT_CALL(visitor_mock_, HeaderDone());
1026 EXPECT_CALL(visitor_mock_, MessageDone());
1027 }
1028 EXPECT_CALL(visitor_mock_, OnHeaderInput(message));
1029
1030 ASSERT_EQ(message.size(),
1031 balsa_frame_.ProcessInput(message.data(), message.size()));
1032 }
1033
TEST_F(HTTPBalsaFrameTest,VisitorInvokedProperlyForRequestWithBlankLines)1034 TEST_F(HTTPBalsaFrameTest, VisitorInvokedProperlyForRequestWithBlankLines) {
1035 std::string message = "\n\n\r\n\nGET /foobar HTTP/1.0\r\n\n";
1036
1037 FakeHeaders fake_headers;
1038
1039 {
1040 InSequence s1;
1041 // Yes, that is correct-- the framer 'eats' the blank-lines at the beginning
1042 // and never notifies the visitor.
1043
1044 EXPECT_CALL(visitor_mock_,
1045 OnRequestFirstLineInput("GET /foobar HTTP/1.0", "GET",
1046 "/foobar", "HTTP/1.0"));
1047 EXPECT_CALL(visitor_mock_, ProcessHeaders(fake_headers));
1048 EXPECT_CALL(visitor_mock_, HeaderDone());
1049 EXPECT_CALL(visitor_mock_, MessageDone());
1050 }
1051 EXPECT_CALL(visitor_mock_, OnHeaderInput("GET /foobar HTTP/1.0\r\n\n"));
1052
1053 ASSERT_EQ(message.size(),
1054 balsa_frame_.ProcessInput(message.data(), message.size()));
1055 }
1056
TEST_F(HTTPBalsaFrameTest,VisitorInvokedProperlyForRequestWithSplitBlankLines)1057 TEST_F(HTTPBalsaFrameTest,
1058 VisitorInvokedProperlyForRequestWithSplitBlankLines) {
1059 std::string blanks =
1060 "\n"
1061 "\n"
1062 "\r\n"
1063 "\n";
1064 std::string header_input = "GET /foobar HTTP/1.0\r\n\n";
1065
1066 FakeHeaders fake_headers;
1067
1068 {
1069 InSequence s1;
1070 // Yes, that is correct-- the framer 'eats' the blank-lines at the beginning
1071 // and never notifies the visitor.
1072
1073 EXPECT_CALL(visitor_mock_,
1074 OnRequestFirstLineInput("GET /foobar HTTP/1.0", "GET",
1075 "/foobar", "HTTP/1.0"));
1076 EXPECT_CALL(visitor_mock_, ProcessHeaders(fake_headers));
1077 EXPECT_CALL(visitor_mock_, HeaderDone());
1078 EXPECT_CALL(visitor_mock_, MessageDone());
1079 }
1080 EXPECT_CALL(visitor_mock_, OnHeaderInput("GET /foobar HTTP/1.0\r\n\n"));
1081
1082 ASSERT_EQ(blanks.size(),
1083 balsa_frame_.ProcessInput(blanks.data(), blanks.size()));
1084 ASSERT_EQ(header_input.size(), balsa_frame_.ProcessInput(
1085 header_input.data(), header_input.size()));
1086 }
1087
TEST_F(HTTPBalsaFrameTest,VisitorInvokedProperlyForRequestWithZeroContentLength)1088 TEST_F(HTTPBalsaFrameTest,
1089 VisitorInvokedProperlyForRequestWithZeroContentLength) {
1090 std::string message =
1091 "PUT /search?q=fo HTTP/1.1\n"
1092 "content-length: 0 \n"
1093 "\n";
1094
1095 FakeHeaders fake_headers;
1096 fake_headers.AddKeyValue("content-length", "0");
1097
1098 {
1099 InSequence s1;
1100
1101 EXPECT_CALL(visitor_mock_,
1102 OnRequestFirstLineInput("PUT /search?q=fo HTTP/1.1", "PUT",
1103 "/search?q=fo", "HTTP/1.1"));
1104 EXPECT_CALL(visitor_mock_, ProcessHeaders(fake_headers));
1105 EXPECT_CALL(visitor_mock_, HeaderDone());
1106 EXPECT_CALL(visitor_mock_, MessageDone());
1107 }
1108 EXPECT_CALL(visitor_mock_, OnHeaderInput(message));
1109
1110 ASSERT_EQ(message.size(),
1111 balsa_frame_.ProcessInput(message.data(), message.size()));
1112 }
1113
TEST_F(HTTPBalsaFrameTest,VisitorInvokedProperlyForRequestWithMissingContentLength)1114 TEST_F(HTTPBalsaFrameTest,
1115 VisitorInvokedProperlyForRequestWithMissingContentLength) {
1116 std::string message =
1117 "PUT /search?q=fo HTTP/1.1\n"
1118 "\n";
1119
1120 auto error_code =
1121 BalsaFrameEnums::BalsaFrameEnums::REQUIRED_BODY_BUT_NO_CONTENT_LENGTH;
1122 EXPECT_CALL(visitor_mock_, HandleError(error_code));
1123
1124 balsa_frame_.ProcessInput(message.data(), message.size());
1125 EXPECT_FALSE(balsa_frame_.MessageFullyRead());
1126 EXPECT_TRUE(balsa_frame_.Error());
1127 EXPECT_EQ(error_code, balsa_frame_.ErrorCode());
1128 }
1129
TEST_F(HTTPBalsaFrameTest,ContentLengthNotRequired)1130 TEST_F(HTTPBalsaFrameTest, ContentLengthNotRequired) {
1131 HttpValidationPolicy http_validation_policy;
1132 http_validation_policy.require_content_length_if_body_required = false;
1133 balsa_frame_.set_http_validation_policy(http_validation_policy);
1134
1135 std::string message =
1136 "PUT /search?q=fo HTTP/1.1\n"
1137 "\n";
1138
1139 balsa_frame_.ProcessInput(message.data(), message.size());
1140 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
1141 EXPECT_FALSE(balsa_frame_.Error());
1142 }
1143
TEST_F(HTTPBalsaFrameTest,VisitorInvokedProperlyForPermittedMissingContentLength)1144 TEST_F(HTTPBalsaFrameTest,
1145 VisitorInvokedProperlyForPermittedMissingContentLength) {
1146 std::string message =
1147 "PUT /search?q=fo HTTP/1.1\n"
1148 "\n";
1149
1150 FakeHeaders fake_headers;
1151
1152 {
1153 InSequence s1;
1154
1155 EXPECT_CALL(visitor_mock_,
1156 OnRequestFirstLineInput("PUT /search?q=fo HTTP/1.1", "PUT",
1157 "/search?q=fo", "HTTP/1.1"));
1158 }
1159 ASSERT_EQ(message.size(),
1160 balsa_frame_.ProcessInput(message.data(), message.size()));
1161 }
1162
TEST_F(HTTPBalsaFrameTest,NothingBadHappensWhenNothingInConnectionLine)1163 TEST_F(HTTPBalsaFrameTest, NothingBadHappensWhenNothingInConnectionLine) {
1164 // This is similar to the test above, but we use different whitespace
1165 // throughout.
1166 std::string message =
1167 "PUT \t /search?q=fo \t HTTP/1.1 \t \r\n"
1168 "Connection:\r\n"
1169 "content-length: 0\r\n"
1170 "\r\n";
1171
1172 FakeHeaders fake_headers;
1173 fake_headers.AddKeyValue("Connection", "");
1174 fake_headers.AddKeyValue("content-length", "0");
1175
1176 {
1177 InSequence s1;
1178
1179 EXPECT_CALL(visitor_mock_,
1180 OnRequestFirstLineInput("PUT \t /search?q=fo \t HTTP/1.1",
1181 "PUT", "/search?q=fo", "HTTP/1.1"));
1182 EXPECT_CALL(visitor_mock_, ProcessHeaders(fake_headers));
1183 EXPECT_CALL(visitor_mock_, HeaderDone());
1184 EXPECT_CALL(visitor_mock_, MessageDone());
1185 }
1186 EXPECT_CALL(visitor_mock_, OnHeaderInput(message));
1187
1188 ASSERT_EQ(message.size(),
1189 balsa_frame_.ProcessInput(message.data(), message.size()));
1190 }
1191
TEST_F(HTTPBalsaFrameTest,NothingBadHappensWhenOnlyCommentsInConnectionLine)1192 TEST_F(HTTPBalsaFrameTest, NothingBadHappensWhenOnlyCommentsInConnectionLine) {
1193 // This is similar to the test above, but we use different whitespace
1194 // throughout.
1195 std::string message =
1196 "PUT \t /search?q=fo \t HTTP/1.1 \t \r\n"
1197 "Connection: ,,,,,,,,\r\n"
1198 "content-length: 0\r\n"
1199 "\r\n";
1200
1201 FakeHeaders fake_headers;
1202 fake_headers.AddKeyValue("Connection", ",,,,,,,,");
1203 fake_headers.AddKeyValue("content-length", "0");
1204
1205 {
1206 InSequence s1;
1207
1208 EXPECT_CALL(visitor_mock_,
1209 OnRequestFirstLineInput("PUT \t /search?q=fo \t HTTP/1.1",
1210 "PUT", "/search?q=fo", "HTTP/1.1"));
1211 EXPECT_CALL(visitor_mock_, ProcessHeaders(fake_headers));
1212 EXPECT_CALL(visitor_mock_, HeaderDone());
1213 EXPECT_CALL(visitor_mock_, MessageDone());
1214 }
1215 EXPECT_CALL(visitor_mock_, OnHeaderInput(message));
1216
1217 ASSERT_EQ(message.size(),
1218 balsa_frame_.ProcessInput(message.data(), message.size()));
1219 }
1220
TEST_F(HTTPBalsaFrameTest,VisitorInvokedProperlyForRequestWithZeroContentLengthMk2)1221 TEST_F(HTTPBalsaFrameTest,
1222 VisitorInvokedProperlyForRequestWithZeroContentLengthMk2) {
1223 // This is similar to the test above, but we use different whitespace
1224 // throughout.
1225 std::string message =
1226 "PUT \t /search?q=fo \t HTTP/1.1 \t \r\n"
1227 "Connection: \t close \t\r\n"
1228 "content-length: \t\t 0 \t\t \r\n"
1229 "\r\n";
1230
1231 FakeHeaders fake_headers;
1232 fake_headers.AddKeyValue("Connection", "close");
1233 fake_headers.AddKeyValue("content-length", "0");
1234
1235 {
1236 InSequence s1;
1237
1238 EXPECT_CALL(visitor_mock_,
1239 OnRequestFirstLineInput("PUT \t /search?q=fo \t HTTP/1.1",
1240 "PUT", "/search?q=fo", "HTTP/1.1"));
1241 EXPECT_CALL(visitor_mock_, ProcessHeaders(fake_headers));
1242 EXPECT_CALL(visitor_mock_, HeaderDone());
1243 EXPECT_CALL(visitor_mock_, MessageDone());
1244 }
1245 EXPECT_CALL(visitor_mock_, OnHeaderInput(message));
1246
1247 ASSERT_EQ(message.size(),
1248 balsa_frame_.ProcessInput(message.data(), message.size()));
1249 }
1250
TEST_F(HTTPBalsaFrameTest,NothingBadHappensWhenNoVisitorIsAssigned)1251 TEST_F(HTTPBalsaFrameTest, NothingBadHappensWhenNoVisitorIsAssigned) {
1252 std::string headers =
1253 "GET / HTTP/1.1\r\n"
1254 "Connection: close\r\n"
1255 "transfer-encoding: chunked\r\n"
1256 "\r\n";
1257
1258 std::string chunks =
1259 "3\r\n"
1260 "123\r\n"
1261 "0\r\n";
1262 std::string trailer =
1263 "crass: monkeys\r\n"
1264 "funky: monkeys\r\n"
1265 "\r\n";
1266
1267 balsa_frame_.set_balsa_visitor(nullptr);
1268 ASSERT_EQ(headers.size(),
1269 balsa_frame_.ProcessInput(headers.data(), headers.size()));
1270 ASSERT_EQ(chunks.size(),
1271 balsa_frame_.ProcessInput(chunks.data(), chunks.size()));
1272 EXPECT_EQ(trailer.size(),
1273 balsa_frame_.ProcessInput(trailer.data(), trailer.size()));
1274 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
1275 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame_.ErrorCode());
1276 }
1277
TEST_F(HTTPBalsaFrameTest,RequestWithTrailers)1278 TEST_F(HTTPBalsaFrameTest, RequestWithTrailers) {
1279 std::string headers =
1280 "GET / HTTP/1.1\r\n"
1281 "Connection: close\r\n"
1282 "transfer-encoding: chunked\r\n"
1283 "\r\n";
1284
1285 std::string chunks =
1286 "3\r\n"
1287 "123\r\n"
1288 "0\r\n";
1289 std::string trailer =
1290 "crass: monkeys\r\n"
1291 "funky: monkeys\r\n"
1292 "\r\n";
1293
1294 InSequence s;
1295
1296 FakeHeaders fake_headers;
1297 fake_headers.AddKeyValue("Connection", "close");
1298 fake_headers.AddKeyValue("transfer-encoding", "chunked");
1299 EXPECT_CALL(visitor_mock_, ProcessHeaders(fake_headers));
1300 ASSERT_EQ(headers.size(),
1301 balsa_frame_.ProcessInput(headers.data(), headers.size()));
1302 testing::Mock::VerifyAndClearExpectations(&visitor_mock_);
1303
1304 ASSERT_EQ(chunks.size(),
1305 balsa_frame_.ProcessInput(chunks.data(), chunks.size()));
1306
1307 FakeHeaders fake_trailers;
1308 fake_trailers.AddKeyValue("crass", "monkeys");
1309 fake_trailers.AddKeyValue("funky", "monkeys");
1310 EXPECT_CALL(visitor_mock_, OnTrailers(fake_trailers));
1311
1312 EXPECT_CALL(visitor_mock_, OnTrailerInput(_)).Times(AtLeast(1));
1313
1314 EXPECT_EQ(trailer.size(),
1315 balsa_frame_.ProcessInput(trailer.data(), trailer.size()));
1316
1317 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
1318 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame_.ErrorCode());
1319 }
1320
TEST_F(HTTPBalsaFrameTest,NothingBadHappensWhenNoVisitorIsAssignedInResponse)1321 TEST_F(HTTPBalsaFrameTest, NothingBadHappensWhenNoVisitorIsAssignedInResponse) {
1322 std::string headers =
1323 "HTTP/1.1 502 Bad Gateway\r\n"
1324 "Connection: close\r\n"
1325 "transfer-encoding: chunked\r\n"
1326 "\r\n";
1327
1328 std::string chunks =
1329 "3\r\n"
1330 "123\r\n"
1331 "0\r\n";
1332 std::string trailer =
1333 "crass: monkeys\r\n"
1334 "funky: monkeys\r\n"
1335 "\r\n";
1336 balsa_frame_.set_is_request(false);
1337 balsa_frame_.set_balsa_visitor(nullptr);
1338
1339 ASSERT_EQ(headers.size(),
1340 balsa_frame_.ProcessInput(headers.data(), headers.size()));
1341 ASSERT_EQ(chunks.size(),
1342 balsa_frame_.ProcessInput(chunks.data(), chunks.size()));
1343 EXPECT_EQ(trailer.size(),
1344 balsa_frame_.ProcessInput(trailer.data(), trailer.size()));
1345 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
1346 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame_.ErrorCode());
1347 }
1348
TEST_F(HTTPBalsaFrameTest,TransferEncodingIdentityIsIgnored)1349 TEST_F(HTTPBalsaFrameTest, TransferEncodingIdentityIsIgnored) {
1350 std::string headers =
1351 "GET / HTTP/1.1\r\n"
1352 "Connection: close\r\n"
1353 "transfer-encoding: identity\r\n"
1354 "content-length: 10\r\n"
1355 "\r\n";
1356
1357 std::string body = "1234567890";
1358 std::string message = (headers + body);
1359
1360 ASSERT_EQ(headers.size(),
1361 balsa_frame_.ProcessInput(message.data(), message.size()));
1362 EXPECT_FALSE(balsa_frame_.MessageFullyRead());
1363 ASSERT_EQ(body.size(), balsa_frame_.ProcessInput(body.data(), body.size()));
1364 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
1365 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame_.ErrorCode());
1366 }
1367
TEST_F(HTTPBalsaFrameTest,NothingBadHappensWhenAVisitorIsChangedToNULLInMidParsing)1368 TEST_F(HTTPBalsaFrameTest,
1369 NothingBadHappensWhenAVisitorIsChangedToNULLInMidParsing) {
1370 std::string headers =
1371 "GET / HTTP/1.1\r\n"
1372 "Connection: close\r\n"
1373 "transfer-encoding: chunked\r\n"
1374 "\r\n";
1375
1376 std::string chunks =
1377 "3\r\n"
1378 "123\r\n"
1379 "0\r\n";
1380 std::string trailer =
1381 "crass: monkeys\r\n"
1382 "funky: monkeys\r\n"
1383 "\n";
1384
1385 ASSERT_EQ(headers.size(),
1386 balsa_frame_.ProcessInput(headers.data(), headers.size()));
1387 balsa_frame_.set_balsa_visitor(nullptr);
1388 ASSERT_EQ(chunks.size(),
1389 balsa_frame_.ProcessInput(chunks.data(), chunks.size()));
1390 ASSERT_EQ(trailer.size(),
1391 balsa_frame_.ProcessInput(trailer.data(), trailer.size()));
1392 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
1393 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame_.ErrorCode());
1394 }
1395
TEST_F(HTTPBalsaFrameTest,NothingBadHappensWhenAVisitorIsChangedToNULLInMidParsingInTrailer)1396 TEST_F(HTTPBalsaFrameTest,
1397 NothingBadHappensWhenAVisitorIsChangedToNULLInMidParsingInTrailer) {
1398 std::string headers =
1399 "HTTP/1.1 503 Server Not Available\r\n"
1400 "Connection: close\r\n"
1401 "transfer-encoding: chunked\r\n"
1402 "\r\n";
1403
1404 std::string chunks =
1405 "3\r\n"
1406 "123\r\n"
1407 "0\r\n";
1408 std::string trailer =
1409 "crass: monkeys\r\n"
1410 "funky: monkeys\r\n"
1411 "\n";
1412
1413 balsa_frame_.set_is_request(false);
1414
1415 ASSERT_EQ(headers.size(),
1416 balsa_frame_.ProcessInput(headers.data(), headers.size()));
1417 balsa_frame_.set_balsa_visitor(nullptr);
1418 ASSERT_EQ(chunks.size(),
1419 balsa_frame_.ProcessInput(chunks.data(), chunks.size()));
1420 ASSERT_EQ(trailer.size(),
1421 balsa_frame_.ProcessInput(trailer.data(), trailer.size()));
1422 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
1423 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame_.ErrorCode());
1424 }
1425
TEST_F(HTTPBalsaFrameTest,NothingBadHappensWhenNoVisitorAssignedAndChunkingErrorOccurs)1426 TEST_F(HTTPBalsaFrameTest,
1427 NothingBadHappensWhenNoVisitorAssignedAndChunkingErrorOccurs) {
1428 std::string headers =
1429 "GET / HTTP/1.1\r\n"
1430 "Connection: close\r\n"
1431 "transfer-encoding: chunked\r\n"
1432 "\r\n";
1433
1434 std::string chunks =
1435 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\r\n" // should overflow
1436 "0\r\n";
1437 std::string trailer =
1438 "crass: monkeys\r\n"
1439 "funky: monkeys\r\n"
1440 "\n";
1441
1442 ASSERT_EQ(headers.size(),
1443 balsa_frame_.ProcessInput(headers.data(), headers.size()));
1444 balsa_frame_.set_balsa_visitor(nullptr);
1445 EXPECT_GE(chunks.size(),
1446 balsa_frame_.ProcessInput(chunks.data(), chunks.size()));
1447 EXPECT_FALSE(balsa_frame_.MessageFullyRead());
1448 EXPECT_TRUE(balsa_frame_.Error());
1449 EXPECT_EQ(BalsaFrameEnums::CHUNK_LENGTH_OVERFLOW, balsa_frame_.ErrorCode());
1450 }
1451
TEST_F(HTTPBalsaFrameTest,FramerRecognizesSemicolonAsChunkSizeDelimiter)1452 TEST_F(HTTPBalsaFrameTest, FramerRecognizesSemicolonAsChunkSizeDelimiter) {
1453 std::string headers =
1454 "GET / HTTP/1.1\r\n"
1455 "Connection: close\r\n"
1456 "transfer-encoding: chunked\r\n"
1457 "\r\n";
1458
1459 std::string chunks =
1460 "8; foo=bar\r\n"
1461 "deadbeef\r\n"
1462 "0\r\n"
1463 "\r\n";
1464
1465 ASSERT_EQ(headers.size(),
1466 balsa_frame_.ProcessInput(headers.data(), headers.size()));
1467
1468 balsa_frame_.set_balsa_visitor(&visitor_mock_);
1469 EXPECT_CALL(visitor_mock_, OnChunkLength(8));
1470 EXPECT_CALL(visitor_mock_, OnChunkLength(0));
1471 EXPECT_CALL(visitor_mock_, OnChunkExtensionInput("; foo=bar"));
1472 EXPECT_CALL(visitor_mock_, OnChunkExtensionInput(""));
1473
1474 EXPECT_EQ(chunks.size(),
1475 balsa_frame_.ProcessInput(chunks.data(), chunks.size()));
1476 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
1477 EXPECT_FALSE(balsa_frame_.Error());
1478 }
1479
TEST_F(HTTPBalsaFrameTest,NonAsciiCharacterInChunkLength)1480 TEST_F(HTTPBalsaFrameTest, NonAsciiCharacterInChunkLength) {
1481 std::string headers =
1482 "GET / HTTP/1.1\r\n"
1483 "Connection: close\r\n"
1484 "transfer-encoding: chunked\r\n"
1485 "\r\n";
1486
1487 std::string chunks =
1488 "555\xAB\r\n" // Character overflowing 7 bits, see b/20238315
1489 "0\r\n";
1490 std::string trailer =
1491 "crass: monkeys\r\n"
1492 "funky: monkeys\r\n"
1493 "\n";
1494
1495 FakeHeaders fake_headers;
1496 fake_headers.AddKeyValue("Connection", "close");
1497 fake_headers.AddKeyValue("transfer-encoding", "chunked");
1498
1499 auto error_code = BalsaFrameEnums::INVALID_CHUNK_LENGTH;
1500 {
1501 InSequence s1;
1502 EXPECT_CALL(visitor_mock_, OnRequestFirstLineInput("GET / HTTP/1.1", "GET",
1503 "/", "HTTP/1.1"));
1504 EXPECT_CALL(visitor_mock_, ProcessHeaders(fake_headers));
1505 EXPECT_CALL(visitor_mock_, HeaderDone());
1506 EXPECT_CALL(visitor_mock_, OnRawBodyInput("555\xAB"));
1507 EXPECT_CALL(visitor_mock_, HandleError(error_code));
1508 }
1509
1510 ASSERT_EQ(headers.size(),
1511 balsa_frame_.ProcessInput(headers.data(), headers.size()));
1512 EXPECT_EQ(strlen("555\xAB"),
1513 balsa_frame_.ProcessInput(chunks.data(), chunks.size()));
1514 EXPECT_FALSE(balsa_frame_.MessageFullyRead());
1515 EXPECT_TRUE(balsa_frame_.Error());
1516 EXPECT_EQ(BalsaFrameEnums::INVALID_CHUNK_LENGTH, balsa_frame_.ErrorCode());
1517 }
1518
TEST_F(HTTPBalsaFrameTest,VisitorCalledAsExpectedWhenChunkingOverflowOccurs)1519 TEST_F(HTTPBalsaFrameTest, VisitorCalledAsExpectedWhenChunkingOverflowOccurs) {
1520 std::string headers =
1521 "GET / HTTP/1.1\r\n"
1522 "Connection: close\r\n"
1523 "transfer-encoding: chunked\r\n"
1524 "\r\n";
1525
1526 std::string chunks =
1527 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\r\n" // should overflow
1528 "0\r\n";
1529 std::string trailer =
1530 "crass: monkeys\r\n"
1531 "funky: monkeys\r\n"
1532 "\n";
1533
1534 const char* chunk_read_before_overflow = "FFFFFFFFFFFFFFFFF";
1535
1536 FakeHeaders fake_headers;
1537 fake_headers.AddKeyValue("Connection", "close");
1538 fake_headers.AddKeyValue("transfer-encoding", "chunked");
1539
1540 auto error_code = BalsaFrameEnums::CHUNK_LENGTH_OVERFLOW;
1541 {
1542 InSequence s1;
1543 EXPECT_CALL(visitor_mock_, OnRequestFirstLineInput("GET / HTTP/1.1", "GET",
1544 "/", "HTTP/1.1"));
1545 EXPECT_CALL(visitor_mock_, ProcessHeaders(fake_headers));
1546 EXPECT_CALL(visitor_mock_, HeaderDone());
1547 EXPECT_CALL(visitor_mock_, OnRawBodyInput(chunk_read_before_overflow));
1548 EXPECT_CALL(visitor_mock_, HandleError(error_code));
1549 }
1550
1551 ASSERT_EQ(headers.size(),
1552 balsa_frame_.ProcessInput(headers.data(), headers.size()));
1553 EXPECT_EQ(strlen(chunk_read_before_overflow),
1554 balsa_frame_.ProcessInput(chunks.data(), chunks.size()));
1555 EXPECT_FALSE(balsa_frame_.MessageFullyRead());
1556 EXPECT_TRUE(balsa_frame_.Error());
1557 EXPECT_EQ(BalsaFrameEnums::CHUNK_LENGTH_OVERFLOW, balsa_frame_.ErrorCode());
1558 }
1559
TEST_F(HTTPBalsaFrameTest,VisitorCalledAsExpectedWhenInvalidChunkLengthOccurs)1560 TEST_F(HTTPBalsaFrameTest,
1561 VisitorCalledAsExpectedWhenInvalidChunkLengthOccurs) {
1562 std::string headers =
1563 "GET / HTTP/1.1\r\n"
1564 "Connection: close\r\n"
1565 "transfer-encoding: chunked\r\n"
1566 "\r\n";
1567
1568 std::string chunks =
1569 "12z123 \r\n" // invalid chunk length
1570 "0\r\n";
1571 std::string trailer =
1572 "crass: monkeys\r\n"
1573 "funky: monkeys\r\n"
1574 "\n";
1575
1576 FakeHeaders fake_headers;
1577 fake_headers.AddKeyValue("Connection", "close");
1578 fake_headers.AddKeyValue("transfer-encoding", "chunked");
1579
1580 auto error_code = BalsaFrameEnums::INVALID_CHUNK_LENGTH;
1581 {
1582 InSequence s1;
1583 EXPECT_CALL(visitor_mock_, OnRequestFirstLineInput("GET / HTTP/1.1", "GET",
1584 "/", "HTTP/1.1"));
1585 EXPECT_CALL(visitor_mock_, ProcessHeaders(fake_headers));
1586 EXPECT_CALL(visitor_mock_, HeaderDone());
1587 EXPECT_CALL(visitor_mock_, OnRawBodyInput("12z"));
1588 EXPECT_CALL(visitor_mock_, HandleError(error_code));
1589 }
1590
1591 ASSERT_EQ(headers.size(),
1592 balsa_frame_.ProcessInput(headers.data(), headers.size()));
1593 EXPECT_EQ(3u, balsa_frame_.ProcessInput(chunks.data(), chunks.size()));
1594 EXPECT_FALSE(balsa_frame_.MessageFullyRead());
1595 EXPECT_TRUE(balsa_frame_.Error());
1596 EXPECT_EQ(BalsaFrameEnums::INVALID_CHUNK_LENGTH, balsa_frame_.ErrorCode());
1597 }
1598
TEST_F(HTTPBalsaFrameTest,VisitorInvokedProperlyForRequestWithContentLength)1599 TEST_F(HTTPBalsaFrameTest, VisitorInvokedProperlyForRequestWithContentLength) {
1600 std::string message_headers =
1601 "PUT \t /search?q=fo \t HTTP/1.1 \t \r\n"
1602 "content-length: \t\t 20 \t\t \r\n"
1603 "\r\n";
1604 std::string message_body = "12345678901234567890";
1605 std::string message =
1606 std::string(message_headers) + std::string(message_body);
1607
1608 FakeHeaders fake_headers;
1609 fake_headers.AddKeyValue("content-length", "20");
1610
1611 {
1612 InSequence s1;
1613 EXPECT_CALL(visitor_mock_,
1614 OnRequestFirstLineInput("PUT \t /search?q=fo \t HTTP/1.1",
1615 "PUT", "/search?q=fo", "HTTP/1.1"));
1616 EXPECT_CALL(visitor_mock_, ProcessHeaders(fake_headers));
1617 EXPECT_CALL(visitor_mock_, HeaderDone());
1618 EXPECT_CALL(visitor_mock_, OnRawBodyInput(message_body));
1619 EXPECT_CALL(visitor_mock_, OnBodyChunkInput(message_body));
1620 EXPECT_CALL(visitor_mock_, MessageDone());
1621 }
1622 EXPECT_CALL(visitor_mock_, OnHeaderInput(message_headers));
1623
1624 ASSERT_EQ(message_headers.size(),
1625 balsa_frame_.ProcessInput(message.data(), message.size()));
1626 ASSERT_EQ(message_body.size(),
1627 balsa_frame_.ProcessInput(message.data() + message_headers.size(),
1628 message.size()));
1629 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
1630 EXPECT_FALSE(balsa_frame_.Error());
1631 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame_.ErrorCode());
1632 }
1633
TEST_F(HTTPBalsaFrameTest,VisitorInvokedProperlyForRequestWithOneCharContentLength)1634 TEST_F(HTTPBalsaFrameTest,
1635 VisitorInvokedProperlyForRequestWithOneCharContentLength) {
1636 std::string message_headers =
1637 "PUT \t /search?q=fo \t HTTP/1.1 \t \r\n"
1638 "content-length: \t\t 2 \t\t \r\n"
1639 "\r\n";
1640 std::string message_body = "12";
1641 std::string message =
1642 std::string(message_headers) + std::string(message_body);
1643
1644 FakeHeaders fake_headers;
1645 fake_headers.AddKeyValue("content-length", "2");
1646
1647 {
1648 InSequence s1;
1649 EXPECT_CALL(visitor_mock_,
1650 OnRequestFirstLineInput("PUT \t /search?q=fo \t HTTP/1.1",
1651 "PUT", "/search?q=fo", "HTTP/1.1"));
1652 EXPECT_CALL(visitor_mock_, ProcessHeaders(fake_headers));
1653 EXPECT_CALL(visitor_mock_, HeaderDone());
1654 EXPECT_CALL(visitor_mock_, OnRawBodyInput(message_body));
1655 EXPECT_CALL(visitor_mock_, OnBodyChunkInput(message_body));
1656 EXPECT_CALL(visitor_mock_, MessageDone());
1657 }
1658 EXPECT_CALL(visitor_mock_, OnHeaderInput(message_headers));
1659
1660 ASSERT_EQ(message_headers.size(),
1661 balsa_frame_.ProcessInput(message.data(), message.size()));
1662 ASSERT_EQ(message_body.size(),
1663 balsa_frame_.ProcessInput(message.data() + message_headers.size(),
1664 message.size()));
1665 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
1666 EXPECT_FALSE(balsa_frame_.Error());
1667 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame_.ErrorCode());
1668 }
1669
TEST_F(HTTPBalsaFrameTest,InvalidChunkExtensionWithCarriageReturn)1670 TEST_F(HTTPBalsaFrameTest, InvalidChunkExtensionWithCarriageReturn) {
1671 balsa_frame_.set_http_validation_policy(
1672 HttpValidationPolicy{.disallow_lone_cr_in_chunk_extension = true});
1673 std::string message_headers =
1674 "POST /potato?salad=withmayo HTTP/1.1\r\n"
1675 "transfer-encoding: chunked\r\n"
1676 "\r\n";
1677 std::string message_body =
1678 "9; bad\rextension\r\n"
1679 "012345678\r\n"
1680 "0\r\n"
1681 "\r\n";
1682 std::string message =
1683 std::string(message_headers) + std::string(message_body);
1684
1685 EXPECT_CALL(visitor_mock_,
1686 HandleError(BalsaFrameEnums::INVALID_CHUNK_EXTENSION));
1687 ASSERT_EQ(message_headers.size(),
1688 balsa_frame_.ProcessInput(message.data(), message.size()));
1689 balsa_frame_.ProcessInput(message.data() + message_headers.size(),
1690 message.size());
1691 }
1692
TEST_F(HTTPBalsaFrameTest,VisitorInvokedProperlyForRequestWithTransferEncoding)1693 TEST_F(HTTPBalsaFrameTest,
1694 VisitorInvokedProperlyForRequestWithTransferEncoding) {
1695 std::string message_headers =
1696 "DELETE /search?q=fo \t HTTP/1.1 \t \r\n"
1697 "trAnsfer-eNcoding: chunked\r\n"
1698 "\r\n";
1699 std::string message_body =
1700 "A chunkjed extension \r\n"
1701 "01234567890 more crud including numbers 123123\r\n"
1702 "3f\n"
1703 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n"
1704 "0 last one\r\n"
1705 "\r\n";
1706 std::string message_body_data =
1707 "0123456789"
1708 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
1709
1710 std::string message =
1711 std::string(message_headers) + std::string(message_body);
1712
1713 FakeHeaders fake_headers;
1714 fake_headers.AddKeyValue("trAnsfer-eNcoding", "chunked");
1715
1716 {
1717 InSequence s1;
1718 EXPECT_CALL(visitor_mock_,
1719 OnRequestFirstLineInput("DELETE /search?q=fo \t HTTP/1.1",
1720 "DELETE", "/search?q=fo", "HTTP/1.1"));
1721 EXPECT_CALL(visitor_mock_, ProcessHeaders(fake_headers));
1722 EXPECT_CALL(visitor_mock_, HeaderDone());
1723 EXPECT_CALL(visitor_mock_, OnChunkLength(10));
1724 EXPECT_CALL(visitor_mock_,
1725 OnChunkExtensionInput(" chunkjed extension "));
1726 EXPECT_CALL(visitor_mock_, OnChunkLength(63));
1727 EXPECT_CALL(visitor_mock_, OnChunkExtensionInput(""));
1728 EXPECT_CALL(visitor_mock_, OnChunkLength(0));
1729 EXPECT_CALL(visitor_mock_, OnChunkExtensionInput(" last one"));
1730 EXPECT_CALL(visitor_mock_, MessageDone());
1731 }
1732 EXPECT_CALL(visitor_mock_, OnHeaderInput(message_headers));
1733 std::string body_input;
1734 EXPECT_CALL(visitor_mock_, OnRawBodyInput(_))
1735 .WillRepeatedly([&body_input](absl::string_view input) {
1736 absl::StrAppend(&body_input, input);
1737 });
1738 std::string body_data;
1739 EXPECT_CALL(visitor_mock_, OnBodyChunkInput(_))
1740 .WillRepeatedly([&body_data](absl::string_view input) {
1741 absl::StrAppend(&body_data, input);
1742 });
1743 EXPECT_CALL(visitor_mock_, OnTrailerInput(_)).Times(0);
1744
1745 ASSERT_EQ(message_headers.size(),
1746 balsa_frame_.ProcessInput(message.data(), message.size()));
1747 EXPECT_EQ(message_body.size(),
1748 balsa_frame_.ProcessInput(message.data() + message_headers.size(),
1749 message.size()));
1750 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
1751 EXPECT_FALSE(balsa_frame_.Error());
1752 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame_.ErrorCode());
1753
1754 EXPECT_EQ(message_body, body_input);
1755 EXPECT_EQ(message_body_data, body_data);
1756 }
1757
TEST_F(HTTPBalsaFrameTest,VisitorInvokedProperlyForRequestWithTransferEncodingAndTrailers)1758 TEST_F(HTTPBalsaFrameTest,
1759 VisitorInvokedProperlyForRequestWithTransferEncodingAndTrailers) {
1760 std::string message_headers =
1761 "DELETE /search?q=fo \t HTTP/1.1 \t \r\n"
1762 "trAnsfer-eNcoding: chunked\r\n"
1763 "another_random_header: \r\n"
1764 " \t \n"
1765 " \t includes a continuation\n"
1766 "\r\n";
1767 std::string message_body =
1768 "A chunkjed extension \r\n"
1769 "01234567890 more crud including numbers 123123\r\n"
1770 "3f\n"
1771 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n"
1772 "1 \r\n"
1773 "x \r\n"
1774 "0 last one\r\n";
1775 std::string trailer_data =
1776 "a_trailer_key: and a trailer value\r\n"
1777 "\r\n";
1778 std::string message_body_data =
1779 "0123456789"
1780 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
1781
1782 std::string message = (std::string(message_headers) +
1783 std::string(message_body) + std::string(trailer_data));
1784
1785 FakeHeaders fake_headers;
1786 fake_headers.AddKeyValue("trAnsfer-eNcoding", "chunked");
1787 fake_headers.AddKeyValue("another_random_header", "includes a continuation");
1788
1789 FakeHeaders fake_trailers;
1790 fake_trailers.AddKeyValue("a_trailer_key", "and a trailer value");
1791
1792 {
1793 InSequence s1;
1794
1795 EXPECT_CALL(visitor_mock_,
1796 OnRequestFirstLineInput("DELETE /search?q=fo \t HTTP/1.1",
1797 "DELETE", "/search?q=fo", "HTTP/1.1"));
1798 EXPECT_CALL(visitor_mock_, ProcessHeaders(fake_headers));
1799 EXPECT_CALL(visitor_mock_, HeaderDone());
1800 EXPECT_CALL(visitor_mock_, OnChunkLength(10));
1801 EXPECT_CALL(visitor_mock_, OnChunkLength(63));
1802 EXPECT_CALL(visitor_mock_, OnChunkLength(1));
1803 EXPECT_CALL(visitor_mock_, OnChunkLength(0));
1804 EXPECT_CALL(visitor_mock_, OnTrailers(fake_trailers));
1805 EXPECT_CALL(visitor_mock_, MessageDone());
1806 }
1807 EXPECT_CALL(visitor_mock_, OnHeaderInput(message_headers));
1808 std::string body_input;
1809 EXPECT_CALL(visitor_mock_, OnRawBodyInput(_))
1810 .WillRepeatedly([&body_input](absl::string_view input) {
1811 absl::StrAppend(&body_input, input);
1812 });
1813 std::string body_data;
1814 EXPECT_CALL(visitor_mock_, OnBodyChunkInput(_))
1815 .WillRepeatedly([&body_data](absl::string_view input) {
1816 absl::StrAppend(&body_data, input);
1817 });
1818 EXPECT_CALL(visitor_mock_, OnTrailerInput(trailer_data));
1819 EXPECT_CALL(visitor_mock_, OnChunkExtensionInput(_)).Times(AnyNumber());
1820
1821 ASSERT_EQ(message_headers.size(),
1822 balsa_frame_.ProcessInput(message.data(), message.size()));
1823 EXPECT_EQ(message_body.size() + trailer_data.size(),
1824 balsa_frame_.ProcessInput(message.data() + message_headers.size(),
1825 message.size()));
1826 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
1827 EXPECT_FALSE(balsa_frame_.Error());
1828 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame_.ErrorCode());
1829
1830 EXPECT_EQ(message_body, body_input);
1831 EXPECT_EQ(message_body_data, body_data);
1832 }
1833
TEST_F(HTTPBalsaFrameTest,VisitorInvokedProperlyWithRequestFirstLineWarningWithOnlyMethod)1834 TEST_F(HTTPBalsaFrameTest,
1835 VisitorInvokedProperlyWithRequestFirstLineWarningWithOnlyMethod) {
1836 std::string message = "GET\n";
1837
1838 FakeHeaders fake_headers;
1839
1840 auto error_code = BalsaFrameEnums::FAILED_TO_FIND_WS_AFTER_REQUEST_METHOD;
1841 {
1842 InSequence s;
1843 EXPECT_CALL(visitor_mock_, HandleWarning(error_code));
1844 EXPECT_CALL(visitor_mock_, OnRequestFirstLineInput("GET", "GET", "", ""));
1845 EXPECT_CALL(visitor_mock_, ProcessHeaders(fake_headers));
1846 EXPECT_CALL(visitor_mock_, HeaderDone());
1847 EXPECT_CALL(visitor_mock_, MessageDone());
1848 }
1849 EXPECT_CALL(visitor_mock_, OnHeaderInput(message));
1850
1851 EXPECT_EQ(message.size(),
1852 balsa_frame_.ProcessInput(message.data(), message.size()));
1853 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
1854 EXPECT_FALSE(balsa_frame_.Error());
1855 EXPECT_EQ(BalsaFrameEnums::FAILED_TO_FIND_WS_AFTER_REQUEST_METHOD,
1856 balsa_frame_.ErrorCode());
1857 }
1858
TEST_F(HTTPBalsaFrameTest,VisitorInvokedProperlyWithRequestFirstLineWarningWithOnlyMethodAndWS)1859 TEST_F(HTTPBalsaFrameTest,
1860 VisitorInvokedProperlyWithRequestFirstLineWarningWithOnlyMethodAndWS) {
1861 std::string message = "GET \n";
1862
1863 FakeHeaders fake_headers;
1864
1865 auto error_code = BalsaFrameEnums::FAILED_TO_FIND_WS_AFTER_REQUEST_METHOD;
1866 {
1867 InSequence s;
1868 EXPECT_CALL(visitor_mock_, HandleWarning(error_code));
1869 // The flag setting here intentionally alters the framer's behavior with
1870 // trailing whitespace.
1871 EXPECT_CALL(visitor_mock_, OnRequestFirstLineInput("GET ", "GET", "", ""));
1872 EXPECT_CALL(visitor_mock_, ProcessHeaders(fake_headers));
1873 EXPECT_CALL(visitor_mock_, HeaderDone());
1874 EXPECT_CALL(visitor_mock_, MessageDone());
1875 }
1876 EXPECT_CALL(visitor_mock_, OnHeaderInput(message));
1877
1878 EXPECT_EQ(message.size(),
1879 balsa_frame_.ProcessInput(message.data(), message.size()));
1880 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
1881 EXPECT_FALSE(balsa_frame_.Error());
1882 EXPECT_EQ(BalsaFrameEnums::FAILED_TO_FIND_WS_AFTER_REQUEST_METHOD,
1883 balsa_frame_.ErrorCode());
1884 }
1885
TEST_F(HTTPBalsaFrameTest,VisitorInvokedProperlyWithRequestFirstLineWarningWithMethodAndURI)1886 TEST_F(HTTPBalsaFrameTest,
1887 VisitorInvokedProperlyWithRequestFirstLineWarningWithMethodAndURI) {
1888 std::string message = "GET /uri\n";
1889
1890 FakeHeaders fake_headers;
1891
1892 auto error_code =
1893 BalsaFrameEnums::FAILED_TO_FIND_WS_AFTER_REQUEST_REQUEST_URI;
1894 {
1895 InSequence s;
1896 EXPECT_CALL(visitor_mock_, HandleWarning(error_code));
1897 EXPECT_CALL(visitor_mock_,
1898 OnRequestFirstLineInput("GET /uri", "GET", "/uri", ""));
1899 EXPECT_CALL(visitor_mock_, ProcessHeaders(fake_headers));
1900 EXPECT_CALL(visitor_mock_, HeaderDone());
1901 EXPECT_CALL(visitor_mock_, MessageDone());
1902 }
1903 EXPECT_CALL(visitor_mock_, OnHeaderInput(message));
1904
1905 EXPECT_EQ(message.size(),
1906 balsa_frame_.ProcessInput(message.data(), message.size()));
1907 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
1908 EXPECT_FALSE(balsa_frame_.Error());
1909 EXPECT_EQ(BalsaFrameEnums::FAILED_TO_FIND_WS_AFTER_REQUEST_REQUEST_URI,
1910 balsa_frame_.ErrorCode());
1911 }
1912
TEST_F(HTTPBalsaFrameTest,VisitorInvokedProperlyWithResponseFirstLineError)1913 TEST_F(HTTPBalsaFrameTest, VisitorInvokedProperlyWithResponseFirstLineError) {
1914 std::string message = "HTTP/1.1\n\n";
1915
1916 FakeHeaders fake_headers;
1917
1918 balsa_frame_.set_is_request(false);
1919 auto error_code = BalsaFrameEnums::FAILED_TO_FIND_WS_AFTER_RESPONSE_VERSION;
1920 {
1921 InSequence s;
1922 EXPECT_CALL(visitor_mock_, HandleError(error_code));
1923 // The function returns before any of the following is called.
1924 EXPECT_CALL(visitor_mock_, OnRequestFirstLineInput).Times(0);
1925 EXPECT_CALL(visitor_mock_, ProcessHeaders(_)).Times(0);
1926 EXPECT_CALL(visitor_mock_, HeaderDone()).Times(0);
1927 EXPECT_CALL(visitor_mock_, MessageDone()).Times(0);
1928 }
1929 EXPECT_CALL(visitor_mock_, OnHeaderInput(_)).Times(0);
1930
1931 EXPECT_GE(message.size(),
1932 balsa_frame_.ProcessInput(message.data(), message.size()));
1933 EXPECT_FALSE(balsa_frame_.MessageFullyRead());
1934 EXPECT_TRUE(balsa_frame_.Error());
1935 EXPECT_EQ(BalsaFrameEnums::FAILED_TO_FIND_WS_AFTER_RESPONSE_VERSION,
1936 balsa_frame_.ErrorCode());
1937 }
1938
TEST_F(HTTPBalsaFrameTest,FlagsErrorWithContentLengthOverflow)1939 TEST_F(HTTPBalsaFrameTest, FlagsErrorWithContentLengthOverflow) {
1940 std::string message =
1941 "HTTP/1.0 200 OK\r\n"
1942 "content-length: 9999999999999999999999999999999999999999\n"
1943 "\n";
1944
1945 balsa_frame_.set_is_request(false);
1946 auto error_code = BalsaFrameEnums::UNPARSABLE_CONTENT_LENGTH;
1947 EXPECT_CALL(visitor_mock_, HandleError(error_code));
1948
1949 EXPECT_EQ(message.size(),
1950 balsa_frame_.ProcessInput(message.data(), message.size()));
1951 EXPECT_FALSE(balsa_frame_.MessageFullyRead());
1952 EXPECT_TRUE(balsa_frame_.Error());
1953 EXPECT_EQ(BalsaFrameEnums::UNPARSABLE_CONTENT_LENGTH,
1954 balsa_frame_.ErrorCode());
1955 }
1956
TEST_F(HTTPBalsaFrameTest,FlagsErrorWithInvalidResponseCode)1957 TEST_F(HTTPBalsaFrameTest, FlagsErrorWithInvalidResponseCode) {
1958 std::string message =
1959 "HTTP/1.0 x OK\r\n"
1960 "\n";
1961
1962 balsa_frame_.set_is_request(false);
1963 auto error_code = BalsaFrameEnums::FAILED_CONVERTING_STATUS_CODE_TO_INT;
1964 EXPECT_CALL(visitor_mock_, HandleError(error_code));
1965
1966 EXPECT_GE(message.size(),
1967 balsa_frame_.ProcessInput(message.data(), message.size()));
1968 EXPECT_FALSE(balsa_frame_.MessageFullyRead());
1969 EXPECT_TRUE(balsa_frame_.Error());
1970 EXPECT_EQ(BalsaFrameEnums::FAILED_CONVERTING_STATUS_CODE_TO_INT,
1971 balsa_frame_.ErrorCode());
1972 }
1973
TEST_F(HTTPBalsaFrameTest,FlagsErrorWithOverflowingResponseCode)1974 TEST_F(HTTPBalsaFrameTest, FlagsErrorWithOverflowingResponseCode) {
1975 std::string message =
1976 "HTTP/1.0 999999999999999999999999999999999999999 OK\r\n"
1977 "\n";
1978
1979 balsa_frame_.set_is_request(false);
1980 auto error_code = BalsaFrameEnums::FAILED_CONVERTING_STATUS_CODE_TO_INT;
1981 EXPECT_CALL(visitor_mock_, HandleError(error_code));
1982
1983 EXPECT_GE(message.size(),
1984 balsa_frame_.ProcessInput(message.data(), message.size()));
1985 EXPECT_FALSE(balsa_frame_.MessageFullyRead());
1986 EXPECT_TRUE(balsa_frame_.Error());
1987 EXPECT_EQ(BalsaFrameEnums::FAILED_CONVERTING_STATUS_CODE_TO_INT,
1988 balsa_frame_.ErrorCode());
1989 }
1990
TEST_F(HTTPBalsaFrameTest,FlagsErrorWithInvalidContentLength)1991 TEST_F(HTTPBalsaFrameTest, FlagsErrorWithInvalidContentLength) {
1992 std::string message =
1993 "HTTP/1.0 200 OK\r\n"
1994 "content-length: xxx\n"
1995 "\n";
1996
1997 balsa_frame_.set_is_request(false);
1998 auto error_code = BalsaFrameEnums::UNPARSABLE_CONTENT_LENGTH;
1999 EXPECT_CALL(visitor_mock_, HandleError(error_code));
2000
2001 EXPECT_EQ(message.size(),
2002 balsa_frame_.ProcessInput(message.data(), message.size()));
2003 EXPECT_FALSE(balsa_frame_.MessageFullyRead());
2004 EXPECT_TRUE(balsa_frame_.Error());
2005 EXPECT_EQ(BalsaFrameEnums::UNPARSABLE_CONTENT_LENGTH,
2006 balsa_frame_.ErrorCode());
2007 }
2008
TEST_F(HTTPBalsaFrameTest,FlagsErrorWithNegativeContentLengthValue)2009 TEST_F(HTTPBalsaFrameTest, FlagsErrorWithNegativeContentLengthValue) {
2010 std::string message =
2011 "HTTP/1.0 200 OK\r\n"
2012 "content-length: -20\n"
2013 "\n";
2014
2015 balsa_frame_.set_is_request(false);
2016 auto error_code = BalsaFrameEnums::UNPARSABLE_CONTENT_LENGTH;
2017 EXPECT_CALL(visitor_mock_, HandleError(error_code));
2018
2019 EXPECT_EQ(message.size(),
2020 balsa_frame_.ProcessInput(message.data(), message.size()));
2021 EXPECT_FALSE(balsa_frame_.MessageFullyRead());
2022 EXPECT_TRUE(balsa_frame_.Error());
2023 EXPECT_EQ(BalsaFrameEnums::UNPARSABLE_CONTENT_LENGTH,
2024 balsa_frame_.ErrorCode());
2025 }
2026
TEST_F(HTTPBalsaFrameTest,FlagsErrorWithEmptyContentLengthValue)2027 TEST_F(HTTPBalsaFrameTest, FlagsErrorWithEmptyContentLengthValue) {
2028 std::string message =
2029 "HTTP/1.0 200 OK\r\n"
2030 "content-length: \n"
2031 "\n";
2032
2033 balsa_frame_.set_is_request(false);
2034 auto error_code = BalsaFrameEnums::UNPARSABLE_CONTENT_LENGTH;
2035 EXPECT_CALL(visitor_mock_, HandleError(error_code));
2036
2037 EXPECT_EQ(message.size(),
2038 balsa_frame_.ProcessInput(message.data(), message.size()));
2039 EXPECT_FALSE(balsa_frame_.MessageFullyRead());
2040 EXPECT_TRUE(balsa_frame_.Error());
2041 EXPECT_EQ(BalsaFrameEnums::UNPARSABLE_CONTENT_LENGTH,
2042 balsa_frame_.ErrorCode());
2043 }
2044
TEST_F(HTTPBalsaFrameTest,VisitorInvokedProperlyForTrivialResponse)2045 TEST_F(HTTPBalsaFrameTest, VisitorInvokedProperlyForTrivialResponse) {
2046 std::string message =
2047 "HTTP/1.0 200 OK\r\n"
2048 "content-length: 0\n"
2049 "\n";
2050
2051 FakeHeaders fake_headers;
2052 fake_headers.AddKeyValue("content-length", "0");
2053
2054 balsa_frame_.set_is_request(false);
2055 {
2056 InSequence s;
2057 EXPECT_CALL(visitor_mock_, OnResponseFirstLineInput(
2058 "HTTP/1.0 200 OK", "HTTP/1.0", "200", "OK"));
2059 EXPECT_CALL(visitor_mock_, ProcessHeaders(fake_headers));
2060 EXPECT_CALL(visitor_mock_, HeaderDone());
2061 EXPECT_CALL(visitor_mock_, MessageDone());
2062 }
2063 EXPECT_CALL(visitor_mock_, OnHeaderInput(message));
2064
2065 EXPECT_EQ(message.size(),
2066 balsa_frame_.ProcessInput(message.data(), message.size()));
2067 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
2068 EXPECT_FALSE(balsa_frame_.Error());
2069 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame_.ErrorCode());
2070 }
2071
TEST_F(HTTPBalsaFrameTest,VisitorInvokedProperlyForResponseWithSplitBlankLines)2072 TEST_F(HTTPBalsaFrameTest,
2073 VisitorInvokedProperlyForResponseWithSplitBlankLines) {
2074 std::string blanks =
2075 "\n"
2076 "\r\n"
2077 "\r\n";
2078 std::string header_input =
2079 "HTTP/1.0 200 OK\r\n"
2080 "content-length: 0\n"
2081 "\n";
2082 FakeHeaders fake_headers;
2083 fake_headers.AddKeyValue("content-length", "0");
2084
2085 balsa_frame_.set_is_request(false);
2086 {
2087 InSequence s;
2088 EXPECT_CALL(visitor_mock_, OnResponseFirstLineInput(
2089 "HTTP/1.0 200 OK", "HTTP/1.0", "200", "OK"));
2090 EXPECT_CALL(visitor_mock_, ProcessHeaders(fake_headers));
2091 EXPECT_CALL(visitor_mock_, HeaderDone());
2092 EXPECT_CALL(visitor_mock_, MessageDone());
2093 }
2094 EXPECT_CALL(visitor_mock_, OnHeaderInput(header_input));
2095
2096 EXPECT_EQ(blanks.size(),
2097 balsa_frame_.ProcessInput(blanks.data(), blanks.size()));
2098 EXPECT_EQ(header_input.size(), balsa_frame_.ProcessInput(
2099 header_input.data(), header_input.size()));
2100 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
2101 EXPECT_FALSE(balsa_frame_.Error());
2102 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame_.ErrorCode());
2103 }
2104
TEST_F(HTTPBalsaFrameTest,VisitorInvokedProperlyForResponseWithBlankLines)2105 TEST_F(HTTPBalsaFrameTest, VisitorInvokedProperlyForResponseWithBlankLines) {
2106 std::string blanks =
2107 "\n"
2108 "\r\n"
2109 "\n"
2110 "\n"
2111 "\r\n"
2112 "\r\n";
2113 std::string header_input =
2114 "HTTP/1.0 200 OK\r\n"
2115 "content-length: 0\n"
2116 "\n";
2117 std::string message = blanks + header_input;
2118
2119 FakeHeaders fake_headers;
2120 fake_headers.AddKeyValue("content-length", "0");
2121
2122 balsa_frame_.set_is_request(false);
2123 {
2124 InSequence s;
2125 EXPECT_CALL(visitor_mock_, OnResponseFirstLineInput(
2126 "HTTP/1.0 200 OK", "HTTP/1.0", "200", "OK"));
2127 EXPECT_CALL(visitor_mock_, ProcessHeaders(fake_headers));
2128 EXPECT_CALL(visitor_mock_, HeaderDone());
2129 EXPECT_CALL(visitor_mock_, MessageDone());
2130 }
2131 EXPECT_CALL(visitor_mock_, OnHeaderInput(header_input));
2132
2133 EXPECT_EQ(message.size(),
2134 balsa_frame_.ProcessInput(message.data(), message.size()));
2135 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
2136 EXPECT_FALSE(balsa_frame_.Error());
2137 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame_.ErrorCode());
2138 }
2139
TEST_F(HTTPBalsaFrameTest,VisitorInvokedProperlyForResponseWithContentLength)2140 TEST_F(HTTPBalsaFrameTest, VisitorInvokedProperlyForResponseWithContentLength) {
2141 std::string message_headers =
2142 "HTTP/1.1 \t 200 Ok all is well\r\n"
2143 "content-length: \t\t 20 \t\t \r\n"
2144 "\r\n";
2145 std::string message_body = "12345678901234567890";
2146 std::string message =
2147 std::string(message_headers) + std::string(message_body);
2148
2149 FakeHeaders fake_headers;
2150 fake_headers.AddKeyValue("content-length", "20");
2151
2152 balsa_frame_.set_is_request(false);
2153 {
2154 InSequence s1;
2155 EXPECT_CALL(visitor_mock_,
2156 OnResponseFirstLineInput("HTTP/1.1 \t 200 Ok all is well",
2157 "HTTP/1.1", "200", "Ok all is well"));
2158 EXPECT_CALL(visitor_mock_, ProcessHeaders(fake_headers));
2159 EXPECT_CALL(visitor_mock_, HeaderDone());
2160 EXPECT_CALL(visitor_mock_, OnRawBodyInput(message_body));
2161 EXPECT_CALL(visitor_mock_, OnBodyChunkInput(message_body));
2162 EXPECT_CALL(visitor_mock_, MessageDone());
2163 }
2164 EXPECT_CALL(visitor_mock_, OnHeaderInput(message_headers));
2165
2166 ASSERT_EQ(message_headers.size(),
2167 balsa_frame_.ProcessInput(message.data(), message.size()));
2168 EXPECT_EQ(message_body.size(),
2169 balsa_frame_.ProcessInput(message.data() + message_headers.size(),
2170 message.size()));
2171 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
2172 EXPECT_FALSE(balsa_frame_.Error());
2173 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame_.ErrorCode());
2174 }
2175
TEST_F(HTTPBalsaFrameTest,VisitorInvokedProperlyForResponseWithTransferEncoding)2176 TEST_F(HTTPBalsaFrameTest,
2177 VisitorInvokedProperlyForResponseWithTransferEncoding) {
2178 std::string message_headers =
2179 "HTTP/1.1 \t 200 Ok all is well\r\n"
2180 "trAnsfer-eNcoding: chunked\r\n"
2181 "\r\n";
2182 std::string message_body =
2183 "A chunkjed extension \r\n"
2184 "01234567890 more crud including numbers 123123\r\n"
2185 "3f\n"
2186 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n"
2187 "0 last one\r\n"
2188 "\r\n";
2189 std::string message_body_data =
2190 "0123456789"
2191 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
2192
2193 std::string message =
2194 std::string(message_headers) + std::string(message_body);
2195
2196 FakeHeaders fake_headers;
2197 fake_headers.AddKeyValue("trAnsfer-eNcoding", "chunked");
2198
2199 balsa_frame_.set_is_request(false);
2200 {
2201 InSequence s1;
2202 EXPECT_CALL(visitor_mock_,
2203 OnResponseFirstLineInput("HTTP/1.1 \t 200 Ok all is well",
2204 "HTTP/1.1", "200", "Ok all is well"));
2205 EXPECT_CALL(visitor_mock_, ProcessHeaders(fake_headers));
2206 EXPECT_CALL(visitor_mock_, HeaderDone());
2207 EXPECT_CALL(visitor_mock_, OnChunkLength(10));
2208 EXPECT_CALL(visitor_mock_, OnChunkLength(63));
2209 EXPECT_CALL(visitor_mock_, OnChunkLength(0));
2210 EXPECT_CALL(visitor_mock_, MessageDone());
2211 }
2212 EXPECT_CALL(visitor_mock_, OnHeaderInput(message_headers));
2213 std::string body_input;
2214 EXPECT_CALL(visitor_mock_, OnRawBodyInput(_))
2215 .WillRepeatedly([&body_input](absl::string_view input) {
2216 absl::StrAppend(&body_input, input);
2217 });
2218 std::string body_data;
2219 EXPECT_CALL(visitor_mock_, OnBodyChunkInput(_))
2220 .WillRepeatedly([&body_data](absl::string_view input) {
2221 absl::StrAppend(&body_data, input);
2222 });
2223 EXPECT_CALL(visitor_mock_, OnTrailerInput(_)).Times(0);
2224
2225 ASSERT_EQ(message_headers.size(),
2226 balsa_frame_.ProcessInput(message.data(), message.size()));
2227 EXPECT_EQ(message_body.size(),
2228 balsa_frame_.ProcessInput(message.data() + message_headers.size(),
2229 message.size()));
2230 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
2231 EXPECT_FALSE(balsa_frame_.Error());
2232 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame_.ErrorCode());
2233
2234 EXPECT_EQ(message_body, body_input);
2235 EXPECT_EQ(message_body_data, body_data);
2236 }
2237
TEST_F(HTTPBalsaFrameTest,VisitorInvokedProperlyForResponseWithTransferEncodingAndTrailers)2238 TEST_F(HTTPBalsaFrameTest,
2239 VisitorInvokedProperlyForResponseWithTransferEncodingAndTrailers) {
2240 std::string message_headers =
2241 "HTTP/1.1 \t 200 Ok all is well\r\n"
2242 "trAnsfer-eNcoding: chunked\r\n"
2243 "\r\n";
2244 std::string message_body =
2245 "A chunkjed extension \r\n"
2246 "01234567890 more crud including numbers 123123\r\n"
2247 "3f\n"
2248 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n"
2249 "0 last one\r\n";
2250 std::string trailer_data =
2251 "a_trailer_key: and a trailer value\r\n"
2252 "\r\n";
2253 std::string message_body_data =
2254 "0123456789"
2255 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
2256
2257 std::string message = (std::string(message_headers) +
2258 std::string(message_body) + std::string(trailer_data));
2259
2260 FakeHeaders fake_headers;
2261 fake_headers.AddKeyValue("trAnsfer-eNcoding", "chunked");
2262
2263 FakeHeaders fake_headers_in_trailer;
2264 fake_headers_in_trailer.AddKeyValue("a_trailer_key", "and a trailer value");
2265
2266 balsa_frame_.set_is_request(false);
2267
2268 {
2269 InSequence s1;
2270 EXPECT_CALL(visitor_mock_,
2271 OnResponseFirstLineInput("HTTP/1.1 \t 200 Ok all is well",
2272 "HTTP/1.1", "200", "Ok all is well"));
2273 EXPECT_CALL(visitor_mock_, ProcessHeaders(fake_headers));
2274 EXPECT_CALL(visitor_mock_, HeaderDone());
2275 EXPECT_CALL(visitor_mock_, OnChunkLength(10));
2276 EXPECT_CALL(visitor_mock_, OnChunkLength(63));
2277 EXPECT_CALL(visitor_mock_, OnChunkLength(0));
2278 EXPECT_CALL(visitor_mock_, OnTrailers(fake_headers_in_trailer));
2279 EXPECT_CALL(visitor_mock_, MessageDone());
2280 }
2281 EXPECT_CALL(visitor_mock_, OnHeaderInput(message_headers));
2282 std::string body_input;
2283 EXPECT_CALL(visitor_mock_, OnRawBodyInput(_))
2284 .WillRepeatedly([&body_input](absl::string_view input) {
2285 absl::StrAppend(&body_input, input);
2286 });
2287 std::string body_data;
2288 EXPECT_CALL(visitor_mock_, OnBodyChunkInput(_))
2289 .WillRepeatedly([&body_data](absl::string_view input) {
2290 absl::StrAppend(&body_data, input);
2291 });
2292 EXPECT_CALL(visitor_mock_, OnTrailerInput(trailer_data));
2293
2294 ASSERT_EQ(message_headers.size(),
2295 balsa_frame_.ProcessInput(message.data(), message.size()));
2296 EXPECT_EQ(message_body.size() + trailer_data.size(),
2297 balsa_frame_.ProcessInput(message.data() + message_headers.size(),
2298 message.size()));
2299 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
2300 EXPECT_FALSE(balsa_frame_.Error());
2301 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame_.ErrorCode());
2302
2303 EXPECT_EQ(message_body, body_input);
2304 EXPECT_EQ(message_body_data, body_data);
2305 }
2306
TEST_F(HTTPBalsaFrameTest,VisitorInvokedProperlyForResponseWithTransferEncodingAndTrailersBytePer)2307 TEST_F(
2308 HTTPBalsaFrameTest,
2309 VisitorInvokedProperlyForResponseWithTransferEncodingAndTrailersBytePer) {
2310 std::string message_headers =
2311 "HTTP/1.1 \t 200 Ok all is well\r\n"
2312 "trAnsfer-eNcoding: chunked\r\n"
2313 "\r\n";
2314 std::string message_body =
2315 "A chunkjed extension \r\n"
2316 "01234567890 more crud including numbers 123123\r\n"
2317 "3f\n"
2318 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n"
2319 "0 last one\r\n";
2320 std::string trailer_data =
2321 "a_trailer_key: and a trailer value\r\n"
2322 "\r\n";
2323 std::string message_body_data =
2324 "0123456789"
2325 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
2326
2327 std::string message = (std::string(message_headers) +
2328 std::string(message_body) + std::string(trailer_data));
2329
2330 FakeHeaders fake_headers;
2331 fake_headers.AddKeyValue("trAnsfer-eNcoding", "chunked");
2332 FakeHeaders fake_headers_in_trailer;
2333 fake_headers_in_trailer.AddKeyValue("a_trailer_key", "and a trailer value");
2334
2335 balsa_frame_.set_is_request(false);
2336
2337 {
2338 InSequence s1;
2339 EXPECT_CALL(visitor_mock_,
2340 OnResponseFirstLineInput("HTTP/1.1 \t 200 Ok all is well",
2341 "HTTP/1.1", "200", "Ok all is well"));
2342 EXPECT_CALL(visitor_mock_, ProcessHeaders(fake_headers));
2343 EXPECT_CALL(visitor_mock_, HeaderDone());
2344 EXPECT_CALL(visitor_mock_, OnChunkLength(10));
2345 EXPECT_CALL(visitor_mock_, OnChunkLength(63));
2346 EXPECT_CALL(visitor_mock_, OnChunkLength(0));
2347 EXPECT_CALL(visitor_mock_, OnTrailers(fake_headers_in_trailer));
2348 EXPECT_CALL(visitor_mock_, MessageDone());
2349 }
2350 EXPECT_CALL(visitor_mock_, OnHeaderInput(message_headers));
2351 std::string body_input;
2352 EXPECT_CALL(visitor_mock_, OnRawBodyInput(_))
2353 .WillRepeatedly([&body_input](absl::string_view input) {
2354 absl::StrAppend(&body_input, input);
2355 });
2356 std::string body_data;
2357 EXPECT_CALL(visitor_mock_, OnBodyChunkInput(_))
2358 .WillRepeatedly([&body_data](absl::string_view input) {
2359 absl::StrAppend(&body_data, input);
2360 });
2361 std::string trailer_input;
2362 EXPECT_CALL(visitor_mock_, OnTrailerInput(_))
2363 .WillRepeatedly([&trailer_input](absl::string_view input) {
2364 absl::StrAppend(&trailer_input, input);
2365 });
2366
2367 for (size_t i = 0; i < message.size(); ++i) {
2368 ASSERT_EQ(1u, balsa_frame_.ProcessInput(message.data() + i, 1));
2369 }
2370 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
2371 EXPECT_FALSE(balsa_frame_.Error());
2372 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame_.ErrorCode());
2373
2374 EXPECT_EQ(message_body, body_input);
2375 EXPECT_EQ(message_body_data, body_data);
2376 EXPECT_EQ(trailer_data, trailer_input);
2377 }
2378
TEST(HTTPBalsaFrame,VisitorInvokedProperlyForResponseWithTransferEncodingAndTrailersRandom)2379 TEST(HTTPBalsaFrame,
2380 VisitorInvokedProperlyForResponseWithTransferEncodingAndTrailersRandom) {
2381 TestSeed seed;
2382 seed.Initialize(GetQuicheCommandLineFlag(FLAGS_randseed));
2383 RandomEngine rng;
2384 rng.seed(seed.GetSeed());
2385 for (int i = 0; i < 1000; ++i) {
2386 std::string message_headers =
2387 "HTTP/1.1 \t 200 Ok all is well\r\n"
2388 "trAnsfer-eNcoding: chunked\r\n"
2389 "\r\n";
2390 std::string message_body =
2391 "A chunkjed extension \r\n"
2392 "01234567890 more crud including numbers 123123\r\n"
2393 "3f\n"
2394 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n"
2395 "0 last one\r\n";
2396 std::string trailer_data =
2397 "a_trailer_key: and a trailer value\r\n"
2398 "\r\n";
2399 std::string message_body_data =
2400 "0123456789"
2401 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
2402
2403 std::string message =
2404 (std::string(message_headers) + std::string(message_body) +
2405 std::string(trailer_data));
2406
2407 FakeHeaders fake_headers;
2408 fake_headers.AddKeyValue("trAnsfer-eNcoding", "chunked");
2409 FakeHeaders fake_headers_in_trailer;
2410 fake_headers_in_trailer.AddKeyValue("a_trailer_key", "and a trailer value");
2411
2412 StrictMock<BalsaVisitorMock> visitor_mock;
2413
2414 BalsaHeaders headers;
2415 BalsaFrame balsa_frame;
2416 balsa_frame.set_is_request(false);
2417 balsa_frame.set_balsa_headers(&headers);
2418 balsa_frame.EnableTrailers();
2419 balsa_frame.set_balsa_visitor(&visitor_mock);
2420
2421 {
2422 InSequence s1;
2423 EXPECT_CALL(visitor_mock, OnResponseFirstLineInput(
2424 "HTTP/1.1 \t 200 Ok all is well",
2425 "HTTP/1.1", "200", "Ok all is well"));
2426 EXPECT_CALL(visitor_mock, ProcessHeaders(fake_headers));
2427 EXPECT_CALL(visitor_mock, HeaderDone());
2428 EXPECT_CALL(visitor_mock, OnTrailers(fake_headers_in_trailer));
2429 EXPECT_CALL(visitor_mock, MessageDone());
2430 }
2431 EXPECT_CALL(visitor_mock, OnHeaderInput(message_headers));
2432 std::string body_input;
2433 EXPECT_CALL(visitor_mock, OnRawBodyInput(_))
2434 .WillRepeatedly([&body_input](absl::string_view input) {
2435 absl::StrAppend(&body_input, input);
2436 });
2437 std::string body_data;
2438 EXPECT_CALL(visitor_mock, OnBodyChunkInput(_))
2439 .WillRepeatedly([&body_data](absl::string_view input) {
2440 absl::StrAppend(&body_data, input);
2441 });
2442 std::string trailer_input;
2443 EXPECT_CALL(visitor_mock, OnTrailerInput(_))
2444 .WillRepeatedly([&trailer_input](absl::string_view input) {
2445 absl::StrAppend(&trailer_input, input);
2446 });
2447 EXPECT_CALL(visitor_mock, OnChunkLength(_)).Times(AtLeast(1));
2448 EXPECT_CALL(visitor_mock, OnChunkExtensionInput(_)).Times(AtLeast(1));
2449
2450 size_t count = 0;
2451 size_t total_processed = 0;
2452 for (size_t j = 0; j < message.size();) {
2453 auto dist = std::uniform_int_distribution<>(0, message.size() - j + 1);
2454 count = dist(rng);
2455 size_t processed = balsa_frame.ProcessInput(message.data() + j, count);
2456 ASSERT_GE(count, processed);
2457 total_processed += processed;
2458 j += processed;
2459 }
2460 EXPECT_EQ(message.size(), total_processed);
2461 EXPECT_TRUE(balsa_frame.MessageFullyRead());
2462 EXPECT_FALSE(balsa_frame.Error());
2463 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame.ErrorCode());
2464
2465 EXPECT_EQ(message_body, body_input);
2466 EXPECT_EQ(message_body_data, body_data);
2467 EXPECT_EQ(trailer_data, trailer_input);
2468 }
2469 }
2470
TEST_F(HTTPBalsaFrameTest,AppropriateActionTakenWhenHeadersTooLongWithTooMuchInput)2471 TEST_F(HTTPBalsaFrameTest,
2472 AppropriateActionTakenWhenHeadersTooLongWithTooMuchInput) {
2473 const absl::string_view message =
2474 "GET /asflkasfdhjsafdkljhasfdlkjhasdflkjhsafdlkjhh HTTP/1.1";
2475 const size_t kAmountLessThanHeaderLen = 10;
2476 ASSERT_LE(kAmountLessThanHeaderLen, message.size());
2477
2478 auto error_code = BalsaFrameEnums::HEADERS_TOO_LONG;
2479 EXPECT_CALL(visitor_mock_, HandleError(error_code));
2480
2481 balsa_frame_.set_max_header_length(message.size() - kAmountLessThanHeaderLen);
2482
2483 ASSERT_EQ(balsa_frame_.max_header_length(),
2484 balsa_frame_.ProcessInput(message.data(), message.size()));
2485 EXPECT_TRUE(balsa_frame_.Error());
2486 EXPECT_EQ(BalsaFrameEnums::HEADERS_TOO_LONG, balsa_frame_.ErrorCode());
2487 }
2488
TEST_F(HTTPBalsaFrameTest,AppropriateActionTakenWhenHeadersTooLongWithBody)2489 TEST_F(HTTPBalsaFrameTest, AppropriateActionTakenWhenHeadersTooLongWithBody) {
2490 std::string message =
2491 "PUT /foo HTTP/1.1\r\n"
2492 "Content-Length: 4\r\n"
2493 "header: xxxxxxxxx\r\n\r\n"
2494 "B"; // body begin
2495
2496 auto error_code = BalsaFrameEnums::HEADERS_TOO_LONG;
2497 EXPECT_CALL(visitor_mock_, HandleError(error_code));
2498
2499 // -2 because we have 1 byte of body, and we want to refuse
2500 // this.
2501 balsa_frame_.set_max_header_length(message.size() - 2);
2502
2503 ASSERT_EQ(balsa_frame_.max_header_length(),
2504 balsa_frame_.ProcessInput(message.data(), message.size()));
2505 EXPECT_TRUE(balsa_frame_.Error());
2506 EXPECT_EQ(BalsaFrameEnums::HEADERS_TOO_LONG, balsa_frame_.ErrorCode());
2507 }
2508
TEST_F(HTTPBalsaFrameTest,AppropriateActionTakenWhenHeadersTooLongWhenReset)2509 TEST_F(HTTPBalsaFrameTest, AppropriateActionTakenWhenHeadersTooLongWhenReset) {
2510 std::string message =
2511 "GET /asflkasfdhjsafdkljhasfdlkjhasdflkjhsafdlkjhh HTTP/1.1\r\n"
2512 "\r\n";
2513 const size_t kAmountLessThanHeaderLen = 10;
2514 ASSERT_LE(kAmountLessThanHeaderLen, message.size());
2515
2516 auto error_code = BalsaFrameEnums::HEADERS_TOO_LONG;
2517
2518 ASSERT_EQ(message.size() - 2,
2519 balsa_frame_.ProcessInput(message.data(), message.size() - 2));
2520
2521 // Now set max header length to something smaller.
2522 balsa_frame_.set_max_header_length(message.size() - kAmountLessThanHeaderLen);
2523 EXPECT_CALL(visitor_mock_, HandleError(error_code));
2524
2525 ASSERT_EQ(0u,
2526 balsa_frame_.ProcessInput(message.data() + message.size() - 2, 2));
2527 EXPECT_TRUE(balsa_frame_.Error());
2528 EXPECT_EQ(BalsaFrameEnums::HEADERS_TOO_LONG, balsa_frame_.ErrorCode());
2529 }
2530
2531 class BalsaFrameParsingTest : public QuicheTest {
2532 protected:
SetUp()2533 void SetUp() override {
2534 balsa_frame_.set_is_request(true);
2535 balsa_frame_.set_balsa_headers(&headers_);
2536 balsa_frame_.set_balsa_visitor(&visitor_mock_);
2537 }
2538
TestEmptyHeaderKeyHelper(const std::string & message)2539 void TestEmptyHeaderKeyHelper(const std::string& message) {
2540 InSequence s;
2541 EXPECT_CALL(visitor_mock_, OnRequestFirstLineInput("GET / HTTP/1.1", "GET",
2542 "/", "HTTP/1.1"));
2543 EXPECT_CALL(visitor_mock_, OnHeaderInput(_));
2544 EXPECT_CALL(visitor_mock_,
2545 HandleError(BalsaFrameEnums::INVALID_HEADER_FORMAT));
2546
2547 ASSERT_EQ(message.size(),
2548 balsa_frame_.ProcessInput(message.data(), message.size()));
2549 EXPECT_TRUE(balsa_frame_.Error());
2550 Mock::VerifyAndClearExpectations(&visitor_mock_);
2551 }
2552
TestInvalidTrailerFormat(const std::string & trailer,bool invalid_name_char)2553 void TestInvalidTrailerFormat(const std::string& trailer,
2554 bool invalid_name_char) {
2555 balsa_frame_.set_is_request(false);
2556 balsa_frame_.EnableTrailers();
2557
2558 std::string headers =
2559 "HTTP/1.0 200 ok\r\n"
2560 "transfer-encoding: chunked\r\n"
2561 "\r\n";
2562
2563 std::string chunks =
2564 "3\r\n"
2565 "123\r\n"
2566 "0\r\n";
2567
2568 InSequence s;
2569
2570 EXPECT_CALL(visitor_mock_, OnResponseFirstLineInput);
2571 EXPECT_CALL(visitor_mock_, OnHeaderInput);
2572 EXPECT_CALL(visitor_mock_, ProcessHeaders);
2573 EXPECT_CALL(visitor_mock_, HeaderDone);
2574 EXPECT_CALL(visitor_mock_, OnChunkLength(3));
2575 EXPECT_CALL(visitor_mock_, OnChunkExtensionInput);
2576 EXPECT_CALL(visitor_mock_, OnRawBodyInput);
2577 EXPECT_CALL(visitor_mock_, OnBodyChunkInput);
2578 EXPECT_CALL(visitor_mock_, OnChunkLength(0));
2579 EXPECT_CALL(visitor_mock_, OnChunkExtensionInput);
2580 EXPECT_CALL(visitor_mock_, OnRawBodyInput);
2581 EXPECT_CALL(visitor_mock_, OnRawBodyInput);
2582 const auto expected_error =
2583 invalid_name_char ? BalsaFrameEnums::INVALID_TRAILER_NAME_CHARACTER
2584 : BalsaFrameEnums::INVALID_TRAILER_FORMAT;
2585 EXPECT_CALL(visitor_mock_, HandleError(expected_error)).Times(1);
2586
2587 EXPECT_CALL(visitor_mock_, OnTrailers(_)).Times(0);
2588 EXPECT_CALL(visitor_mock_, MessageDone()).Times(0);
2589
2590 ASSERT_EQ(headers.size(),
2591 balsa_frame_.ProcessInput(headers.data(), headers.size()));
2592 ASSERT_EQ(chunks.size(),
2593 balsa_frame_.ProcessInput(chunks.data(), chunks.size()));
2594 EXPECT_EQ(trailer.size(),
2595 balsa_frame_.ProcessInput(trailer.data(), trailer.size()));
2596 EXPECT_FALSE(balsa_frame_.MessageFullyRead());
2597 EXPECT_TRUE(balsa_frame_.Error());
2598 EXPECT_EQ(expected_error, balsa_frame_.ErrorCode());
2599
2600 Mock::VerifyAndClearExpectations(&visitor_mock_);
2601 }
2602
2603 BalsaHeaders headers_;
2604 BalsaFrame balsa_frame_;
2605 StrictMock<BalsaVisitorMock> visitor_mock_;
2606 };
2607
TEST_F(BalsaFrameParsingTest,AppropriateActionTakenWhenHeaderColonsAreFunny)2608 TEST_F(BalsaFrameParsingTest, AppropriateActionTakenWhenHeaderColonsAreFunny) {
2609 std::string message =
2610 "GET / HTTP/1.1\r\n"
2611 "a\r\n"
2612 "b\r\n"
2613 "c\r\n"
2614 "d\r\n"
2615 "e\r\n"
2616 "f\r\n"
2617 "g\r\n"
2618 "h\r\n"
2619 "i:\r\n"
2620 "j\r\n"
2621 "k\r\n"
2622 "l\r\n"
2623 "m\r\n"
2624 "n\r\n"
2625 "o\r\n"
2626 "p\r\n"
2627 "q\r\n"
2628 "r\r\n"
2629 "s\r\n"
2630 "t\r\n"
2631 "u\r\n"
2632 "v\r\n"
2633 "w\r\n"
2634 "x\r\n"
2635 "y\r\n"
2636 "z\r\n"
2637 "A\r\n"
2638 "B\r\n"
2639 ": val\r\n"
2640 "\r\n";
2641
2642 EXPECT_CALL(visitor_mock_, OnRequestFirstLineInput("GET / HTTP/1.1", "GET",
2643 "/", "HTTP/1.1"));
2644 EXPECT_CALL(visitor_mock_, OnHeaderInput(_));
2645 EXPECT_CALL(visitor_mock_,
2646 HandleWarning(BalsaFrameEnums::HEADER_MISSING_COLON))
2647 .Times(27);
2648 EXPECT_CALL(visitor_mock_,
2649 HandleError(BalsaFrameEnums::INVALID_HEADER_FORMAT));
2650
2651 ASSERT_EQ(message.size(),
2652 balsa_frame_.ProcessInput(message.data(), message.size()));
2653
2654 EXPECT_TRUE(balsa_frame_.Error());
2655 }
2656
TEST_F(BalsaFrameParsingTest,ErrorWhenHeaderKeyIsEmpty)2657 TEST_F(BalsaFrameParsingTest, ErrorWhenHeaderKeyIsEmpty) {
2658 std::string firstKeyIsEmpty =
2659 "GET / HTTP/1.1\r\n"
2660 ": \r\n"
2661 "a:b\r\n"
2662 "c:d\r\n"
2663 "\r\n";
2664 TestEmptyHeaderKeyHelper(firstKeyIsEmpty);
2665
2666 balsa_frame_.Reset();
2667
2668 std::string laterKeyIsEmpty =
2669 "GET / HTTP/1.1\r\n"
2670 "a:b\r\n"
2671 ": \r\n"
2672 "c:d\r\n"
2673 "\r\n";
2674 TestEmptyHeaderKeyHelper(laterKeyIsEmpty);
2675 }
2676
TEST_F(BalsaFrameParsingTest,InvalidTrailerFormat)2677 TEST_F(BalsaFrameParsingTest, InvalidTrailerFormat) {
2678 std::string trailer =
2679 ":monkeys\n"
2680 "\r\n";
2681 TestInvalidTrailerFormat(trailer, /*invalid_name_char=*/false);
2682
2683 balsa_frame_.Reset();
2684
2685 std::string trailer2 =
2686 " \r\n"
2687 "test: test\r\n"
2688 "\r\n";
2689 TestInvalidTrailerFormat(trailer2, /*invalid_name_char=*/true);
2690
2691 balsa_frame_.Reset();
2692
2693 std::string trailer3 =
2694 "a: b\r\n"
2695 ": test\r\n"
2696 "\r\n";
2697 TestInvalidTrailerFormat(trailer3, /*invalid_name_char=*/false);
2698 }
2699
TEST_F(HTTPBalsaFrameTest,EnsureHeaderFramingFoundWithVariousCombinationsOfRN_RN)2700 TEST_F(HTTPBalsaFrameTest,
2701 EnsureHeaderFramingFoundWithVariousCombinationsOfRN_RN) {
2702 const std::string message =
2703 "GET / HTTP/1.1\r\n"
2704 "content-length: 0\r\n"
2705 "a\r\n"
2706 "b\r\n"
2707 "c\r\n"
2708 "d\r\n"
2709 "e\r\n"
2710 "f\r\n"
2711 "g\r\n"
2712 "h\r\n"
2713 "i\r\n"
2714 "\r\n";
2715 EXPECT_EQ(message.size(),
2716 balsa_frame_.ProcessInput(message.data(), message.size()));
2717 EXPECT_FALSE(balsa_frame_.Error())
2718 << BalsaFrameEnums::ErrorCodeToString(balsa_frame_.ErrorCode());
2719 }
2720
TEST_F(HTTPBalsaFrameTest,EnsureHeaderFramingFoundWithVariousCombinationsOfRN_N)2721 TEST_F(HTTPBalsaFrameTest,
2722 EnsureHeaderFramingFoundWithVariousCombinationsOfRN_N) {
2723 const std::string message =
2724 "GET / HTTP/1.1\n"
2725 "content-length: 0\n"
2726 "a\n"
2727 "b\n"
2728 "c\n"
2729 "d\n"
2730 "e\n"
2731 "f\n"
2732 "g\n"
2733 "h\n"
2734 "i\n"
2735 "\n";
2736 EXPECT_EQ(message.size(),
2737 balsa_frame_.ProcessInput(message.data(), message.size()));
2738 EXPECT_FALSE(balsa_frame_.Error())
2739 << BalsaFrameEnums::ErrorCodeToString(balsa_frame_.ErrorCode());
2740 }
2741
TEST_F(HTTPBalsaFrameTest,EnsureHeaderFramingFoundWithVariousCombinationsOfRN_RN_N)2742 TEST_F(HTTPBalsaFrameTest,
2743 EnsureHeaderFramingFoundWithVariousCombinationsOfRN_RN_N) {
2744 const std::string message =
2745 "GET / HTTP/1.1\n"
2746 "content-length: 0\r\n"
2747 "a\r\n"
2748 "b\n"
2749 "c\r\n"
2750 "d\n"
2751 "e\r\n"
2752 "f\n"
2753 "g\r\n"
2754 "h\n"
2755 "i\r\n"
2756 "\n";
2757 EXPECT_EQ(message.size(),
2758 balsa_frame_.ProcessInput(message.data(), message.size()));
2759 EXPECT_FALSE(balsa_frame_.Error())
2760 << BalsaFrameEnums::ErrorCodeToString(balsa_frame_.ErrorCode());
2761 }
2762
TEST_F(HTTPBalsaFrameTest,EnsureHeaderFramingFoundWithVariousCombinationsOfRN_N_RN)2763 TEST_F(HTTPBalsaFrameTest,
2764 EnsureHeaderFramingFoundWithVariousCombinationsOfRN_N_RN) {
2765 const std::string message =
2766 "GET / HTTP/1.1\n"
2767 "content-length: 0\r\n"
2768 "a\n"
2769 "b\r\n"
2770 "c\n"
2771 "d\r\n"
2772 "e\n"
2773 "f\r\n"
2774 "g\n"
2775 "h\r\n"
2776 "i\n"
2777 "\r\n";
2778 EXPECT_EQ(message.size(),
2779 balsa_frame_.ProcessInput(message.data(), message.size()));
2780 EXPECT_FALSE(balsa_frame_.Error())
2781 << BalsaFrameEnums::ErrorCodeToString(balsa_frame_.ErrorCode());
2782 }
2783
TEST_F(HTTPBalsaFrameTest,ReadUntilCloseStateEnteredAsExpectedAndNotExited)2784 TEST_F(HTTPBalsaFrameTest, ReadUntilCloseStateEnteredAsExpectedAndNotExited) {
2785 std::string message =
2786 "HTTP/1.1 200 OK\r\n"
2787 "\r\n";
2788 balsa_frame_.set_is_request(false);
2789 EXPECT_EQ(message.size(),
2790 balsa_frame_.ProcessInput(message.data(), message.size()));
2791 EXPECT_FALSE(balsa_frame_.Error())
2792 << BalsaFrameEnums::ErrorCodeToString(balsa_frame_.ErrorCode());
2793 EXPECT_EQ(BalsaFrameEnums::READING_UNTIL_CLOSE, balsa_frame_.ParseState());
2794
2795 std::string gobldygook = "-198324-9182-43981-23498-98342-jasldfn-1294hj";
2796 for (int i = 0; i < 1000; ++i) {
2797 EXPECT_EQ(gobldygook.size(),
2798 balsa_frame_.ProcessInput(gobldygook.data(), gobldygook.size()));
2799 EXPECT_FALSE(balsa_frame_.Error())
2800 << BalsaFrameEnums::ErrorCodeToString(balsa_frame_.ErrorCode());
2801 EXPECT_EQ(BalsaFrameEnums::READING_UNTIL_CLOSE, balsa_frame_.ParseState());
2802 }
2803 }
2804
TEST_F(HTTPBalsaFrameTest,BytesSafeToSpliceAndBytesSplicedWorksWithContentLength)2805 TEST_F(HTTPBalsaFrameTest,
2806 BytesSafeToSpliceAndBytesSplicedWorksWithContentLength) {
2807 std::string header =
2808 "HTTP/1.1 200 OK\r\n"
2809 "content-length: 1000\r\n"
2810 "\r\n";
2811 balsa_frame_.set_is_request(false);
2812 size_t bytes_safe_to_splice = 1000;
2813 EXPECT_EQ(0u, balsa_frame_.BytesSafeToSplice());
2814 EXPECT_EQ(header.size(),
2815 balsa_frame_.ProcessInput(header.data(), header.size()));
2816 EXPECT_EQ(bytes_safe_to_splice, balsa_frame_.BytesSafeToSplice());
2817 while (bytes_safe_to_splice > 0) {
2818 balsa_frame_.BytesSpliced(1);
2819 bytes_safe_to_splice -= 1;
2820 ASSERT_FALSE(balsa_frame_.Error())
2821 << BalsaFrameEnums::ParseStateToString(balsa_frame_.ParseState()) << " "
2822 << BalsaFrameEnums::ErrorCodeToString(balsa_frame_.ErrorCode())
2823 << " with bytes_safe_to_splice: " << bytes_safe_to_splice
2824 << " and BytesSafeToSplice(): " << balsa_frame_.BytesSafeToSplice();
2825 }
2826 EXPECT_EQ(0u, balsa_frame_.BytesSafeToSplice());
2827 EXPECT_FALSE(balsa_frame_.Error());
2828 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
2829 }
2830
TEST_F(HTTPBalsaFrameTest,BytesSplicedFlagsErrorsWhenNotInProperState)2831 TEST_F(HTTPBalsaFrameTest, BytesSplicedFlagsErrorsWhenNotInProperState) {
2832 balsa_frame_.set_is_request(false);
2833 balsa_frame_.BytesSpliced(1);
2834 EXPECT_TRUE(balsa_frame_.Error());
2835 EXPECT_EQ(BalsaFrameEnums::CALLED_BYTES_SPLICED_WHEN_UNSAFE_TO_DO_SO,
2836 balsa_frame_.ErrorCode());
2837 EXPECT_FALSE(balsa_frame_.MessageFullyRead());
2838 }
2839
TEST_F(HTTPBalsaFrameTest,BytesSplicedFlagsErrorsWhenTooMuchSplicedForContentLen)2840 TEST_F(HTTPBalsaFrameTest,
2841 BytesSplicedFlagsErrorsWhenTooMuchSplicedForContentLen) {
2842 std::string header =
2843 "HTTP/1.1 200 OK\r\n"
2844 "content-length: 1000\r\n"
2845 "\r\n";
2846 balsa_frame_.set_is_request(false);
2847 EXPECT_EQ(0u, balsa_frame_.BytesSafeToSplice());
2848 EXPECT_EQ(header.size(),
2849 balsa_frame_.ProcessInput(header.data(), header.size()));
2850 EXPECT_EQ(1000u, balsa_frame_.BytesSafeToSplice());
2851 balsa_frame_.BytesSpliced(1001);
2852 EXPECT_TRUE(balsa_frame_.Error());
2853 EXPECT_EQ(
2854 BalsaFrameEnums::CALLED_BYTES_SPLICED_AND_EXCEEDED_SAFE_SPLICE_AMOUNT,
2855 balsa_frame_.ErrorCode());
2856 EXPECT_FALSE(balsa_frame_.MessageFullyRead());
2857 }
2858
TEST_F(HTTPBalsaFrameTest,BytesSplicedWorksAsExpectedForReadUntilClose)2859 TEST_F(HTTPBalsaFrameTest, BytesSplicedWorksAsExpectedForReadUntilClose) {
2860 std::string header =
2861 "HTTP/1.1 200 OK\r\n"
2862 "\r\n";
2863 balsa_frame_.set_is_request(false);
2864 EXPECT_EQ(0u, balsa_frame_.BytesSafeToSplice());
2865 EXPECT_EQ(header.size(),
2866 balsa_frame_.ProcessInput(header.data(), header.size()));
2867 EXPECT_EQ(BalsaFrameEnums::READING_UNTIL_CLOSE, balsa_frame_.ParseState());
2868 EXPECT_EQ(std::numeric_limits<size_t>::max(),
2869 balsa_frame_.BytesSafeToSplice());
2870 for (int i = 0; i < 1000; ++i) {
2871 EXPECT_EQ(std::numeric_limits<size_t>::max(),
2872 balsa_frame_.BytesSafeToSplice());
2873 balsa_frame_.BytesSpliced(12312312);
2874 EXPECT_FALSE(balsa_frame_.Error());
2875 EXPECT_FALSE(balsa_frame_.MessageFullyRead());
2876 }
2877 EXPECT_EQ(std::numeric_limits<size_t>::max(),
2878 balsa_frame_.BytesSafeToSplice());
2879 }
2880
TEST_F(HTTPBalsaFrameTest,BytesSplicedFlagsErrorsWhenTooMuchSplicedForChunked)2881 TEST_F(HTTPBalsaFrameTest,
2882 BytesSplicedFlagsErrorsWhenTooMuchSplicedForChunked) {
2883 std::string header =
2884 "HTTP/1.1 200 OK\r\n"
2885 "transfer-encoding: chunked\r\n"
2886 "\r\n";
2887 std::string body_fragment = "a\r\n";
2888 balsa_frame_.set_is_request(false);
2889 EXPECT_EQ(0u, balsa_frame_.BytesSafeToSplice());
2890 EXPECT_EQ(header.size(),
2891 balsa_frame_.ProcessInput(header.data(), header.size()));
2892 EXPECT_EQ(0u, balsa_frame_.BytesSafeToSplice());
2893 EXPECT_EQ(
2894 body_fragment.size(),
2895 balsa_frame_.ProcessInput(body_fragment.data(), body_fragment.size()));
2896 EXPECT_EQ(10u, balsa_frame_.BytesSafeToSplice());
2897 balsa_frame_.BytesSpliced(11);
2898 EXPECT_TRUE(balsa_frame_.Error());
2899 EXPECT_EQ(
2900 BalsaFrameEnums::CALLED_BYTES_SPLICED_AND_EXCEEDED_SAFE_SPLICE_AMOUNT,
2901 balsa_frame_.ErrorCode());
2902 EXPECT_FALSE(balsa_frame_.MessageFullyRead());
2903 }
2904
TEST_F(HTTPBalsaFrameTest,BytesSafeToSpliceAndBytesSplicedWorksWithChunks)2905 TEST_F(HTTPBalsaFrameTest, BytesSafeToSpliceAndBytesSplicedWorksWithChunks) {
2906 std::string header =
2907 "HTTP/1.1 200 OK\r\n"
2908 "transfer-encoding: chunked\r\n"
2909 "\r\n";
2910 balsa_frame_.set_is_request(false);
2911 EXPECT_EQ(0u, balsa_frame_.BytesSafeToSplice());
2912 EXPECT_EQ(header.size(),
2913 balsa_frame_.ProcessInput(header.data(), header.size()));
2914
2915 {
2916 std::string body_fragment = "3e8\r\n";
2917 EXPECT_FALSE(balsa_frame_.MessageFullyRead());
2918 size_t bytes_safe_to_splice = 1000;
2919 EXPECT_EQ(0u, balsa_frame_.BytesSafeToSplice());
2920 EXPECT_EQ(
2921 body_fragment.size(),
2922 balsa_frame_.ProcessInput(body_fragment.data(), body_fragment.size()));
2923 EXPECT_EQ(bytes_safe_to_splice, balsa_frame_.BytesSafeToSplice());
2924 while (bytes_safe_to_splice > 0) {
2925 balsa_frame_.BytesSpliced(1);
2926 bytes_safe_to_splice -= 1;
2927 ASSERT_FALSE(balsa_frame_.Error());
2928 }
2929 EXPECT_EQ(0u, balsa_frame_.BytesSafeToSplice());
2930 EXPECT_FALSE(balsa_frame_.Error());
2931 }
2932 {
2933 std::string body_fragment = "\r\n7d0\r\n";
2934 EXPECT_FALSE(balsa_frame_.MessageFullyRead());
2935 size_t bytes_safe_to_splice = 2000;
2936 EXPECT_EQ(0u, balsa_frame_.BytesSafeToSplice());
2937 EXPECT_EQ(
2938 body_fragment.size(),
2939 balsa_frame_.ProcessInput(body_fragment.data(), body_fragment.size()));
2940 EXPECT_EQ(bytes_safe_to_splice, balsa_frame_.BytesSafeToSplice());
2941 while (bytes_safe_to_splice > 0) {
2942 balsa_frame_.BytesSpliced(1);
2943 bytes_safe_to_splice -= 1;
2944 ASSERT_FALSE(balsa_frame_.Error());
2945 }
2946 EXPECT_EQ(0u, balsa_frame_.BytesSafeToSplice());
2947 EXPECT_FALSE(balsa_frame_.Error());
2948 }
2949 {
2950 std::string body_fragment = "\r\n1\r\n";
2951 EXPECT_FALSE(balsa_frame_.MessageFullyRead());
2952 size_t bytes_safe_to_splice = 1;
2953 EXPECT_EQ(0u, balsa_frame_.BytesSafeToSplice());
2954 EXPECT_EQ(
2955 body_fragment.size(),
2956 balsa_frame_.ProcessInput(body_fragment.data(), body_fragment.size()));
2957 EXPECT_EQ(bytes_safe_to_splice, balsa_frame_.BytesSafeToSplice());
2958 while (bytes_safe_to_splice > 0) {
2959 balsa_frame_.BytesSpliced(1);
2960 bytes_safe_to_splice -= 1;
2961 ASSERT_FALSE(balsa_frame_.Error());
2962 }
2963 EXPECT_EQ(0u, balsa_frame_.BytesSafeToSplice());
2964 EXPECT_FALSE(balsa_frame_.Error());
2965 }
2966 {
2967 std::string body_fragment = "\r\n0\r\n\r\n";
2968 EXPECT_FALSE(balsa_frame_.MessageFullyRead());
2969 EXPECT_EQ(0u, balsa_frame_.BytesSafeToSplice());
2970 EXPECT_EQ(
2971 body_fragment.size(),
2972 balsa_frame_.ProcessInput(body_fragment.data(), body_fragment.size()));
2973 EXPECT_EQ(0u, balsa_frame_.BytesSafeToSplice());
2974 EXPECT_FALSE(balsa_frame_.Error());
2975 }
2976 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
2977 }
2978
TEST_F(HTTPBalsaFrameTest,TwoDifferentContentLengthHeadersIsAnError)2979 TEST_F(HTTPBalsaFrameTest, TwoDifferentContentLengthHeadersIsAnError) {
2980 std::string header =
2981 "HTTP/1.1 200 OK\r\n"
2982 "content-length: 12\r\n"
2983 "content-length: 14\r\n"
2984 "\r\n";
2985 balsa_frame_.set_is_request(false);
2986 balsa_frame_.ProcessInput(header.data(), header.size());
2987 EXPECT_TRUE(balsa_frame_.Error());
2988 EXPECT_EQ(BalsaFrameEnums::MULTIPLE_CONTENT_LENGTH_KEYS,
2989 balsa_frame_.ErrorCode());
2990 }
2991
TEST_F(HTTPBalsaFrameTest,TwoSameContentLengthHeadersIsNotAnError)2992 TEST_F(HTTPBalsaFrameTest, TwoSameContentLengthHeadersIsNotAnError) {
2993 std::string header =
2994 "POST / HTTP/1.1\r\n"
2995 "content-length: 1\r\n"
2996 "content-length: 1\r\n"
2997 "\r\n"
2998 "1";
2999 balsa_frame_.ProcessInput(header.data(), header.size());
3000 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame_.ErrorCode());
3001 EXPECT_FALSE(balsa_frame_.Error());
3002 balsa_frame_.ProcessInput(header.data(), header.size());
3003 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame_.ErrorCode());
3004 EXPECT_FALSE(balsa_frame_.Error());
3005 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
3006 }
3007
TEST_F(HTTPBalsaFrameTest,TwoSameContentLengthHeadersIsAnError)3008 TEST_F(HTTPBalsaFrameTest, TwoSameContentLengthHeadersIsAnError) {
3009 HttpValidationPolicy http_validation_policy;
3010 http_validation_policy.disallow_multiple_content_length = true;
3011 balsa_frame_.set_http_validation_policy(http_validation_policy);
3012
3013 std::string header =
3014 "POST / HTTP/1.1\r\n"
3015 "content-length: 1\r\n"
3016 "content-length: 1\r\n"
3017 "\r\n"
3018 "1";
3019 balsa_frame_.ProcessInput(header.data(), header.size());
3020 EXPECT_TRUE(balsa_frame_.Error());
3021 EXPECT_EQ(BalsaFrameEnums::MULTIPLE_CONTENT_LENGTH_KEYS,
3022 balsa_frame_.ErrorCode());
3023 }
3024
TEST_F(HTTPBalsaFrameTest,TwoTransferEncodingHeadersIsAnError)3025 TEST_F(HTTPBalsaFrameTest, TwoTransferEncodingHeadersIsAnError) {
3026 std::string header =
3027 "HTTP/1.1 200 OK\r\n"
3028 "transfer-encoding: chunked\r\n"
3029 "transfer-encoding: identity\r\n"
3030 "content-length: 3\r\n"
3031 "\r\n";
3032 balsa_frame_.set_is_request(false);
3033 balsa_frame_.ProcessInput(header.data(), header.size());
3034 EXPECT_TRUE(balsa_frame_.Error());
3035 EXPECT_EQ(BalsaFrameEnums::MULTIPLE_TRANSFER_ENCODING_KEYS,
3036 balsa_frame_.ErrorCode());
3037 }
3038
TEST_F(HTTPBalsaFrameTest,AcceptTwoTransferEncodingHeaders)3039 TEST_F(HTTPBalsaFrameTest, AcceptTwoTransferEncodingHeaders) {
3040 HttpValidationPolicy http_validation_policy;
3041 http_validation_policy.validate_transfer_encoding = false;
3042 balsa_frame_.set_http_validation_policy(http_validation_policy);
3043
3044 std::string header =
3045 "HTTP/1.1 200 OK\r\n"
3046 "transfer-encoding: chunked\r\n"
3047 "transfer-encoding: identity\r\n"
3048 "content-length: 3\r\n"
3049 "\r\n";
3050 balsa_frame_.set_is_request(false);
3051 balsa_frame_.ProcessInput(header.data(), header.size());
3052
3053 EXPECT_FALSE(balsa_frame_.Error());
3054 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame_.ErrorCode());
3055 }
3056
TEST_F(HTTPBalsaFrameTest,TwoTransferEncodingTokensIsAnError)3057 TEST_F(HTTPBalsaFrameTest, TwoTransferEncodingTokensIsAnError) {
3058 std::string header =
3059 "HTTP/1.1 200 OK\r\n"
3060 "transfer-encoding: chunked, identity\r\n"
3061 "content-length: 3\r\n"
3062 "\r\n";
3063 balsa_frame_.set_is_request(false);
3064 balsa_frame_.ProcessInput(header.data(), header.size());
3065 EXPECT_TRUE(balsa_frame_.Error());
3066 EXPECT_EQ(BalsaFrameEnums::UNKNOWN_TRANSFER_ENCODING,
3067 balsa_frame_.ErrorCode());
3068 }
3069
TEST_F(HTTPBalsaFrameTest,AcceptTwoTransferEncodingTokens)3070 TEST_F(HTTPBalsaFrameTest, AcceptTwoTransferEncodingTokens) {
3071 HttpValidationPolicy http_validation_policy;
3072 http_validation_policy.validate_transfer_encoding = false;
3073 balsa_frame_.set_http_validation_policy(http_validation_policy);
3074
3075 std::string header =
3076 "HTTP/1.1 200 OK\r\n"
3077 "transfer-encoding: chunked, identity\r\n"
3078 "content-length: 3\r\n"
3079 "\r\n";
3080 balsa_frame_.set_is_request(false);
3081 balsa_frame_.ProcessInput(header.data(), header.size());
3082
3083 EXPECT_FALSE(balsa_frame_.Error());
3084 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame_.ErrorCode());
3085 }
3086
TEST_F(HTTPBalsaFrameTest,UnknownTransferEncodingTokenIsAnError)3087 TEST_F(HTTPBalsaFrameTest, UnknownTransferEncodingTokenIsAnError) {
3088 std::string header =
3089 "HTTP/1.1 200 OK\r\n"
3090 "transfer-encoding: chunked-identity\r\n"
3091 "content-length: 3\r\n"
3092 "\r\n";
3093 balsa_frame_.set_is_request(false);
3094 balsa_frame_.ProcessInput(header.data(), header.size());
3095 EXPECT_TRUE(balsa_frame_.Error());
3096 EXPECT_EQ(BalsaFrameEnums::UNKNOWN_TRANSFER_ENCODING,
3097 balsa_frame_.ErrorCode());
3098 }
3099
TEST_F(HTTPBalsaFrameTest,AcceptUnknownTransferEncodingToken)3100 TEST_F(HTTPBalsaFrameTest, AcceptUnknownTransferEncodingToken) {
3101 HttpValidationPolicy http_validation_policy;
3102 http_validation_policy.validate_transfer_encoding = false;
3103 balsa_frame_.set_http_validation_policy(http_validation_policy);
3104
3105 std::string header =
3106 "HTTP/1.1 200 OK\r\n"
3107 "transfer-encoding: chunked-identity\r\n"
3108 "content-length: 3\r\n"
3109 "\r\n";
3110 balsa_frame_.set_is_request(false);
3111 balsa_frame_.ProcessInput(header.data(), header.size());
3112
3113 EXPECT_FALSE(balsa_frame_.Error());
3114 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame_.ErrorCode());
3115 }
3116
TEST_F(HTTPBalsaFrameTest,MissingContentLength)3117 TEST_F(HTTPBalsaFrameTest, MissingContentLength) {
3118 std::string header = "HTTP/1.1 200 OK\r\n\r\n";
3119 balsa_frame_.set_is_request(false);
3120 balsa_frame_.ProcessInput(header.data(), header.size());
3121
3122 EXPECT_FALSE(balsa_frame_.Error());
3123 EXPECT_EQ(BalsaFrameEnums::MAYBE_BODY_BUT_NO_CONTENT_LENGTH,
3124 balsa_frame_.ErrorCode());
3125 }
3126
TEST_F(HTTPBalsaFrameTest,MultipleTransferEncodingsWithMissingContentLength)3127 TEST_F(HTTPBalsaFrameTest, MultipleTransferEncodingsWithMissingContentLength) {
3128 HttpValidationPolicy http_validation_policy;
3129 http_validation_policy.validate_transfer_encoding = false;
3130 balsa_frame_.set_http_validation_policy(http_validation_policy);
3131
3132 std::string header =
3133 "HTTP/1.1 200 OK\r\n"
3134 "transfer-encoding: chunked\r\n"
3135 "transfer-encoding: identity\r\n"
3136 "\r\n";
3137 balsa_frame_.set_is_request(false);
3138 balsa_frame_.ProcessInput(header.data(), header.size());
3139
3140 EXPECT_FALSE(balsa_frame_.Error());
3141 EXPECT_EQ(BalsaFrameEnums::MAYBE_BODY_BUT_NO_CONTENT_LENGTH,
3142 balsa_frame_.ErrorCode());
3143 }
3144
3145 class DetachOnDoneFramer : public NoOpBalsaVisitor {
3146 public:
DetachOnDoneFramer()3147 DetachOnDoneFramer() {
3148 framer_.set_balsa_headers(&headers_);
3149 framer_.set_balsa_visitor(this);
3150 }
3151
MessageDone()3152 void MessageDone() override { framer_.set_balsa_headers(nullptr); }
3153
framer()3154 BalsaFrame* framer() { return &framer_; }
3155
3156 protected:
3157 BalsaFrame framer_;
3158 BalsaHeaders headers_;
3159 };
3160
TEST(HTTPBalsaFrame,TestDetachOnDone)3161 TEST(HTTPBalsaFrame, TestDetachOnDone) {
3162 DetachOnDoneFramer framer;
3163 const char* message = "GET HTTP/1.1\r\n\r\n";
3164 // Frame the whole message. The framer will call MessageDone which will set
3165 // the headers to nullptr.
3166 framer.framer()->ProcessInput(message, strlen(message));
3167 EXPECT_TRUE(framer.framer()->MessageFullyRead());
3168 EXPECT_FALSE(framer.framer()->Error());
3169 }
3170
3171 // We simply extend DetachOnDoneFramer so that we do not have
3172 // to provide trivial implementation for various functions.
3173 class ModifyMaxHeaderLengthFramerInFirstLine : public DetachOnDoneFramer {
3174 public:
MessageDone()3175 void MessageDone() override {}
3176 // This sets to max_header_length to a low number and
3177 // this would cause us to reject the query. Even though
3178 // our original headers length was acceptable.
OnRequestFirstLineInput(absl::string_view,absl::string_view,absl::string_view,absl::string_view)3179 void OnRequestFirstLineInput(absl::string_view /*line_input*/,
3180 absl::string_view /*method_input*/,
3181 absl::string_view /*request_uri*/,
3182 absl::string_view /*version_input*/
3183 ) override {
3184 framer_.set_max_header_length(1);
3185 }
3186 };
3187
3188 // In this case we have already processed the headers and called on
3189 // the visitor HeadersDone and hence its too late to reduce the
3190 // max_header_length here.
3191 class ModifyMaxHeaderLengthFramerInHeaderDone : public DetachOnDoneFramer {
3192 public:
MessageDone()3193 void MessageDone() override {}
HeaderDone()3194 void HeaderDone() override { framer_.set_max_header_length(1); }
3195 };
3196
TEST(HTTPBalsaFrame,ChangeMaxHeadersLengthOnFirstLine)3197 TEST(HTTPBalsaFrame, ChangeMaxHeadersLengthOnFirstLine) {
3198 std::string message =
3199 "PUT /foo HTTP/1.1\r\n"
3200 "Content-Length: 2\r\n"
3201 "header: xxxxxxxxx\r\n\r\n"
3202 "B"; // body begin
3203
3204 ModifyMaxHeaderLengthFramerInFirstLine balsa_frame;
3205 balsa_frame.framer()->set_is_request(true);
3206 balsa_frame.framer()->set_max_header_length(message.size() - 1);
3207
3208 balsa_frame.framer()->ProcessInput(message.data(), message.size());
3209 EXPECT_EQ(BalsaFrameEnums::HEADERS_TOO_LONG,
3210 balsa_frame.framer()->ErrorCode());
3211 }
3212
TEST(HTTPBalsaFrame,ChangeMaxHeadersLengthOnHeaderDone)3213 TEST(HTTPBalsaFrame, ChangeMaxHeadersLengthOnHeaderDone) {
3214 std::string message =
3215 "PUT /foo HTTP/1.1\r\n"
3216 "Content-Length: 2\r\n"
3217 "header: xxxxxxxxx\r\n\r\n"
3218 "B"; // body begin
3219
3220 ModifyMaxHeaderLengthFramerInHeaderDone balsa_frame;
3221 balsa_frame.framer()->set_is_request(true);
3222 balsa_frame.framer()->set_max_header_length(message.size() - 1);
3223
3224 balsa_frame.framer()->ProcessInput(message.data(), message.size());
3225 EXPECT_EQ(0, balsa_frame.framer()->ErrorCode());
3226 }
3227
3228 // This is a simple test to ensure the simple case that we accept
3229 // a query which has headers size same as the max_header_length.
3230 // (i.e., there is no off by one error).
TEST(HTTPBalsaFrame,HeadersSizeSameAsMaxLengthIsAccepted)3231 TEST(HTTPBalsaFrame, HeadersSizeSameAsMaxLengthIsAccepted) {
3232 std::string message =
3233 "GET /foo HTTP/1.1\r\n"
3234 "header: xxxxxxxxx\r\n\r\n";
3235
3236 ModifyMaxHeaderLengthFramerInHeaderDone balsa_frame;
3237 balsa_frame.framer()->set_is_request(true);
3238 balsa_frame.framer()->set_max_header_length(message.size());
3239 balsa_frame.framer()->ProcessInput(message.data(), message.size());
3240 EXPECT_EQ(0, balsa_frame.framer()->ErrorCode());
3241 }
3242
TEST_F(HTTPBalsaFrameTest,KeyHasSpaces)3243 TEST_F(HTTPBalsaFrameTest, KeyHasSpaces) {
3244 const std::string message =
3245 "GET / HTTP/1.1\r\n"
3246 "key has spaces: lock\r\n"
3247 "\r\n";
3248 EXPECT_EQ(message.size(),
3249 balsa_frame_.ProcessInput(message.data(), message.size()));
3250 EXPECT_TRUE(balsa_frame_.Error());
3251 EXPECT_EQ(BalsaFrameEnums::INVALID_HEADER_NAME_CHARACTER,
3252 balsa_frame_.ErrorCode());
3253 }
3254
TEST_F(HTTPBalsaFrameTest,SpaceBeforeColon)3255 TEST_F(HTTPBalsaFrameTest, SpaceBeforeColon) {
3256 const std::string message =
3257 "GET / HTTP/1.1\r\n"
3258 "key : lock\r\n"
3259 "\r\n";
3260 EXPECT_EQ(message.size(),
3261 balsa_frame_.ProcessInput(message.data(), message.size()));
3262 EXPECT_TRUE(balsa_frame_.Error());
3263 EXPECT_EQ(BalsaFrameEnums::INVALID_HEADER_NAME_CHARACTER,
3264 balsa_frame_.ErrorCode());
3265 }
3266
TEST_F(HTTPBalsaFrameTest,SpaceBeforeColonNotAfter)3267 TEST_F(HTTPBalsaFrameTest, SpaceBeforeColonNotAfter) {
3268 const std::string message =
3269 "GET / HTTP/1.1\r\n"
3270 "key :lock\r\n"
3271 "\r\n";
3272 EXPECT_EQ(message.size(),
3273 balsa_frame_.ProcessInput(message.data(), message.size()));
3274 EXPECT_TRUE(balsa_frame_.Error());
3275 EXPECT_EQ(BalsaFrameEnums::INVALID_HEADER_NAME_CHARACTER,
3276 balsa_frame_.ErrorCode());
3277 }
3278
TEST_F(HTTPBalsaFrameTest,KeyHasTabs)3279 TEST_F(HTTPBalsaFrameTest, KeyHasTabs) {
3280 const std::string message =
3281 "GET / HTTP/1.1\r\n"
3282 "key\thas\ttabs: lock\r\n"
3283 "\r\n";
3284 EXPECT_EQ(message.size(),
3285 balsa_frame_.ProcessInput(message.data(), message.size()));
3286 EXPECT_TRUE(balsa_frame_.Error());
3287 EXPECT_EQ(BalsaFrameEnums::INVALID_HEADER_NAME_CHARACTER,
3288 balsa_frame_.ErrorCode());
3289 }
3290
TEST_F(HTTPBalsaFrameTest,TabBeforeColon)3291 TEST_F(HTTPBalsaFrameTest, TabBeforeColon) {
3292 const std::string message =
3293 "GET / HTTP/1.1\r\n"
3294 "key\t: lock\r\n"
3295 "\r\n";
3296 EXPECT_EQ(message.size(),
3297 balsa_frame_.ProcessInput(message.data(), message.size()));
3298 EXPECT_TRUE(balsa_frame_.Error());
3299 EXPECT_EQ(BalsaFrameEnums::INVALID_HEADER_NAME_CHARACTER,
3300 balsa_frame_.ErrorCode());
3301 }
3302
TEST_F(HTTPBalsaFrameTest,KeyHasContinuation)3303 TEST_F(HTTPBalsaFrameTest, KeyHasContinuation) {
3304 const std::string message =
3305 "GET / HTTP/1.1\r\n"
3306 "key\n includes continuation: but not value\r\n"
3307 "\r\n";
3308 EXPECT_EQ(message.size(),
3309 balsa_frame_.ProcessInput(message.data(), message.size()));
3310 EXPECT_TRUE(balsa_frame_.Error());
3311 EXPECT_EQ(BalsaFrameEnums::INVALID_HEADER_NAME_CHARACTER,
3312 balsa_frame_.ErrorCode());
3313 }
3314
TEST_F(HTTPBalsaFrameTest,KeyHasMultipleContinuations)3315 TEST_F(HTTPBalsaFrameTest, KeyHasMultipleContinuations) {
3316 const std::string message =
3317 "GET / HTTP/1.1\r\n"
3318 "key\n includes\r\n multiple\n continuations: but not value\r\n"
3319 "\r\n";
3320 EXPECT_EQ(message.size(),
3321 balsa_frame_.ProcessInput(message.data(), message.size()));
3322 EXPECT_TRUE(balsa_frame_.Error());
3323 EXPECT_EQ(BalsaFrameEnums::INVALID_HEADER_NAME_CHARACTER,
3324 balsa_frame_.ErrorCode());
3325 }
3326
TEST_F(HTTPBalsaFrameTest,KeyHasDoubleQuote)3327 TEST_F(HTTPBalsaFrameTest, KeyHasDoubleQuote) {
3328 const std::string message =
3329 "GET / HTTP/1.1\r\n"
3330 "key\"hasquote: lock\r\n"
3331 "\r\n";
3332 EXPECT_EQ(message.size(),
3333 balsa_frame_.ProcessInput(message.data(), message.size()));
3334 EXPECT_FALSE(balsa_frame_.Error());
3335 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame_.ErrorCode());
3336 EXPECT_TRUE(headers_.HasHeader("key\"hasquote"));
3337 }
3338
TEST_F(HTTPBalsaFrameTest,KeyHasDisallowedDoubleQuote)3339 TEST_F(HTTPBalsaFrameTest, KeyHasDisallowedDoubleQuote) {
3340 HttpValidationPolicy http_validation_policy;
3341 http_validation_policy.disallow_double_quote_in_header_name = true;
3342 balsa_frame_.set_http_validation_policy(http_validation_policy);
3343
3344 const std::string message =
3345 "GET / HTTP/1.1\r\n"
3346 "key\"hasquote: lock\r\n"
3347 "\r\n";
3348 EXPECT_EQ(message.size(),
3349 balsa_frame_.ProcessInput(message.data(), message.size()));
3350 EXPECT_TRUE(balsa_frame_.Error());
3351 EXPECT_EQ(BalsaFrameEnums::INVALID_HEADER_NAME_CHARACTER,
3352 balsa_frame_.ErrorCode());
3353 }
3354
3355 // Missing colon is a warning, not an error.
TEST_F(HTTPBalsaFrameTest,TrailerMissingColon)3356 TEST_F(HTTPBalsaFrameTest, TrailerMissingColon) {
3357 std::string headers =
3358 "HTTP/1.0 302 Redirect\r\n"
3359 "transfer-encoding: chunked\r\n"
3360 "\r\n";
3361
3362 std::string chunks =
3363 "3\r\n"
3364 "123\r\n"
3365 "0\r\n";
3366 std::string trailer =
3367 "crass_monkeys\n"
3368 "\r\n";
3369
3370 balsa_frame_.set_is_request(false);
3371 EXPECT_CALL(visitor_mock_,
3372 HandleWarning(BalsaFrameEnums::TRAILER_MISSING_COLON));
3373 ASSERT_EQ(headers.size(),
3374 balsa_frame_.ProcessInput(headers.data(), headers.size()));
3375 ASSERT_EQ(chunks.size(),
3376 balsa_frame_.ProcessInput(chunks.data(), chunks.size()));
3377
3378 FakeHeaders fake_trailers;
3379 fake_trailers.AddKeyValue("crass_monkeys", "");
3380 EXPECT_CALL(visitor_mock_, OnTrailers(fake_trailers));
3381 EXPECT_EQ(trailer.size(),
3382 balsa_frame_.ProcessInput(trailer.data(), trailer.size()));
3383
3384 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
3385 EXPECT_FALSE(balsa_frame_.Error());
3386 EXPECT_EQ(BalsaFrameEnums::TRAILER_MISSING_COLON, balsa_frame_.ErrorCode());
3387 }
3388
3389 // This tests multiple headers in trailer. We currently do not and have no plan
3390 // to support Trailer field in headers to limit valid field-name in trailer.
3391 // Test that we aren't confused by the non-alphanumeric characters in the
3392 // trailer, especially ':'.
TEST_F(HTTPBalsaFrameTest,MultipleHeadersInTrailer)3393 TEST_F(HTTPBalsaFrameTest, MultipleHeadersInTrailer) {
3394 std::string headers =
3395 "HTTP/1.1 200 OK\r\n"
3396 "transfer-encoding: chunked\r\n"
3397 "\r\n";
3398
3399 std::string chunks =
3400 "3\r\n"
3401 "123\n"
3402 "0\n";
3403 std::map<std::string, std::string> trailer;
3404 trailer["X-Trace"] =
3405 "http://trace.example.com/trace?host="
3406 "foobar.example.com&start=2012-06-03_15:59:06&rpc_duration=0.243349";
3407 trailer["Date"] = "Sun, 03 Jun 2012 22:59:06 GMT";
3408 trailer["Content-Type"] = "text/html";
3409 trailer["X-Backends"] = "127.0.0.1_0,foo.example.com:39359";
3410 trailer["X-Request-Trace"] =
3411 "foo.example.com:39359,127.0.0.1_1,"
3412 "foo.example.com:39359,127.0.0.1_0,"
3413 "foo.example.com:39359";
3414 trailer["X-Service-Trace"] = "default";
3415 trailer["X-Service"] = "default";
3416
3417 std::map<std::string, std::string>::const_iterator iter;
3418 std::string trailer_data;
3419 TestSeed seed;
3420 seed.Initialize(GetQuicheCommandLineFlag(FLAGS_randseed));
3421 RandomEngine rng;
3422 rng.seed(seed.GetSeed());
3423 FakeHeaders fake_headers_in_trailer;
3424 for (iter = trailer.begin(); iter != trailer.end(); ++iter) {
3425 trailer_data += iter->first;
3426 trailer_data += ":";
3427 std::stringstream leading_whitespace_for_value;
3428 AppendRandomWhitespace(rng, &leading_whitespace_for_value);
3429 trailer_data += leading_whitespace_for_value.str();
3430 trailer_data += iter->second;
3431 std::stringstream trailing_whitespace_for_value;
3432 AppendRandomWhitespace(rng, &trailing_whitespace_for_value);
3433 trailer_data += trailing_whitespace_for_value.str();
3434 trailer_data += random_line_term(rng);
3435 fake_headers_in_trailer.AddKeyValue(iter->first, iter->second);
3436 }
3437 trailer_data += random_line_term(rng);
3438
3439 FakeHeaders fake_headers;
3440 fake_headers.AddKeyValue("transfer-encoding", "chunked");
3441
3442 {
3443 InSequence s1;
3444 EXPECT_CALL(visitor_mock_, OnResponseFirstLineInput(
3445 "HTTP/1.1 200 OK", "HTTP/1.1", "200", "OK"));
3446 EXPECT_CALL(visitor_mock_, ProcessHeaders(fake_headers));
3447 EXPECT_CALL(visitor_mock_, HeaderDone());
3448 EXPECT_CALL(visitor_mock_, OnChunkLength(3));
3449 EXPECT_CALL(visitor_mock_, OnChunkLength(0));
3450 EXPECT_CALL(visitor_mock_, OnTrailers(fake_headers_in_trailer));
3451 EXPECT_CALL(visitor_mock_, OnTrailerInput(trailer_data));
3452 EXPECT_CALL(visitor_mock_, MessageDone());
3453 }
3454 EXPECT_CALL(visitor_mock_, OnHeaderInput(headers));
3455 std::string body_input;
3456 EXPECT_CALL(visitor_mock_, OnRawBodyInput(_))
3457 .WillRepeatedly([&body_input](absl::string_view input) {
3458 absl::StrAppend(&body_input, input);
3459 });
3460 EXPECT_CALL(visitor_mock_, OnBodyChunkInput("123"));
3461
3462 balsa_frame_.set_is_request(false);
3463
3464 ASSERT_EQ(headers.size(),
3465 balsa_frame_.ProcessInput(headers.data(), headers.size()));
3466 ASSERT_EQ(chunks.size(),
3467 balsa_frame_.ProcessInput(chunks.data(), chunks.size()));
3468 EXPECT_EQ(trailer_data.size(), balsa_frame_.ProcessInput(
3469 trailer_data.data(), trailer_data.size()));
3470 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
3471 EXPECT_FALSE(balsa_frame_.Error());
3472 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame_.ErrorCode());
3473
3474 EXPECT_EQ(chunks, body_input);
3475 }
3476
3477 // Test if trailer is not set (the common case), everything will be fine.
TEST_F(HTTPBalsaFrameTest,NothingBadHappensWithNULLTrailer)3478 TEST_F(HTTPBalsaFrameTest, NothingBadHappensWithNULLTrailer) {
3479 std::string headers =
3480 "HTTP/1.1 200 OK\r\n"
3481 "transfer-encoding: chunked\r\n"
3482 "\r\n";
3483
3484 std::string chunks =
3485 "3\r\n"
3486 "123\r\n"
3487 "0\r\n";
3488 std::string trailer =
3489 "crass: monkeys\r\n"
3490 "funky: monkeys\r\n"
3491 "\n";
3492
3493 // Use another BalsaFrame, which does not have the trailers option set.
3494 BalsaFrame balsa_frame;
3495 balsa_frame.set_balsa_headers(&headers_);
3496 balsa_frame.set_is_request(false);
3497 balsa_frame.set_balsa_visitor(nullptr);
3498
3499 ASSERT_EQ(headers.size(),
3500 balsa_frame.ProcessInput(headers.data(), headers.size()));
3501 ASSERT_EQ(chunks.size(),
3502 balsa_frame.ProcessInput(chunks.data(), chunks.size()));
3503 ASSERT_EQ(trailer.size(),
3504 balsa_frame.ProcessInput(trailer.data(), trailer.size()));
3505 EXPECT_TRUE(balsa_frame.MessageFullyRead());
3506 EXPECT_FALSE(balsa_frame.Error());
3507 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame.ErrorCode());
3508 }
3509
3510 // Test Reset() correctly resets trailer related states.
TEST_F(HTTPBalsaFrameTest,FrameAndResetAndFrameAgain)3511 TEST_F(HTTPBalsaFrameTest, FrameAndResetAndFrameAgain) {
3512 std::string headers =
3513 "HTTP/1.1 200 OK\r\n"
3514 "transfer-encoding: chunked\r\n"
3515 "\r\n";
3516
3517 std::string chunks =
3518 "3\r\n"
3519 "123\r\n"
3520 "0\r\n";
3521 std::string trailer =
3522 "k: v\n"
3523 "\n";
3524
3525 balsa_frame_.set_is_request(false);
3526
3527 ASSERT_EQ(headers.size(),
3528 balsa_frame_.ProcessInput(headers.data(), headers.size()));
3529 ASSERT_EQ(chunks.size(),
3530 balsa_frame_.ProcessInput(chunks.data(), chunks.size()));
3531 {
3532 FakeHeaders fake_trailers;
3533 fake_trailers.AddKeyValue("k", "v");
3534 EXPECT_CALL(visitor_mock_, OnTrailers(fake_trailers));
3535 }
3536 ASSERT_EQ(trailer.size(),
3537 balsa_frame_.ProcessInput(trailer.data(), trailer.size()));
3538 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
3539 EXPECT_FALSE(balsa_frame_.Error());
3540 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame_.ErrorCode());
3541
3542 balsa_frame_.Reset();
3543
3544 headers =
3545 "HTTP/1.1 404 Error\r\n"
3546 "transfer-encoding: chunked\r\n"
3547 "\r\n";
3548
3549 chunks =
3550 "4\r\n"
3551 "1234\r\n"
3552 "0\r\n";
3553 trailer =
3554 "nk: nv\n"
3555 "\n";
3556
3557 ASSERT_EQ(headers.size(),
3558 balsa_frame_.ProcessInput(headers.data(), headers.size()));
3559 ASSERT_EQ(chunks.size(),
3560 balsa_frame_.ProcessInput(chunks.data(), chunks.size()));
3561 {
3562 FakeHeaders fake_trailers;
3563 fake_trailers.AddKeyValue("nk", "nv");
3564 EXPECT_CALL(visitor_mock_, OnTrailers(fake_trailers));
3565 }
3566 ASSERT_EQ(trailer.size(),
3567 balsa_frame_.ProcessInput(trailer.data(), trailer.size()));
3568 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
3569 EXPECT_FALSE(balsa_frame_.Error());
3570 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame_.ErrorCode());
3571 }
3572
TEST_F(HTTPBalsaFrameTest,TrackInvalidChars)3573 TEST_F(HTTPBalsaFrameTest, TrackInvalidChars) {
3574 EXPECT_FALSE(balsa_frame_.track_invalid_chars());
3575 }
3576
3577 // valid chars are 9 (tab), 10 (LF), 13(CR), and 32-255
TEST_F(HTTPBalsaFrameTest,InvalidCharsInHeaderValueWarning)3578 TEST_F(HTTPBalsaFrameTest, InvalidCharsInHeaderValueWarning) {
3579 balsa_frame_.set_invalid_chars_level(BalsaFrame::InvalidCharsLevel::kWarning);
3580 // nulls are double escaped since otherwise this initialized wrong
3581 const std::string kEscapedInvalid1 =
3582 "GET /foo HTTP/1.1\r\n"
3583 "Bogus-Head: val\\x00\r\n"
3584 "More-Invalid: \\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0E\x0F\r\n"
3585 "And-More: \x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D"
3586 "\x1E\x1F\r\n\r\n";
3587 std::string message;
3588 // now we convert to real embedded nulls
3589 absl::CUnescape(kEscapedInvalid1, &message);
3590
3591 EXPECT_CALL(visitor_mock_,
3592 HandleWarning(BalsaFrameEnums::INVALID_HEADER_CHARACTER));
3593
3594 balsa_frame_.ProcessInput(message.data(), message.size());
3595 EXPECT_FALSE(balsa_frame_.Error());
3596 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
3597 }
3598
3599 // Header names reject invalid chars even at the warning level.
TEST_F(HTTPBalsaFrameTest,InvalidCharsInHeaderKeyError)3600 TEST_F(HTTPBalsaFrameTest, InvalidCharsInHeaderKeyError) {
3601 balsa_frame_.set_invalid_chars_level(BalsaFrame::InvalidCharsLevel::kWarning);
3602 // nulls are double escaped since otherwise this initialized wrong
3603 const std::string kEscapedInvalid1 =
3604 "GET /foo HTTP/1.1\r\n"
3605 "Bogus\\x00-Head: val\r\n\r\n";
3606 std::string message;
3607 // now we convert to real embedded nulls
3608 absl::CUnescape(kEscapedInvalid1, &message);
3609
3610 EXPECT_CALL(visitor_mock_,
3611 HandleError(BalsaFrameEnums::INVALID_HEADER_NAME_CHARACTER));
3612
3613 balsa_frame_.ProcessInput(message.data(), message.size());
3614 EXPECT_TRUE(balsa_frame_.Error());
3615 EXPECT_FALSE(balsa_frame_.MessageFullyRead());
3616 }
3617
TEST_F(HTTPBalsaFrameTest,InvalidCharsInRequestHeaderError)3618 TEST_F(HTTPBalsaFrameTest, InvalidCharsInRequestHeaderError) {
3619 balsa_frame_.set_invalid_chars_level(BalsaFrame::InvalidCharsLevel::kError);
3620 const std::string kEscapedInvalid =
3621 "GET /foo HTTP/1.1\r\n"
3622 "Smuggle-Me: \\x00GET /bar HTTP/1.1\r\n"
3623 "Another-Header: value\r\n\r\n";
3624 std::string message;
3625 absl::CUnescape(kEscapedInvalid, &message);
3626
3627 EXPECT_CALL(visitor_mock_,
3628 HandleError(BalsaFrameEnums::INVALID_HEADER_CHARACTER));
3629
3630 balsa_frame_.ProcessInput(message.data(), message.size());
3631 EXPECT_TRUE(balsa_frame_.Error());
3632 EXPECT_FALSE(balsa_frame_.MessageFullyRead());
3633 }
3634
TEST_F(HTTPBalsaFrameTest,InvalidCharsInResponseHeaderAllowed)3635 TEST_F(HTTPBalsaFrameTest, InvalidCharsInResponseHeaderAllowed) {
3636 balsa_frame_.set_is_request(false);
3637 balsa_frame_.set_invalid_chars_level(BalsaFrame::InvalidCharsLevel::kError);
3638
3639 const absl::string_view headers =
3640 "HTTP/1.1 200 OK\r\n"
3641 "Content-Length: 5\r\n"
3642 "foo: a\022b\r\n"
3643 "\r\n";
3644 EXPECT_EQ(headers.size(),
3645 balsa_frame_.ProcessInput(headers.data(), headers.size()));
3646
3647 EXPECT_FALSE(balsa_frame_.Error());
3648 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame_.ErrorCode());
3649 }
3650
TEST_F(HTTPBalsaFrameTest,InvalidCharsInResponseHeaderError)3651 TEST_F(HTTPBalsaFrameTest, InvalidCharsInResponseHeaderError) {
3652 balsa_frame_.set_is_request(false);
3653 balsa_frame_.set_invalid_chars_level(BalsaFrame::InvalidCharsLevel::kError);
3654
3655 HttpValidationPolicy http_validation_policy;
3656 http_validation_policy.disallow_invalid_header_characters_in_response = true;
3657 balsa_frame_.set_http_validation_policy(http_validation_policy);
3658
3659 const absl::string_view headers =
3660 "HTTP/1.1 200 OK\r\n"
3661 "Content-Length: 5\r\n"
3662 "foo: a\022b\r\n"
3663 "\r\n";
3664 EXPECT_EQ(headers.size(),
3665 balsa_frame_.ProcessInput(headers.data(), headers.size()));
3666
3667 EXPECT_TRUE(balsa_frame_.Error());
3668 EXPECT_EQ(BalsaFrameEnums::INVALID_HEADER_CHARACTER,
3669 balsa_frame_.ErrorCode());
3670 }
3671
3672 class HTTPBalsaFrameTestOneChar : public HTTPBalsaFrameTest,
3673 public testing::WithParamInterface<char> {
3674 public:
GetCharUnderTest()3675 char GetCharUnderTest() { return GetParam(); }
3676 };
3677
TEST_P(HTTPBalsaFrameTestOneChar,InvalidCharsWarningSet)3678 TEST_P(HTTPBalsaFrameTestOneChar, InvalidCharsWarningSet) {
3679 balsa_frame_.set_invalid_chars_level(BalsaFrame::InvalidCharsLevel::kWarning);
3680 const std::string kRequest =
3681 "GET /foo HTTP/1.1\r\n"
3682 "Bogus-Char-Goes-Here: ";
3683 const std::string kEnding = "\r\n\r\n";
3684 std::string message = kRequest;
3685 const char c = GetCharUnderTest();
3686 message.append(1, c);
3687 message.append(kEnding);
3688 if (c == 9 || c == 10 || c == 13) {
3689 // valid char
3690 EXPECT_CALL(visitor_mock_,
3691 HandleWarning(BalsaFrameEnums::INVALID_HEADER_CHARACTER))
3692 .Times(0);
3693 balsa_frame_.ProcessInput(message.data(), message.size());
3694 EXPECT_THAT(balsa_frame_.get_invalid_chars(), IsEmpty());
3695 } else {
3696 // invalid char
3697 absl::flat_hash_map<char, int> expected_count = {{c, 1}};
3698 EXPECT_CALL(visitor_mock_,
3699 HandleWarning(BalsaFrameEnums::INVALID_HEADER_CHARACTER));
3700 balsa_frame_.ProcessInput(message.data(), message.size());
3701 EXPECT_EQ(balsa_frame_.get_invalid_chars(), expected_count);
3702 }
3703 EXPECT_FALSE(balsa_frame_.Error());
3704 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
3705 }
3706
3707 INSTANTIATE_TEST_SUITE_P(TestInvalidCharSet, HTTPBalsaFrameTestOneChar,
3708 Range<char>(0, 32));
3709
TEST_F(HTTPBalsaFrameTest,InvalidCharEndOfLine)3710 TEST_F(HTTPBalsaFrameTest, InvalidCharEndOfLine) {
3711 balsa_frame_.set_invalid_chars_level(BalsaFrame::InvalidCharsLevel::kWarning);
3712 const std::string kInvalid1 =
3713 "GET /foo HTTP/1.1\r\n"
3714 "Header-Key: headervalue\\x00\r\n"
3715 "Legit-Header: legitvalue\r\n\r\n";
3716 std::string message;
3717 absl::CUnescape(kInvalid1, &message);
3718
3719 EXPECT_CALL(visitor_mock_,
3720 HandleWarning(BalsaFrameEnums::INVALID_HEADER_CHARACTER));
3721 balsa_frame_.ProcessInput(message.data(), message.size());
3722 EXPECT_FALSE(balsa_frame_.Error());
3723 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
3724 }
3725
TEST_F(HTTPBalsaFrameTest,InvalidCharInFirstLine)3726 TEST_F(HTTPBalsaFrameTest, InvalidCharInFirstLine) {
3727 balsa_frame_.set_invalid_chars_level(BalsaFrame::InvalidCharsLevel::kWarning);
3728 const std::string kInvalid1 =
3729 "GET /foo \\x00HTTP/1.1\r\n"
3730 "Legit-Header: legitvalue\r\n\r\n";
3731 std::string message;
3732 absl::CUnescape(kInvalid1, &message);
3733
3734 EXPECT_CALL(visitor_mock_,
3735 HandleWarning(BalsaFrameEnums::INVALID_HEADER_CHARACTER));
3736 balsa_frame_.ProcessInput(message.data(), message.size());
3737 EXPECT_FALSE(balsa_frame_.Error());
3738 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
3739 }
3740
TEST_F(HTTPBalsaFrameTest,InvalidCharsAreCounted)3741 TEST_F(HTTPBalsaFrameTest, InvalidCharsAreCounted) {
3742 balsa_frame_.set_invalid_chars_level(BalsaFrame::InvalidCharsLevel::kWarning);
3743 const std::string kInvalid1 =
3744 "GET /foo \\x00\\x00\\x00HTTP/1.1\r\n"
3745 "Bogus-Header: \\x00\\x04\\x04value\r\n\r\n";
3746 std::string message;
3747 absl::CUnescape(kInvalid1, &message);
3748
3749 EXPECT_CALL(visitor_mock_,
3750 HandleWarning(BalsaFrameEnums::INVALID_HEADER_CHARACTER));
3751 balsa_frame_.ProcessInput(message.data(), message.size());
3752 absl::flat_hash_map<char, int> expected_count = {{'\0', 4}, {'\4', 2}};
3753 EXPECT_FALSE(balsa_frame_.Error());
3754 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
3755 EXPECT_EQ(balsa_frame_.get_invalid_chars(), expected_count);
3756
3757 absl::flat_hash_map<char, int> empty_count;
3758 balsa_frame_.Reset();
3759 EXPECT_EQ(balsa_frame_.get_invalid_chars(), empty_count);
3760 }
3761
3762 // Test gibberish in headers and trailer. GFE does not crash but garbage in
3763 // garbage out.
TEST_F(HTTPBalsaFrameTest,GibberishInHeadersAndTrailer)3764 TEST_F(HTTPBalsaFrameTest, GibberishInHeadersAndTrailer) {
3765 // Use static_cast<char> for values exceeding SCHAR_MAX to make sure this
3766 // compiles on platforms where char is signed.
3767 const char kGibberish1[] = {static_cast<char>(138), static_cast<char>(175),
3768 static_cast<char>(233), 0};
3769 const char kGibberish2[] = {'?',
3770 '?',
3771 static_cast<char>(128),
3772 static_cast<char>(255),
3773 static_cast<char>(129),
3774 static_cast<char>(254),
3775 0};
3776 const char kGibberish3[] = "foo: bar : eeep : baz";
3777
3778 std::string gibberish_headers =
3779 absl::StrCat(kGibberish1, ":", kGibberish2, "\r\n", kGibberish3, "\r\n");
3780
3781 std::string headers = absl::StrCat(
3782 "HTTP/1.1 200 OK\r\n"
3783 "transfer-encoding: chunked\r\n",
3784 gibberish_headers, "\r\n");
3785
3786 std::string chunks =
3787 "3\r\n"
3788 "123\r\n"
3789 "0\r\n";
3790
3791 std::string trailer = absl::StrCat("k: v\n", gibberish_headers, "\n");
3792
3793 balsa_frame_.set_is_request(false);
3794
3795 ASSERT_EQ(headers.size(),
3796 balsa_frame_.ProcessInput(headers.data(), headers.size()));
3797 ASSERT_EQ(chunks.size(),
3798 balsa_frame_.ProcessInput(chunks.data(), chunks.size()));
3799
3800 FakeHeaders fake_trailers;
3801 fake_trailers.AddKeyValue("k", "v");
3802 fake_trailers.AddKeyValue(kGibberish1, kGibberish2);
3803 fake_trailers.AddKeyValue("foo", "bar : eeep : baz");
3804 EXPECT_CALL(visitor_mock_, OnTrailers(fake_trailers));
3805 ASSERT_EQ(trailer.size(),
3806 balsa_frame_.ProcessInput(trailer.data(), trailer.size()));
3807
3808 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
3809 EXPECT_FALSE(balsa_frame_.Error());
3810 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame_.ErrorCode());
3811
3812 // Transfer-encoding can be multi-valued, so GetHeader does not work.
3813 EXPECT_TRUE(headers_.transfer_encoding_is_chunked());
3814 absl::string_view field_value = headers_.GetHeader(kGibberish1);
3815 EXPECT_EQ(kGibberish2, field_value);
3816 field_value = headers_.GetHeader("foo");
3817 EXPECT_EQ("bar : eeep : baz", field_value);
3818 }
3819
3820 // Note we reuse the header length limit because trailer is just multiple
3821 // headers.
TEST_F(HTTPBalsaFrameTest,TrailerTooLong)3822 TEST_F(HTTPBalsaFrameTest, TrailerTooLong) {
3823 std::string headers =
3824 "HTTP/1.0 200 ok\r\n"
3825 "transfer-encoding: chunked\r\n"
3826 "\r\n";
3827
3828 std::string chunks =
3829 "3\r\n"
3830 "123\r\n"
3831 "0\r\n";
3832 std::string trailer =
3833 "very : long trailer\n"
3834 "should:cause\r\n"
3835 "trailer :too long error\n"
3836 "\r\n";
3837
3838 balsa_frame_.set_is_request(false);
3839 ASSERT_LT(headers.size(), trailer.size());
3840 balsa_frame_.set_max_header_length(headers.size());
3841
3842 EXPECT_CALL(visitor_mock_, HandleError(BalsaFrameEnums::TRAILER_TOO_LONG));
3843 EXPECT_CALL(visitor_mock_, OnTrailers(_)).Times(0);
3844 EXPECT_CALL(visitor_mock_, MessageDone()).Times(0);
3845 ASSERT_EQ(headers.size(),
3846 balsa_frame_.ProcessInput(headers.data(), headers.size()));
3847 ASSERT_EQ(chunks.size(),
3848 balsa_frame_.ProcessInput(chunks.data(), chunks.size()));
3849 EXPECT_EQ(balsa_frame_.max_header_length(),
3850 balsa_frame_.ProcessInput(trailer.data(), trailer.size()));
3851 EXPECT_FALSE(balsa_frame_.MessageFullyRead());
3852 EXPECT_TRUE(balsa_frame_.Error());
3853 EXPECT_EQ(BalsaFrameEnums::TRAILER_TOO_LONG, balsa_frame_.ErrorCode());
3854 }
3855
TEST_F(HTTPBalsaFrameTest,Parse100ContinueNoContinueHeadersNoCallback)3856 TEST_F(HTTPBalsaFrameTest, Parse100ContinueNoContinueHeadersNoCallback) {
3857 std::string continue_headers =
3858 "HTTP/1.1 100 Continue\r\n"
3859 "\r\n";
3860
3861 // Do not set continue headers (or use interim callbacks). Then the parsed
3862 // continue headers are treated as final headers.
3863 balsa_frame_.set_is_request(false);
3864 balsa_frame_.set_use_interim_headers_callback(false);
3865
3866 InSequence s;
3867 EXPECT_CALL(visitor_mock_, HeaderDone());
3868 EXPECT_CALL(visitor_mock_, MessageDone());
3869
3870 ASSERT_EQ(balsa_frame_.ProcessInput(continue_headers.data(),
3871 continue_headers.size()),
3872 continue_headers.size())
3873 << balsa_frame_.ErrorCode();
3874 EXPECT_FALSE(balsa_frame_.Error());
3875 EXPECT_EQ(headers_.parsed_response_code(), 100);
3876 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
3877 }
3878
TEST_F(HTTPBalsaFrameTest,Parse100Continue)3879 TEST_F(HTTPBalsaFrameTest, Parse100Continue) {
3880 std::string continue_headers =
3881 "HTTP/1.1 100 Continue\r\n"
3882 "\r\n";
3883
3884 // The parsed continue headers are delivered as interim headers.
3885 balsa_frame_.set_is_request(false);
3886 balsa_frame_.set_use_interim_headers_callback(true);
3887
3888 InSequence s;
3889 EXPECT_CALL(visitor_mock_, OnInterimHeaders(Pointee(Property(
3890 &BalsaHeaders::parsed_response_code, 100))));
3891 EXPECT_CALL(visitor_mock_, HeaderDone()).Times(0);
3892 EXPECT_CALL(visitor_mock_, MessageDone()).Times(0);
3893
3894 ASSERT_EQ(balsa_frame_.ProcessInput(continue_headers.data(),
3895 continue_headers.size()),
3896 continue_headers.size())
3897 << balsa_frame_.ErrorCode();
3898 EXPECT_FALSE(balsa_frame_.Error());
3899 EXPECT_EQ(headers_.parsed_response_code(), 0u);
3900 EXPECT_FALSE(balsa_frame_.MessageFullyRead());
3901 }
3902
3903 // Handle two sets of headers when set up properly and the first is 100
3904 // Continue.
TEST_F(HTTPBalsaFrameTest,Support100ContinueNoCallback)3905 TEST_F(HTTPBalsaFrameTest, Support100ContinueNoCallback) {
3906 std::string initial_headers =
3907 "HTTP/1.1 100 Continue\r\n"
3908 "\r\n";
3909 std::string real_headers =
3910 "HTTP/1.1 200 OK\r\n"
3911 "content-length: 3\r\n"
3912 "\r\n";
3913 std::string body = "foo";
3914
3915 balsa_frame_.set_is_request(false);
3916 BalsaHeaders continue_headers;
3917 balsa_frame_.set_continue_headers(&continue_headers);
3918 balsa_frame_.set_use_interim_headers_callback(false);
3919
3920 ASSERT_EQ(initial_headers.size(),
3921 balsa_frame_.ProcessInput(initial_headers.data(),
3922 initial_headers.size()));
3923 ASSERT_EQ(real_headers.size(),
3924 balsa_frame_.ProcessInput(real_headers.data(), real_headers.size()))
3925 << balsa_frame_.ErrorCode();
3926 ASSERT_EQ(body.size(), balsa_frame_.ProcessInput(body.data(), body.size()));
3927 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
3928 EXPECT_FALSE(balsa_frame_.Error());
3929 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame_.ErrorCode());
3930 }
3931
3932 // Handle two sets of headers when set up properly and the first is 100
3933 // Continue.
TEST_F(HTTPBalsaFrameTest,Support100Continue)3934 TEST_F(HTTPBalsaFrameTest, Support100Continue) {
3935 std::string initial_headers =
3936 "HTTP/1.1 100 Continue\r\n"
3937 "\r\n";
3938 std::string real_headers =
3939 "HTTP/1.1 200 OK\r\n"
3940 "content-length: 3\r\n"
3941 "\r\n";
3942 std::string body = "foo";
3943
3944 balsa_frame_.set_is_request(false);
3945 balsa_frame_.set_use_interim_headers_callback(true);
3946
3947 InSequence s;
3948 EXPECT_CALL(visitor_mock_, OnInterimHeaders(Pointee(Property(
3949 &BalsaHeaders::parsed_response_code, 100))));
3950 ASSERT_EQ(
3951 balsa_frame_.ProcessInput(initial_headers.data(), initial_headers.size()),
3952 initial_headers.size());
3953 ASSERT_FALSE(balsa_frame_.Error());
3954
3955 EXPECT_CALL(visitor_mock_, HeaderDone());
3956 ASSERT_EQ(balsa_frame_.ProcessInput(real_headers.data(), real_headers.size()),
3957 real_headers.size())
3958 << balsa_frame_.ErrorCode();
3959 EXPECT_EQ(headers_.parsed_response_code(), 200);
3960
3961 EXPECT_CALL(visitor_mock_, MessageDone());
3962 ASSERT_EQ(balsa_frame_.ProcessInput(body.data(), body.size()), body.size());
3963
3964 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
3965 EXPECT_FALSE(balsa_frame_.Error());
3966 EXPECT_EQ(balsa_frame_.ErrorCode(), BalsaFrameEnums::BALSA_NO_ERROR);
3967 }
3968
3969 // If both the interim headers callback and continue headers are set, only the
3970 // former should be used.
TEST_F(HTTPBalsaFrameTest,InterimHeadersCallbackTakesPrecedence)3971 TEST_F(HTTPBalsaFrameTest, InterimHeadersCallbackTakesPrecedence) {
3972 std::string initial_headers =
3973 "HTTP/1.1 100 Continue\r\n"
3974 "\r\n";
3975 std::string real_headers =
3976 "HTTP/1.1 200 OK\r\n"
3977 "content-length: 3\r\n"
3978 "\r\n";
3979 std::string body = "foo";
3980
3981 balsa_frame_.set_is_request(false);
3982 BalsaHeaders continue_headers;
3983 balsa_frame_.set_continue_headers(&continue_headers);
3984 balsa_frame_.set_use_interim_headers_callback(true);
3985
3986 InSequence s;
3987 EXPECT_CALL(visitor_mock_, OnInterimHeaders(Pointee(Property(
3988 &BalsaHeaders::parsed_response_code, 100))));
3989 EXPECT_CALL(visitor_mock_, ContinueHeaderDone).Times(0);
3990 ASSERT_EQ(
3991 balsa_frame_.ProcessInput(initial_headers.data(), initial_headers.size()),
3992 initial_headers.size());
3993 EXPECT_EQ(continue_headers.parsed_response_code(), 0u);
3994 ASSERT_FALSE(balsa_frame_.Error());
3995
3996 EXPECT_CALL(visitor_mock_, HeaderDone());
3997 ASSERT_EQ(balsa_frame_.ProcessInput(real_headers.data(), real_headers.size()),
3998 real_headers.size())
3999 << balsa_frame_.ErrorCode();
4000 EXPECT_EQ(headers_.parsed_response_code(), 200);
4001
4002 EXPECT_CALL(visitor_mock_, MessageDone());
4003 ASSERT_EQ(balsa_frame_.ProcessInput(body.data(), body.size()), body.size());
4004
4005 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
4006 EXPECT_FALSE(balsa_frame_.Error());
4007 EXPECT_EQ(balsa_frame_.ErrorCode(), BalsaFrameEnums::BALSA_NO_ERROR);
4008 }
4009
4010 // Handle two sets of headers when set up properly and the first is 100
4011 // Continue and it meets the conditions for b/62408297.
TEST_F(HTTPBalsaFrameTest,Support100Continue401UnauthorizedNoCallback)4012 TEST_F(HTTPBalsaFrameTest, Support100Continue401UnauthorizedNoCallback) {
4013 std::string initial_headers =
4014 "HTTP/1.1 100 Continue\r\n"
4015 "\r\n";
4016 std::string real_headers =
4017 "HTTP/1.1 401 Unauthorized\r\n"
4018 "content-length: 3\r\n"
4019 "\r\n";
4020 std::string body = "foo";
4021
4022 balsa_frame_.set_is_request(false);
4023 BalsaHeaders continue_headers;
4024 balsa_frame_.set_continue_headers(&continue_headers);
4025 balsa_frame_.set_use_interim_headers_callback(false);
4026
4027 ASSERT_EQ(initial_headers.size(),
4028 balsa_frame_.ProcessInput(initial_headers.data(),
4029 initial_headers.size()));
4030 ASSERT_EQ(real_headers.size(),
4031 balsa_frame_.ProcessInput(real_headers.data(), real_headers.size()))
4032 << balsa_frame_.ErrorCode();
4033 ASSERT_EQ(body.size(), balsa_frame_.ProcessInput(body.data(), body.size()));
4034 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
4035 EXPECT_FALSE(balsa_frame_.Error());
4036 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame_.ErrorCode());
4037 }
4038
4039 // Handle two sets of headers when set up properly and the first is 100
4040 // Continue and it meets the conditions for b/62408297.
TEST_F(HTTPBalsaFrameTest,Support100Continue401Unauthorized)4041 TEST_F(HTTPBalsaFrameTest, Support100Continue401Unauthorized) {
4042 std::string initial_headers =
4043 "HTTP/1.1 100 Continue\r\n"
4044 "\r\n";
4045 std::string real_headers =
4046 "HTTP/1.1 401 Unauthorized\r\n"
4047 "content-length: 3\r\n"
4048 "\r\n";
4049 std::string body = "foo";
4050
4051 balsa_frame_.set_is_request(false);
4052 balsa_frame_.set_use_interim_headers_callback(true);
4053
4054 InSequence s;
4055 EXPECT_CALL(visitor_mock_, OnInterimHeaders(Pointee(Property(
4056 &BalsaHeaders::parsed_response_code, 100))));
4057 ASSERT_EQ(
4058 balsa_frame_.ProcessInput(initial_headers.data(), initial_headers.size()),
4059 initial_headers.size());
4060 ASSERT_FALSE(balsa_frame_.Error());
4061
4062 EXPECT_CALL(visitor_mock_, HeaderDone());
4063 ASSERT_EQ(balsa_frame_.ProcessInput(real_headers.data(), real_headers.size()),
4064 real_headers.size())
4065 << balsa_frame_.ErrorCode();
4066 EXPECT_EQ(headers_.parsed_response_code(), 401);
4067
4068 EXPECT_CALL(visitor_mock_, MessageDone());
4069 ASSERT_EQ(balsa_frame_.ProcessInput(body.data(), body.size()), body.size());
4070
4071 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
4072 EXPECT_FALSE(balsa_frame_.Error());
4073 EXPECT_EQ(balsa_frame_.ErrorCode(), BalsaFrameEnums::BALSA_NO_ERROR);
4074 }
4075
TEST_F(HTTPBalsaFrameTest,Support100ContinueRunTogetherNoCallback)4076 TEST_F(HTTPBalsaFrameTest, Support100ContinueRunTogetherNoCallback) {
4077 std::string both_headers =
4078 "HTTP/1.1 100 Continue\r\n"
4079 "\r\n"
4080 "HTTP/1.1 200 OK\r\n"
4081 "content-length: 3\r\n"
4082 "\r\n";
4083 std::string body = "foo";
4084
4085 {
4086 InSequence s;
4087 EXPECT_CALL(visitor_mock_, ContinueHeaderDone());
4088 EXPECT_CALL(visitor_mock_, HeaderDone());
4089 EXPECT_CALL(visitor_mock_, MessageDone());
4090 }
4091
4092 balsa_frame_.set_is_request(false);
4093 BalsaHeaders continue_headers;
4094 balsa_frame_.set_continue_headers(&continue_headers);
4095 balsa_frame_.set_use_interim_headers_callback(false);
4096
4097 ASSERT_EQ(both_headers.size(),
4098 balsa_frame_.ProcessInput(both_headers.data(), both_headers.size()))
4099 << balsa_frame_.ErrorCode();
4100 ASSERT_EQ(body.size(), balsa_frame_.ProcessInput(body.data(), body.size()));
4101 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
4102 EXPECT_FALSE(balsa_frame_.Error());
4103 EXPECT_EQ(BalsaFrameEnums::BALSA_NO_ERROR, balsa_frame_.ErrorCode());
4104 }
4105
TEST_F(HTTPBalsaFrameTest,Support100ContinueRunTogether)4106 TEST_F(HTTPBalsaFrameTest, Support100ContinueRunTogether) {
4107 std::string both_headers =
4108 "HTTP/1.1 100 Continue\r\n"
4109 "\r\n"
4110 "HTTP/1.1 200 OK\r\n"
4111 "content-length: 3\r\n"
4112 "\r\n";
4113 std::string body = "foo";
4114
4115 balsa_frame_.set_is_request(false);
4116 balsa_frame_.set_use_interim_headers_callback(true);
4117
4118 InSequence s;
4119 EXPECT_CALL(visitor_mock_, OnInterimHeaders(Pointee(Property(
4120 &BalsaHeaders::parsed_response_code, 100))));
4121 EXPECT_CALL(visitor_mock_, HeaderDone());
4122
4123 ASSERT_EQ(balsa_frame_.ProcessInput(both_headers.data(), both_headers.size()),
4124 both_headers.size())
4125 << balsa_frame_.ErrorCode();
4126 ASSERT_FALSE(balsa_frame_.Error());
4127 EXPECT_EQ(headers_.parsed_response_code(), 200);
4128
4129 EXPECT_CALL(visitor_mock_, MessageDone());
4130 ASSERT_EQ(balsa_frame_.ProcessInput(body.data(), body.size()), body.size());
4131 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
4132 EXPECT_FALSE(balsa_frame_.Error());
4133 EXPECT_EQ(balsa_frame_.ErrorCode(), BalsaFrameEnums::BALSA_NO_ERROR);
4134 }
4135
TEST_F(HTTPBalsaFrameTest,MultipleInterimHeaders)4136 TEST_F(HTTPBalsaFrameTest, MultipleInterimHeaders) {
4137 std::string all_headers =
4138 "HTTP/1.1 100 Continue\r\n"
4139 "\r\n"
4140 "HTTP/1.1 103 Early Hints\r\n"
4141 "\r\n"
4142 "HTTP/1.1 200 OK\r\n"
4143 "content-length: 3\r\n"
4144 "\r\n";
4145 std::string body = "foo";
4146
4147 balsa_frame_.set_is_request(false);
4148 balsa_frame_.set_use_interim_headers_callback(true);
4149
4150 InSequence s;
4151 EXPECT_CALL(visitor_mock_, OnInterimHeaders(Pointee(Property(
4152 &BalsaHeaders::parsed_response_code, 100))));
4153 EXPECT_CALL(visitor_mock_, OnInterimHeaders(Pointee(Property(
4154 &BalsaHeaders::parsed_response_code, 103))));
4155 EXPECT_CALL(visitor_mock_, HeaderDone());
4156
4157 ASSERT_EQ(balsa_frame_.ProcessInput(all_headers.data(), all_headers.size()),
4158 all_headers.size())
4159 << balsa_frame_.ErrorCode();
4160 ASSERT_FALSE(balsa_frame_.Error());
4161 EXPECT_EQ(headers_.parsed_response_code(), 200);
4162
4163 EXPECT_CALL(visitor_mock_, MessageDone());
4164 ASSERT_EQ(balsa_frame_.ProcessInput(body.data(), body.size()), body.size());
4165 EXPECT_TRUE(balsa_frame_.MessageFullyRead());
4166 EXPECT_FALSE(balsa_frame_.Error());
4167 EXPECT_EQ(balsa_frame_.ErrorCode(), BalsaFrameEnums::BALSA_NO_ERROR);
4168 }
4169
TEST_F(HTTPBalsaFrameTest,SwitchingProtocols)4170 TEST_F(HTTPBalsaFrameTest, SwitchingProtocols) {
4171 const std::string headers =
4172 "HTTP/1.1 101 Switching Protocols\r\n"
4173 "\r\n";
4174 const std::string body = "Bytes for the new protocol";
4175 const std::string message = absl::StrCat(headers, body);
4176
4177 // Even with the interim headers callback set, the 101 response is delivered
4178 // as final response headers.
4179 balsa_frame_.set_is_request(false);
4180 balsa_frame_.set_use_interim_headers_callback(true);
4181
4182 InSequence s;
4183 EXPECT_CALL(visitor_mock_, ProcessHeaders);
4184 EXPECT_CALL(visitor_mock_, HeaderDone());
4185
4186 ASSERT_EQ(balsa_frame_.ProcessInput(message.data(), message.size()),
4187 headers.size())
4188 << balsa_frame_.ErrorCode();
4189 ASSERT_FALSE(balsa_frame_.Error());
4190 EXPECT_EQ(headers_.parsed_response_code(), 101);
4191
4192 balsa_frame_.AllowArbitraryBody();
4193
4194 EXPECT_CALL(visitor_mock_, OnRawBodyInput("Bytes for the new protocol"));
4195 EXPECT_CALL(visitor_mock_, OnBodyChunkInput("Bytes for the new protocol"));
4196 EXPECT_CALL(visitor_mock_, MessageDone()).Times(0);
4197
4198 ASSERT_EQ(balsa_frame_.ProcessInput(body.data(), body.size()), body.size());
4199 EXPECT_FALSE(balsa_frame_.MessageFullyRead());
4200 EXPECT_FALSE(balsa_frame_.Error());
4201 EXPECT_EQ(balsa_frame_.ErrorCode(), BalsaFrameEnums::BALSA_NO_ERROR);
4202 }
4203
TEST_F(HTTPBalsaFrameTest,Http09)4204 TEST_F(HTTPBalsaFrameTest, Http09) {
4205 constexpr absl::string_view request = "GET /\r\n";
4206
4207 InSequence s;
4208 StrictMock<BalsaVisitorMock> visitor_mock;
4209 balsa_frame_.set_balsa_visitor(&visitor_mock);
4210
4211 EXPECT_CALL(
4212 visitor_mock,
4213 HandleWarning(
4214 BalsaFrameEnums::FAILED_TO_FIND_WS_AFTER_REQUEST_REQUEST_URI));
4215 EXPECT_CALL(visitor_mock, OnRequestFirstLineInput("GET /", "GET", "/", ""));
4216 EXPECT_CALL(visitor_mock, OnHeaderInput(request));
4217 EXPECT_CALL(visitor_mock, ProcessHeaders(FakeHeaders{}));
4218 EXPECT_CALL(visitor_mock, HeaderDone());
4219 EXPECT_CALL(visitor_mock, MessageDone());
4220
4221 EXPECT_EQ(request.size(),
4222 balsa_frame_.ProcessInput(request.data(), request.size()));
4223
4224 // HTTP/0.9 request is parsed with a warning.
4225 EXPECT_FALSE(balsa_frame_.Error());
4226 EXPECT_EQ(BalsaFrameEnums::FAILED_TO_FIND_WS_AFTER_REQUEST_REQUEST_URI,
4227 balsa_frame_.ErrorCode());
4228 }
4229
TEST_F(HTTPBalsaFrameTest,ContinuationAllowed)4230 TEST_F(HTTPBalsaFrameTest, ContinuationAllowed) {
4231 // See RFC7230 Section 3.2 for the definition of obs-fold:
4232 // https://httpwg.org/specs/rfc7230.html#header.fields.
4233 const std::string message =
4234 "GET / HTTP/1.1\r\n"
4235 "key1: \n value starts with obs-fold\r\n"
4236 "key2: value\n includes obs-fold\r\n"
4237 "key3: value ends in obs-fold \n \r\n"
4238 "\r\n";
4239
4240 // TODO(b/314138604): RFC9110 Section 5.5 requires received CR, LF and NUL
4241 // characters to be replaced with SP, see
4242 // https://www.rfc-editor.org/rfc/rfc9110.html#name-field-values.
4243 // BalsaFrame currently strips (instead of replacing) CR and LF if the value
4244 // starts or ends with obs-fold, and keeps them if they occur in the middle.
4245 FakeHeaders fake_headers;
4246 fake_headers.AddKeyValue("key1", "value starts with obs-fold");
4247 fake_headers.AddKeyValue("key2", "value\n includes obs-fold");
4248 fake_headers.AddKeyValue("key3", "value ends in obs-fold");
4249 EXPECT_CALL(visitor_mock_, ProcessHeaders(fake_headers));
4250
4251 EXPECT_EQ(message.size(),
4252 balsa_frame_.ProcessInput(message.data(), message.size()));
4253 EXPECT_FALSE(balsa_frame_.Error());
4254 }
4255
TEST_F(HTTPBalsaFrameTest,ContinuationDisallowed)4256 TEST_F(HTTPBalsaFrameTest, ContinuationDisallowed) {
4257 HttpValidationPolicy http_validation_policy;
4258 http_validation_policy.disallow_header_continuation_lines = true;
4259 balsa_frame_.set_http_validation_policy(http_validation_policy);
4260
4261 const std::string message =
4262 "GET / HTTP/1.1\r\n"
4263 "key: value\n includes obs-fold\r\n"
4264 "\r\n";
4265 EXPECT_EQ(message.size(),
4266 balsa_frame_.ProcessInput(message.data(), message.size()));
4267 EXPECT_TRUE(balsa_frame_.Error());
4268 EXPECT_EQ(BalsaFrameEnums::INVALID_HEADER_FORMAT, balsa_frame_.ErrorCode());
4269 }
4270
TEST_F(HTTPBalsaFrameTest,NullInValue)4271 TEST_F(HTTPBalsaFrameTest, NullInValue) {
4272 constexpr absl::string_view null_string("\0", 1);
4273 const std::string message =
4274 absl::StrCat("GET / HTTP/1.1\r\n", //
4275 "key1: ", null_string, "value starts with null\r\n", //
4276 "key2: value ", null_string, "includes null\r\n", //
4277 "key3: value ends in null", null_string, "\r\n", //
4278 "\r\n");
4279
4280 // TODO(b/314138604): RFC9110 Section 5.5 requires received CR, LF and NUL
4281 // characters to be replaced with SP, see
4282 // https://www.rfc-editor.org/rfc/rfc9110.html#name-field-values.
4283 // BalsaFrame currently strips (instead of replacing) NUL at the beginning or
4284 // end of the header value, but keeps it if it occurs in the middle.
4285 FakeHeaders fake_headers;
4286 fake_headers.AddKeyValue("key1", "value starts with null");
4287 fake_headers.AddKeyValue(
4288 "key2", absl::StrCat("value ", null_string, "includes null"));
4289 fake_headers.AddKeyValue("key3", "value ends in null");
4290 EXPECT_CALL(visitor_mock_, ProcessHeaders(fake_headers));
4291
4292 EXPECT_EQ(message.size(),
4293 balsa_frame_.ProcessInput(message.data(), message.size()));
4294 EXPECT_FALSE(balsa_frame_.Error());
4295 }
4296
4297 } // namespace
4298
4299 } // namespace test
4300
4301 } // namespace quiche
4302