Subject: bug#31946: 27.0.50; The NSM should warn about more TLS problems

From: Andy Moreton <[email-masked]>
Date: Mon, 26 Aug 2019 23:56:06 +0100

On Mon 26 Aug 2019, Eli Zaretskii wrote:

>> From: Andy Moreton <[email-masked]>
>> Date: Mon, 26 Aug 2019 19:19:56 +0100
>> 
>> On Mon 26 Aug 2019, Eli Zaretskii wrote:
>> 
>> >> Agreed, but master built from commit 1071a4f still crashes in the same
>> >> way:
>> >
>> > Can you show a recipe?
>> 
>> 1) Delete ~/.emacs.d/network-security.data (to ensure NSM will query the user).
>> 2) Run "emacs -Q"
>> 3) "M-x list-packages", and at the NSM prompt, answer 'a' or 's' or 'd'.
>
> Looks like something is wrong with how I'm using gnutls_free when it
> comes from the DLL.  I need to look into that.

Found it I think. gnutls_free is a pointer of type gnutls_free_function,
so the value returned from GetProcAddress is a data pointer, not a
function address. Something like the following patch appears to work
i.e. no longer crashes with the recipe above.

If this is the right fix then we will need to add e.g. DEF_DLL_DATA and
LOAD_DLL_DATA macros for runtime import of data (and an equivalent to
get_proc_addr to use the right types for runtime data imports).

The patch also has "#undef gnutls_free" because gnutls.h also defines
gnutls_free as a macro, if GNUTLS_INTERNAL_BUILD is defined. For some
reason the MSYS2 maintainers add a patch to their build to define
GNUTLS_INTERNAL_BUILD unconditionally: see 0001-add-missing-define.patch
at <https://github.com/msys2/MINGW-packages/tree/master/mingw-w64-gnutls>.

diff --git a/src/gnutls.c b/src/gnutls.c
index 67d1fb9552..c4bce62869 100644
--- a/src/gnutls.c
+++ b/src/gnutls.c
@@ -140,6 +140,7 @@ DEF_DLL_FN (void, gnutls_dh_set_prime_bits,
 DEF_DLL_FN (int, gnutls_dh_get_prime_bits, (gnutls_session_t));
 DEF_DLL_FN (int, gnutls_error_is_fatal, (int));
 DEF_DLL_FN (int, gnutls_global_init, (void));
+#undef gnutls_free /* Also defined as a macro in gnutls.h */
 DEF_DLL_FN (void, gnutls_free, (void *));
 DEF_DLL_FN (void, gnutls_global_set_log_function, (gnutls_log_func));
 #  ifdef HAVE_GNUTLS3
@@ -1616,7 +1617,7 @@ DEFUN ("gnutls-format-certificate", Fgnutls_format_certificate,
   memset (out_buf, 0, (out.size + 1) * sizeof (char));
   memcpy (out_buf, out.data, out.size);
 
-  gnutls_free (out.data);
+  (*((gnutls_free_function *)gnutls_free)) (out.data);
   gnutls_x509_crt_deinit (crt);
 
   Lisp_Object result = build_string (out_buf);