Subject: Re: bug#25061: consider adding %COMPAT to default gnutls priority string

From: Andy Moreton <[email-masked]>
Date: Wed, 20 Dec 2017 16:38:20 +0000

On Wed 20 Dec 2017, Eli Zaretskii wrote:

>> From: Andy Moreton <[email-masked]>
>> Date: Wed, 20 Dec 2017 12:54:45 +0000
>> 
>> diff --git a/src/gnutls.c b/src/gnutls.c
>> index 8db201ae83..f2b078d964 100644
>> --- a/src/gnutls.c
>> +++ b/src/gnutls.c
>> @@ -238,6 +238,7 @@ DEF_DLL_FN (int, gnutls_hash, (gnutls_hash_hd_t, const void *, size_t));
>>  DEF_DLL_FN (void, gnutls_hash_deinit, (gnutls_hash_hd_t, void *));
>>  DEF_DLL_FN (void, gnutls_hash_output, (gnutls_hash_hd_t, void *));
>>  #  endif        /* HAVE_GNUTLS3 */
>> +DEF_DLL_FN (const char *, gnutls_ext_get_name, (unsigned int));
>> 
>> 
>>  static bool
>> @@ -357,6 +358,7 @@ init_gnutls_functions (void)
>>    LOAD_DLL_FN (library, gnutls_hash_deinit);
>>    LOAD_DLL_FN (library, gnutls_hash_output);
>>  #  endif        /* HAVE_GNUTLS3 */
>> +  LOAD_DLL_FN (library, gnutls_ext_get_name);
>> 
>>    max_log_level = global_gnutls_log_level;
>> 
>> @@ -470,6 +472,8 @@ init_gnutls_functions (void)
>>  #  define gnutls_hash_deinit fn_gnutls_hash_deinit
>>  #  define gnutls_hash_output fn_gnutls_hash_output
>>  #  endif        /* HAVE_GNUTLS3 */
>> +#  define gnutls_ext_get_name fn_gnutls_ext_get_name
>
> Thanks, but this means Emacs will now refuse to load GnuTLS on systems
> that have version 3.4 or older of the library, right?  If so, I think
> the loading and the use of the function should be conditioned by an
> appropriate preprocessor directive to compile that code only for
> 3.5.X.

Agreed. This version also fixes a bug in the previous version, where
the capabilities stored in Vlibrary_cache were not updated properly.

diff --git a/src/gnutls.c b/src/gnutls.c
index 8db201ae83..48ea25397a 100644
--- a/src/gnutls.c
+++ b/src/gnutls.c
@@ -46,6 +46,10 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 # define HAVE_GNUTLS_MAC_GET_NONCE_SIZE
 #endif
 
+#if GNUTLS_VERSION_NUMBER >= 0x030501
+# define HAVE_GNUTLS_EXT_GET_NAME
+#endif
+
 #ifdef HAVE_GNUTLS
 
 # ifdef WINDOWSNT
@@ -237,6 +241,9 @@ DEF_DLL_FN (int, gnutls_hash_get_len, (gnutls_digest_algorithm_t));
 DEF_DLL_FN (int, gnutls_hash, (gnutls_hash_hd_t, const void *, size_t));
 DEF_DLL_FN (void, gnutls_hash_deinit, (gnutls_hash_hd_t, void *));
 DEF_DLL_FN (void, gnutls_hash_output, (gnutls_hash_hd_t, void *));
+#   ifdef HAVE_GNUTLS_EXT_GET_NAME
+DEF_DLL_FN (const char *, gnutls_ext_get_name, (unsigned int));
+#   endif
 #  endif	 /* HAVE_GNUTLS3 */

@@ -356,6 +363,9 @@ init_gnutls_functions (void)
   LOAD_DLL_FN (library, gnutls_hash);
   LOAD_DLL_FN (library, gnutls_hash_deinit);
   LOAD_DLL_FN (library, gnutls_hash_output);
+#   ifdef HAVE_GNUTLS_EXT_GET_NAME
+  LOAD_DLL_FN (library, gnutls_ext_get_name);
+#   endif
 #  endif	 /* HAVE_GNUTLS3 */
 
   max_log_level = global_gnutls_log_level;
@@ -469,8 +479,12 @@ init_gnutls_functions (void)
 #  define gnutls_hash fn_gnutls_hash
 #  define gnutls_hash_deinit fn_gnutls_hash_deinit
 #  define gnutls_hash_output fn_gnutls_hash_output
+#   ifdef HAVE_GNUTLS_EXT_GET_NAME
+#    define gnutls_ext_get_name fn_gnutls_ext_get_name
+#   endif
 #  endif	 /* HAVE_GNUTLS3 */
 
+
 /* This wrapper is called from fns.c, which doesn't know about the
    LOAD_DLL_FN stuff above.  */
 int
@@ -2425,6 +2439,18 @@ Any GnuTLS extension with ID up to 100
 
 #ifdef HAVE_GNUTLS
 
+# ifdef WINDOWSNT
+  Lisp_Object found = Fassq (Qgnutls, Vlibrary_cache);
+  if (CONSP (found))
+    return XCDR (found);
+
+  /* Load the GnuTLS DLL and find exported functions.  The external
+     library cache is updated after the capabilities have been
+     determined.  */
+  if (!init_gnutls_functions ())
+    return Qnil;
+# endif /* WINDOWSNT */
+
   capabilities = Fcons (intern("gnutls"), capabilities);
 
 # ifdef HAVE_GNUTLS3
@@ -2437,8 +2463,8 @@ Any GnuTLS extension with ID up to 100
 #  endif
 
   capabilities = Fcons (intern("macs"), capabilities);
-# endif	  /* HAVE_GNUTLS3 */
 
+#  ifdef HAVE_GNUTLS_EXT_GET_NAME
   for (unsigned int ext=0; ext < 100; ext++)
     {
       const char* name = gnutls_ext_get_name(ext);
@@ -2447,18 +2473,11 @@ Any GnuTLS extension with ID up to 100
           capabilities = Fcons (intern(name), capabilities);
         }
     }
+#  endif
+# endif	  /* HAVE_GNUTLS3 */
 
 # ifdef WINDOWSNT
-  Lisp_Object found = Fassq (Qgnutls, Vlibrary_cache);
-  if (CONSP (found))
-    return XCDR (found);
-  else
-    {
-      Lisp_Object status;
-      status = init_gnutls_functions () ? capabilities : Qnil;
-      Vlibrary_cache = Fcons (Fcons (Qgnutls, status), Vlibrary_cache);
-      return status;
-    }
+  Vlibrary_cache = Fcons (Fcons (Qgnutls, capabilities), Vlibrary_cache);
 # endif /* WINDOWSNT */
 #endif	/* HAVE_GNUTLS */