]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
multi: fix bad splay management
authorDaniel Stenberg <daniel@haxx.se>
Wed, 6 Aug 2025 07:03:31 +0000 (09:03 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Wed, 6 Aug 2025 12:13:36 +0000 (14:13 +0200)
The splay tree is a tree where each easy handle can be added *once*. The
expire time for that node is the closest expire time for that easy
handle.

Easy handles can however have more expire times queued up, so when the
node is removed from the splay tree because it is the next in line to
take care of, we must check if there is another expire time in the queue
and then add the node back into the splay.

Failing to do the later part, the calling of add_next_timeout after
Curl_splaygetbest, would leave the state.expiretime on the previous time
stamp, which when could make the next call to Curl_splaygetbest use the
wrong time stamp and get a wrong node out, causing trouble.

Reported-by: letshack9707 on hackerone
Closes #18201

lib/multi.c

index 049e71ac7ac58cc41dc8ec0c7911f74697cadac5..cbecd6a7d564eff7109ad6b1f6b7f05b35a1a4e5 100644 (file)
@@ -2793,16 +2793,15 @@ CURLMcode curl_multi_perform(CURLM *m, int *running_handles)
     if(t) {
       /* the removed may have another timeout in queue */
       struct Curl_easy *data = Curl_splayget(t);
+      (void)add_next_timeout(now, multi, data);
       if(data->mstate == MSTATE_PENDING) {
         bool stream_unused;
         CURLcode result_unused;
         if(multi_handle_timeout(data, &now, &stream_unused, &result_unused)) {
           infof(data, "PENDING handle timeout");
           move_pending_to_connect(multi, data);
-          continue;
         }
       }
-      (void)add_next_timeout(now, multi, Curl_splayget(t));
     }
   } while(t);