Details
- Version
- 1.6.0
Event Timeline
It wasn't apparent to me until I looked at tests/gpg/t-encrypt.c that
gpgme_op_encrypt_sign expects an array of keys for the second parameter. It worked
when my code was straight C with a pointer to just a single key. In C++ I started
getting segfaults so I switched to an array.
gpgme_key_t keys[1] = {NULL};
gpgErr = gpgme_get_key(gpgCtx,to.c_str(),&keys[0],0);
It still segfaulted, further review, I THINK the array of keys needs to have one
blank key at the end else it may result in a buffer overrun in GPGME? Shouldn't
sizeof be used to determine the length of the array or something similar? Otherwise
the array would have to be at least 2 elements with the last element not a key so
the GPGME doesn't seg.
Process 12727 stopped
- thread #1: tid = 0x864b5, 0x00000001000107ea
libgpgme.11.dylib`gpgme_op_encrypt_sign(ctx=0x0000000100200850,
recp=0x00007fff5fbffa50, flags=GPGME_ENCRYPT_NO_ENCRYPT_TO,
plain=0x0000000100201000, cipher=0x0000000100200dc0) + 474 at encrypt-sign.c:168,
queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
frame #0: 0x00000001000107ea
libgpgme.11.dylib`gpgme_op_encrypt_sign(ctx=0x0000000100200850,
recp=0x00007fff5fbffa50, flags=GPGME_ENCRYPT_NO_ENCRYPT_TO,
plain=0x0000000100201000, cipher=0x0000000100200dc0) + 474 at encrypt-sign.c:168
165 166 while (recp[i]) 167 {
-> 168 TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i],
169 (recp[i]->subkeys && recp[i]->subkeys->fpr) ? 170 recp[i]->subkeys->fpr : "invalid"); 171 i++;
(lldb) bt
- thread #1: tid = 0x864b5, 0x00000001000107ea
libgpgme.11.dylib`gpgme_op_encrypt_sign(ctx=0x0000000100200850,
recp=0x00007fff5fbffa50, flags=GPGME_ENCRYPT_NO_ENCRYPT_TO,
plain=0x0000000100201000, cipher=0x0000000100200dc0) + 474 at encrypt-sign.c:168,
queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
- frame #0: 0x00000001000107ea
libgpgme.11.dylib`gpgme_op_encrypt_sign(ctx=0x0000000100200850,
recp=0x00007fff5fbffa50, flags=GPGME_ENCRYPT_NO_ENCRYPT_TO,
plain=0x0000000100201000, cipher=0x0000000100200dc0) + 474 at encrypt-sign.c:168
frame #1: 0x0000000100000b76
pgtalk`GPGWrapper::encryptAndSign(this=0x00007fff5fbffb30, message="This is a
test\n", to="044E9E1D78D510E4C798D3B803254F162CFF2601") + 166 at GPGWrapper.cpp:32
frame #2: 0x00000001000019c6 pgtalk`main(argc=1, argv=0x00007fff5fbffc38) + 486
at pgtalk.cpp:13
frame #3: 0x00007fff910ad5ad libdyld.dylib`start + 1 frame #4: 0x00007fff910ad5ad libdyld.dylib`start + 1
(lldb) quit
The manual states:
RECP must be a ‘NULL’-terminated array of keys. The user must keep references for all keys during the whole duration of the call (but see ‘gpgme_op_encrypt_start’ for the requirements with the asynchronous variant).
What you call a blank key is a NULL stored in the array. A common way to
allocate such an array is by using
gpgme_key_t *keys = calloc(nkeys+1, sizeof *keys);
and then fill the array with the keys: If you don't put keys into the array
(i.e.NULL as first item) the fucntion retruns GPG_ERR_INV_VALUE.
Regarding your problem with gpgme_get_key: You need to pass a variabale of type
gpgme_key_t to that function. The fucntion allocates a new key objects and
_stores_ it at that variable:
gpgme_key_t akey; err = gpgme_get_key (ctx, fingerprint, &akey, 0); .. processing goes here ... gpgme_key_unref (akey);
Note that on error NULL is stored at AKEY and thus gpgme_key_unref can be called
in any case.
Thank you! All set.
On Friday, April 15, 2016, Werner Koch via BTS <gnupg@bugs.g10code.com>
wrote:
Werner Koch <wk@gnupg.org <javascript:;>> added the comment:
The manual states:
RECP must be a ‘NULL’-terminated array of keys. The user must keep references for all keys during the whole duration of the call (but see ‘gpgme_op_encrypt_start’ for the requirements with the asynchronous variant).What you call a blank key is a NULL stored in the array. A common way to
allocate such an array is by usinggpgme_key_t *keys = calloc(nkeys+1, sizeof *keys);and then fill the array with the keys: If you don't put keys into the
array
(i.e.NULL as first item) the fucntion retruns GPG_ERR_INV_VALUE.Regarding your problem with gpgme_get_key: You need to pass a variabale
of type
gpgme_key_t to that function. The fucntion allocates a new key objects and
_stores_ it at that variable:gpgme_key_t akey; err = gpgme_get_key (ctx, fingerprint, &akey, 0); .. processing goes here ... gpgme_key_unref (akey);Note that on error NULL is stored at AKEY and thus gpgme_key_unref can be
called
in any case.
category: -> gpgme
topic: +nobug
GnuPG's BTS <gnupg@bugs.g10code.com <javascript:;>>
<T2304>