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> | |
10 | 8 |
11 #include "base/format_macros.h" | |
12 #include "base/strings/stringprintf.h" | |
13 #include "net/base/net_errors.h" | 9 #include "net/base/net_errors.h" |
14 #include "net/test/gtest_util.h" | 10 #include "net/test/gtest_util.h" |
15 #include "testing/gmock/include/gmock/gmock.h" | 11 #include "testing/gmock/include/gmock/gmock.h" |
16 #include "testing/gtest/include/gtest/gtest.h" | 12 #include "testing/gtest/include/gtest/gtest.h" |
17 | 13 |
18 using net::test::IsError; | 14 using net::test::IsError; |
19 using net::test::IsOk; | 15 using net::test::IsOk; |
20 | 16 |
21 namespace net { | 17 namespace net { |
22 | 18 |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
288 | 284 |
289 TEST(HttpChunkedDecoderTest, InvalidConsecutiveCRLFs) { | 285 TEST(HttpChunkedDecoderTest, InvalidConsecutiveCRLFs) { |
290 const char* const inputs[] = { | 286 const char* const inputs[] = { |
291 "5\r\nhello\r\n", | 287 "5\r\nhello\r\n", |
292 "\r\n\r\n\r\n\r\n", | 288 "\r\n\r\n\r\n\r\n", |
293 "0\r\n\r\n" | 289 "0\r\n\r\n" |
294 }; | 290 }; |
295 RunTestUntilFailure(inputs, arraysize(inputs), 1); | 291 RunTestUntilFailure(inputs, arraysize(inputs), 1); |
296 } | 292 } |
297 | 293 |
298 TEST(HttpChunkedDecoderTest, ReallyBigChunks) { | 294 TEST(HttpChunkedDecoderTest, ExcessiveChunkLen) { |
299 // Number of bytes sent through the chunked decoder per loop iteration. To | 295 const char* const inputs[] = { |
300 // minimize runtime, should be the square root of the chunk lengths, below. | 296 "c0000000\r\nhello\r\n" |
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 }; | 297 }; |
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 | |
353 TEST(HttpChunkedDecoderTest, ExcessiveChunkLen) { | |
354 // Smallest number that can't be represented as a signed int64. | |
355 const char* const inputs[] = {"8000000000000000\r\nhello\r\n"}; | |
356 RunTestUntilFailure(inputs, arraysize(inputs), 0); | 298 RunTestUntilFailure(inputs, arraysize(inputs), 0); |
357 } | 299 } |
358 | 300 |
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 | |
365 TEST(HttpChunkedDecoderTest, BasicExtraData) { | 301 TEST(HttpChunkedDecoderTest, BasicExtraData) { |
366 const char* const inputs[] = { | 302 const char* const inputs[] = { |
367 "5\r\nhello\r\n0\r\n\r\nextra bytes" | 303 "5\r\nhello\r\n0\r\n\r\nextra bytes" |
368 }; | 304 }; |
369 RunTest(inputs, arraysize(inputs), "hello", true, 11); | 305 RunTest(inputs, arraysize(inputs), "hello", true, 11); |
370 } | 306 } |
371 | 307 |
372 TEST(HttpChunkedDecoderTest, IncrementalExtraData) { | 308 TEST(HttpChunkedDecoderTest, IncrementalExtraData) { |
373 const char* const inputs[] = { | 309 const char* const inputs[] = { |
374 "5", | 310 "5", |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 const char* const inputs[] = { | 353 const char* const inputs[] = { |
418 "5;", | 354 "5;", |
419 big_chunk.get() | 355 big_chunk.get() |
420 }; | 356 }; |
421 RunTestUntilFailure(inputs, arraysize(inputs), 1); | 357 RunTestUntilFailure(inputs, arraysize(inputs), 1); |
422 } | 358 } |
423 | 359 |
424 } // namespace | 360 } // namespace |
425 | 361 |
426 } // namespace net | 362 } // namespace net |
OLD | NEW |