Skip to content

cmd/cgo: missing pointer check for struct passed through a union type #15942

Closed
@bcmills

Description

@bcmills

I was thinking some more about the examples in #14210. Here's a more realistic false-negative example that does "follow the rules", but still manages to leak a Go pointer into C undetected. It's not unlike what you might find in a program using, say, the SDL API.

It doesn't do any iffy casting in C, and its only iffy casting in Go is due to language support - this is exactly the code you end up writing if you have to deal with a C API with unions.

package main

/*
typedef enum {
  DIRECT,
  INDIRECT,
} kind;

typedef struct {
  kind k;
} header;

typedef struct {
  header hdr;
  int payload;
} direct;

typedef struct {
  header hdr;
  int *payload;
} indirect;

typedef union {
  header hdr;
  direct d;
  indirect i;
} either;

int get_payload(either *e) {
  switch (e->hdr.k) {
  case DIRECT:
    return e->d.payload;
  case INDIRECT:
    return *(e->i.payload);
  default:
    return -1;
  }
}
*/
import "C"

import (
    "fmt"
    "unsafe"
)

func main() {
    var escapee C.int = 42
    i := C.indirect{
        hdr:     C.header{k: C.INDIRECT},
        payload: &escapee,
    }

    escaped := C.get_payload((*C.either)(unsafe.Pointer(&i)))
    fmt.Println(escaped)
}

With go version go1.6.1 linux/amd64, this program outputs 42 and exits with code 0. It should instead panic with a cgo pointer violation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeNeedsFixThe path to resolution is known, but the work has not been done.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions