+2014-12-28 Paul Eggert <eggert@Penguin.CS.UCLA.EDU>
+
+ Port memory-full checking to GnuTLS 3.3
+ Instead of using gnutls_global_set_mem_functions, check every call
+ to a GnuTLS function that might return an indication of memory
+ exhaustion. Suggested by Dmitry Antipov in:
+ http://lists.gnu.org/archive/html/emacs-devel/2014-12/msg02056.html
+ * gnutls.c (gnutls_global_set_mem_functions) [WINDOWSNT]: Remove.
+ (init_gnutls_functions): Do not load gnutls_global_set_mem_functions.
+ (fn_gnutls_global_set_mem_functions) [!WINDOWSNT]: Remove.
+ All uses removed.
+ (check_memory_full): New function.
+ (emacs_gnutls_handshake, emacs_gnutls_handle_error)
+ (gnutls_make_error, Fgnutls_boot): Use it.
+ (emacs_gnutls_global_init): Avoid gnutls_global_set_mem_functions.
+
2014-12-25 Eli Zaretskii <eliz@gnu.org>
* xdisp.c (set_iterator_to_next) <GET_FROM_STRING>: Limit search in
DEF_GNUTLS_FN (void, gnutls_global_set_audit_log_function, (gnutls_audit_log_func));
#endif
DEF_GNUTLS_FN (void, gnutls_global_set_log_level, (int));
-DEF_GNUTLS_FN (void, gnutls_global_set_mem_functions,
- (gnutls_alloc_function, gnutls_alloc_function,
- gnutls_is_secure_function, gnutls_realloc_function,
- gnutls_free_function));
DEF_GNUTLS_FN (int, gnutls_handshake, (gnutls_session_t));
DEF_GNUTLS_FN (int, gnutls_init, (gnutls_session_t *, unsigned int));
DEF_GNUTLS_FN (int, gnutls_priority_set_direct,
LOAD_GNUTLS_FN (library, gnutls_global_set_audit_log_function);
#endif
LOAD_GNUTLS_FN (library, gnutls_global_set_log_level);
- LOAD_GNUTLS_FN (library, gnutls_global_set_mem_functions);
LOAD_GNUTLS_FN (library, gnutls_handshake);
LOAD_GNUTLS_FN (library, gnutls_init);
LOAD_GNUTLS_FN (library, gnutls_priority_set_direct);
#define fn_gnutls_global_set_audit_log_function gnutls_global_set_audit_log_function
#endif
#define fn_gnutls_global_set_log_level gnutls_global_set_log_level
-#define fn_gnutls_global_set_mem_functions gnutls_global_set_mem_functions
#define fn_gnutls_handshake gnutls_handshake
#define fn_gnutls_init gnutls_init
#define fn_gnutls_priority_set_direct gnutls_priority_set_direct
#endif /* !WINDOWSNT */
\f
+/* Report memory exhaustion if ERR is an out-of-memory indication. */
+static void
+check_memory_full (int err)
+{
+ /* When GnuTLS exhausts memory, it doesn't say how much memory it
+ asked for, so tell the Emacs allocator that GnuTLS asked for no
+ bytes. This isn't accurate, but it's good enough. */
+ if (err == GNUTLS_E_MEMORY_ERROR)
+ memory_full (0);
+}
+
#ifdef HAVE_GNUTLS3
/* Function to log a simple audit message. */
static void
}
else
{
- fn_gnutls_alert_send_appropriate (state, ret);
+ check_memory_full (fn_gnutls_alert_send_appropriate (state, ret));
}
return ret;
}
if (err >= 0)
return 1;
+ check_memory_full (err);
+
max_log_level = global_gnutls_log_level;
/* TODO: use gnutls-error-fatalp and gnutls-error-string. */
return Qgnutls_e_invalid_session;
}
+ check_memory_full (err);
return make_number (err);
}
int ret = GNUTLS_E_SUCCESS;
if (!gnutls_global_initialized)
- {
- fn_gnutls_global_set_mem_functions (xmalloc, xmalloc, NULL,
- xrealloc, xfree);
- ret = fn_gnutls_global_init ();
- }
+ ret = fn_gnutls_global_init ();
+
gnutls_global_initialized = 1;
return gnutls_make_error (ret);
unsigned int gnutls_verify_flags = GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT;
GNUTLS_LOG (2, max_log_level, "allocating x509 credentials");
- fn_gnutls_certificate_allocate_credentials (&x509_cred);
+ check_memory_full ((fn_gnutls_certificate_allocate_credentials
+ (&x509_cred)));
XPROCESS (proc)->gnutls_x509_cred = x509_cred;
verify_flags = Fplist_get (proplist, QCgnutls_bootprop_verify_flags);
else /* Qgnutls_anon: */
{
GNUTLS_LOG (2, max_log_level, "allocating anon credentials");
- fn_gnutls_anon_allocate_client_credentials (&anon_cred);
+ check_memory_full ((fn_gnutls_anon_allocate_client_credentials
+ (&anon_cred)));
XPROCESS (proc)->gnutls_anon_cred = anon_cred;
}
return gnutls_make_error (ret);
}
- if (!fn_gnutls_x509_crt_check_hostname (gnutls_verify_cert, c_hostname))
+ int err
+ = fn_gnutls_x509_crt_check_hostname (gnutls_verify_cert, c_hostname);
+ check_memory_full (err);
+ if (!err)
{
if (verify_error_all
|| !NILP (Fmember (QCgnutls_bootprop_hostname, verify_error)))