Loading system/gd/l2cap/l2cap_packet_test.cc +62 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,68 @@ DEFINE_AND_INSTANTIATE_GroupFrameReflectionTest(g_frame); std::vector<uint8_t> config_mtu_request = {0x04, 0x05, 0x08, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x02, 0xa0, 0x02}; DEFINE_AND_INSTANTIATE_ConfigurationRequestReflectionTest(config_mtu_request); std::vector<uint8_t> config_request_one_defined_option = {0x04, 0x05, 0x08, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x02, 0x12, 0x34}; std::vector<uint8_t> config_request_two_defined_options = {0x04, 0x05, 0x0c, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x02, 0x12, 0x34, 0x02, 0x02, 0x56, 0x78}; std::vector<uint8_t> config_request_two_undefined_options = {0x04, 0x05, 0x0e, 0x00, 0x41, 0x00, 0x00, 0x00, 0x7f, 0x02, 0x01, 0x00, 0x7e, 0x04, 0x11, 0x11, 0x00, 0x00}; std::vector<uint8_t> config_request_hint_one_defined_option = {0x04, 0x05, 0x08, 0x00, 0x41, 0x00, 0x00, 0x00, 0x81, 0x02, 0x12, 0x34}; std::vector<uint8_t> config_request_hint_two_undefined_options = {0x04, 0x05, 0x0c, 0x00, 0x41, 0x00, 0x00, 0x00, 0x90, 0x02, 0x01, 0x00, 0x91, 0x02, 0x11, 0x11}; TEST(L2capPacketsTest, testConfigRequestOptions) { { std::shared_ptr<std::vector<uint8_t>> view_bytes = std::make_shared<std::vector<uint8_t>>(config_request_one_defined_option); PacketView<kLittleEndian> packet_bytes_view(view_bytes); auto view = ConfigurationRequestView::Create(ControlView::Create(packet_bytes_view)); ASSERT_TRUE(view.IsValid()); ASSERT_EQ(1, view.GetConfig().size()); } { std::shared_ptr<std::vector<uint8_t>> view_bytes = std::make_shared<std::vector<uint8_t>>(config_request_two_defined_options); PacketView<kLittleEndian> packet_bytes_view(view_bytes); auto view = ConfigurationRequestView::Create(ControlView::Create(packet_bytes_view)); ASSERT_TRUE(view.IsValid()); ASSERT_EQ(2, view.GetConfig().size()); } { std::shared_ptr<std::vector<uint8_t>> view_bytes = std::make_shared<std::vector<uint8_t>>(config_request_two_undefined_options); PacketView<kLittleEndian> packet_bytes_view(view_bytes); auto view = ConfigurationRequestView::Create(ControlView::Create(packet_bytes_view)); ASSERT_TRUE(view.IsValid()); ASSERT_EQ(2, view.GetConfig().size()); } { std::shared_ptr<std::vector<uint8_t>> view_bytes = std::make_shared<std::vector<uint8_t>>(config_request_hint_one_defined_option); PacketView<kLittleEndian> packet_bytes_view(view_bytes); auto view = ConfigurationRequestView::Create(ControlView::Create(packet_bytes_view)); ASSERT_TRUE(view.IsValid()); ASSERT_EQ(1, view.GetConfig().size()); } { std::shared_ptr<std::vector<uint8_t>> view_bytes = std::make_shared<std::vector<uint8_t>>(config_request_hint_two_undefined_options); PacketView<kLittleEndian> packet_bytes_view(view_bytes); auto view = ConfigurationRequestView::Create(ControlView::Create(packet_bytes_view)); ASSERT_TRUE(view.IsValid()); ASSERT_EQ(2, view.GetConfig().size()); } } DEFINE_ConfigurationRequestReflectionFuzzTest(); TEST(L2capFuzzRegressions, ConfigurationRequestFuzz_5691566077247488) { Loading system/gd/l2cap/l2cap_packets.pdl +8 −8 Original line number Diff line number Diff line Loading @@ -309,15 +309,15 @@ enum ConfigurationOptionIsHint : 1 { struct ConfigurationOption { type : ConfigurationOptionType, is_hint : ConfigurationOptionIsHint, length : 8, _size_(_body_) : 8, _body_, } struct MtuConfigurationOption : ConfigurationOption (type = MTU, length = 2) { struct MtuConfigurationOption : ConfigurationOption (type = MTU) { mtu : 16, } struct FlushTimeoutConfigurationOption : ConfigurationOption (type = FLUSH_TIMEOUT, length = 2) { struct FlushTimeoutConfigurationOption : ConfigurationOption (type = FLUSH_TIMEOUT) { flush_timeout : 16, } Loading @@ -327,7 +327,7 @@ enum QosServiceType : 8 { GUARANTEED = 0x02, } struct QualityOfServiceConfigurationOption : ConfigurationOption (type = QUALITY_OF_SERVICE, length = 22) { struct QualityOfServiceConfigurationOption : ConfigurationOption (type = QUALITY_OF_SERVICE) { _reserved_ : 8, // Flags service_type : QosServiceType, token_rate : 32, // 0 = ignore, 0xffffffff = max available Loading @@ -346,7 +346,7 @@ enum RetransmissionAndFlowControlModeOption : 8 { } struct RetransmissionAndFlowControlConfigurationOption : ConfigurationOption (type = RETRANSMISSION_AND_FLOW_CONTROL, length = 9) { struct RetransmissionAndFlowControlConfigurationOption : ConfigurationOption (type = RETRANSMISSION_AND_FLOW_CONTROL) { mode : RetransmissionAndFlowControlModeOption, tx_window_size : 8, // 1-32 for Flow Control and Retransmission, 1-63 for Enhanced max_transmit : 8, Loading @@ -360,12 +360,12 @@ enum FcsType : 8 { DEFAULT = 1, // 16-bit FCS } struct FrameCheckSequenceOption : ConfigurationOption (type = FRAME_CHECK_SEQUENCE, length = 1) { struct FrameCheckSequenceOption : ConfigurationOption (type = FRAME_CHECK_SEQUENCE) { fcs_type : FcsType, } struct ExtendedFlowSpecificationOption : ConfigurationOption (type = EXTENDED_FLOW_SPECIFICATION, length = 16) { struct ExtendedFlowSpecificationOption : ConfigurationOption (type = EXTENDED_FLOW_SPECIFICATION) { identifier : 8, // Default 0x01, must be 0x01 for Extended Flow-Best-Effort service_type : QosServiceType, maximum_sdu_size : 16, // Octets Loading @@ -374,7 +374,7 @@ struct ExtendedFlowSpecificationOption : ConfigurationOption (type = EXTENDED_FL flush_timeout : 32, // in microseconds 0x0 = no retransmissions 0xFFFFFFFF = never flushed } struct ExtendedWindowSizeOption : ConfigurationOption (type = EXTENDED_WINDOW_SIZE, length = 2) { struct ExtendedWindowSizeOption : ConfigurationOption (type = EXTENDED_WINDOW_SIZE) { max_window_size : 16, // 0x0000 = Valid for streaming, 0x0001-0x3FFF Valid for Enhanced Retransmission } Loading system/gd/packet/parser/fields/body_field.cc +12 −1 Original line number Diff line number Diff line Loading @@ -20,13 +20,24 @@ const std::string BodyField::kFieldType = "BodyField"; BodyField::BodyField(ParseLocation loc) : PacketField("body", loc) {} void BodyField::SetSizeField(const SizeField* size_field) { if (size_field_ != nullptr) { ERROR(this, size_field_, size_field) << "The size field for the body has already been assigned."; } size_field_ = size_field; } const std::string& BodyField::GetFieldType() const { return BodyField::kFieldType; } Size BodyField::GetSize() const { if (size_field_ == nullptr) { return Size(0); } std::string dynamic_size = "(" + size_field_->GetName() + " * 8)"; return dynamic_size; } std::string BodyField::GetDataType() const { ERROR(this) << "No need to know the type of a body field."; Loading system/gd/packet/parser/fields/body_field.h +5 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,8 @@ class BodyField : public PacketField { virtual const std::string& GetFieldType() const override; void SetSizeField(const SizeField* size_field); virtual Size GetSize() const override; virtual std::string GetDataType() const override; Loading @@ -47,4 +49,7 @@ class BodyField : public PacketField { virtual void GenInserter(std::ostream&) const override; virtual void GenValidator(std::ostream&) const override; // Body fields can only be dynamically sized. const SizeField* size_field_{nullptr}; }; system/gd/packet/parser/fields/vector_field.cc +4 −4 Original line number Diff line number Diff line Loading @@ -89,15 +89,15 @@ Size VectorField::GetStructSize() const { // size_field_ is of type SIZE if (size_field_->GetFieldType() == SizeField::kFieldType) { std::string ret = "(static_cast<size_t>(" + size_field_->GetName() + "_extracted) * 8)"; std::string ret = "(static_cast<size_t>(to_fill->" + size_field_->GetName() + "_extracted_) * 8)"; if (!size_modifier_.empty()) ret += "-" + size_modifier_; return ret; } // size_field_ is of type COUNT and elements have a fixed size if (!element_size_.empty() && !element_size_.has_dynamic()) { return "(static_cast<size_t>(" + size_field_->GetName() + "_extracted) * " + std::to_string(element_size_.bits()) + ")"; return "(static_cast<size_t>(to_fill->" + size_field_->GetName() + "_extracted_) * " + std::to_string(element_size_.bits()) + ")"; } return Size(); Loading @@ -112,7 +112,7 @@ void VectorField::GenExtractor(std::ostream& s, int num_leading_bits, bool for_s if (size_field_ != nullptr && size_field_->GetFieldType() == CountField::kFieldType) { s << "size_t " << element_field_->GetName() << "_count = "; if (for_struct) { s << size_field_->GetName() << "_extracted;"; s << "to_fill->" << size_field_->GetName() << "_extracted_;"; } else { s << "Get" << util::UnderscoreToCamelCase(size_field_->GetName()) << "();"; } Loading Loading
system/gd/l2cap/l2cap_packet_test.cc +62 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,68 @@ DEFINE_AND_INSTANTIATE_GroupFrameReflectionTest(g_frame); std::vector<uint8_t> config_mtu_request = {0x04, 0x05, 0x08, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x02, 0xa0, 0x02}; DEFINE_AND_INSTANTIATE_ConfigurationRequestReflectionTest(config_mtu_request); std::vector<uint8_t> config_request_one_defined_option = {0x04, 0x05, 0x08, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x02, 0x12, 0x34}; std::vector<uint8_t> config_request_two_defined_options = {0x04, 0x05, 0x0c, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x02, 0x12, 0x34, 0x02, 0x02, 0x56, 0x78}; std::vector<uint8_t> config_request_two_undefined_options = {0x04, 0x05, 0x0e, 0x00, 0x41, 0x00, 0x00, 0x00, 0x7f, 0x02, 0x01, 0x00, 0x7e, 0x04, 0x11, 0x11, 0x00, 0x00}; std::vector<uint8_t> config_request_hint_one_defined_option = {0x04, 0x05, 0x08, 0x00, 0x41, 0x00, 0x00, 0x00, 0x81, 0x02, 0x12, 0x34}; std::vector<uint8_t> config_request_hint_two_undefined_options = {0x04, 0x05, 0x0c, 0x00, 0x41, 0x00, 0x00, 0x00, 0x90, 0x02, 0x01, 0x00, 0x91, 0x02, 0x11, 0x11}; TEST(L2capPacketsTest, testConfigRequestOptions) { { std::shared_ptr<std::vector<uint8_t>> view_bytes = std::make_shared<std::vector<uint8_t>>(config_request_one_defined_option); PacketView<kLittleEndian> packet_bytes_view(view_bytes); auto view = ConfigurationRequestView::Create(ControlView::Create(packet_bytes_view)); ASSERT_TRUE(view.IsValid()); ASSERT_EQ(1, view.GetConfig().size()); } { std::shared_ptr<std::vector<uint8_t>> view_bytes = std::make_shared<std::vector<uint8_t>>(config_request_two_defined_options); PacketView<kLittleEndian> packet_bytes_view(view_bytes); auto view = ConfigurationRequestView::Create(ControlView::Create(packet_bytes_view)); ASSERT_TRUE(view.IsValid()); ASSERT_EQ(2, view.GetConfig().size()); } { std::shared_ptr<std::vector<uint8_t>> view_bytes = std::make_shared<std::vector<uint8_t>>(config_request_two_undefined_options); PacketView<kLittleEndian> packet_bytes_view(view_bytes); auto view = ConfigurationRequestView::Create(ControlView::Create(packet_bytes_view)); ASSERT_TRUE(view.IsValid()); ASSERT_EQ(2, view.GetConfig().size()); } { std::shared_ptr<std::vector<uint8_t>> view_bytes = std::make_shared<std::vector<uint8_t>>(config_request_hint_one_defined_option); PacketView<kLittleEndian> packet_bytes_view(view_bytes); auto view = ConfigurationRequestView::Create(ControlView::Create(packet_bytes_view)); ASSERT_TRUE(view.IsValid()); ASSERT_EQ(1, view.GetConfig().size()); } { std::shared_ptr<std::vector<uint8_t>> view_bytes = std::make_shared<std::vector<uint8_t>>(config_request_hint_two_undefined_options); PacketView<kLittleEndian> packet_bytes_view(view_bytes); auto view = ConfigurationRequestView::Create(ControlView::Create(packet_bytes_view)); ASSERT_TRUE(view.IsValid()); ASSERT_EQ(2, view.GetConfig().size()); } } DEFINE_ConfigurationRequestReflectionFuzzTest(); TEST(L2capFuzzRegressions, ConfigurationRequestFuzz_5691566077247488) { Loading
system/gd/l2cap/l2cap_packets.pdl +8 −8 Original line number Diff line number Diff line Loading @@ -309,15 +309,15 @@ enum ConfigurationOptionIsHint : 1 { struct ConfigurationOption { type : ConfigurationOptionType, is_hint : ConfigurationOptionIsHint, length : 8, _size_(_body_) : 8, _body_, } struct MtuConfigurationOption : ConfigurationOption (type = MTU, length = 2) { struct MtuConfigurationOption : ConfigurationOption (type = MTU) { mtu : 16, } struct FlushTimeoutConfigurationOption : ConfigurationOption (type = FLUSH_TIMEOUT, length = 2) { struct FlushTimeoutConfigurationOption : ConfigurationOption (type = FLUSH_TIMEOUT) { flush_timeout : 16, } Loading @@ -327,7 +327,7 @@ enum QosServiceType : 8 { GUARANTEED = 0x02, } struct QualityOfServiceConfigurationOption : ConfigurationOption (type = QUALITY_OF_SERVICE, length = 22) { struct QualityOfServiceConfigurationOption : ConfigurationOption (type = QUALITY_OF_SERVICE) { _reserved_ : 8, // Flags service_type : QosServiceType, token_rate : 32, // 0 = ignore, 0xffffffff = max available Loading @@ -346,7 +346,7 @@ enum RetransmissionAndFlowControlModeOption : 8 { } struct RetransmissionAndFlowControlConfigurationOption : ConfigurationOption (type = RETRANSMISSION_AND_FLOW_CONTROL, length = 9) { struct RetransmissionAndFlowControlConfigurationOption : ConfigurationOption (type = RETRANSMISSION_AND_FLOW_CONTROL) { mode : RetransmissionAndFlowControlModeOption, tx_window_size : 8, // 1-32 for Flow Control and Retransmission, 1-63 for Enhanced max_transmit : 8, Loading @@ -360,12 +360,12 @@ enum FcsType : 8 { DEFAULT = 1, // 16-bit FCS } struct FrameCheckSequenceOption : ConfigurationOption (type = FRAME_CHECK_SEQUENCE, length = 1) { struct FrameCheckSequenceOption : ConfigurationOption (type = FRAME_CHECK_SEQUENCE) { fcs_type : FcsType, } struct ExtendedFlowSpecificationOption : ConfigurationOption (type = EXTENDED_FLOW_SPECIFICATION, length = 16) { struct ExtendedFlowSpecificationOption : ConfigurationOption (type = EXTENDED_FLOW_SPECIFICATION) { identifier : 8, // Default 0x01, must be 0x01 for Extended Flow-Best-Effort service_type : QosServiceType, maximum_sdu_size : 16, // Octets Loading @@ -374,7 +374,7 @@ struct ExtendedFlowSpecificationOption : ConfigurationOption (type = EXTENDED_FL flush_timeout : 32, // in microseconds 0x0 = no retransmissions 0xFFFFFFFF = never flushed } struct ExtendedWindowSizeOption : ConfigurationOption (type = EXTENDED_WINDOW_SIZE, length = 2) { struct ExtendedWindowSizeOption : ConfigurationOption (type = EXTENDED_WINDOW_SIZE) { max_window_size : 16, // 0x0000 = Valid for streaming, 0x0001-0x3FFF Valid for Enhanced Retransmission } Loading
system/gd/packet/parser/fields/body_field.cc +12 −1 Original line number Diff line number Diff line Loading @@ -20,13 +20,24 @@ const std::string BodyField::kFieldType = "BodyField"; BodyField::BodyField(ParseLocation loc) : PacketField("body", loc) {} void BodyField::SetSizeField(const SizeField* size_field) { if (size_field_ != nullptr) { ERROR(this, size_field_, size_field) << "The size field for the body has already been assigned."; } size_field_ = size_field; } const std::string& BodyField::GetFieldType() const { return BodyField::kFieldType; } Size BodyField::GetSize() const { if (size_field_ == nullptr) { return Size(0); } std::string dynamic_size = "(" + size_field_->GetName() + " * 8)"; return dynamic_size; } std::string BodyField::GetDataType() const { ERROR(this) << "No need to know the type of a body field."; Loading
system/gd/packet/parser/fields/body_field.h +5 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,8 @@ class BodyField : public PacketField { virtual const std::string& GetFieldType() const override; void SetSizeField(const SizeField* size_field); virtual Size GetSize() const override; virtual std::string GetDataType() const override; Loading @@ -47,4 +49,7 @@ class BodyField : public PacketField { virtual void GenInserter(std::ostream&) const override; virtual void GenValidator(std::ostream&) const override; // Body fields can only be dynamically sized. const SizeField* size_field_{nullptr}; };
system/gd/packet/parser/fields/vector_field.cc +4 −4 Original line number Diff line number Diff line Loading @@ -89,15 +89,15 @@ Size VectorField::GetStructSize() const { // size_field_ is of type SIZE if (size_field_->GetFieldType() == SizeField::kFieldType) { std::string ret = "(static_cast<size_t>(" + size_field_->GetName() + "_extracted) * 8)"; std::string ret = "(static_cast<size_t>(to_fill->" + size_field_->GetName() + "_extracted_) * 8)"; if (!size_modifier_.empty()) ret += "-" + size_modifier_; return ret; } // size_field_ is of type COUNT and elements have a fixed size if (!element_size_.empty() && !element_size_.has_dynamic()) { return "(static_cast<size_t>(" + size_field_->GetName() + "_extracted) * " + std::to_string(element_size_.bits()) + ")"; return "(static_cast<size_t>(to_fill->" + size_field_->GetName() + "_extracted_) * " + std::to_string(element_size_.bits()) + ")"; } return Size(); Loading @@ -112,7 +112,7 @@ void VectorField::GenExtractor(std::ostream& s, int num_leading_bits, bool for_s if (size_field_ != nullptr && size_field_->GetFieldType() == CountField::kFieldType) { s << "size_t " << element_field_->GetName() << "_count = "; if (for_struct) { s << size_field_->GetName() << "_extracted;"; s << "to_fill->" << size_field_->GetName() << "_extracted_;"; } else { s << "Get" << util::UnderscoreToCamelCase(size_field_->GetName()) << "();"; } Loading