diff --git a/pairing.go b/pairing.go index 6abc8974e9cd2a0f2cea5370f5f01f800b42f5b3..f023415f13dbe3dc0a2cd54330d04cff1a7c91e3 100644 --- a/pairing.go +++ b/pairing.go @@ -56,13 +56,25 @@ const ( // created in G1, G2, GT, or Zr. Additionally, elements can be checked or // unchecked. See the Element type for more details. type Pairing struct { + params *Params // Prevents garbage collection cptr *C.struct_pairing_s } // NewPairing instantiates a pairing from a set of parameters. func NewPairing(params *Params) *Pairing { - pairing := makePairing() + pairing := makePairing(params) C.pairing_init_pbc_param(pairing.cptr, params.cptr) + + // pairing.params must point to params during the C call. Otherwise, the + // garbage collector might free params.cptr (through the Params finalizer) + // while pairing_init_pbc_param is still running! However, this function no + // longer requires access to the parameters once control has returned. We + // set pairing.params to nil to indicate that we no longer care if params + // is garbage collected. If the caller still needs params (e.g., to + // initialize more pairings), the garbage collector will know not to free + // params even though pairing.params does not point to it. + pairing.params = nil + return pairing } @@ -161,8 +173,11 @@ func clearPairing(pairing *Pairing) { C.freePairingStruct(pairing.cptr) } -func makePairing() *Pairing { - pairing := &Pairing{cptr: C.newPairingStruct()} +func makePairing(params *Params) *Pairing { + pairing := &Pairing{ + params: params, + cptr: C.newPairingStruct(), + } runtime.SetFinalizer(pairing, clearPairing) return pairing }