@@ -92,6 +92,30 @@ void write_u32(
9292 raw <= static_cast <std::uint8_t >(SvDeviceWireType::timestamp);
9393}
9494
95+ [[nodiscard]] std::optional<std::uint16_t > canonical_wire_width (
96+ const SvDeviceWireType type) noexcept {
97+ switch (type) {
98+ case SvDeviceWireType::boolean:
99+ case SvDeviceWireType::int8:
100+ case SvDeviceWireType::uint8:
101+ return static_cast <std::uint16_t >(1U );
102+ case SvDeviceWireType::int16:
103+ case SvDeviceWireType::uint16:
104+ return static_cast <std::uint16_t >(2U );
105+ case SvDeviceWireType::int32:
106+ case SvDeviceWireType::uint32:
107+ case SvDeviceWireType::float32:
108+ case SvDeviceWireType::quality:
109+ return static_cast <std::uint16_t >(4U );
110+ case SvDeviceWireType::int64:
111+ case SvDeviceWireType::uint64:
112+ case SvDeviceWireType::float64:
113+ case SvDeviceWireType::timestamp:
114+ return static_cast <std::uint16_t >(8U );
115+ }
116+ return std::nullopt ;
117+ }
118+
95119[[nodiscard]] bool valid_profile_shape (
96120 const CompiledSvDeviceProfile& profile) noexcept {
97121 if (profile.schema_version != compiled_sv_device_profile_version ||
@@ -112,6 +136,26 @@ void write_u32(
112136 profile.data_set_reference_length == 0U ) {
113137 return false ;
114138 }
139+ if (!profile.asdu_options .element_present &&
140+ (profile.asdu_options .refresh_time ||
141+ profile.asdu_options .sample_synchronized ||
142+ profile.asdu_options .sample_rate ||
143+ profile.asdu_options .data_set ||
144+ profile.asdu_options .security ||
145+ profile.asdu_options .synch_source_id )) {
146+ return false ;
147+ }
148+ if (!profile.vlan_present &&
149+ (profile.vlan_id != 0U || profile.vlan_priority != 0U )) {
150+ return false ;
151+ }
152+ const std::string_view sv_id{
153+ profile.sv_id .data (), profile.sv_id_length };
154+ const std::string_view data_set{
155+ profile.data_set_reference .data (), profile.data_set_reference_length };
156+ if (contains_nul (sv_id) || contains_nul (data_set)) {
157+ return false ;
158+ }
115159 if (!is_valid_sv_app_id (profile.app_id )) return false ;
116160 if (profile.transport_mode == SvTransportMode::multicast) {
117161 if (!is_iec_sv_multicast_mac (profile.destination_mac )) return false ;
@@ -131,7 +175,11 @@ void write_u32(
131175 std::uint64_t payload{};
132176 for (std::size_t index = 0U ; index < profile.leaf_count ; ++index) {
133177 const auto & leaf = profile.leaves [index];
134- if (!valid_wire_type (leaf.wire_type ) || leaf.wire_width_bytes == 0U ) {
178+ const auto expected_width = canonical_wire_width (leaf.wire_type );
179+ if (!expected_width.has_value () ||
180+ leaf.wire_width_bytes != *expected_width ||
181+ leaf.quality != (leaf.wire_type == SvDeviceWireType::quality) ||
182+ leaf.timestamp != (leaf.wire_type == SvDeviceWireType::timestamp)) {
135183 return false ;
136184 }
137185 payload += leaf.wire_width_bytes ;
0 commit comments