| // Copyright 2016 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <stddef.h> |
| #include <stdint.h> |
| #include <string> |
| |
| #include <fuzzer/FuzzedDataProvider.h> |
| |
| #include "base/check_op.h" |
| #include "net/cookies/parsed_cookie.h" |
| |
| const std::string GetArbitraryNameValueString( |
| FuzzedDataProvider* data_provider) { |
| // There's no longer an upper bound on the size of a cookie line, but |
| // in practice using double kMaxCookieNamePlusValueSize should allow |
| // the majority of interesting cases to be covered. |
| return data_provider->ConsumeRandomLengthString( |
| net::ParsedCookie::kMaxCookieNamePlusValueSize * 2); |
| } |
| |
| const std::string GetArbitraryAttributeValueString( |
| FuzzedDataProvider* data_provider) { |
| // Adding a fudge factor to kMaxCookieAttributeValueSize so that both branches |
| // of the bounds detection code will be tested. |
| return data_provider->ConsumeRandomLengthString( |
| net::ParsedCookie::kMaxCookieAttributeValueSize + 10); |
| } |
| |
| // Entry point for LibFuzzer. |
| extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { |
| FuzzedDataProvider data_provider(data, size); |
| const std::string cookie_line = GetArbitraryNameValueString(&data_provider); |
| net::ParsedCookie parsed_cookie(cookie_line); |
| |
| // Call zero or one of ParsedCookie's mutator methods. Should not call |
| // anything other than SetName/SetValue when !IsValid(). |
| const uint8_t action = data_provider.ConsumeIntegralInRange(0, 12); |
| switch (action) { |
| case 1: |
| parsed_cookie.SetName(GetArbitraryNameValueString(&data_provider)); |
| break; |
| case 2: |
| parsed_cookie.SetValue(GetArbitraryNameValueString(&data_provider)); |
| break; |
| } |
| |
| if (parsed_cookie.IsValid()) { |
| switch (action) { |
| case 3: |
| if (parsed_cookie.IsValid()) |
| parsed_cookie.SetPath( |
| GetArbitraryAttributeValueString(&data_provider)); |
| break; |
| case 4: |
| parsed_cookie.SetDomain( |
| GetArbitraryAttributeValueString(&data_provider)); |
| break; |
| case 5: |
| parsed_cookie.SetExpires( |
| GetArbitraryAttributeValueString(&data_provider)); |
| break; |
| case 6: |
| parsed_cookie.SetMaxAge( |
| GetArbitraryAttributeValueString(&data_provider)); |
| break; |
| case 7: |
| parsed_cookie.SetIsSecure(data_provider.ConsumeBool()); |
| break; |
| case 8: |
| parsed_cookie.SetIsHttpOnly(data_provider.ConsumeBool()); |
| break; |
| case 9: |
| parsed_cookie.SetSameSite( |
| GetArbitraryAttributeValueString(&data_provider)); |
| break; |
| case 10: |
| parsed_cookie.SetPriority( |
| GetArbitraryAttributeValueString(&data_provider)); |
| break; |
| case 11: |
| parsed_cookie.SetIsSameParty(data_provider.ConsumeBool()); |
| break; |
| case 12: |
| parsed_cookie.SetIsPartitioned(data_provider.ConsumeBool()); |
| break; |
| } |
| } |
| |
| // Check that serialize/deserialize inverse property holds for valid cookies. |
| if (parsed_cookie.IsValid()) { |
| const std::string serialized = parsed_cookie.ToCookieLine(); |
| net::ParsedCookie reparsed_cookie(serialized); |
| const std::string reserialized = reparsed_cookie.ToCookieLine(); |
| CHECK(reparsed_cookie.IsValid()); |
| CHECK_EQ(serialized, reserialized); |
| } |
| |
| return 0; |
| } |