[gnutls-devel] GnuTLS | The GNUTLS Release 3.3.16 has a bug in the DTLS Non-Blocking logic, bug located at gnutls-3.6.16/lib/record.c in function _gnutls_recv_in_buffers at lines 1307 and 1322 (#1413)

Read-only notification of GnuTLS library development activities gnutls-devel at lists.gnutls.org
Thu Oct 13 18:57:16 CEST 2022

Chuck Wanner commented:

I was reading the documentation for the `gnutls_transport_set_pull_timeout_function` and `gnutls_transport_set_pull_function`.  I am a bit confused.  If the `GNUTLS_NONBLOCK` flag is set, the documentation indicates the pull timeout callback will not be invoked.  But the `gnutls_transport_set_pull_function` indicates that the pull callback should only return when data is received (number of bytes received), the connection is terminated (return 0), or connection error (return -1).  The pull function does not have a return value to indicate there is no data and the connection is valid.

How is GNUTLS consider non-blocking, if only the pull function is invoked?

The `gnutls_transport_set_pull_timeout_function` documentation indicates if the timeout is zero, the function should return 0 immediately if no data is available.  I do not think this is correct.  Reviewing the code, if the timeout is zero the pull timeout function will not be invoked.   The pull function is invoked which will pend forever until data is received, the connection is terminated, or the connection has an error.

In the gnutls-3.6.16/lib/buffers.c, function `_gnutls_dgram_read` at line 251 will not invoke the pull timeout function if the timeout is zero.

	if (ms && *ms > 0) {
		ret = _gnutls_io_check_recv(session, *ms);
		if (ret < 0)
			return gnutls_assert_val(ret);
	*bufel = _mbuffer_alloc_align16(max_size, get_total_headers(session));
	if (*bufel == NULL)
		return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

	ptr = (*bufel)->msg.data;

	i = pull_func(fd, ptr, recv_size);

Note: Function `_gnutls_io_check_recv` invokes the Pull Timeout function

/* Checks whether there are received data within
 * a timeframe.
 * Returns 0 if data were received, GNUTLS_E_TIMEDOUT
 * on timeout and a negative error code on error.
int _gnutls_io_check_recv(gnutls_session_t session, unsigned int ms)
	gnutls_transport_ptr_t fd = session->internals.transport_recv_ptr;
	int ret = 0, err;

	if (NO_TIMEOUT_FUNC_SET(session)) {
		_gnutls_debug_log("The pull function has been replaced but not the pull timeout.\n");
		return gnutls_assert_val(GNUTLS_E_PULL_ERROR);


	ret = session->internals.pull_timeout_func(fd, ms);
	if (ret == -1) {
		err = get_errno(session);
		    ("READ_TIMEOUT: %d returned from %p, errno=%d (timeout: %u)\n",
		     (int) ret, fd, err, ms);
		return errno_to_gerr(err, IS_DTLS(session));

	if (ret > 0)
		return 0;

Reply to this email directly or view it on GitLab: https://gitlab.com/gnutls/gnutls/-/issues/1413#note_1135039277
You're receiving this email because of your account on gitlab.com.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.gnupg.org/pipermail/gnutls-devel/attachments/20221013/715ef53f/attachment.html>

More information about the Gnutls-devel mailing list