I'm attaching new version of the patch. It fixes another missed crash at "else if (TLS_buffer[buf_end] != '\n')" line, as well as the same issues in duplicate code of SSL_readline().
P.S. I have concerns about "i <= buf_end" inside another condition branch. Most likely, it needs to be '<' instead of '<=', but I'm not quite familiar with the code, so this change is not included into the patch. -- ...Bye..Dmitry.
--- echoping-6.0.2.orig/readline.c +++ echoping-6.0.2/readline.c @@ -65,7 +65,7 @@ if (ln) { /* Empty buffer */ if (buf_end == 0) { - rc = SSL_read(sslh, SSL_buffer, maxlen); + rc = SSL_read(sslh, SSL_buffer, maxlen > MAXTOREAD ? MAXTOREAD : maxlen); if (rc == -1) return rc; buf_end = rc; @@ -74,25 +74,26 @@ /* No more data in the buffer */ else if (buf_ptr == buf_end) { buf_ptr = 0; - rc = SSL_read(sslh, SSL_buffer, maxlen); + rc = SSL_read(sslh, SSL_buffer, maxlen > MAXTOREAD ? MAXTOREAD : maxlen); if (rc == -1) return rc; buf_end = rc; - } else if (SSL_buffer[buf_end] != '\n') { + } else if (SSL_buffer[buf_end - 1] != '\n') { /* We have a probleme here is the first SSL_read sent back a * text not finished by a \n. See www.SSL.de for an example. * We get more data. See bug #230384 */ - rc = SSL_read(sslh, SSL_buffer + buf_end, maxlen); + rc = SSL_read(sslh, SSL_buffer + buf_end, + maxlen > MAXTOREAD - buf_end ? MAXTOREAD - buf_end : maxlen); if (rc == -1) return rc; buf_end = buf_end + rc; } for (oi = buf_ptr, i = buf_ptr; - i <= buf_end && SSL_buffer[i] != '\n'; i++) { + i < buf_end && SSL_buffer[i] != '\n'; i++) { *ptr++ = SSL_buffer[i]; buf_ptr++; } - if (SSL_buffer[i] == '\n') + if (i < buf_end && SSL_buffer[i] == '\n') buf_ptr++; *ptr = '\0'; /* if (ln) printf ("SSL_readline returns %d (%s)\n", i - oi, @@ -139,7 +140,8 @@ if (ln) { /* Empty buffer */ if (buf_end == 0) { - rc = gnutls_record_recv(session, TLS_buffer, maxlen); + rc = gnutls_record_recv(session, TLS_buffer, + maxlen > MAXTOREAD ? MAXTOREAD : maxlen); if (rc == -1) return rc; buf_end = rc; @@ -148,23 +150,24 @@ /* No more data in the buffer */ else if (buf_ptr == buf_end) { buf_ptr = 0; - rc = gnutls_record_recv(session, TLS_buffer, maxlen); + rc = gnutls_record_recv(session, TLS_buffer, + maxlen > MAXTOREAD ? MAXTOREAD : maxlen); if (rc == -1) return rc; buf_end = rc; - } else if (TLS_buffer[buf_end] != '\n') { + } else if (TLS_buffer[buf_end - 1] != '\n') { rc = gnutls_record_recv(session, TLS_buffer + buf_end, - maxlen); + maxlen > MAXTOREAD - buf_end ? MAXTOREAD - buf_end : maxlen); if (rc == -1) return rc; buf_end = buf_end + rc; } for (oi = buf_ptr, i = buf_ptr; - i <= buf_end && TLS_buffer[i] != '\n'; i++) { + i < buf_end && TLS_buffer[i] != '\n'; i++) { *ptr++ = TLS_buffer[i]; buf_ptr++; } - if (TLS_buffer[i] == '\n') + if (i < buf_end && TLS_buffer[i] == '\n') buf_ptr++; *ptr = '\0'; /* printf ("DEBUG: TLS_readline returns %d (%s)\n", i - oi,