xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/balsa/balsa_frame_test.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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