]> xenbits.xensource.com Git - people/sstabellini/xen-unstable.git/.git/commitdiff
golang/xenlight: Fix handling of marshalling of empty elements for keyed unions
authorGeorge Dunlap <george.dunlap@citrix.com>
Thu, 5 Mar 2020 11:34:07 +0000 (11:34 +0000)
committerGeorge Dunlap <george.dunlap@citrix.com>
Mon, 9 Mar 2020 14:36:29 +0000 (14:36 +0000)
Keyed types in libxl_types.idl can have elements of type 'None'.  The
golang type generator (correctly) don't implement any union types for
these empty elements.  However, the toC and fromC helper generators
incorrectly treat these elements as invalid.

Consider for example, libxl_channelinfo.  The idl contains the
following keyed element:

    ("u", KeyedUnion(None, libxl_channel_connection, "connection",
           [("unknown", None),
            ("pty", Struct(None, [("path", string),])),
            ("socket", None),
           ])),

But the toC marshaller currently looks like this:

switch x.Connection {
case ChannelConnectionPty:
tmp, ok := x.ConnectionUnion.(ChannelinfoConnectionUnionPty)
if !ok {
return errors.New("wrong type for union key connection")
}
var pty C.libxl_channelinfo_connection_union_pty
if tmp.Path != "" {
pty.path = C.CString(tmp.Path)
}
ptyBytes := C.GoBytes(unsafe.Pointer(&pty), C.sizeof_libxl_channelinfo_connection_union_pty)
copy(xc.u[:], ptyBytes)
default:
return fmt.Errorf("invalid union key '%v'", x.Connection)
}

Which means toC() will fail for ChannelConnectionUnknown or
ChannelConnectionSocket.

Modify the generator to handle keyed union elements of type 'None'.
For fromC, set the value to 'nil'; for toC, leave things as-is.

Signed-off-by: George Dunlap <george.dunlap@citrix.com>
Reviewed-by: Nick Rosbrook <rosbrookn@ainfosec.com>
tools/golang/xenlight/gengotypes.py
tools/golang/xenlight/helpers.gen.go

index f81271f3c0a491bd846a84cd8c7e5f1995b71aa4..50dada309b8d51ff70c3c7931edfb7d376887324 100644 (file)
@@ -335,6 +335,7 @@ def xenlight_golang_union_from_C(ty = None, union_name = '', struct_name = ''):
     gokeyname = xenlight_golang_fmt_name(keyname)
     keytype   = ty.keyvar.type.typename
     gokeytype = xenlight_golang_fmt_name(keytype)
+    field_name = xenlight_golang_fmt_name('{}_union'.format(keyname))
 
     interface_name = '{}_{}_union'.format(struct_name, keyname)
     interface_name = xenlight_golang_fmt_name(interface_name, exported=False)
@@ -351,11 +352,11 @@ def xenlight_golang_union_from_C(ty = None, union_name = '', struct_name = ''):
 
         # Add to list of cases to make for the switch
         # statement below.
+        cases[f.name] = (val, f.type)
+
         if f.type is None:
             continue
 
-        cases[f.name] = val
-
         # Define fromC func for 'union' struct.
         typename   = '{}_{}_union_{}'.format(struct_name,keyname,f.name)
         gotypename = xenlight_golang_fmt_name(typename)
@@ -382,9 +383,15 @@ def xenlight_golang_union_from_C(ty = None, union_name = '', struct_name = ''):
 
     # Create switch statement to determine which 'union element'
     # to populate in the Go struct.
-    for case_name, case_val in cases.items():
+    for case_name, case_tuple in cases.items():
+        (case_val, case_type) = case_tuple
+
         s += 'case {}:\n'.format(case_val)
 
+        if case_type is None:
+            s += "x.{} = nil\n".format(field_name)
+            continue
+
         gotype = '{}_{}_union_{}'.format(struct_name,keyname,case_name)
         gotype = xenlight_golang_fmt_name(gotype)
         goname = '{}_{}'.format(keyname,case_name)
@@ -394,7 +401,6 @@ def xenlight_golang_union_from_C(ty = None, union_name = '', struct_name = ''):
         s += 'if err := {}.fromC(xc);'.format(goname)
         s += 'err != nil {{\n return fmt.Errorf("converting field {}: %v", err) \n}}\n'.format(goname)
 
-        field_name = xenlight_golang_fmt_name('{}_union'.format(keyname))
         s += 'x.{} = {}\n'.format(field_name, goname)
 
     # End switch statement
@@ -551,10 +557,13 @@ def xenlight_golang_union_to_C(ty = None, union_name = '',
     for f in ty.fields:
         key_val = '{}_{}'.format(keytype, f.name)
         key_val = xenlight_golang_fmt_name(key_val)
+
+        s += 'case {}:\n'.format(key_val)
+
         if f.type is None:
+            s += "break\n"
             continue
 
-        s += 'case {}:\n'.format(key_val)
         cgotype = '{}_{}_union_{}'.format(struct_name,keyname,f.name)
         gotype  = xenlight_golang_fmt_name(cgotype)
 
index 37cd3b8249558d13d696bfa76e9c6305081df316..344ce9a461a88d7b534551ca8b056e944c5f6862 100644 (file)
@@ -493,12 +493,16 @@ func (x *Channelinfo) fromC(xc *C.libxl_channelinfo) error {
        x.Rref = int(xc.rref)
        x.Connection = ChannelConnection(xc.connection)
        switch x.Connection {
+       case ChannelConnectionUnknown:
+               x.ConnectionUnion = nil
        case ChannelConnectionPty:
                var connectionPty ChannelinfoConnectionUnionPty
                if err := connectionPty.fromC(xc); err != nil {
                        return fmt.Errorf("converting field connectionPty: %v", err)
                }
                x.ConnectionUnion = connectionPty
+       case ChannelConnectionSocket:
+               x.ConnectionUnion = nil
        default:
                return fmt.Errorf("invalid union key '%v'", x.Connection)
        }
@@ -537,6 +541,8 @@ func (x *Channelinfo) toC(xc *C.libxl_channelinfo) (err error) {
        xc.rref = C.int(x.Rref)
        xc.connection = C.libxl_channel_connection(x.Connection)
        switch x.Connection {
+       case ChannelConnectionUnknown:
+               break
        case ChannelConnectionPty:
                tmp, ok := x.ConnectionUnion.(ChannelinfoConnectionUnionPty)
                if !ok {
@@ -548,6 +554,8 @@ func (x *Channelinfo) toC(xc *C.libxl_channelinfo) (err error) {
                }
                ptyBytes := C.GoBytes(unsafe.Pointer(&pty), C.sizeof_libxl_channelinfo_connection_union_pty)
                copy(xc.u[:], ptyBytes)
+       case ChannelConnectionSocket:
+               break
        default:
                return fmt.Errorf("invalid union key '%v'", x.Connection)
        }
@@ -1223,6 +1231,8 @@ func (x *DomainBuildInfo) fromC(xc *C.libxl_domain_build_info) error {
                        return fmt.Errorf("converting field typePvh: %v", err)
                }
                x.TypeUnion = typePvh
+       case DomainTypeInvalid:
+               x.TypeUnion = nil
        default:
                return fmt.Errorf("invalid union key '%v'", x.Type)
        }
@@ -1723,6 +1733,8 @@ func (x *DomainBuildInfo) toC(xc *C.libxl_domain_build_info) (err error) {
                }
                pvhBytes := C.GoBytes(unsafe.Pointer(&pvh), C.sizeof_libxl_domain_build_info_type_union_pvh)
                copy(xc.u[:], pvhBytes)
+       case DomainTypeInvalid:
+               break
        default:
                return fmt.Errorf("invalid union key '%v'", x.Type)
        }
@@ -2650,6 +2662,10 @@ func (x *DeviceChannel) fromC(xc *C.libxl_device_channel) error {
        x.Name = C.GoString(xc.name)
        x.Connection = ChannelConnection(xc.connection)
        switch x.Connection {
+       case ChannelConnectionUnknown:
+               x.ConnectionUnion = nil
+       case ChannelConnectionPty:
+               x.ConnectionUnion = nil
        case ChannelConnectionSocket:
                var connectionSocket DeviceChannelConnectionUnionSocket
                if err := connectionSocket.fromC(xc); err != nil {
@@ -2690,6 +2706,10 @@ func (x *DeviceChannel) toC(xc *C.libxl_device_channel) (err error) {
        }
        xc.connection = C.libxl_channel_connection(x.Connection)
        switch x.Connection {
+       case ChannelConnectionUnknown:
+               break
+       case ChannelConnectionPty:
+               break
        case ChannelConnectionSocket:
                tmp, ok := x.ConnectionUnion.(DeviceChannelConnectionUnionSocket)
                if !ok {
@@ -4376,6 +4396,8 @@ func (x *Event) fromC(xc *C.libxl_event) error {
                        return fmt.Errorf("converting field typeDomainShutdown: %v", err)
                }
                x.TypeUnion = typeDomainShutdown
+       case EventTypeDomainDeath:
+               x.TypeUnion = nil
        case EventTypeDiskEject:
                var typeDiskEject EventTypeUnionDiskEject
                if err := typeDiskEject.fromC(xc); err != nil {
@@ -4388,6 +4410,8 @@ func (x *Event) fromC(xc *C.libxl_event) error {
                        return fmt.Errorf("converting field typeOperationComplete: %v", err)
                }
                x.TypeUnion = typeOperationComplete
+       case EventTypeDomainCreateConsoleAvailable:
+               x.TypeUnion = nil
        default:
                return fmt.Errorf("invalid union key '%v'", x.Type)
        }
@@ -4454,6 +4478,8 @@ func (x *Event) toC(xc *C.libxl_event) (err error) {
                domain_shutdown.shutdown_reason = C.uint8_t(tmp.ShutdownReason)
                domain_shutdownBytes := C.GoBytes(unsafe.Pointer(&domain_shutdown), C.sizeof_libxl_event_type_union_domain_shutdown)
                copy(xc.u[:], domain_shutdownBytes)
+       case EventTypeDomainDeath:
+               break
        case EventTypeDiskEject:
                tmp, ok := x.TypeUnion.(EventTypeUnionDiskEject)
                if !ok {
@@ -4477,6 +4503,8 @@ func (x *Event) toC(xc *C.libxl_event) (err error) {
                operation_complete.rc = C.int(tmp.Rc)
                operation_completeBytes := C.GoBytes(unsafe.Pointer(&operation_complete), C.sizeof_libxl_event_type_union_operation_complete)
                copy(xc.u[:], operation_completeBytes)
+       case EventTypeDomainCreateConsoleAvailable:
+               break
        default:
                return fmt.Errorf("invalid union key '%v'", x.Type)
        }