diff --git a/backport-CVE-2024-2004.patch b/backport-CVE-2024-2004.patch new file mode 100644 index 0000000000000000000000000000000000000000..b8d947bdaa7458e9bf8afe047cf94b8fdb399368 --- /dev/null +++ b/backport-CVE-2024-2004.patch @@ -0,0 +1,139 @@ +From 17d302e56221f5040092db77d4f85086e8a20e0e Mon Sep 17 00:00:00 2001 +From: Daniel Gustafsson +Date: Tue, 27 Feb 2024 15:43:56 +0100 +Subject: [PATCH] setopt: Fix disabling all protocols + +When disabling all protocols without enabling any, the resulting +set of allowed protocols remained the default set. Clearing the +allowed set before inspecting the passed value from --proto make +the set empty even in the errorpath of no protocols enabled. + +Co-authored-by: Dan Fandrich +Reported-by: Dan Fandrich +Reviewed-by: Daniel Stenberg +Closes: #13004 + +Conflict:Context adapt +Reference:https://github.com/curl/curl/commit/17d302e56221f5040092db77d4f85086e8a20e0e +--- + lib/setopt.c | 16 ++++++++-------- + tests/data/Makefile.inc | 2 +- + tests/data/test1474 | 42 +++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 51 insertions(+), 9 deletions(-) + create mode 100644 tests/data/test1474 + +diff --git a/lib/setopt.c b/lib/setopt.c +index 6a4990cce..ce1321fc8 100644 +--- a/lib/setopt.c ++++ b/lib/setopt.c +@@ -155,6 +155,12 @@ static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp) + + static CURLcode protocol2num(const char *str, curl_prot_t *val) + { ++ /* ++ * We are asked to cherry-pick protocols, so play it safe and disallow all ++ * protocols to start with, and re-add the wanted ones back in. ++ */ ++ *val = 0; ++ + if(!str) + return CURLE_BAD_FUNCTION_ARGUMENT; + +@@ -163,8 +169,6 @@ static CURLcode protocol2num(const char *str, curl_prot_t *val) + return CURLE_OK; + } + +- *val = 0; +- + do { + const char *token = str; + size_t tlen; +@@ -2654,22 +2658,18 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) + break; + + case CURLOPT_PROTOCOLS_STR: { +- curl_prot_t prot; + argptr = va_arg(param, char *); +- result = protocol2num(argptr, &prot); ++ result = protocol2num(argptr, &data->set.allowed_protocols); + if(result) + return result; +- data->set.allowed_protocols = prot; + break; + } + + case CURLOPT_REDIR_PROTOCOLS_STR: { +- curl_prot_t prot; + argptr = va_arg(param, char *); +- result = protocol2num(argptr, &prot); ++ result = protocol2num(argptr, &data->set.redir_protocols); + if(result) + return result; +- data->set.redir_protocols = prot; + break; + } + +diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc +index c20f90d94..b80ffb618 100644 +--- a/tests/data/Makefile.inc ++++ b/tests/data/Makefile.inc +@@ -187,7 +187,7 @@ test1439 test1440 test1441 test1442 test1443 test1444 test1445 test1446 \ + test1447 test1448 test1449 test1450 test1451 test1452 test1453 test1454 \ + test1455 test1456 test1457 test1458 test1459 test1460 test1461 test1462 \ + test1463 test1464 test1465 test1466 test1467 test1468 test1469 test1470 \ +-test1471 test1472 test1473 \ ++test1471 test1472 test1473 test1474 \ + \ + test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \ + test1508 test1509 test1510 test1511 test1512 test1513 test1514 test1515 \ +diff --git a/tests/data/test1474 b/tests/data/test1474 +new file mode 100644 +index 000000000..c66fa2810 +--- /dev/null ++++ b/tests/data/test1474 +@@ -0,0 +1,42 @@ ++ ++ ++ ++HTTP ++HTTP GET ++--proto ++ ++ ++ ++# ++# Server-side ++ ++ ++ ++ ++ ++# ++# Client-side ++ ++ ++none ++ ++ ++http ++ ++ ++--proto -all disables all protocols ++ ++ ++--proto -all http://%HOSTIP:%NOLISTENPORT/%TESTNUMBER ++ ++ ++ ++# ++# Verify data after the test has been "shot" ++ ++# 1 - Protocol "http" disabled ++ ++1 ++ ++ ++ +-- +2.33.0 + diff --git a/backport-CVE-2024-2398.patch b/backport-CVE-2024-2398.patch new file mode 100644 index 0000000000000000000000000000000000000000..c3128b148aef15d93cddc32e3078a59c9a601823 --- /dev/null +++ b/backport-CVE-2024-2398.patch @@ -0,0 +1,96 @@ +From deca8039991886a559b67bcd6701db800a5cf764 Mon Sep 17 00:00:00 2001 +From: Stefan Eissing +Date: Wed, 6 Mar 2024 09:36:08 +0100 +Subject: [PATCH] http2: push headers better cleanup + +- provide common cleanup method for push headers + +Closes #13054 + +Conflict:struct h2_stream_ctx *stream => struct stream_ctx *stream +Context adapt +Reference:https://github.com/curl/curl/commit/deca8039991886a559b67bcd6701db800a5cf764 +--- + lib/http2.c | 34 +++++++++++++++------------------- + 1 file changed, 15 insertions(+), 19 deletions(-) + +diff --git a/lib/http2.c b/lib/http2.c +index c63ecd383..96868728a 100644 +--- a/lib/http2.c ++++ b/lib/http2.c +@@ -271,6 +271,15 @@ static CURLcode http2_data_setup(struct Curl_cfilter *cf, + return CURLE_OK; + } + ++static void free_push_headers(struct stream_ctx *stream) ++{ ++ size_t i; ++ for(i = 0; ipush_headers_used; i++) ++ free(stream->push_headers[i]); ++ Curl_safefree(stream->push_headers); ++ stream->push_headers_used = 0; ++} ++ + static void http2_data_done(struct Curl_cfilter *cf, + struct Curl_easy *data, bool premature) + { +@@ -306,15 +315,7 @@ static void http2_data_done(struct Curl_cfilter *cf, + Curl_bufq_free(&stream->recvbuf); + Curl_h1_req_parse_free(&stream->h1); + Curl_dynhds_free(&stream->resp_trailers); +- if(stream->push_headers) { +- /* if they weren't used and then freed before */ +- for(; stream->push_headers_used > 0; --stream->push_headers_used) { +- free(stream->push_headers[stream->push_headers_used - 1]); +- } +- free(stream->push_headers); +- stream->push_headers = NULL; +- } +- ++ free_push_headers(stream); + free(stream); + H2_STREAM_LCTX(data) = NULL; + } +@@ -860,7 +861,6 @@ static int push_promise(struct Curl_cfilter *cf, + struct curl_pushheaders heads; + CURLMcode rc; + CURLcode result; +- size_t i; + /* clone the parent */ + struct Curl_easy *newhandle = h2_duphandle(cf, data); + if(!newhandle) { +@@ -905,11 +905,7 @@ static int push_promise(struct Curl_cfilter *cf, + Curl_set_in_callback(data, false); + + /* free the headers again */ +- for(i = 0; ipush_headers_used; i++) +- free(stream->push_headers[i]); +- free(stream->push_headers); +- stream->push_headers = NULL; +- stream->push_headers_used = 0; ++ free_push_headers(stream); + + if(rv) { + DEBUGASSERT((rv > CURL_PUSH_OK) && (rv <= CURL_PUSH_ERROROUT)); +@@ -1430,14 +1426,14 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, + if(stream->push_headers_alloc > 1000) { + /* this is beyond crazy many headers, bail out */ + failf(data_s, "Too many PUSH_PROMISE headers"); +- Curl_safefree(stream->push_headers); ++ free_push_headers(stream); + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } + stream->push_headers_alloc *= 2; +- headp = Curl_saferealloc(stream->push_headers, +- stream->push_headers_alloc * sizeof(char *)); ++ headp = realloc(stream->push_headers, ++ stream->push_headers_alloc * sizeof(char *)); + if(!headp) { +- stream->push_headers = NULL; ++ free_push_headers(stream); + return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; + } + stream->push_headers = headp; +-- +2.33.0 + diff --git a/backport-CVE-2024-7264-x509asn1-clean-up-GTime2str.patch b/backport-CVE-2024-7264-x509asn1-clean-up-GTime2str.patch new file mode 100644 index 0000000000000000000000000000000000000000..4f3ef5d803b36a3808722801572e43c531083768 --- /dev/null +++ b/backport-CVE-2024-7264-x509asn1-clean-up-GTime2str.patch @@ -0,0 +1,60 @@ +From 3c914bc680155b32178f1f15ca8d47c7f4640afe Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Tue, 30 Jul 2024 10:05:17 +0200 +Subject: [PATCH] x509asn1: clean up GTime2str + +Co-authored-by: Stefan Eissing +Reported-by: Dov Murik + +Closes #14307 +--- + lib/vtls/x509asn1.c | 23 ++++++++++++++--------- + 1 file changed, 14 insertions(+), 9 deletions(-) + +diff --git a/lib/vtls/x509asn1.c b/lib/vtls/x509asn1.c +index c3fd3a3..dd7985d 100644 +--- a/lib/vtls/x509asn1.c ++++ b/lib/vtls/x509asn1.c +@@ -537,7 +537,7 @@ static const char *GTime2str(const char *beg, const char *end) + /* Convert an ASN.1 Generalized time to a printable string. + Return the dynamically allocated string, or NULL if an error occurs. */ + +- for(fracp = beg; fracp < end && *fracp >= '0' && *fracp <= '9'; fracp++) ++ for(fracp = beg; fracp < end && ISDIGIT(*fracp); fracp++) + ; + + /* Get seconds digits. */ +@@ -556,17 +556,22 @@ static const char *GTime2str(const char *beg, const char *end) + return NULL; + } + +- /* Scan for timezone, measure fractional seconds. */ ++ /* timezone follows optional fractional seconds. */ + tzp = fracp; +- fracl = 0; ++ fracl = 0; /* no fractional seconds detected so far */ + if(fracp < end && (*fracp == '.' || *fracp == ',')) { +- fracp++; +- do ++ /* Have fractional seconds, e.g. "[.,]\d+". How many? */ ++ tzp = fracp++; /* should be a digit char or BAD ARGUMENT */ ++ while(tzp < end && ISDIGIT(*tzp)) + tzp++; +- while(tzp < end && *tzp >= '0' && *tzp <= '9'); +- /* Strip leading zeroes in fractional seconds. */ +- for(fracl = tzp - fracp - 1; fracl && fracp[fracl - 1] == '0'; fracl--) +- ; ++ if(tzp == fracp) /* never looped, no digit after [.,] */ ++ return CURLE_BAD_FUNCTION_ARGUMENT; ++ fracl = tzp - fracp - 1; /* number of fractional sec digits */ ++ DEBUGASSERT(fracl > 0); ++ /* Strip trailing zeroes in fractional seconds. ++ * May reduce fracl to 0 if only '0's are present. */ ++ while(fracl && fracp[fracl - 1] == '0') ++ fracl--; + } + + /* Process timezone. */ +-- +2.41.0 + diff --git a/backport-CVE-2024-7264-x509asn1-unittests-and-fixes-fo.patch b/backport-CVE-2024-7264-x509asn1-unittests-and-fixes-fo.patch new file mode 100644 index 0000000000000000000000000000000000000000..f4949bc61f0ad9d1177aad9d269a0727c6336b61 --- /dev/null +++ b/backport-CVE-2024-7264-x509asn1-unittests-and-fixes-fo.patch @@ -0,0 +1,315 @@ +From 27959ecce75cdb2809c0bdb3286e60e08fadb519 Mon Sep 17 00:00:00 2001 +From: Stefan Eissing +Date: Tue, 30 Jul 2024 16:40:48 +0200 +Subject: [PATCH] x509asn1: unittests and fixes for gtime2str + +Fix issues in GTime2str() and add unit test cases to verify correct +behaviour. + +Follow-up to 3c914bc6801 + +Closes #14316 +--- + lib/vtls/x509asn1.c | 32 +++++++--- + lib/vtls/x509asn1.h | 11 ++++ + tests/data/Makefile.inc | 2 +- + tests/data/test1656 | 22 +++++++ + tests/unit/Makefile.inc | 4 +- + tests/unit/unit1656.c | 133 ++++++++++++++++++++++++++++++++++++++++ + 6 files changed, 194 insertions(+), 10 deletions(-) + create mode 100644 tests/data/test1656 + create mode 100644 tests/unit/unit1656.c + +diff --git a/lib/vtls/x509asn1.c b/lib/vtls/x509asn1.c +index dd7985d..5c65df1 100644 +--- a/lib/vtls/x509asn1.c ++++ b/lib/vtls/x509asn1.c +@@ -561,12 +561,13 @@ static const char *GTime2str(const char *beg, const char *end) + fracl = 0; /* no fractional seconds detected so far */ + if(fracp < end && (*fracp == '.' || *fracp == ',')) { + /* Have fractional seconds, e.g. "[.,]\d+". How many? */ +- tzp = fracp++; /* should be a digit char or BAD ARGUMENT */ ++ fracp++; /* should be a digit char or BAD ARGUMENT */ ++ tzp = fracp; + while(tzp < end && ISDIGIT(*tzp)) + tzp++; + if(tzp == fracp) /* never looped, no digit after [.,] */ + return CURLE_BAD_FUNCTION_ARGUMENT; +- fracl = tzp - fracp - 1; /* number of fractional sec digits */ ++ fracl = tzp - fracp; /* number of fractional sec digits */ + DEBUGASSERT(fracl > 0); + /* Strip trailing zeroes in fractional seconds. + * May reduce fracl to 0 if only '0's are present. */ +@@ -575,18 +576,24 @@ static const char *GTime2str(const char *beg, const char *end) + } + + /* Process timezone. */ +- if(tzp >= end) +- ; /* Nothing to do. */ ++ if(tzp >= end) { ++ tzp = ""; ++ tzl = 0; ++ } + else if(*tzp == 'Z') { +- tzp = " GMT"; +- end = tzp + 4; ++ sep = " "; ++ tzp = "GMT"; ++ tzl = 3; ++ } ++ else if((*tzp == '+') || (*tzp == '-')) { ++ sep = " UTC"; ++ tzl = end - tzp; + } + else { + sep = " "; +- tzp++; ++ tzl = end - tzp; + } + +- tzl = end - tzp; + return curl_maprintf("%.4s-%.2s-%.2s %.2s:%.2s:%c%c%s%.*s%s%.*s", + beg, beg + 4, beg + 6, + beg + 8, beg + 10, sec1, sec2, +@@ -594,6 +601,15 @@ static const char *GTime2str(const char *beg, const char *end) + sep, (int)tzl, tzp); + } + ++#ifdef UNITTESTS ++/* used by unit1656.c */ ++CURLcode Curl_x509_GTime2str(struct dynbuf *store, ++ const char *beg, const char *end) ++{ ++ return GTime2str(store, beg, end); ++} ++#endif ++ + /* + * Convert an ASN.1 UTC time to a printable string. + * Return the dynamically allocated string, or NULL if an error occurs. +diff --git a/lib/vtls/x509asn1.h b/lib/vtls/x509asn1.h +index 23a67b8..1d8bbab 100644 +--- a/lib/vtls/x509asn1.h ++++ b/lib/vtls/x509asn1.h +@@ -76,5 +76,16 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, int certnum, + const char *beg, const char *end); + CURLcode Curl_verifyhost(struct Curl_cfilter *cf, struct Curl_easy *data, + const char *beg, const char *end); ++ ++#ifdef UNITTESTS ++#if defined(USE_GNUTLS) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \ ++ defined(USE_MBEDTLS) ++ ++/* used by unit1656.c */ ++CURLcode Curl_x509_GTime2str(struct dynbuf *store, ++ const char *beg, const char *end); ++#endif ++#endif ++ + #endif /* USE_GNUTLS or USE_WOLFSSL or USE_SCHANNEL or USE_SECTRANSP */ + #endif /* HEADER_CURL_X509ASN1_H */ +diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc +index 1472b19..0af94e6 100644 +--- a/tests/data/Makefile.inc ++++ b/tests/data/Makefile.inc +@@ -207,7 +207,7 @@ test1620 test1621 \ + \ + test1630 test1631 test1632 test1633 test1634 test1635 \ + \ +-test1650 test1651 test1652 test1653 test1654 test1655 \ ++test1650 test1651 test1652 test1653 test1654 test1655 test1656 \ + test1660 test1661 test1662 \ + \ + test1670 test1671 \ +diff --git a/tests/data/test1656 b/tests/data/test1656 +new file mode 100644 +index 0000000..2fab21b +--- /dev/null ++++ b/tests/data/test1656 +@@ -0,0 +1,22 @@ ++ ++ ++ ++unittest ++Curl_x509_GTime2str ++ ++ ++ ++# ++# Client-side ++ ++ ++none ++ ++ ++unittest ++ ++ ++Curl_x509_GTime2str unit tests ++ ++ ++ +diff --git a/tests/unit/Makefile.inc b/tests/unit/Makefile.inc +index 36e922b..b0eaf64 100644 +--- a/tests/unit/Makefile.inc ++++ b/tests/unit/Makefile.inc +@@ -36,7 +36,7 @@ UNITPROGS = unit1300 unit1302 unit1303 unit1304 unit1305 unit1307 \ + unit1600 unit1601 unit1602 unit1603 unit1604 unit1605 unit1606 unit1607 \ + unit1608 unit1609 unit1610 unit1611 unit1612 unit1614 \ + unit1620 unit1621 \ +- unit1650 unit1651 unit1652 unit1653 unit1654 unit1655 \ ++ unit1650 unit1651 unit1652 unit1653 unit1654 unit1655 unit1656 \ + unit1660 unit1661 \ + unit2600 unit2601 unit2602 unit2603 \ + unit3200 +@@ -117,6 +117,8 @@ unit1654_SOURCES = unit1654.c $(UNITFILES) + + unit1655_SOURCES = unit1655.c $(UNITFILES) + ++unit1656_SOURCES = unit1656.c $(UNITFILES) ++ + unit1660_SOURCES = unit1660.c $(UNITFILES) + + unit1661_SOURCES = unit1661.c $(UNITFILES) +diff --git a/tests/unit/unit1656.c b/tests/unit/unit1656.c +new file mode 100644 +index 0000000..644e72f +--- /dev/null ++++ b/tests/unit/unit1656.c +@@ -0,0 +1,133 @@ ++/*************************************************************************** ++ * _ _ ____ _ ++ * Project ___| | | | _ \| | ++ * / __| | | | |_) | | ++ * | (__| |_| | _ <| |___ ++ * \___|\___/|_| \_\_____| ++ * ++ * Copyright (C) Daniel Stenberg, , et al. ++ * ++ * This software is licensed as described in the file COPYING, which ++ * you should have received as part of this distribution. The terms ++ * are also available at https://curl.se/docs/copyright.html. ++ * ++ * You may opt to use, copy, modify, merge, publish, distribute and/or sell ++ * copies of the Software, and permit persons to whom the Software is ++ * furnished to do so, under the terms of the COPYING file. ++ * ++ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY ++ * KIND, either express or implied. ++ * ++ * SPDX-License-Identifier: curl ++ * ++ ***************************************************************************/ ++#include "curlcheck.h" ++ ++#include "vtls/x509asn1.h" ++ ++static CURLcode unit_setup(void) ++{ ++ return CURLE_OK; ++} ++ ++static void unit_stop(void) ++{ ++ ++} ++ ++#if defined(USE_GNUTLS) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \ ++ defined(USE_MBEDTLS) ++ ++#ifndef ARRAYSIZE ++#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) ++#endif ++ ++struct test_spec { ++ const char *input; ++ const char *exp_output; ++ CURLcode exp_result; ++}; ++ ++static struct test_spec test_specs[] = { ++ { "190321134340", "1903-21-13 43:40:00", CURLE_OK }, ++ { "", NULL, CURLE_BAD_FUNCTION_ARGUMENT }, ++ { "WTF", NULL, CURLE_BAD_FUNCTION_ARGUMENT }, ++ { "0WTF", NULL, CURLE_BAD_FUNCTION_ARGUMENT }, ++ { "19032113434", NULL, CURLE_BAD_FUNCTION_ARGUMENT }, ++ { "19032113434WTF", NULL, CURLE_BAD_FUNCTION_ARGUMENT }, ++ { "190321134340.", NULL, CURLE_BAD_FUNCTION_ARGUMENT }, ++ { "190321134340.1", "1903-21-13 43:40:00.1", CURLE_OK }, ++ { "19032113434017.0", "1903-21-13 43:40:17", CURLE_OK }, ++ { "19032113434017.01", "1903-21-13 43:40:17.01", CURLE_OK }, ++ { "19032113434003.001", "1903-21-13 43:40:03.001", CURLE_OK }, ++ { "19032113434003.090", "1903-21-13 43:40:03.09", CURLE_OK }, ++ { "190321134340Z", "1903-21-13 43:40:00 GMT", CURLE_OK }, ++ { "19032113434017.0Z", "1903-21-13 43:40:17 GMT", CURLE_OK }, ++ { "19032113434017.01Z", "1903-21-13 43:40:17.01 GMT", CURLE_OK }, ++ { "19032113434003.001Z", "1903-21-13 43:40:03.001 GMT", CURLE_OK }, ++ { "19032113434003.090Z", "1903-21-13 43:40:03.09 GMT", CURLE_OK }, ++ { "190321134340CET", "1903-21-13 43:40:00 CET", CURLE_OK }, ++ { "19032113434017.0CET", "1903-21-13 43:40:17 CET", CURLE_OK }, ++ { "19032113434017.01CET", "1903-21-13 43:40:17.01 CET", CURLE_OK }, ++ { "190321134340+02:30", "1903-21-13 43:40:00 UTC+02:30", CURLE_OK }, ++ { "19032113434017.0+02:30", "1903-21-13 43:40:17 UTC+02:30", CURLE_OK }, ++ { "19032113434017.01+02:30", "1903-21-13 43:40:17.01 UTC+02:30", CURLE_OK }, ++ { "190321134340-3", "1903-21-13 43:40:00 UTC-3", CURLE_OK }, ++ { "19032113434017.0-04", "1903-21-13 43:40:17 UTC-04", CURLE_OK }, ++ { "19032113434017.01-01:10", "1903-21-13 43:40:17.01 UTC-01:10", CURLE_OK }, ++}; ++ ++static bool do_test(struct test_spec *spec, size_t i, struct dynbuf *dbuf) ++{ ++ CURLcode result; ++ const char *in = spec->input; ++ ++ Curl_dyn_reset(dbuf); ++ result = Curl_x509_GTime2str(dbuf, in, in + strlen(in)); ++ if(result != spec->exp_result) { ++ fprintf(stderr, "test %zu: expect result %d, got %d\n", ++ i, spec->exp_result, result); ++ return FALSE; ++ } ++ else if(!result && strcmp(spec->exp_output, Curl_dyn_ptr(dbuf))) { ++ fprintf(stderr, "test %zu: input '%s', expected output '%s', got '%s'\n", ++ i, in, spec->exp_output, Curl_dyn_ptr(dbuf)); ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++UNITTEST_START ++{ ++ size_t i; ++ struct dynbuf dbuf; ++ bool all_ok = TRUE; ++ ++ Curl_dyn_init(&dbuf, 32*1024); ++ ++ if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { ++ fprintf(stderr, "curl_global_init() failed\n"); ++ return TEST_ERR_MAJOR_BAD; ++ } ++ ++ for(i = 0; i < ARRAYSIZE(test_specs); ++i) { ++ if(!do_test(&test_specs[i], i, &dbuf)) ++ all_ok = FALSE; ++ } ++ fail_unless(all_ok, "some tests of Curl_x509_GTime2str() fails"); ++ ++ Curl_dyn_free(&dbuf); ++ curl_global_cleanup(); ++} ++UNITTEST_STOP ++ ++#else ++ ++UNITTEST_START ++{ ++ puts("not tested since Curl_x509_GTime2str() is not built-in"); ++} ++UNITTEST_STOP ++ ++#endif +-- +2.41.0 + diff --git a/backport-libssh2-set-length-to-0-if-strdup-failed.patch b/backport-libssh2-set-length-to-0-if-strdup-failed.patch new file mode 100644 index 0000000000000000000000000000000000000000..eeeb7c069c7924f8188b25b93b7058ea9e40a9e5 --- /dev/null +++ b/backport-libssh2-set-length-to-0-if-strdup-failed.patch @@ -0,0 +1,31 @@ +From 6f3204820052263f488f86e02c206e1d24c4da2c Mon Sep 17 00:00:00 2001 +From: Tobias Stoeckmann +Date: Thu, 28 Mar 2024 00:38:09 +0100 +Subject: [PATCH] libssh2: set length to 0 if strdup failed + +Internally, libssh2 dereferences the NULL pointer if length is non-zero. +The callback function cannot return the error condition, so at least +prevent subsequent crash. + +Closes #13213 + +Conflict:NA +Reference:https://github.com/curl/curl/commit/6f3204820052263f488f86e02c206e1d24c4da2c +--- + lib/vssh/libssh2.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/lib/vssh/libssh2.c b/lib/vssh/libssh2.c +index 3cfbe126c69df3..7d8d5f46571e9f 100644 +--- a/lib/vssh/libssh2.c ++++ b/lib/vssh/libssh2.c +@@ -201,7 +201,8 @@ kbd_callback(const char *name, int name_len, const char *instruction, + if(num_prompts == 1) { + struct connectdata *conn = data->conn; + responses[0].text = strdup(conn->passwd); +- responses[0].length = curlx_uztoui(strlen(conn->passwd)); ++ responses[0].length = ++ responses[0].text == NULL ? 0 : curlx_uztoui(strlen(conn->passwd)); + } + (void)prompts; + } /* kbd_callback */ diff --git a/backport-multi-avoid-memory-leak-risk.patch b/backport-multi-avoid-memory-leak-risk.patch new file mode 100644 index 0000000000000000000000000000000000000000..0a0ed597b58c4d7ad7b16b8b57b3dc079a933433 --- /dev/null +++ b/backport-multi-avoid-memory-leak-risk.patch @@ -0,0 +1,46 @@ +From 3572dd65bb233fc2720634804312192e3bdf4adf Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 25 Apr 2024 09:52:51 +0200 +Subject: [PATCH] multi: avoid memory-leak risk + +'newurl' is allocated in some conditions and used in a few scenarios, +but there were theoretical combinations in which it would not get freed. +Move the free to happen unconditionally. Never triggered by tests, but +spotted by Coverity. + +Closes #13471 + +Conflict:Context adapt +Reference:https://github.com/curl/curl/commit/3572dd65bb233fc2720634804312192e3bdf4adf +--- + lib/multi.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/lib/multi.c b/lib/multi.c +index fb98d80639f3b7..7e7590d60f8bcb 100644 +--- a/lib/multi.c ++++ b/lib/multi.c +@@ -2530,7 +2530,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, + multistate(data, MSTATE_CONNECT); + rc = CURLM_CALL_MULTI_PERFORM; + } +- free(newurl); + } + else { + /* after the transfer is done, go DONE */ +@@ -2542,7 +2541,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, + newurl = data->req.location; + data->req.location = NULL; + result = Curl_follow(data, newurl, FOLLOW_FAKE); +- free(newurl); + if(result) { + stream_error = TRUE; + result = multi_done(data, result, TRUE); +@@ -2561,6 +2559,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, + transfers */ + Curl_expire(data, 0, EXPIRE_RUN_NOW); + } ++ free(newurl); + break; + } + diff --git a/backport-openldap-create-ldap-URLs-correctly-for-IPv6-addresses.patch b/backport-openldap-create-ldap-URLs-correctly-for-IPv6-addresses.patch new file mode 100644 index 0000000000000000000000000000000000000000..aabfa79c87f860bdd22b2698e84cefe6aa3fd80f --- /dev/null +++ b/backport-openldap-create-ldap-URLs-correctly-for-IPv6-addresses.patch @@ -0,0 +1,35 @@ +From 56935a7dada6975d5a46aa494de0af195e4e8659 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Sat, 30 Mar 2024 11:14:54 +0100 +Subject: [PATCH] openldap: create ldap URLs correctly for IPv6 addresses + +Reported-by: Sergio Durigan Junior +Fixes #13228 +Closes #13235 + +Conflict:Context adapt +Reference:https://github.com/curl/curl/commit/56935a7dada6975d5a46aa494de0af195e4e8659 +--- + lib/openldap.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/lib/openldap.c b/lib/openldap.c +index 47266f64e44733..85a37b8186041a 100644 +--- a/lib/openldap.c ++++ b/lib/openldap.c +@@ -548,9 +548,12 @@ static CURLcode oldap_connect(struct Curl_easy *data, bool *done) + + (void)done; + +- hosturl = aprintf("ldap%s://%s:%d", +- conn->handler->flags & PROTOPT_SSL? "s": "", +- conn->host.name, conn->remote_port); ++ hosturl = aprintf("%s://%s%s%s:%d", ++ conn->handler->scheme, ++ conn->bits.ipv6_ip? "[": "", ++ conn->host.name, ++ conn->bits.ipv6_ip? "]": "", ++ conn->remote_port); + if(!hosturl) + return CURLE_OUT_OF_MEMORY; + diff --git a/backport-paramhlp-fix-CRLF-stripping-files-with-d-file.patch b/backport-paramhlp-fix-CRLF-stripping-files-with-d-file.patch new file mode 100644 index 0000000000000000000000000000000000000000..2e2bd2357df2fe3f0130e91e7371d89eda7e473f --- /dev/null +++ b/backport-paramhlp-fix-CRLF-stripping-files-with-d-file.patch @@ -0,0 +1,100 @@ +From 923f7f8ce51b7f2f20282883cdafeb283310f3d9 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Wed, 6 Mar 2024 15:39:09 +0100 +Subject: [PATCH] paramhlp: fix CRLF-stripping files with "-d @file" + +All CR and LF bytes should be stripped, as documented, and all other +bytes are inluded in the data. Starting now, it also excludes null bytes +as they would otherwise also cut the data short. + +Reported-by: Simon K +Fixes #13063 +Closes #13064 + +Conflict:remove change of docs/cmdline-opts/data.md which is not exist +Reference:https://github.com/curl/curl/commit/923f7f8ce51b7f2f20282883cdafeb283310f3d9 +--- + src/tool_paramhlp.c | 63 +++++++++++++++++++++++++++++++-------- + 1 files changed, 51 insertions(+), 12 deletions(-) + +diff --git a/src/tool_paramhlp.c b/src/tool_paramhlp.c +index 2725815000dc95..c26f6bbefd775c 100644 +--- a/src/tool_paramhlp.c ++++ b/src/tool_paramhlp.c +@@ -63,6 +63,33 @@ struct getout *new_getout(struct OperationConfig *config) + return node; + } + ++#define ISCRLF(x) (((x) == '\r') || ((x) == '\n') || ((x) == '\0')) ++ ++/* memcrlf() has two modes. Both operate on a given memory area with ++ a specified size. ++ ++ countcrlf FALSE - return number of bytes from the start that DO NOT include ++ any CR or LF or NULL ++ ++ countcrlf TRUE - return number of bytes from the start that are ONLY CR or ++ LF or NULL. ++ ++*/ ++static size_t memcrlf(char *orig, ++ bool countcrlf, /* TRUE if we count CRLF, FALSE ++ if we count non-CRLF */ ++ size_t max) ++{ ++ char *ptr = orig; ++ size_t total = max; ++ for(ptr = orig; max; max--, ptr++) { ++ bool crlf = ISCRLF(*ptr); ++ if(countcrlf ^ crlf) ++ return ptr - orig; ++ } ++ return total; /* no delimiter found */ ++} ++ + #define MAX_FILE2STRING (256*1024*1024) /* big enough ? */ + + ParameterError file2string(char **bufp, FILE *file) +@@ -71,18 +98,30 @@ ParameterError file2string(char **bufp, FILE *file) + DEBUGASSERT(MAX_FILE2STRING < INT_MAX); /* needs to fit in an int later */ + curlx_dyn_init(&dyn, MAX_FILE2STRING); + if(file) { +- char buffer[256]; +- +- while(fgets(buffer, sizeof(buffer), file)) { +- char *ptr = strchr(buffer, '\r'); +- if(ptr) +- *ptr = '\0'; +- ptr = strchr(buffer, '\n'); +- if(ptr) +- *ptr = '\0'; +- if(curlx_dyn_add(&dyn, buffer)) +- return PARAM_NO_MEM; +- } ++ do { ++ char buffer[4096]; ++ char *ptr; ++ size_t nread = fread(buffer, 1, sizeof(buffer), file); ++ if(ferror(file)) { ++ curlx_dyn_free(&dyn); ++ *bufp = NULL; ++ return PARAM_READ_ERROR; ++ } ++ ptr = buffer; ++ while(nread) { ++ size_t nlen = memcrlf(ptr, FALSE, nread); ++ if(curlx_dyn_addn(&dyn, ptr, nlen)) ++ return PARAM_NO_MEM; ++ nread -= nlen; ++ ++ if(nread) { ++ ptr += nlen; ++ nlen = memcrlf(ptr, TRUE, nread); ++ ptr += nlen; ++ nread -= nlen; ++ } ++ } ++ } while(!feof(file)); + } + *bufp = curlx_dyn_ptr(&dyn); + return PARAM_OK; diff --git a/backport-pre-CVE-2024-2004.patch b/backport-pre-CVE-2024-2004.patch new file mode 100644 index 0000000000000000000000000000000000000000..d2975551337f5f0d2c66d6799c1688d0ba2867ac --- /dev/null +++ b/backport-pre-CVE-2024-2004.patch @@ -0,0 +1,159 @@ +From de0cd5e8e7c9a0cbf28c4a9dec998ad4b6dfa08c Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Mon, 11 Dec 2023 23:17:26 +0100 +Subject: [PATCH] test1474: removed + +The test was already somewhat flaky and disabled on several platforms, +and after 1da640abb688 even more unstable. + +Conflict:Context adapt +Reference:https://github.com/curl/curl/commit/de0cd5e8e7c9a0cbf28c4a9dec998ad4b6dfa08c +--- + tests/data/Makefile.inc | 2 +- + tests/data/test1474 | 121 ---------------------------------------- + 2 files changed, 1 insertion(+), 122 deletions(-) + delete mode 100644 tests/data/test1474 + +diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc +index de13c525e..6d1a2ad13 100644 +--- a/tests/data/Makefile.inc ++++ b/tests/data/Makefile.inc +@@ -186,7 +186,7 @@ test1439 test1440 test1441 test1442 test1443 test1444 test1445 test1446 \ + test1447 test1448 test1449 test1450 test1451 test1452 test1453 test1454 \ + test1455 test1456 test1457 test1458 test1459 test1460 test1461 test1462 \ + test1463 test1464 test1465 test1466 test1467 test1468 test1469 test1470 \ +-test1471 test1472 test1473 test1474 \ ++test1471 test1472 test1473 \ + \ + test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \ + test1508 test1509 test1510 test1511 test1512 test1513 test1514 test1515 \ +diff --git a/tests/data/test1474 b/tests/data/test1474 +deleted file mode 100644 +index a87044d1a..000000000 +--- a/tests/data/test1474 ++++ /dev/null +@@ -1,121 +0,0 @@ +- +-# This test is quite timing dependent and tricky to set up. The time line of +-# test operations looks like this: +-# +-# 1. curl sends a PUT request with Expect: 100-continue and waits only 1 msec +-# for a 100 response. +-# 2. The HTTP server accepts the connection but waits 500 msec before acting +-# on the request. +-# 3. curl doesn't receive the expected 100 response before its timeout expires, +-# so it starts sending the body. It is throttled by a --limit-rate, so it +-# sends the first 64 KiB then stops for 1000 msec due to this +-# throttling. +-# 4. The server sends its 417 response while curl is throttled. +-# 5. curl responds to this 417 response by closing the connection (because it +-# has a half-completed response outstanding) and starting a new one. This +-# new request does not have an Expect: header so it is sent without delay. +-# It's still throttled, however, so it takes about 16 seconds to finish +-# sending. +-# 6. The server receives the response and this time acks it with 200. +-# +-# Because of the timing sensitivity (scheduling delays of 500 msec can cause +-# the test to fail), this test is marked flaky to avoid it being run in the CI +-# builds which are often run on overloaded servers. +-# Increasing the --limit-rate would decrease the test time, but at the cost of +-# becoming even more sensitive to delays (going from 500 msec to 250 msec or +-# less of accepted delay before failure). Adding a --speed-time would increase +-# the 1 second delay between writes to longer, but it would also increase the +-# total time needed by the test, which is already quite high. +-# +-# The assumption in step 3 is also broken on NetBSD 9.3, OpenBSD 7.3 and +-# Solaris 10 as they only usually send about half the requested amount of data +-# (see https://curl.se/mail/lib-2023-09/0021.html). +- +- +-HTTP +-HTTP PUT +-Expect +-flaky +-timing-dependent +- +- +-# Server-side +- +-# 417 means the server didn't like the Expect header +- +-HTTP/1.1 417 BAD swsbounce +-Date: Tue, 09 Nov 2010 14:49:00 GMT +-Server: test-server/fake +-Content-Length: 0 +- +- +- +-HTTP/1.1 200 OK +-Date: Tue, 09 Nov 2010 14:49:00 GMT +-Server: test-server/fake +-Content-Length: 10 +- +-blablabla +- +- +-HTTP/1.1 417 BAD swsbounce +-Date: Tue, 09 Nov 2010 14:49:00 GMT +-Server: test-server/fake +-Content-Length: 0 +- +-HTTP/1.1 200 OK +-Date: Tue, 09 Nov 2010 14:49:00 GMT +-Server: test-server/fake +-Content-Length: 10 +- +-blablabla +- +- +-no-expect +-delay: 500 +-connection-monitor +- +- +- +-# Client-side +- +- +-http +- +- +-HTTP PUT with Expect: 100-continue and 417 response during upload +- +- +-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -T %LOGDIR/test%TESTNUMBER.txt --limit-rate 64K --expect100-timeout 0.001 +- +- +-perl -e "print 'Test does not work on this BSD system' if ( $^O eq 'netbsd' || $^O eq 'openbsd' || ($^O eq 'solaris' && qx/uname -r/ * 100 <= 510));" +- +-# Must be large enough to trigger curl's automatic 100-continue behaviour +- +-%repeat[132 x S]%%repeat[16462 x xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%0a]% +- +- +- +-# Verify data after the test has been "shot" +- +- +-PUT /we/want/%TESTNUMBER HTTP/1.1 +-Host: %HOSTIP:%HTTPPORT +-User-Agent: curl/%VERSION +-Accept: */* +-Content-Length: 1053701 +-Expect: 100-continue +- +-%repeat[132 x S]%%repeat[1021 x xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%0a]%%repeat[60 x x]%[DISCONNECT] +-PUT /we/want/%TESTNUMBER HTTP/1.1 +-Host: %HOSTIP:%HTTPPORT +-User-Agent: curl/%VERSION +-Accept: */* +-Content-Length: 1053701 +- +-%repeat[132 x S]%%repeat[16462 x xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%0a]% +-[DISCONNECT] +- +- +- +-- +2.33.0 + diff --git a/backport-tool_cb_rea-limit-rate-unpause-for-T-uploads.patch b/backport-tool_cb_rea-limit-rate-unpause-for-T-uploads.patch new file mode 100644 index 0000000000000000000000000000000000000000..fd9874966cf03456c40039648dcc807d45b62cd5 --- /dev/null +++ b/backport-tool_cb_rea-limit-rate-unpause-for-T-uploads.patch @@ -0,0 +1,61 @@ +From 5f4aaf8b66ef04208c1c2121d4b780c792303f32 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Tue, 30 Apr 2024 11:07:28 +0200 +Subject: [PATCH] tool_cb_rea: limit rate unpause for -T . uploads +Reference:https://github.com/curl/curl/pull/13506 + +--- + src/tool_cb_rea.c | 30 ++++++++++++++++++++++++++++-- + 1 file changed, 28 insertions(+), 2 deletions(-) + +diff --git a/src/tool_cb_rea.c b/src/tool_cb_rea.c +index d70a9b9..f510f81 100644 +--- a/src/tool_cb_rea.c ++++ b/src/tool_cb_rea.c +@@ -36,6 +36,7 @@ + #include "tool_operate.h" + #include "tool_util.h" + #include "tool_msgs.h" ++#include "tool_sleep.h" + + #include "memdebug.h" /* keep this as LAST include */ + +@@ -124,8 +125,33 @@ int tool_readbusy_cb(void *clientp, + (void)ulnow; /* unused */ + + if(config->readbusy) { +- config->readbusy = FALSE; +- curl_easy_pause(per->curl, CURLPAUSE_CONT); ++ /* lame code to keep the rate down because the input might not deliver ++ anything, get paused again and come back here immediately */ ++ static long rate = 500; ++ static struct timeval prev; ++ static curl_off_t ulprev; ++ ++ if(ulprev == ulnow) { ++ /* it did not upload anything since last call */ ++ struct timeval now = tvnow(); ++ if(prev.tv_sec) ++ /* get a rolling average rate */ ++ /* rate = rate - rate/4 + tvdiff(now, prev)/4; */ ++ rate -= rate/4 - tvdiff(now, prev)/4; ++ prev = now; ++ } ++ else { ++ rate = 50; ++ ulprev = ulnow; ++ } ++ if(rate >= 50) { ++ /* keeps the looping down to 20 times per second in the crazy case */ ++ config->readbusy = FALSE; ++ curl_easy_pause(per->curl, CURLPAUSE_CONT); ++ } ++ else ++ /* sleep half a period */ ++ tool_go_sleep(25); + } + + return per->noprogress? 0 : CURL_PROGRESSFUNC_CONTINUE; +-- +2.27.0 + diff --git a/backport-tool_cfgable-free-proxy_-cipher13_list-on-exit.patch b/backport-tool_cfgable-free-proxy_-cipher13_list-on-exit.patch new file mode 100644 index 0000000000000000000000000000000000000000..ada0c62ca534dc4c439b04002332dc879fa7afbc --- /dev/null +++ b/backport-tool_cfgable-free-proxy_-cipher13_list-on-exit.patch @@ -0,0 +1,28 @@ +From 87d14e77b7d59a961eb56500017c0580f89f252b Mon Sep 17 00:00:00 2001 +From: Jan Venekamp <1422460+jan2000@users.noreply.github.com> +Date: Sat, 4 May 2024 03:05:51 +0200 +Subject: [PATCH] tool_cfgable: free {proxy_}cipher13_list on exit + +Author: Jan Venekamp +Reviewed-by: Daniel Gustafsson +Closes: #13531 + +Conflict:NA +Reference:https://github.com/curl/curl/commit/87d14e77b7d59a961eb56500017c0580f89f252b +--- + src/tool_cfgable.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/tool_cfgable.c b/src/tool_cfgable.c +index bb271583263db3..5564e250d33782 100644 +--- a/src/tool_cfgable.c ++++ b/src/tool_cfgable.c +@@ -114,6 +114,8 @@ static void free_config_fields(struct OperationConfig *config) + Curl_safefree(config->doh_url); + Curl_safefree(config->cipher_list); + Curl_safefree(config->proxy_cipher_list); ++ Curl_safefree(config->cipher13_list); ++ Curl_safefree(config->proxy_cipher13_list); + Curl_safefree(config->cert); + Curl_safefree(config->proxy_cert); + Curl_safefree(config->cert_type); diff --git a/curl.spec b/curl.spec index 9c3d9e4ecf1ad831fd63ff816dfb4599728f9608..018269934d5569d963378dd67e90af22194e45dc 100644 --- a/curl.spec +++ b/curl.spec @@ -2,11 +2,12 @@ %global libpsl_version %(pkg-config --modversion libpsl 2>/dev/null || echo 0) %global libssh_version %(pkg-config --modversion libssh 2>/dev/null || echo 0) %global openssl_version %({ pkg-config --modversion openssl 2>/dev/null || echo 0;} | sed 's|-|-0.|') +%global libnghttp2_version %(pkg-config --modversion libnghttp2 2>/dev/null || echo 0) %global _configure ../configure Name: curl Version: 8.4.0 -Release: 1 +Release: 6 Summary: Curl is used in command lines or scripts to transfer data License: curl URL: https://curl.se/ @@ -19,6 +20,18 @@ Patch11: backport-CVE-2023-46218.patch Patch12: backport-0001-CVE-2023-46219.patch Patch13: backport-0002-CVE-2023-46219.patch Patch15: backport-openssl-avoid-BN_num_bits-NULL-pointer-derefs.patch +Patch16: backport-pre-CVE-2024-2004.patch +Patch17: backport-CVE-2024-2004.patch +Patch18: backport-CVE-2024-2398.patch +Patch19: backport-tool_cb_rea-limit-rate-unpause-for-T-uploads.patch +#https://github.com/curl/curl/pull/13506 +Patch20: backport-paramhlp-fix-CRLF-stripping-files-with-d-file.patch +Patch21: backport-libssh2-set-length-to-0-if-strdup-failed.patch +Patch22: backport-openldap-create-ldap-URLs-correctly-for-IPv6-addresses.patch +Patch23: backport-multi-avoid-memory-leak-risk.patch +Patch24: backport-tool_cfgable-free-proxy_-cipher13_list-on-exit.patch +Patch25: backport-CVE-2024-7264-x509asn1-clean-up-GTime2str.patch +Patch26: backport-CVE-2024-7264-x509asn1-unittests-and-fixes-fo.patch BuildRequires: automake brotli-devel coreutils gcc groff krb5-devel BuildRequires: libidn2-devel libnghttp2-devel libpsl-devel @@ -45,6 +58,7 @@ command-line tool (curl) for transferring data using various protocols. Summary: A library for getting files from web servers Requires: libssh >= %{libssh_version} libpsl >= %{libpsl_version} Requires: openssl-libs >= 1:%{openssl_version} +Requires: libnghttp2 >= %{libnghttp2_version} Provides: libcurl-full = %{version}-%{release} Conflicts: curl < 7.66.0-3 @@ -203,6 +217,37 @@ rm -rf ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %{_mandir}/man3/* %changelog +* Wed Jul 31 2024 yinyongkang - 8.4.0-6 +- Type:CVE +- CVE:CVE-2024-7264 +- SUG:NA +- DESC:fix CVE-2024-7264 + +* Mon Jun 24 2024 zhouyihang - 8.4.0-5 +- Type:bugfix +- CVE:NA +- SUG:NA +- DESC:paramhlp: fix CRLF-stripping files with "-d @file" + libssh2: set length to 0 if strdup failed + openldap: create ldap URLs correctly for IPv6 addresses + multi: avoid memory-leak risk + tool_cfgable: free {proxy_}cipher13_list on exit + +* Wed Jun 12 2024 zhouyihang - 8.4.0-4 +- Type:bugfix +- CVE:NA +- SUG:NA +- DESC:add version require of nghttp2 for libcurl + +* Thu May 09 2024 baiguo - 8.4.0-3 +- DESC: tool_cb_rea: limit rate unpause for -T . uploads + +* Mon Apr 01 2024 zhouyihang - 8.4.0-2 +- Type:CVE +- CVE:CVE-2024-2004 CVE-2024-2398 +- SUG:NA +- DESC:fix CVE-2024-2004 CVE-2024-2398 + * Tue Jan 09 2024 zhouyihang - 8.4.0-1 - Type:requirement - CVE:NA