OPC UA Data types : support Unions and Structures with optional fields

Description

Add new data structure management into encodeable type :

  1. Add Unions
  2. Add Structures with optional fields

Code version identification

171b7cab

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

  1. BSD parsing (gen-sopc-types.py): Management of BaseType="ua:Union" for Unions, TypeName="opc:Bit" for optional field, ..
  2. Generation of C types of these new types (impact on current types due to change in SOPC_EncodeableType_FieldDescriptor for optional field management, see bellow)

Generic encoder

  • Add an enumerate to define the type of encodeable type (SOPC_EncodeableType_StructureType): structure, union, optional fields.
  1. 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.
  2. 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 : 1 in SOPC_EncodeableType_FieldDescriptor struct.
  1. 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.
  2. 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.

Edited by Sebastien Tajan