summaryrefslogtreecommitdiff
path: root/vendor/github.com/mtrmac/gpgme/gpgme.go
diff options
context:
space:
mode:
authorValentin Rothberg <rothberg@redhat.com>2020-02-03 16:09:04 +0100
committerValentin Rothberg <rothberg@redhat.com>2020-02-05 09:55:50 +0100
commit801977b40d8500ff68cf5a6facd82f035735076a (patch)
tree3e67e319511dce7b84a6ab16dfa8ecc3d8ec5e7a /vendor/github.com/mtrmac/gpgme/gpgme.go
parent5092c078ec635c9f1598989b27ccf53369b3cf2b (diff)
downloadpodman-801977b40d8500ff68cf5a6facd82f035735076a.tar.gz
podman-801977b40d8500ff68cf5a6facd82f035735076a.tar.bz2
podman-801977b40d8500ff68cf5a6facd82f035735076a.zip
vendor github.com/containers/image/v5@v5.2.0
See release notes: https://github.com/containers/image/releases/tag/v5.2.0 Fixes: #4877 Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
Diffstat (limited to 'vendor/github.com/mtrmac/gpgme/gpgme.go')
-rw-r--r--vendor/github.com/mtrmac/gpgme/gpgme.go346
1 files changed, 275 insertions, 71 deletions
diff --git a/vendor/github.com/mtrmac/gpgme/gpgme.go b/vendor/github.com/mtrmac/gpgme/gpgme.go
index 20aad737c..c19b9aebc 100644
--- a/vendor/github.com/mtrmac/gpgme/gpgme.go
+++ b/vendor/github.com/mtrmac/gpgme/gpgme.go
@@ -7,7 +7,6 @@ package gpgme
// #include <gpgme.h>
// #include "go_gpgme.h"
import "C"
-
import (
"fmt"
"io"
@@ -48,9 +47,8 @@ const (
ProtocolAssuan Protocol = C.GPGME_PROTOCOL_ASSUAN
ProtocolG13 Protocol = C.GPGME_PROTOCOL_G13
ProtocolUIServer Protocol = C.GPGME_PROTOCOL_UISERVER
- // ProtocolSpawn Protocol = C.GPGME_PROTOCOL_SPAWN // Unavailable in 1.4.3
- ProtocolDefault Protocol = C.GPGME_PROTOCOL_DEFAULT
- ProtocolUnknown Protocol = C.GPGME_PROTOCOL_UNKNOWN
+ ProtocolDefault Protocol = C.GPGME_PROTOCOL_DEFAULT
+ ProtocolUnknown Protocol = C.GPGME_PROTOCOL_UNKNOWN
)
type PinEntryMode int
@@ -70,7 +68,6 @@ const (
EncryptNoEncryptTo EncryptFlag = C.GPGME_ENCRYPT_NO_ENCRYPT_TO
EncryptPrepare EncryptFlag = C.GPGME_ENCRYPT_PREPARE
EncryptExceptSign EncryptFlag = C.GPGME_ENCRYPT_EXPECT_SIGN
- // EncryptNoCompress EncryptFlag = C.GPGME_ENCRYPT_NO_COMPRESS // Unavailable in 1.4.3
)
type HashAlgo int
@@ -84,7 +81,6 @@ const (
KeyListModeExtern KeyListMode = C.GPGME_KEYLIST_MODE_EXTERN
KeyListModeSigs KeyListMode = C.GPGME_KEYLIST_MODE_SIGS
KeyListModeSigNotations KeyListMode = C.GPGME_KEYLIST_MODE_SIG_NOTATIONS
- // KeyListModeWithSecret KeyListMode = C.GPGME_KEYLIST_MODE_WITH_SECRET // Unavailable in 1.4.3
KeyListModeEphemeral KeyListMode = C.GPGME_KEYLIST_MODE_EPHEMERAL
KeyListModeModeValidate KeyListMode = C.GPGME_KEYLIST_MODE_VALIDATE
)
@@ -168,39 +164,60 @@ func EngineCheckVersion(p Protocol) error {
}
type EngineInfo struct {
- info C.gpgme_engine_info_t
+ next *EngineInfo
+ protocol Protocol
+ fileName string
+ homeDir string
+ version string
+ requiredVersion string
}
-func (e *EngineInfo) Next() *EngineInfo {
- if e.info.next == nil {
- return nil
+func copyEngineInfo(info C.gpgme_engine_info_t) *EngineInfo {
+ res := &EngineInfo{
+ next: nil,
+ protocol: Protocol(info.protocol),
+ fileName: C.GoString(info.file_name),
+ homeDir: C.GoString(info.home_dir),
+ version: C.GoString(info.version),
+ requiredVersion: C.GoString(info.req_version),
+ }
+ if info.next != nil {
+ res.next = copyEngineInfo(info.next)
}
- return &EngineInfo{info: e.info.next}
+ return res
+}
+
+func (e *EngineInfo) Next() *EngineInfo {
+ return e.next
}
func (e *EngineInfo) Protocol() Protocol {
- return Protocol(e.info.protocol)
+ return e.protocol
}
func (e *EngineInfo) FileName() string {
- return C.GoString(e.info.file_name)
+ return e.fileName
}
func (e *EngineInfo) Version() string {
- return C.GoString(e.info.version)
+ return e.version
}
func (e *EngineInfo) RequiredVersion() string {
- return C.GoString(e.info.req_version)
+ return e.requiredVersion
}
func (e *EngineInfo) HomeDir() string {
- return C.GoString(e.info.home_dir)
+ return e.homeDir
}
func GetEngineInfo() (*EngineInfo, error) {
- info := &EngineInfo{}
- return info, handleError(C.gpgme_get_engine_info(&info.info))
+ var cInfo C.gpgme_engine_info_t
+ err := handleError(C.gpgme_get_engine_info(&cInfo))
+ if err != nil {
+ return nil, err
+ }
+ return copyEngineInfo(cInfo), nil // It is up to the caller not to invalidate cInfo concurrently until this is done.
}
func SetEngineInfo(proto Protocol, fileName, homeDir string) error {
@@ -261,9 +278,9 @@ type Context struct {
KeyError error
callback Callback
- cbc uintptr
+ cbc uintptr // WARNING: Call runtime.KeepAlive(c) after ANY use of c.cbc in C (typically via c.ctx)
- ctx C.gpgme_ctx_t
+ ctx C.gpgme_ctx_t // WARNING: Call runtime.KeepAlive(c) after ANY passing of c.ctx to C
}
func New() (*Context, error) {
@@ -281,49 +298,68 @@ func (c *Context) Release() {
callbackDelete(c.cbc)
}
C.gpgme_release(c.ctx)
+ runtime.KeepAlive(c)
c.ctx = nil
}
func (c *Context) SetArmor(yes bool) {
C.gpgme_set_armor(c.ctx, cbool(yes))
+ runtime.KeepAlive(c)
}
func (c *Context) Armor() bool {
- return C.gpgme_get_armor(c.ctx) != 0
+ res := C.gpgme_get_armor(c.ctx) != 0
+ runtime.KeepAlive(c)
+ return res
}
func (c *Context) SetTextMode(yes bool) {
C.gpgme_set_textmode(c.ctx, cbool(yes))
+ runtime.KeepAlive(c)
}
func (c *Context) TextMode() bool {
- return C.gpgme_get_textmode(c.ctx) != 0
+ res := C.gpgme_get_textmode(c.ctx) != 0
+ runtime.KeepAlive(c)
+ return res
}
func (c *Context) SetProtocol(p Protocol) error {
- return handleError(C.gpgme_set_protocol(c.ctx, C.gpgme_protocol_t(p)))
+ err := handleError(C.gpgme_set_protocol(c.ctx, C.gpgme_protocol_t(p)))
+ runtime.KeepAlive(c)
+ return err
}
func (c *Context) Protocol() Protocol {
- return Protocol(C.gpgme_get_protocol(c.ctx))
+ res := Protocol(C.gpgme_get_protocol(c.ctx))
+ runtime.KeepAlive(c)
+ return res
}
func (c *Context) SetKeyListMode(m KeyListMode) error {
- return handleError(C.gpgme_set_keylist_mode(c.ctx, C.gpgme_keylist_mode_t(m)))
+ err := handleError(C.gpgme_set_keylist_mode(c.ctx, C.gpgme_keylist_mode_t(m)))
+ runtime.KeepAlive(c)
+ return err
}
func (c *Context) KeyListMode() KeyListMode {
- return KeyListMode(C.gpgme_get_keylist_mode(c.ctx))
+ res := KeyListMode(C.gpgme_get_keylist_mode(c.ctx))
+ runtime.KeepAlive(c)
+ return res
}
// Unavailable in 1.3.2:
// func (c *Context) SetPinEntryMode(m PinEntryMode) error {
-// return handleError(C.gpgme_set_pinentry_mode(c.ctx, C.gpgme_pinentry_mode_t(m)))
+// err := handleError(C.gpgme_set_pinentry_mode(c.ctx, C.gpgme_pinentry_mode_t(m)))
+// runtime.KeepAlive(c)
+// return err
// }
// Unavailable in 1.3.2:
// func (c *Context) PinEntryMode() PinEntryMode {
-// return PinEntryMode(C.gpgme_get_pinentry_mode(c.ctx))
+// res := PinEntryMode(C.gpgme_get_pinentry_mode(c.ctx))
+// runtime.KeepAlive(c)
+// return res
// }
func (c *Context) SetCallback(callback Callback) error {
@@ -340,11 +376,17 @@ func (c *Context) SetCallback(callback Callback) error {
c.cbc = 0
_, err = C.gogpgme_set_passphrase_cb(c.ctx, nil, 0)
}
+ runtime.KeepAlive(c)
return err
}
func (c *Context) EngineInfo() *EngineInfo {
- return &EngineInfo{info: C.gpgme_ctx_get_engine_info(c.ctx)}
+ cInfo := C.gpgme_ctx_get_engine_info(c.ctx)
+ runtime.KeepAlive(c)
+ // NOTE: c must be live as long as we are accessing cInfo.
+ res := copyEngineInfo(cInfo)
+ runtime.KeepAlive(c) // for accesses to cInfo
+ return res
}
func (c *Context) SetEngineInfo(proto Protocol, fileName, homeDir string) error {
@@ -357,19 +399,23 @@ func (c *Context) SetEngineInfo(proto Protocol, fileName, homeDir string) error
chome = C.CString(homeDir)
defer C.free(unsafe.Pointer(chome))
}
- return handleError(C.gpgme_ctx_set_engine_info(c.ctx, C.gpgme_protocol_t(proto), cfn, chome))
+ err := handleError(C.gpgme_ctx_set_engine_info(c.ctx, C.gpgme_protocol_t(proto), cfn, chome))
+ runtime.KeepAlive(c)
+ return err
}
func (c *Context) KeyListStart(pattern string, secretOnly bool) error {
cpattern := C.CString(pattern)
defer C.free(unsafe.Pointer(cpattern))
- err := C.gpgme_op_keylist_start(c.ctx, cpattern, cbool(secretOnly))
- return handleError(err)
+ err := handleError(C.gpgme_op_keylist_start(c.ctx, cpattern, cbool(secretOnly)))
+ runtime.KeepAlive(c)
+ return err
}
func (c *Context) KeyListNext() bool {
c.Key = newKey()
err := handleError(C.gpgme_op_keylist_next(c.ctx, &c.Key.k))
+ runtime.KeepAlive(c) // implies runtime.KeepAlive(c.Key)
if err != nil {
if e, ok := err.(Error); ok && e.Code() == ErrorEOF {
c.KeyError = nil
@@ -383,7 +429,9 @@ func (c *Context) KeyListNext() bool {
}
func (c *Context) KeyListEnd() error {
- return handleError(C.gpgme_op_keylist_end(c.ctx))
+ err := handleError(C.gpgme_op_keylist_end(c.ctx))
+ runtime.KeepAlive(c)
+ return err
}
func (c *Context) GetKey(fingerprint string, secret bool) (*Key, error) {
@@ -391,7 +439,11 @@ func (c *Context) GetKey(fingerprint string, secret bool) (*Key, error) {
cfpr := C.CString(fingerprint)
defer C.free(unsafe.Pointer(cfpr))
err := handleError(C.gpgme_get_key(c.ctx, cfpr, &key.k, cbool(secret)))
- if e, ok := err.(Error); key.k == nil && ok && e.Code() == ErrorEOF {
+ runtime.KeepAlive(c)
+ runtime.KeepAlive(key)
+ keyKIsNil := key.k == nil
+ runtime.KeepAlive(key)
+ if e, ok := err.(Error); keyKIsNil && ok && e.Code() == ErrorEOF {
return nil, fmt.Errorf("key %q not found", fingerprint)
}
if err != nil {
@@ -401,11 +453,19 @@ func (c *Context) GetKey(fingerprint string, secret bool) (*Key, error) {
}
func (c *Context) Decrypt(ciphertext, plaintext *Data) error {
- return handleError(C.gpgme_op_decrypt(c.ctx, ciphertext.dh, plaintext.dh))
+ err := handleError(C.gpgme_op_decrypt(c.ctx, ciphertext.dh, plaintext.dh))
+ runtime.KeepAlive(c)
+ runtime.KeepAlive(ciphertext)
+ runtime.KeepAlive(plaintext)
+ return err
}
func (c *Context) DecryptVerify(ciphertext, plaintext *Data) error {
- return handleError(C.gpgme_op_decrypt_verify(c.ctx, ciphertext.dh, plaintext.dh))
+ err := handleError(C.gpgme_op_decrypt_verify(c.ctx, ciphertext.dh, plaintext.dh))
+ runtime.KeepAlive(c)
+ runtime.KeepAlive(ciphertext)
+ runtime.KeepAlive(plaintext)
+ return err
}
type Signature struct {
@@ -432,10 +492,20 @@ func (c *Context) Verify(sig, signedText, plain *Data) (string, []Signature, err
plainPtr = plain.dh
}
err := handleError(C.gpgme_op_verify(c.ctx, sig.dh, signedTextPtr, plainPtr))
+ runtime.KeepAlive(c)
+ runtime.KeepAlive(sig)
+ if signedText != nil {
+ runtime.KeepAlive(signedText)
+ }
+ if plain != nil {
+ runtime.KeepAlive(plain)
+ }
if err != nil {
return "", nil, err
}
res := C.gpgme_op_verify_result(c.ctx)
+ runtime.KeepAlive(c)
+ // NOTE: c must be live as long as we are accessing res.
sigs := []Signature{}
for s := res.signatures; s != nil; s = s.next {
sig := Signature{
@@ -455,7 +525,9 @@ func (c *Context) Verify(sig, signedText, plain *Data) (string, []Signature, err
}
sigs = append(sigs, sig)
}
- return C.GoString(res.file_name), sigs, nil
+ fileName := C.GoString(res.file_name)
+ runtime.KeepAlive(c) // for all accesses to res above
+ return fileName, sigs, nil
}
func (c *Context) Encrypt(recipients []*Key, flags EncryptFlag, plaintext, ciphertext *Data) error {
@@ -467,18 +539,116 @@ func (c *Context) Encrypt(recipients []*Key, flags EncryptFlag, plaintext, ciphe
*ptr = recipients[i].k
}
err := C.gpgme_op_encrypt(c.ctx, (*C.gpgme_key_t)(recp), C.gpgme_encrypt_flags_t(flags), plaintext.dh, ciphertext.dh)
+ runtime.KeepAlive(c)
+ runtime.KeepAlive(recipients)
+ runtime.KeepAlive(plaintext)
+ runtime.KeepAlive(ciphertext)
return handleError(err)
}
func (c *Context) Sign(signers []*Key, plain, sig *Data, mode SigMode) error {
C.gpgme_signers_clear(c.ctx)
+ runtime.KeepAlive(c)
for _, k := range signers {
- if err := handleError(C.gpgme_signers_add(c.ctx, k.k)); err != nil {
+ err := handleError(C.gpgme_signers_add(c.ctx, k.k))
+ runtime.KeepAlive(c)
+ runtime.KeepAlive(k)
+ if err != nil {
C.gpgme_signers_clear(c.ctx)
+ runtime.KeepAlive(c)
return err
}
}
- return handleError(C.gpgme_op_sign(c.ctx, plain.dh, sig.dh, C.gpgme_sig_mode_t(mode)))
+ err := handleError(C.gpgme_op_sign(c.ctx, plain.dh, sig.dh, C.gpgme_sig_mode_t(mode)))
+ runtime.KeepAlive(c)
+ runtime.KeepAlive(plain)
+ runtime.KeepAlive(sig)
+ return err
+}
+
+type AssuanDataCallback func(data []byte) error
+type AssuanInquireCallback func(name, args string) error
+type AssuanStatusCallback func(status, args string) error
+
+// AssuanSend sends a raw Assuan command to gpg-agent
+func (c *Context) AssuanSend(
+ cmd string,
+ data AssuanDataCallback,
+ inquiry AssuanInquireCallback,
+ status AssuanStatusCallback,
+) error {
+ var operr C.gpgme_error_t
+
+ dataPtr := callbackAdd(&data)
+ inquiryPtr := callbackAdd(&inquiry)
+ statusPtr := callbackAdd(&status)
+ cmdCStr := C.CString(cmd)
+ defer C.free(unsafe.Pointer(cmdCStr))
+ err := C.gogpgme_op_assuan_transact_ext(
+ c.ctx,
+ cmdCStr,
+ C.uintptr_t(dataPtr),
+ C.uintptr_t(inquiryPtr),
+ C.uintptr_t(statusPtr),
+ &operr,
+ )
+ runtime.KeepAlive(c)
+
+ if handleError(operr) != nil {
+ return handleError(operr)
+ }
+ return handleError(err)
+}
+
+//export gogpgme_assuan_data_callback
+func gogpgme_assuan_data_callback(handle unsafe.Pointer, data unsafe.Pointer, datalen C.size_t) C.gpgme_error_t {
+ c := callbackLookup(uintptr(handle)).(*AssuanDataCallback)
+ if *c == nil {
+ return 0
+ }
+ (*c)(C.GoBytes(data, C.int(datalen)))
+ return 0
+}
+
+//export gogpgme_assuan_inquiry_callback
+func gogpgme_assuan_inquiry_callback(handle unsafe.Pointer, cName *C.char, cArgs *C.char) C.gpgme_error_t {
+ name := C.GoString(cName)
+ args := C.GoString(cArgs)
+ c := callbackLookup(uintptr(handle)).(*AssuanInquireCallback)
+ if *c == nil {
+ return 0
+ }
+ (*c)(name, args)
+ return 0
+}
+
+//export gogpgme_assuan_status_callback
+func gogpgme_assuan_status_callback(handle unsafe.Pointer, cStatus *C.char, cArgs *C.char) C.gpgme_error_t {
+ status := C.GoString(cStatus)
+ args := C.GoString(cArgs)
+ c := callbackLookup(uintptr(handle)).(*AssuanStatusCallback)
+ if *c == nil {
+ return 0
+ }
+ (*c)(status, args)
+ return 0
+}
+
+// ExportModeFlags defines how keys are exported from Export
+type ExportModeFlags uint
+
+const (
+ ExportModeExtern ExportModeFlags = C.GPGME_EXPORT_MODE_EXTERN
+ ExportModeMinimal ExportModeFlags = C.GPGME_EXPORT_MODE_MINIMAL
+)
+
+func (c *Context) Export(pattern string, mode ExportModeFlags, data *Data) error {
+ pat := C.CString(pattern)
+ defer C.free(unsafe.Pointer(pat))
+ err := handleError(C.gpgme_op_export(c.ctx, pat, C.gpgme_export_mode_t(mode), data.dh))
+ runtime.KeepAlive(c)
+ runtime.KeepAlive(data)
+ return err
}
// ImportStatusFlags describes the type of ImportStatus.Status. The C API in gpgme.h simply uses "unsigned".
@@ -517,10 +687,14 @@ type ImportResult struct {
func (c *Context) Import(keyData *Data) (*ImportResult, error) {
err := handleError(C.gpgme_op_import(c.ctx, keyData.dh))
+ runtime.KeepAlive(c)
+ runtime.KeepAlive(keyData)
if err != nil {
return nil, err
}
res := C.gpgme_op_import_result(c.ctx)
+ runtime.KeepAlive(c)
+ // NOTE: c must be live as long as we are accessing res.
imports := []ImportStatus{}
for s := res.imports; s != nil; s = s.next {
imports = append(imports, ImportStatus{
@@ -529,7 +703,7 @@ func (c *Context) Import(keyData *Data) (*ImportResult, error) {
Status: ImportStatusFlags(s.status),
})
}
- return &ImportResult{
+ importResult := &ImportResult{
Considered: int(res.considered),
NoUserID: int(res.no_user_id),
Imported: int(res.imported),
@@ -544,11 +718,13 @@ func (c *Context) Import(keyData *Data) (*ImportResult, error) {
SecretUnchanged: int(res.secret_unchanged),
NotImported: int(res.not_imported),
Imports: imports,
- }, nil
+ }
+ runtime.KeepAlive(c) // for all accesses to res above
+ return importResult, nil
}
type Key struct {
- k C.gpgme_key_t
+ k C.gpgme_key_t // WARNING: Call Runtime.KeepAlive(k) after ANY passing of k.k to C
}
func newKey() *Key {
@@ -559,85 +735,122 @@ func newKey() *Key {
func (k *Key) Release() {
C.gpgme_key_release(k.k)
+ runtime.KeepAlive(k)
k.k = nil
}
func (k *Key) Revoked() bool {
- return C.key_revoked(k.k) != 0
+ res := C.key_revoked(k.k) != 0
+ runtime.KeepAlive(k)
+ return res
}
func (k *Key) Expired() bool {
- return C.key_expired(k.k) != 0
+ res := C.key_expired(k.k) != 0
+ runtime.KeepAlive(k)
+ return res
}
func (k *Key) Disabled() bool {
- return C.key_disabled(k.k) != 0
+ res := C.key_disabled(k.k) != 0
+ runtime.KeepAlive(k)
+ return res
}
func (k *Key) Invalid() bool {
- return C.key_invalid(k.k) != 0
+ res := C.key_invalid(k.k) != 0
+ runtime.KeepAlive(k)
+ return res
}
func (k *Key) CanEncrypt() bool {
- return C.key_can_encrypt(k.k) != 0
+ res := C.key_can_encrypt(k.k) != 0
+ runtime.KeepAlive(k)
+ return res
}
func (k *Key) CanSign() bool {
- return C.key_can_sign(k.k) != 0
+ res := C.key_can_sign(k.k) != 0
+ runtime.KeepAlive(k)
+ return res
}
func (k *Key) CanCertify() bool {
- return C.key_can_certify(k.k) != 0
+ res := C.key_can_certify(k.k) != 0
+ runtime.KeepAlive(k)
+ return res
}
func (k *Key) Secret() bool {
- return C.key_secret(k.k) != 0
+ res := C.key_secret(k.k) != 0
+ runtime.KeepAlive(k)
+ return res
}
func (k *Key) CanAuthenticate() bool {
- return C.key_can_authenticate(k.k) != 0
+ res := C.key_can_authenticate(k.k) != 0
+ runtime.KeepAlive(k)
+ return res
}
func (k *Key) IsQualified() bool {
- return C.key_is_qualified(k.k) != 0
+ res := C.key_is_qualified(k.k) != 0
+ runtime.KeepAlive(k)
+ return res
}
func (k *Key) Protocol() Protocol {
- return Protocol(k.k.protocol)
+ res := Protocol(k.k.protocol)
+ runtime.KeepAlive(k)
+ return res
}
func (k *Key) IssuerSerial() string {
- return C.GoString(k.k.issuer_serial)
+ res := C.GoString(k.k.issuer_serial)
+ runtime.KeepAlive(k)
+ return res
}
func (k *Key) IssuerName() string {
- return C.GoString(k.k.issuer_name)
+ res := C.GoString(k.k.issuer_name)
+ runtime.KeepAlive(k)
+ return res
}
func (k *Key) ChainID() string {
- return C.GoString(k.k.chain_id)
+ res := C.GoString(k.k.chain_id)
+ runtime.KeepAlive(k)
+ return res
}
func (k *Key) OwnerTrust() Validity {
- return Validity(k.k.owner_trust)
+ res := Validity(k.k.owner_trust)
+ runtime.KeepAlive(k)
+ return res
}
func (k *Key) SubKeys() *SubKey {
- if k.k.subkeys == nil {
+ subKeys := k.k.subkeys
+ runtime.KeepAlive(k)
+ if subKeys == nil {
return nil
}
- return &SubKey{k: k.k.subkeys, parent: k}
+ return &SubKey{k: subKeys, parent: k} // The parent: k reference ensures subKeys remains valid
}
func (k *Key) UserIDs() *UserID {
- if k.k.uids == nil {
+ uids := k.k.uids
+ runtime.KeepAlive(k)
+ if uids == nil {
return nil
}
- return &UserID{u: k.k.uids, parent: k}
+ return &UserID{u: uids, parent: k} // The parent: k reference ensures uids remains valid
}
func (k *Key) KeyListMode() KeyListMode {
- return KeyListMode(k.k.keylist_mode)
+ res := KeyListMode(k.k.keylist_mode)
+ runtime.KeepAlive(k)
+ return res
}
type SubKey struct {
@@ -737,12 +950,3 @@ func (u *UserID) Comment() string {
func (u *UserID) Email() string {
return C.GoString(u.u.email)
}
-
-// This is somewhat of a horrible hack. We need to unset GPG_AGENT_INFO so that gpgme does not pass --use-agent to GPG.
-// os.Unsetenv should be enough, but that only calls the underlying C library (which gpgme uses) if cgo is involved
-// - and cgo can't be used in tests. So, provide this helper for test initialization.
-func unsetenvGPGAgentInfo() {
- v := C.CString("GPG_AGENT_INFO")
- defer C.free(unsafe.Pointer(v))
- C.unsetenv(v)
-}