| // Copyright 2019 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "base/values.h" |
| #include "components/cast_channel/cast_message_util.h" |
| #include "components/cast_channel/enum_table.h" |
| #include "components/cast_channel/fuzz_proto/fuzzer_inputs.pb.h" |
| #include "testing/libfuzzer/proto/lpm_interface.h" |
| |
| using cast_util::EnumToString; |
| |
| namespace cast_channel { |
| namespace fuzz { |
| |
| namespace { |
| |
| base::Value MakeValue(const JunkValue& junk) { |
| base::Value result(base::Value::Type::DICTIONARY); |
| for (int i = 0; i < junk.field_size(); i++) { |
| const auto& field = junk.field(i); |
| base::Value field_value = field.has_int_value() |
| ? base::Value(field.int_value()) |
| : field.has_string_value() |
| ? base::Value(field.string_value()) |
| : field.has_float_value() |
| ? base::Value(field.float_value()) |
| : base::Value(field.bool_value()); |
| result.SetKey(field.name(), std::move(field_value)); |
| } |
| return result; |
| } |
| |
| template <typename Field, typename T = typename Field::value_type> |
| std::vector<T> MakeVector(const Field& field) { |
| return std::vector<T>(field.cbegin(), field.cend()); |
| } |
| |
| } // namespace |
| |
| DEFINE_PROTO_FUZZER(const CastMessageUtilInputs& input_union) { |
| // TODO(crbug.com/796717): Add test for CreateAuthChallengeMessage() |
| switch (input_union.input_case()) { |
| case CastMessageUtilInputs::kCreateBroadcastRequestInput: { |
| const auto& input = input_union.create_broadcast_request_input(); |
| CreateBroadcastRequest(input.source_id(), input.request_id(), |
| MakeVector(input.app_id()), |
| BroadcastRequest(input.broadcast_namespace(), |
| input.broadcast_message())); |
| break; |
| } |
| case CastMessageUtilInputs::kCreateLaunchRequestInput: { |
| const auto& input = input_union.create_launch_request_input(); |
| absl::optional<base::Value> app_params; |
| if (input.has_app_params()) |
| app_params = MakeValue(input.app_params()); |
| CreateLaunchRequest(input.source_id(), input.request_id(), input.app_id(), |
| input.locale(), |
| MakeVector(input.supported_app_types()), app_params); |
| break; |
| } |
| case CastMessageUtilInputs::kCreateStopRequestInput: { |
| const auto& input = input_union.create_stop_request_input(); |
| CreateStopRequest(input.source_id(), input.request_id(), |
| input.session_id()); |
| break; |
| } |
| case CastMessageUtilInputs::kCreateCastMessageInput: { |
| const auto& input = input_union.create_cast_message_input(); |
| base::Value body = MakeValue(input.body()); |
| CreateCastMessage(input.message_namespace(), body, input.source_id(), |
| input.destination_id()); |
| break; |
| } |
| case CastMessageUtilInputs::kCreateMediaRequestInput: { |
| const auto& input = input_union.create_media_request_input(); |
| auto type = static_cast<V2MessageType>(input.type()); |
| if (IsMediaRequestMessageType(type)) { |
| base::Value body = MakeValue(input.body()); |
| body.SetKey("type", base::Value(*EnumToString(type))); |
| CreateMediaRequest(body, input.request_id(), input.source_id(), |
| input.destination_id()); |
| } |
| break; |
| } |
| case CastMessageUtilInputs::kCreateSetVolumeRequestInput: { |
| const auto& input = input_union.create_set_volume_request_input(); |
| base::Value body = MakeValue(input.body()); |
| body.SetKey( |
| "type", |
| base::Value( |
| EnumToString<V2MessageType, V2MessageType::kSetVolume>())); |
| CreateSetVolumeRequest(body, input.request_id(), input.source_id()); |
| break; |
| } |
| case CastMessageUtilInputs::kIntInput: { |
| IsMediaRequestMessageType( |
| static_cast<V2MessageType>(input_union.int_input())); |
| ToString(static_cast<GetAppAvailabilityResult>(input_union.int_input())); |
| ToString(static_cast<CastMessageType>(input_union.int_input())); |
| ToString(static_cast<V2MessageType>(input_union.int_input())); |
| break; |
| } |
| case CastMessageUtilInputs::kStringInput: { |
| IsCastReservedNamespace(input_union.string_input()); |
| break; |
| } |
| case CastMessageUtilInputs::kCastMessage: { |
| const auto& message = input_union.cast_message(); |
| IsCastMessageValid(message); |
| IsAuthMessage(message); |
| IsReceiverMessage(message); |
| IsPlatformSenderMessage(message); |
| break; |
| } |
| case CastMessageUtilInputs::kCreateVirtualConnectionRequestInput: { |
| const auto& input = input_union.create_virtual_connection_request_input(); |
| CreateVirtualConnectionRequest( |
| input.source_id(), input.destination_id(), |
| static_cast<VirtualConnectionType>(input.connection_type()), |
| input.user_agent(), input.browser_version()); |
| break; |
| } |
| case CastMessageUtilInputs::kCreateGetAppAvailabilityRequestInput: { |
| const auto& input = |
| input_union.create_get_app_availability_request_input(); |
| CreateGetAppAvailabilityRequest(input.source_id(), input.request_id(), |
| input.app_id()); |
| break; |
| } |
| case CastMessageUtilInputs::kGetRequestIdFromResponseInput: { |
| const auto& input = input_union.get_request_id_from_response_input(); |
| base::Value payload = MakeValue(input.payload()); |
| if (input.has_request_id()) |
| payload.SetKey("requestId", base::Value(input.request_id())); |
| GetRequestIdFromResponse(payload); |
| break; |
| } |
| case CastMessageUtilInputs::kGetLaunchSessionResponseInput: { |
| const auto& input = input_union.get_launch_session_response_input(); |
| base::Value payload = MakeValue(input.payload()); |
| GetLaunchSessionResponse(payload); |
| break; |
| } |
| case CastMessageUtilInputs::kParseMessageTypeFromPayloadInput: { |
| const auto& input = input_union.parse_message_type_from_payload_input(); |
| base::Value payload = MakeValue(input.payload()); |
| if (input.has_type()) |
| payload.SetKey("type", base::Value(input.type())); |
| ParseMessageTypeFromPayload(payload); |
| break; |
| } |
| case CastMessageUtilInputs::kCreateReceiverStatusRequestInput: { |
| const auto& input = input_union.create_receiver_status_request_input(); |
| CreateReceiverStatusRequest(input.source_id(), input.request_id()); |
| break; |
| } |
| case CastMessageUtilInputs::INPUT_NOT_SET: |
| break; |
| } |
| } |
| |
| } // namespace fuzz |
| } // namespace cast_channel |