OPC UA Data types : support Unions and Structures with optional fields
Description
Add new data structure management into encodeable type :
- Add Unions
- Add Structures with optional fields
Code version identification
Current behavior
We currently do not support Unions and optional fields in defined types:
- We can't parse BSD with these types (BSD parsing failed -> No types generated) => we can't provide a definition of these types.
- We can't decode/encode these types.
Expected behavior
Management of Unions and optional fields, from type generation (BSD parsing) to high-level functions (compare, copy, etc.), including management of these new types in generic encoders/decoders.
Security impact
It's just a new feature that shouldn't have any impact on security.
Perhaps fuzzing can prevent some typical encoding/decoding vulnerabilities.
Implementation
type generation
- BSD parsing (
gen-sopc-types.py): Management ofBaseType="ua:Union"for Unions,TypeName="opc:Bit"for optional field, .. - Generation of C types of these new types (impact on current types due to change in
SOPC_EncodeableType_FieldDescriptorfor optional field management, see bellow)
Generic encoder
- Add an enumerate to define the type of encodeable type (SOPC_EncodeableType_StructureType): structure, union, optional fields.
-
Unions (decode):
- Decode the first field to identify which union field is present : the value of the first field directly gives us the index of the selected union field.
- Jump to the selected union field, and initialize it.
- Decode it.
-
Unions (encode):
- Encode first field (selector).
- Encode union field.
Note : The Union structure must be initialized to 0 until we know which field is selected, then we can reinitialize the selected field (at decoding time), because the initialization may be different from 0.
- Add
bool isOptional : 1in SOPC_EncodeableType_FieldDescriptor struct.
-
Optional fields (decode):
- Decode the mask field which is locally stored (not present in C struct).
- Initiate a counter of optional field (incremented each time an optional field is encountered:
isOptional = true). - For each optional field encountered: if
bit_rank(mask) == counter-> Decode field, else give NULL value.
-
Optional fields (encode):
- First iteration to elaborate the mask field.
- Encode mask field.
- For all fields, if it is NOT NULL, encode the field.
Note : Be careful of array type representation with 2 fields in EncodeableType.