<pre style='margin:0'>
Joshua Root (jmroot) pushed a commit to branch master
in repository macports-base.

</pre>
<p><a href="https://github.com/macports/macports-base/commit/ff881a52faeb700213259c33163a552bd7325f05">https://github.com/macports/macports-base/commit/ff881a52faeb700213259c33163a552bd7325f05</a></p>
<pre style="white-space: pre; background: #F8F8F8"><span style='display:block; white-space:pre;color:#808000;'>commit ff881a52faeb700213259c33163a552bd7325f05
</span>Author: Joshua Root <jmr@macports.org>
AuthorDate: Sat Sep 21 10:08:19 2024 +1000

<span style='display:block; white-space:pre;color:#404040;'>    Work around libcurl crash when reusing handles
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    Closes: https://trac.macports.org/ticket/70764
</span>---
 src/pextlib1.0/curl.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 67 insertions(+), 2 deletions(-)

<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/pextlib1.0/curl.c b/src/pextlib1.0/curl.c
</span><span style='display:block; white-space:pre;color:#808080;'>index f45bcb351..4edacd2a2 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/pextlib1.0/curl.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/pextlib1.0/curl.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -41,6 +41,7 @@
</span> #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
<span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <strings.h>
</span> #include <sys/select.h>
 #include <utime.h>
 
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -82,6 +83,9 @@ static CURLM* theMHandle = NULL;
</span>  * take advantage of HTTP pipelining, especially to the packages servers. */
 static CURL* theHandle = NULL;
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+/* Global libcurl version info. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static curl_version_info_data *libcurl_version_info = NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> /* ------------------------------------------------------------------------- **
  * Prototypes
  * ------------------------------------------------------------------------- */
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -103,6 +107,7 @@ static int CurlProgressHandler(tcl_callback_t *callback, double dltotal, double
</span> static void CurlProgressCleanup(tcl_callback_t *callback);
 
 void CurlInit(void);
<span style='display:block; white-space:pre;background:#e0ffe0;'>+static void set_curl_version_info(void);
</span> 
 /* ========================================================================= **
  * Entry points
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -204,6 +209,9 @@ CurlFetchCmd(Tcl_Interp* interp, int objc, Tcl_Obj* const objv[])
</span>           struct CURLMsg *info = NULL;
                int running; /* number of running transfers */
                char* acceptEncoding = NULL;
<span style='display:block; white-space:pre;background:#e0ffe0;'>+#if LIBCURL_VERSION_NUM >= 0x074d00
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           char *previous_scheme = NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#endif
</span> 
                /* we might have options and then the url and the file */
                /* let's process the options first */
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -349,6 +357,22 @@ CurlFetchCmd(Tcl_Interp* interp, int objc, Tcl_Obj* const objv[])
</span>                           break;
                        }
                }
<span style='display:block; white-space:pre;background:#e0ffe0;'>+#if LIBCURL_VERSION_NUM >= 0x074d00
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            set_curl_version_info();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if (libcurl_version_info == NULL) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                theResult = TCL_ERROR;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                Tcl_SetResult(interp, "set_curl_version_info failed", TCL_STATIC);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            /* for mitigation of reused handle bug - see below */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if (libcurl_version_info->version_num >= 0x080600 && libcurl_version_info->version_num < 0x080800) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                if (curl_easy_getinfo(theHandle, CURLINFO_SCHEME, &previous_scheme) != CURLE_OK) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    previous_scheme = NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#endif
</span>           /* If we're re-using a handle, the previous call did ensure to reset it
                 * to the default state using curl_easy_reset(3) */
 
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -359,6 +383,33 @@ CurlFetchCmd(Tcl_Interp* interp, int objc, Tcl_Obj* const objv[])
</span>                   break;
                }
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+        /* Bug affecting some macOS releases (Monterey through Sequoia):
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           reusing an easy handle for different protocols can cause a
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           crash. https://github.com/curl/curl/issues/13731
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           TODO: Add upper bound here when we know what version macOS 16 ships. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#if LIBCURL_VERSION_NUM >= 0x074d00
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if (previous_scheme != NULL) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            char *current_scheme = NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if (curl_easy_getinfo(theHandle, CURLINFO_SCHEME, &current_scheme) == CURLE_OK
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                && current_scheme != NULL && 0 != strcasecmp(previous_scheme, current_scheme)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                /* deallocate the handle and start again */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                curl_easy_cleanup(theHandle);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                theHandle = NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                theHandle = curl_easy_init();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                if (theHandle == NULL) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    theResult = TCL_ERROR;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    Tcl_SetResult(interp, "error in curl_easy_init", TCL_STATIC);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                theCurlCode = curl_easy_setopt(theHandle, CURLOPT_URL, theURL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                if (theCurlCode != CURLE_OK) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    theResult = SetResultFromCurlErrorCode(interp, theCurlCode);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#endif
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> #if LIBCURL_VERSION_NUM >= 0x071304 && LIBCURL_VERSION_NUM <= 0x071307
                /* FTP_PROXY workaround for Snow Leopard */
                if (strncmp(theURL, "ftp:", 4) == 0) {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -649,7 +700,7 @@ CurlFetchCmd(Tcl_Interp* interp, int objc, Tcl_Obj* const objv[])
</span>                   theResult = TCL_ERROR;
                        break;
                }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span>           if (info->data.result != CURLE_OK) {
                        /* execution failed, use the error string if it is set */
                        if (theErrorString[0] != '\0') {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1436,6 +1487,14 @@ CurlPostCmd(Tcl_Interp* interp, int objc, Tcl_Obj* const objv[])
</span>   return theResult;
 }
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+/* Fill in global libcurl_version_info structure */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static void set_curl_version_info(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (libcurl_version_info == NULL) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        libcurl_version_info = curl_version_info(CURLVERSION_NOW);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> /**
  * curl version subcommand entry point.
  *
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1448,8 +1507,14 @@ CurlVersionCmd(Tcl_Interp* interp, int objc, Tcl_Obj* const objv[])
</span> {
        int theResult = TCL_OK;
        Tcl_Obj *tcl_result = NULL;
<span style='display:block; white-space:pre;background:#e0ffe0;'>+        curl_version_info_data *theVersionInfo;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set_curl_version_info();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if (libcurl_version_info == NULL) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return TCL_ERROR;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    theVersionInfo = libcurl_version_info;
</span> 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        curl_version_info_data *theVersionInfo = curl_version_info(CURLVERSION_NOW);
</span>   tcl_result = Tcl_NewDictObj();
 
        // info from the curl version we were built against:
</pre><pre style='margin:0'>

</pre>