From: Matthias A. <mat...@gm...> - 2025-06-16 16:40:16
|
Am 16.06.25 um 17:45 schrieb Andrea Venturoli: > Hello. > > Recently fetchmail has started crashing on a couple of servers of mine. Hi Andrea, mille grazie for the report and debugging. I've put this up as issue #71 <https://gitlab.com/fetchmail/fetchmail/-/issues/71>. Would you also know a quick way to reproduce it? > > The problem seems to be in socket.c: > >> int SockWrite(int sock, const char *buf, int len) >> { >> /* WARNING: This is messy - we use an int pointer, so does >> SSL_write, but fm_write/write would use ssize_t instead. >> Assume that write() won't ever return something that wouldn't >> fit an int. */ >> int n; >> int wrlen = 0; >> #ifdef SSL_ENABLE >> SSL *ssl = SSLGetContext(sock); >> #endif >> >> while (len) >> { >> #ifdef SSL_ENABLE >> if (ssl) { >> ERR_clear_error(); >> n = SSL_write(ssl, buf, len); >> } else >> #endif /* SSL_ENABLE */ >> n = fm_write(sock, buf, len); >> #ifdef SSL_ENABLE >> if (n <= 0) { >> int ssle = SSL_get_error(ssl, n); // do this before >> flushing the error queue! >> // map error code to n = 0 -> retryable or n = -1 -> true >> error >> switch(ssle) { >> case SSL_ERROR_ZERO_RETURN: >> case SSL_ERROR_SYSCALL: >> case SSL_ERROR_SSL: >> n = -1; break; >> default: >> /* assume retryable */ >> n = 0; break; >> } >> if (n) >> ERR_print_errors_fp(stderr); // do this after >> SSL_get_error - and only on fatal errors >> } >> #endif >> if (n < 0) >> return -1; >> len -= n; >> wrlen += n; >> buf += n; >> } >> return wrlen; >> } > > Here ssl is first checked in order to decide if SSL_write or fm_write > should be called. > Then, regardless of the choice, in case of error, SSL_get_error is > called (even when ssl is NULL) and that's where the program crashes. Plausible. I could issue 6.5.4 once I understand or reproduce this with a fix. > > > > Maybe I'm wrong, but I think the lines: >>> if (n <= 0) { >>> int ssle = SSL_get_error(ssl, n); // do this before >>> flushing the error queue! > > should be changed to: > >>> if (ssl && n <= 0) { >>> int ssle = SSL_get_error(ssl, n); // do this before >>> flushing the error queue! > > > (Or the whole "if {...}" could be moved inside the first "if (ssl)"). > > > > > In any case, thanks a lot for providing this software! Thanks a lot for your report! Cheers, Matthias |