OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/http/http_chunked_decoder.h" | 5 #include "net/http/http_chunked_decoder.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
| 8 #include <string> |
| 9 #include <vector> |
8 | 10 |
| 11 #include "base/format_macros.h" |
| 12 #include "base/strings/stringprintf.h" |
9 #include "net/base/net_errors.h" | 13 #include "net/base/net_errors.h" |
10 #include "net/test/gtest_util.h" | 14 #include "net/test/gtest_util.h" |
11 #include "testing/gmock/include/gmock/gmock.h" | 15 #include "testing/gmock/include/gmock/gmock.h" |
12 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
13 | 17 |
14 using net::test::IsError; | 18 using net::test::IsError; |
15 using net::test::IsOk; | 19 using net::test::IsOk; |
16 | 20 |
17 namespace net { | 21 namespace net { |
18 | 22 |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
284 | 288 |
285 TEST(HttpChunkedDecoderTest, InvalidConsecutiveCRLFs) { | 289 TEST(HttpChunkedDecoderTest, InvalidConsecutiveCRLFs) { |
286 const char* const inputs[] = { | 290 const char* const inputs[] = { |
287 "5\r\nhello\r\n", | 291 "5\r\nhello\r\n", |
288 "\r\n\r\n\r\n\r\n", | 292 "\r\n\r\n\r\n\r\n", |
289 "0\r\n\r\n" | 293 "0\r\n\r\n" |
290 }; | 294 }; |
291 RunTestUntilFailure(inputs, arraysize(inputs), 1); | 295 RunTestUntilFailure(inputs, arraysize(inputs), 1); |
292 } | 296 } |
293 | 297 |
| 298 TEST(HttpChunkedDecoderTest, ReallyBigChunks) { |
| 299 // Number of bytes sent through the chunked decoder per loop iteration. To |
| 300 // minimize runtime, should be the square root of the chunk lengths, below. |
| 301 const int64_t kWrittenBytesPerIteration = 0x10000; |
| 302 |
| 303 // Length of chunks to test. Must be multiples of kWrittenBytesPerIteration. |
| 304 int64_t kChunkLengths[] = { |
| 305 // Overflows when cast to a signed int32. |
| 306 0x0c0000000, |
| 307 // Overflows when cast to an unsigned int32. |
| 308 0x100000000, |
| 309 }; |
| 310 |
| 311 for (int64_t chunk_length : kChunkLengths) { |
| 312 HttpChunkedDecoder decoder; |
| 313 EXPECT_FALSE(decoder.reached_eof()); |
| 314 |
| 315 // Feed just the header to the decode. |
| 316 std::string chunk_header = |
| 317 base::StringPrintf("%" PRIx64 "\r\n", chunk_length); |
| 318 std::vector<char> data(chunk_header.begin(), chunk_header.end()); |
| 319 EXPECT_EQ(OK, decoder.FilterBuf(data.data(), data.size())); |
| 320 EXPECT_FALSE(decoder.reached_eof()); |
| 321 |
| 322 // Set |data| to be kWrittenBytesPerIteration long, and have a repeating |
| 323 // pattern. |
| 324 data.clear(); |
| 325 data.reserve(kWrittenBytesPerIteration); |
| 326 for (size_t i = 0; i < kWrittenBytesPerIteration; i++) { |
| 327 data.push_back(static_cast<char>(i)); |
| 328 } |
| 329 |
| 330 // Repeatedly feed the data to the chunked decoder. Since the data doesn't |
| 331 // include any chunk lengths, the decode will never have to move the data, |
| 332 // and should run fairly quickly. |
| 333 for (int64_t total_written = 0; total_written < chunk_length; |
| 334 total_written += kWrittenBytesPerIteration) { |
| 335 EXPECT_EQ(kWrittenBytesPerIteration, |
| 336 decoder.FilterBuf(data.data(), kWrittenBytesPerIteration)); |
| 337 EXPECT_FALSE(decoder.reached_eof()); |
| 338 } |
| 339 |
| 340 // Chunk terminator and the final chunk. |
| 341 char final_chunk[] = "\r\n0\r\n\r\n"; |
| 342 EXPECT_EQ(OK, decoder.FilterBuf(final_chunk, arraysize(final_chunk))); |
| 343 EXPECT_TRUE(decoder.reached_eof()); |
| 344 |
| 345 // Since |data| never included any chunk headers, it should not have been |
| 346 // modified. |
| 347 for (size_t i = 0; i < kWrittenBytesPerIteration; i++) { |
| 348 EXPECT_EQ(static_cast<char>(i), data[i]); |
| 349 } |
| 350 } |
| 351 } |
| 352 |
294 TEST(HttpChunkedDecoderTest, ExcessiveChunkLen) { | 353 TEST(HttpChunkedDecoderTest, ExcessiveChunkLen) { |
295 const char* const inputs[] = { | 354 // Smallest number that can't be represented as a signed int64. |
296 "c0000000\r\nhello\r\n" | 355 const char* const inputs[] = {"8000000000000000\r\nhello\r\n"}; |
297 }; | |
298 RunTestUntilFailure(inputs, arraysize(inputs), 0); | 356 RunTestUntilFailure(inputs, arraysize(inputs), 0); |
299 } | 357 } |
300 | 358 |
| 359 TEST(HttpChunkedDecoderTest, ExcessiveChunkLen2) { |
| 360 // Smallest number that can't be represented as an unsigned int64. |
| 361 const char* const inputs[] = {"10000000000000000\r\nhello\r\n"}; |
| 362 RunTestUntilFailure(inputs, arraysize(inputs), 0); |
| 363 } |
| 364 |
301 TEST(HttpChunkedDecoderTest, BasicExtraData) { | 365 TEST(HttpChunkedDecoderTest, BasicExtraData) { |
302 const char* const inputs[] = { | 366 const char* const inputs[] = { |
303 "5\r\nhello\r\n0\r\n\r\nextra bytes" | 367 "5\r\nhello\r\n0\r\n\r\nextra bytes" |
304 }; | 368 }; |
305 RunTest(inputs, arraysize(inputs), "hello", true, 11); | 369 RunTest(inputs, arraysize(inputs), "hello", true, 11); |
306 } | 370 } |
307 | 371 |
308 TEST(HttpChunkedDecoderTest, IncrementalExtraData) { | 372 TEST(HttpChunkedDecoderTest, IncrementalExtraData) { |
309 const char* const inputs[] = { | 373 const char* const inputs[] = { |
310 "5", | 374 "5", |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
353 const char* const inputs[] = { | 417 const char* const inputs[] = { |
354 "5;", | 418 "5;", |
355 big_chunk.get() | 419 big_chunk.get() |
356 }; | 420 }; |
357 RunTestUntilFailure(inputs, arraysize(inputs), 1); | 421 RunTestUntilFailure(inputs, arraysize(inputs), 1); |
358 } | 422 } |
359 | 423 |
360 } // namespace | 424 } // namespace |
361 | 425 |
362 } // namespace net | 426 } // namespace net |
OLD | NEW |