]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
pingpong: on disconnect, check for unflushed pingpong state
authorStefan Eissing <stefan@eissing.org>
Sun, 8 Jun 2025 10:00:00 +0000 (12:00 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 9 Jun 2025 09:22:19 +0000 (11:22 +0200)
When a pingpong based protocol tries to perform a connection disconnect,
it sends a sort of "logout" command to the server, unless the connection
is deemed dead.

But the disconnect might happen before pingpong data has been completely
sent, in which case sending the "logout" will not work. Check the
pingpong state and do not "logout" when data is pending.

This was detected as a condition in fuzzing that triggered a debug
assert in the pingpong sending.

Closes #17555

lib/ftp.c
lib/imap.c
lib/pop3.c
lib/smtp.c

index 2c6138e98020e1a859118a97e221883afe41028e..3dd7fed045d618d74d7a00d460700925cd9158f3 100644 (file)
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -4117,7 +4117,7 @@ static CURLcode ftp_disconnect(struct Curl_easy *data,
      will try to send the QUIT command, otherwise it will just return.
   */
   ftpc->shutdown = TRUE;
-  if(dead_connection)
+  if(dead_connection || Curl_pp_needs_flush(data, &ftpc->pp))
     ftpc->ctl_valid = FALSE;
 
   /* The FTP session may or may not have been allocated/setup at this point! */
index fc38a5b61e0d85e8c79ea491e43b48525c2b1d0b..fa17b77151b5c7d114420c6ef04a73cbd21bde6d 100644 (file)
@@ -1780,12 +1780,11 @@ static CURLcode imap_disconnect(struct Curl_easy *data,
   (void)data;
   if(imapc) {
     /* We cannot send quit unconditionally. If this connection is stale or
-       bad in any way, sending quit and waiting around here will make the
+       bad in any way (pingpong has pending data to send),
+       sending quit and waiting around here will make the
        disconnect wait in vain and cause more problems than we need to. */
-
-    /* The IMAP session may or may not have been allocated/setup at this
-       point! */
-    if(!dead_connection && conn->bits.protoconnstart) {
+    if(!dead_connection && conn->bits.protoconnstart &&
+       !Curl_pp_needs_flush(data, &imapc->pp)) {
       if(!imap_perform_logout(data, imapc))
         (void)imap_block_statemach(data, imapc, TRUE); /* ignore errors */
     }
index aa8c2d834a90c848e2fcfff1c8472e6cef199f4d..3e3070e333a8eed2c64a317308e8d19590e06e7b 100644 (file)
@@ -1450,7 +1450,8 @@ static CURLcode pop3_disconnect(struct Curl_easy *data,
      bad in any way, sending quit and waiting around here will make the
      disconnect wait in vain and cause more problems than we need to. */
 
-  if(!dead_connection && conn->bits.protoconnstart) {
+  if(!dead_connection && conn->bits.protoconnstart &&
+     !Curl_pp_needs_flush(data, &pop3c->pp)) {
     if(!pop3_perform_quit(data, conn))
       (void)pop3_block_statemach(data, conn, TRUE); /* ignore errors on QUIT */
   }
index d39bb58d5de78609115c9ada459eea6acca505ae..99a348e2346dc41fdad38ef124641189876e01fe 100644 (file)
@@ -1625,7 +1625,8 @@ static CURLcode smtp_disconnect(struct Curl_easy *data,
      bad in any way, sending quit and waiting around here will make the
      disconnect wait in vain and cause more problems than we need to. */
 
-  if(!dead_connection && conn->bits.protoconnstart) {
+  if(!dead_connection && conn->bits.protoconnstart &&
+     !Curl_pp_needs_flush(data, &smtpc->pp)) {
     if(!smtp_perform_quit(data, smtpc))
       (void)smtp_block_statemach(data, smtpc, TRUE); /* ignore on QUIT */
   }