Compare commits

...

10 Commits

Author SHA1 Message Date
openeuler-ci-bot
f2bd9e6727
!390 [sync] PR-389: backport some patches from community
From: @openeuler-sync-bot 
Reviewed-by: @robertxw 
Signed-off-by: @robertxw
2025-05-07 08:47:09 +00:00
sherlock2010
b8fde0f065 backport some patches from community
(cherry picked from commit 32e5f660297b98c7d843705f97d988611853c2b5)
2025-05-07 14:36:24 +08:00
openeuler-ci-bot
6b3982853f
!379 backport patches
From: @XWwalker 
Reviewed-by: @jiangheng12 
Signed-off-by: @jiangheng12
2025-03-25 09:15:29 +00:00
xingwei
d322d176cf backport patches 2025-03-25 07:53:18 +00:00
openeuler-ci-bot
dc35064ac9
!373 [sync] PR-370: fix CVE-2025-0167 CVE-2025-0725
From: @openeuler-sync-bot 
Reviewed-by: @jiangheng12 
Signed-off-by: @jiangheng12
2025-02-12 02:04:16 +00:00
sherlock2010
b2ea774234 fix CVE-2025-0167 CVE-2025-0725
(cherry picked from commit 3606e8000c460859267b7358f19919fd80b1ff3c)
2025-02-11 16:11:13 +08:00
openeuler-ci-bot
e809167868
!364 [sync] PR-361: fix CVE-2024-11053
From: @openeuler-sync-bot 
Reviewed-by: @jiangheng12 
Signed-off-by: @jiangheng12
2025-01-03 08:56:56 +00:00
sherlock2010
99b8b65391 fix CVE-2024-11053
(cherry picked from commit ad320b0ab2028bcbb0c7371035f201624e3a01a2)
2025-01-03 16:01:45 +08:00
openeuler-ci-bot
7cf8495b55
!360 [sync] PR-354: cookie: treat cookie name case sensitively
From: @openeuler-sync-bot 
Reviewed-by: @jiangheng12 
Signed-off-by: @jiangheng12
2024-12-13 09:39:19 +00:00
sherlock2010
43afd63dd7 cookie: treat cookie name case sensitively
(cherry picked from commit 151d12ece23e52fa288aeda79ca98fe9e30ebb70)
2024-12-10 15:39:51 +08:00
11 changed files with 1692 additions and 1 deletions

View File

@ -0,0 +1,358 @@
From e9b9bbac22c26cf67316fa8e6c6b9e831af31949 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Fri, 15 Nov 2024 11:06:36 +0100
Subject: [PATCH] netrc: address several netrc parser flaws
- make sure that a match that returns a username also returns a
password, that should be blank if no password is found
- fix handling of multiple logins for same host where the password/login
order might be reversed.
- reject credentials provided in the .netrc if they contain ASCII control
codes - if the used protocol does not support such (like HTTP and WS do)
Reported-by: Harry Sintonen
Add test 478, 479 and 480 to verify. Updated unit 1304.
Closes #15586
Conflict:context adapt
remove some code irrelevant with CVE
Reference:https://github.com/curl/curl/commit/e9b9bbac22c26cf67316fa8e6c6b9e831af31949
---
lib/netrc.c | 19 ++++++++++++++++++
tests/data/Makefile.inc | 1 +
tests/data/test479 | 107 ++++++++++++++++++++++++++++++++++++++
tests/unit/unit1304.c | 75 ++++++++-------------------
3 files changed, 180 insertions(+), 20 deletions(-)
create mode 100644 tests/data/test478
create mode 100644 tests/data/test479
create mode 100644 tests/data/test480
diff --git a/lib/netrc.c b/lib/netrc.c
index b771b60..9e183a2 100644
--- a/lib/netrc.c
+++ b/lib/netrc.c
@@ -152,6 +152,7 @@ static int parsenetrc(const char *host,
retcode = NETRC_FAILED; /* allocation failed */
goto out;
}
+ state_our_login = TRUE;
login_alloc = TRUE;
}
state_login = 0;
@@ -181,6 +182,16 @@ static int parsenetrc(const char *host,
state = HOSTFOUND;
state_our_login = FALSE;
}
+ else if(strcasecompare("default", tok)) {
+ state = HOSTVALID;
+ retcode = NETRC_SUCCESS; /* we did find our host */
+ Curl_safefree(password);
+ if(!specific_login)
+ if(login_alloc) {
+ free(login);
+ login_alloc = FALSE;
+ }
+ }
break;
} /* switch (state) */
@@ -189,6 +200,14 @@ static int parsenetrc(const char *host,
} /* while fgets() */
out:
+ if(!retcode && !password && state_our_login) {
+ /* success without a password, set a blank one */
+ password = strdup("");
+ if(!password)
+ retcode = 1; /* out of memory */
+ else
+ password_alloc = TRUE;
+ }
if(!retcode) {
/* success */
*login_changed = FALSE;
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
index ea5221c00fd419..53f62c6e28f650 100644
--- a/tests/data/Makefile.inc
+++ b/tests/data/Makefile.inc
@@ -77,6 +77,7 @@ test435 test436 test437 test438 test439 test440 test441 test442 test443 \
test430 test431 test432 test433 test434 test435 test445 test446\
\
test442 test443 test444 \
+test479 \
test490 test491 test492 test493 test494 \
\
test500 test501 test502 test503 test504 test505 test506 test507 test508 \
diff --git a/tests/data/test479 b/tests/data/test479
new file mode 100644
index 00000000000000..d7ce4652fae272
--- /dev/null
+++ b/tests/data/test479
@@ -0,0 +1,107 @@
+<testcase>
+<info>
+<keywords>
+netrc
+HTTP
+</keywords>
+</info>
+#
+# Server-side
+<reply>
+<data crlf="yes">
+HTTP/1.1 301 Follow this you fool
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 6
+Connection: close
+Location: http://b.com/%TESTNUMBER0002
+
+-foo-
+</data>
+
+<data2 crlf="yes">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 7
+Connection: close
+
+target
+</data2>
+
+<datacheck crlf="yes">
+HTTP/1.1 301 Follow this you fool
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 6
+Connection: close
+Location: http://b.com/%TESTNUMBER0002
+
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 7
+Connection: close
+
+target
+</datacheck>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+<features>
+proxy
+</features>
+<name>
+.netrc with redirect and default without password
+</name>
+<command>
+--netrc --netrc-file log/netrc%TESTNUMBER -L -x http://%HOSTIP:%HTTPPORT/ http://a.com/
+</command>
+<file name="log/netrc%TESTNUMBER" >
+
+machine a.com
+ login alice
+ password alicespassword
+
+default
+ login bob
+
+</file>
+</client>
+
+<verify>
+<protocol>
+GET http://a.com/ HTTP/1.1
+Host: a.com
+Authorization: Basic %b64[alice:alicespassword]b64%
+User-Agent: curl/%VERSION
+Accept: */*
+Proxy-Connection: Keep-Alive
+
+GET http://b.com/%TESTNUMBER0002 HTTP/1.1
+Host: b.com
+Authorization: Basic %b64[bob:]b64%
+User-Agent: curl/%VERSION
+Accept: */*
+Proxy-Connection: Keep-Alive
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/unit/unit1304.c b/tests/unit/unit1304.c
index 238d3c0f7fb09a..817887b94c8748 100644
--- a/tests/unit/unit1304.c
+++ b/tests/unit/unit1304.c
@@ -32,13 +32,8 @@ static char *password;
static CURLcode unit_setup(void)
{
- password = strdup("");
- login = strdup("");
- if(!password || !login) {
- Curl_safefree(password);
- Curl_safefree(login);
- return CURLE_OUT_OF_MEMORY;
- }
+ password = NULL;
+ login = NULL;
return CURLE_OK;
}
@@ -60,86 +55,52 @@ UNITTEST_START
result = Curl_parsenetrc("test.example.com", &login, &password,
&login_changed, &password_changed, filename);
fail_unless(result == 1, "Host not found should return 1");
- abort_unless(password != NULL, "returned NULL!");
- fail_unless(password[0] == 0, "password should not have been changed");
- abort_unless(login != NULL, "returned NULL!");
- fail_unless(login[0] == 0, "login should not have been changed");
+ abort_unless(password == NULL, "password did not return NULL!");
+ abort_unless(login == NULL, "user did not return NULL!");
/*
* Test a non existent login in our netrc file.
*/
- free(login);
- login = strdup("me");
- abort_unless(login != NULL, "returned NULL!");
+ login = (char *)"me";
result = Curl_parsenetrc("example.com", &login, &password,
&login_changed, &password_changed, filename);
fail_unless(result == 0, "Host should have been found");
- abort_unless(password != NULL, "returned NULL!");
- fail_unless(password[0] == 0, "password should not have been changed");
- fail_unless(!password_changed, "password should not have been changed");
- abort_unless(login != NULL, "returned NULL!");
- fail_unless(strncmp(login, "me", 2) == 0,
- "login should not have been changed");
- fail_unless(!login_changed, "login should not have been changed");
+ abort_unless(password == NULL, "password is not NULL!");
/*
* Test a non existent login and host in our netrc file.
*/
- free(login);
- login = strdup("me");
- abort_unless(login != NULL, "returned NULL!");
+ login = (char *)"me";
result = Curl_parsenetrc("test.example.com", &login, &password,
&login_changed, &password_changed, filename);
fail_unless(result == 1, "Host not found should return 1");
- abort_unless(password != NULL, "returned NULL!");
- fail_unless(password[0] == 0, "password should not have been changed");
- abort_unless(login != NULL, "returned NULL!");
- fail_unless(strncmp(login, "me", 2) == 0,
- "login should not have been changed");
+ abort_unless(password == NULL, "password is not NULL!");
/*
* Test a non existent login (substring of an existing one) in our
* netrc file.
*/
- free(login);
- login = strdup("admi");
- abort_unless(login != NULL, "returned NULL!");
+ login = (char *)"admi";
result = Curl_parsenetrc("example.com", &login, &password,
&login_changed, &password_changed, filename);
fail_unless(result == 0, "Host should have been found");
- abort_unless(password != NULL, "returned NULL!");
- fail_unless(password[0] == 0, "password should not have been changed");
- fail_unless(!password_changed, "password should not have been changed");
- abort_unless(login != NULL, "returned NULL!");
- fail_unless(strncmp(login, "admi", 4) == 0,
- "login should not have been changed");
- fail_unless(!login_changed, "login should not have been changed");
+ abort_unless(password == NULL, "password is not NULL!");
/*
* Test a non existent login (superstring of an existing one)
* in our netrc file.
*/
- free(login);
- login = strdup("adminn");
- abort_unless(login != NULL, "returned NULL!");
+ login = (char *)"adminn";
result = Curl_parsenetrc("example.com", &login, &password,
&login_changed, &password_changed, filename);
fail_unless(result == 0, "Host should have been found");
- abort_unless(password != NULL, "returned NULL!");
- fail_unless(password[0] == 0, "password should not have been changed");
- fail_unless(!password_changed, "password should not have been changed");
- abort_unless(login != NULL, "returned NULL!");
- fail_unless(strncmp(login, "adminn", 6) == 0,
- "login should not have been changed");
- fail_unless(!login_changed, "login should not have been changed");
+ abort_unless(password == NULL, "password is not NULL!");
/*
* Test for the first existing host in our netrc file
* with login[0] = 0.
*/
- free(login);
- login = strdup("");
- abort_unless(login != NULL, "returned NULL!");
+ login = NULL;
result = Curl_parsenetrc("example.com", &login, &password,
&login_changed, &password_changed, filename);
fail_unless(result == 0, "Host should have been found");
@@ -159,8 +126,9 @@ UNITTEST_START
* with login[0] != 0.
*/
free(password);
- password = strdup("");
- abort_unless(password != NULL, "returned NULL!");
+ free(login);
+ password = NULL;
+ login = NULL;
result = Curl_parsenetrc("example.com", &login, &password,
&login_changed, &password_changed, filename);
fail_unless(result == 0, "Host should have been found");
@@ -177,11 +145,9 @@ UNITTEST_START
* with login[0] = 0.
*/
free(password);
- password = strdup("");
- abort_unless(password != NULL, "returned NULL!");
+ password = NULL;
free(login);
- login = strdup("");
- abort_unless(login != NULL, "returned NULL!");
+ login = NULL;
result = Curl_parsenetrc("curl.example.com", &login, &password,
&login_changed, &password_changed, filename);
fail_unless(result == 0, "Host should have been found");
@@ -198,8 +164,9 @@ UNITTEST_START
* with login[0] != 0.
*/
free(password);
- password = strdup("");
- abort_unless(password != NULL, "returned NULL!");
+ free(login);
+ password = NULL;
+ login = NULL;
result = Curl_parsenetrc("curl.example.com", &login, &password,
&login_changed, &password_changed, filename);
fail_unless(result == 0, "Host should have been found");

View File

@ -0,0 +1,174 @@
From 0e120c5b925e8ca75d5319e319e5ce4b8080d8eb Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Fri, 3 Jan 2025 16:22:27 +0100
Subject: [PATCH] netrc: 'default' with no credentials is not a match
Test 486 verifies.
Reported-by: Yihang Zhou
Closes #15908
Conflict:context adapt
Reference:https://github.com/curl/curl/commit/0e120c5b925e8ca75d5319e
---
lib/netrc.c | 19 ++++--
tests/data/Makefile.inc | 2 +-
tests/data/test486 | 105 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 118 insertions(+), 8 deletions(-)
create mode 100644 tests/data/test486
diff --git a/lib/netrc.c b/lib/netrc.c
index 7d2b903..8096b4b 100644
--- a/lib/netrc.c
+++ b/lib/netrc.c
@@ -200,13 +200,18 @@ static int parsenetrc(const char *host,
} /* while fgets() */
out:
- if(!retcode && !password && state_our_login) {
- /* success without a password, set a blank one */
- password = strdup("");
- if(!password)
- retcode = 1; /* out of memory */
- else
- password_alloc = TRUE;
+ if(!retcode) {
+ if(!password && state_our_login) {
+ /* success without a password, set a blank one */
+ password = strdup("");
+ if(!password)
+ retcode = 1; /* out of memory */
+ else
+ password_alloc = TRUE;
+ }
+ else if(!login && !password)
+ /* a default with no credentials */
+ retcode = NETRC_FILE_MISSING;
}
if(!retcode) {
/* success */
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
index 9ec101a7c74b..fc5e4cef5668 100644
--- a/tests/data/Makefile.inc
+++ b/tests/data/Makefile.inc
@@ -78,7 +78,7 @@ test426 \
test430 test431 test432 test433 test434 test435 test445 test446\
\
test442 test443 test444 \
-test479 \
+test479 test486 \
test490 test491 test492 test493 test494 \
\
test500 test501 test502 test503 test504 test505 test506 test507 test508 \
diff --git a/tests/data/test486 b/tests/data/test486
new file mode 100644
index 000000000000..53efae597a1b
--- /dev/null
+++ b/tests/data/test486
@@ -0,0 +1,105 @@
+<testcase>
+<info>
+<keywords>
+netrc
+HTTP
+</keywords>
+</info>
+#
+# Server-side
+<reply>
+<data crlf="yes">
+HTTP/1.1 301 Follow this you fool
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 6
+Connection: close
+Location: http://b.com/%TESTNUMBER0002
+
+-foo-
+</data>
+
+<data2 crlf="yes">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 7
+Connection: close
+
+target
+</data2>
+
+<datacheck crlf="yes">
+HTTP/1.1 301 Follow this you fool
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 6
+Connection: close
+Location: http://b.com/%TESTNUMBER0002
+
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 7
+Connection: close
+
+target
+</datacheck>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+<features>
+proxy
+</features>
+<name>
+.netrc with redirect and "default" with no password or login
+</name>
+<command>
+--netrc --netrc-file log/netrc%TESTNUMBER -L -x http://%HOSTIP:%HTTPPORT/ http://a.com/
+</command>
+<file name="log/netrc%TESTNUMBER" >
+
+machine a.com
+ login alice
+ password alicespassword
+
+default
+
+</file>
+</client>
+
+<verify>
+<protocol>
+GET http://a.com/ HTTP/1.1
+Host: a.com
+Authorization: Basic %b64[alice:alicespassword]b64%
+User-Agent: curl/%VERSION
+Accept: */*
+Proxy-Connection: Keep-Alive
+
+GET http://b.com/%TESTNUMBER0002 HTTP/1.1
+Host: b.com
+User-Agent: curl/%VERSION
+Accept: */*
+Proxy-Connection: Keep-Alive
+
+</protocol>
+</verify>
+</testcase>

View File

@ -0,0 +1,326 @@
From 76f83f0db23846e254d940ec7fe141010077eb88 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Fri, 24 Jan 2025 11:13:24 +0100
Subject: [PATCH] content_encoding: drop support for zlib before 1.2.0.4
zlib 1.2.0.4 was released on 10 August 2003
Closes #16079
Conflict:context adapt
Reference:https://github.com/curl/curl/commit/76f83f0db23846e254d940ec7
---
docs/INTERNALS.md | 2 +-
lib/content_encoding.c | 232 ++---------------------------------------
2 files changed, 8 insertions(+), 226 deletions(-)
diff --git a/docs/INTERNALS.md b/docs/INTERNALS.md
index 176ca52..a5b0efb 100644
--- a/docs/INTERNALS.md
+++ b/docs/INTERNALS.md
@@ -86,7 +86,7 @@ Dependencies
- OpenSSL 0.9.7
- GnuTLS 3.1.10
- - zlib 1.1.4
+ - zlib 1.2.0.4
- libssh2 1.0
- c-ares 1.16.0
- libidn2 2.0.0
diff --git a/lib/content_encoding.c b/lib/content_encoding.c
index c870df2..74f2e68 100644
--- a/lib/content_encoding.c
+++ b/lib/content_encoding.c
@@ -52,31 +52,13 @@
#define DSIZ CURL_MAX_WRITE_SIZE /* buffer size for decompressed data */
-
#ifdef HAVE_LIBZ
-/* Comment this out if zlib is always going to be at least ver. 1.2.0.4
- (doing so will reduce code size slightly). */
-#define OLD_ZLIB_SUPPORT 1
-
-#define GZIP_MAGIC_0 0x1f
-#define GZIP_MAGIC_1 0x8b
-
-/* gzip flag byte */
-#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
-#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
-#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
-#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
-#define COMMENT 0x10 /* bit 4 set: file comment present */
-#define RESERVED 0xE0 /* bits 5..7: reserved */
-
typedef enum {
ZLIB_UNINIT, /* uninitialized */
ZLIB_INIT, /* initialized */
ZLIB_INFLATING, /* inflating started. */
ZLIB_EXTERNAL_TRAILER, /* reading external trailer */
- ZLIB_GZIP_HEADER, /* reading gzip header */
- ZLIB_GZIP_INFLATING, /* inflating gzip stream */
ZLIB_INIT_GZIP /* initialized in transparent gzip mode */
} zlibInitState;
@@ -120,9 +102,6 @@ static CURLcode
exit_zlib(struct Curl_easy *data,
z_stream *z, zlibInitState *zlib_init, CURLcode result)
{
- if(*zlib_init == ZLIB_GZIP_HEADER)
- Curl_safefree(z->next_in);
-
if(*zlib_init != ZLIB_UNINIT) {
if(inflateEnd(z) != Z_OK && result == CURLE_OK)
result = process_zlib_error(data, z);
@@ -171,8 +150,7 @@ static CURLcode inflate_stream(struct Curl_easy *data,
/* Check state. */
if(zp->zlib_init != ZLIB_INIT &&
zp->zlib_init != ZLIB_INFLATING &&
- zp->zlib_init != ZLIB_INIT_GZIP &&
- zp->zlib_init != ZLIB_GZIP_INFLATING)
+ zp->zlib_init != ZLIB_INIT_GZIP)
return exit_zlib(data, z, &zp->zlib_init, CURLE_WRITE_ERROR);
/* Dynamically allocate a buffer for decompression because it's uncommonly
@@ -321,6 +299,7 @@ static CURLcode gzip_init_writer(struct Curl_easy *data,
{
struct zlib_params *zp = (struct zlib_params *) &writer->params;
z_stream *z = &zp->z; /* zlib state structure */
+ const char *v = zlibVersion();
if(!writer->downstream)
return CURLE_WRITE_ERROR;
@@ -329,109 +308,21 @@ static CURLcode gzip_init_writer(struct Curl_easy *data,
z->zalloc = (alloc_func) zalloc_cb;
z->zfree = (free_func) zfree_cb;
- if(strcmp(zlibVersion(), "1.2.0.4") >= 0) {
- /* zlib ver. >= 1.2.0.4 supports transparent gzip decompressing */
+ if(strcmp(v, "1.2.0.4") >= 0) {
+ /* zlib version >= 1.2.0.4 supports transparent gzip decompressing */
if(inflateInit2(z, MAX_WBITS + 32) != Z_OK) {
return process_zlib_error(data, z);
}
zp->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */
}
else {
- /* we must parse the gzip header and trailer ourselves */
- if(inflateInit2(z, -MAX_WBITS) != Z_OK) {
- return process_zlib_error(data, z);
- }
- zp->trailerlen = 8; /* A CRC-32 and a 32-bit input size (RFC 1952, 2.2) */
- zp->zlib_init = ZLIB_INIT; /* Initial call state */
+ failf(data, "too old zlib version: %s", v);
+ return CURLE_FAILED_INIT;
}
return CURLE_OK;
}
-#ifdef OLD_ZLIB_SUPPORT
-/* Skip over the gzip header */
-static enum {
- GZIP_OK,
- GZIP_BAD,
- GZIP_UNDERFLOW
-} check_gzip_header(unsigned char const *data, ssize_t len, ssize_t *headerlen)
-{
- int method, flags;
- const ssize_t totallen = len;
-
- /* The shortest header is 10 bytes */
- if(len < 10)
- return GZIP_UNDERFLOW;
-
- if((data[0] != GZIP_MAGIC_0) || (data[1] != GZIP_MAGIC_1))
- return GZIP_BAD;
-
- method = data[2];
- flags = data[3];
-
- if(method != Z_DEFLATED || (flags & RESERVED) != 0) {
- /* Can't handle this compression method or unknown flag */
- return GZIP_BAD;
- }
-
- /* Skip over time, xflags, OS code and all previous bytes */
- len -= 10;
- data += 10;
-
- if(flags & EXTRA_FIELD) {
- ssize_t extra_len;
-
- if(len < 2)
- return GZIP_UNDERFLOW;
-
- extra_len = (data[1] << 8) | data[0];
-
- if(len < (extra_len + 2))
- return GZIP_UNDERFLOW;
-
- len -= (extra_len + 2);
- data += (extra_len + 2);
- }
-
- if(flags & ORIG_NAME) {
- /* Skip over NUL-terminated file name */
- while(len && *data) {
- --len;
- ++data;
- }
- if(!len || *data)
- return GZIP_UNDERFLOW;
-
- /* Skip over the NUL */
- --len;
- ++data;
- }
-
- if(flags & COMMENT) {
- /* Skip over NUL-terminated comment */
- while(len && *data) {
- --len;
- ++data;
- }
- if(!len || *data)
- return GZIP_UNDERFLOW;
-
- /* Skip over the NUL */
- --len;
- }
-
- if(flags & HEAD_CRC) {
- if(len < 2)
- return GZIP_UNDERFLOW;
-
- len -= 2;
- }
-
- *headerlen = totallen - len;
- return GZIP_OK;
-}
-#endif
-
static CURLcode gzip_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes)
@@ -447,117 +338,8 @@ static CURLcode gzip_unencode_write(struct Curl_easy *data,
return inflate_stream(data, writer, ZLIB_INIT_GZIP);
}
-#ifndef OLD_ZLIB_SUPPORT
- /* Support for old zlib versions is compiled away and we are running with
- an old version, so return an error. */
+ /* We are running with an old version: return error. */
return exit_zlib(data, z, &zp->zlib_init, CURLE_WRITE_ERROR);
-
-#else
- /* This next mess is to get around the potential case where there isn't
- * enough data passed in to skip over the gzip header. If that happens, we
- * malloc a block and copy what we have then wait for the next call. If
- * there still isn't enough (this is definitely a worst-case scenario), we
- * make the block bigger, copy the next part in and keep waiting.
- *
- * This is only required with zlib versions < 1.2.0.4 as newer versions
- * can handle the gzip header themselves.
- */
-
- switch(zp->zlib_init) {
- /* Skip over gzip header? */
- case ZLIB_INIT:
- {
- /* Initial call state */
- ssize_t hlen;
-
- switch(check_gzip_header((unsigned char *) buf, nbytes, &hlen)) {
- case GZIP_OK:
- z->next_in = (Bytef *) buf + hlen;
- z->avail_in = (uInt) (nbytes - hlen);
- zp->zlib_init = ZLIB_GZIP_INFLATING; /* Inflating stream state */
- break;
-
- case GZIP_UNDERFLOW:
- /* We need more data so we can find the end of the gzip header. It's
- * possible that the memory block we malloc here will never be freed if
- * the transfer abruptly aborts after this point. Since it's unlikely
- * that circumstances will be right for this code path to be followed in
- * the first place, and it's even more unlikely for a transfer to fail
- * immediately afterwards, it should seldom be a problem.
- */
- z->avail_in = (uInt) nbytes;
- z->next_in = malloc(z->avail_in);
- if(!z->next_in) {
- return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
- }
- memcpy(z->next_in, buf, z->avail_in);
- zp->zlib_init = ZLIB_GZIP_HEADER; /* Need more gzip header data state */
- /* We don't have any data to inflate yet */
- return CURLE_OK;
-
- case GZIP_BAD:
- default:
- return exit_zlib(data, z, &zp->zlib_init, process_zlib_error(data, z));
- }
-
- }
- break;
-
- case ZLIB_GZIP_HEADER:
- {
- /* Need more gzip header data state */
- ssize_t hlen;
- z->avail_in += (uInt) nbytes;
- z->next_in = Curl_saferealloc(z->next_in, z->avail_in);
- if(!z->next_in) {
- return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
- }
- /* Append the new block of data to the previous one */
- memcpy(z->next_in + z->avail_in - nbytes, buf, nbytes);
-
- switch(check_gzip_header(z->next_in, z->avail_in, &hlen)) {
- case GZIP_OK:
- /* This is the zlib stream data */
- free(z->next_in);
- /* Don't point into the malloced block since we just freed it */
- z->next_in = (Bytef *) buf + hlen + nbytes - z->avail_in;
- z->avail_in = (uInt) (z->avail_in - hlen);
- zp->zlib_init = ZLIB_GZIP_INFLATING; /* Inflating stream state */
- break;
-
- case GZIP_UNDERFLOW:
- /* We still don't have any data to inflate! */
- return CURLE_OK;
-
- case GZIP_BAD:
- default:
- return exit_zlib(data, z, &zp->zlib_init, process_zlib_error(data, z));
- }
-
- }
- break;
-
- case ZLIB_EXTERNAL_TRAILER:
- z->next_in = (Bytef *) buf;
- z->avail_in = (uInt) nbytes;
- return process_trailer(data, zp);
-
- case ZLIB_GZIP_INFLATING:
- default:
- /* Inflating stream state */
- z->next_in = (Bytef *) buf;
- z->avail_in = (uInt) nbytes;
- break;
- }
-
- if(z->avail_in == 0) {
- /* We don't have any data to inflate; wait until next time */
- return CURLE_OK;
- }
-
- /* We've parsed the header, now uncompress the data */
- return inflate_stream(data, writer, ZLIB_GZIP_INFLATING);
-#endif
}
static void gzip_close_writer(struct Curl_easy *data,

View File

@ -0,0 +1,41 @@
From c3857eca70e3bf293fff2fe0b3766cfcad1b1251 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Sat, 14 Dec 2024 23:09:16 +0100
Subject: [PATCH] altsvc: avoid integer overflow in expire calculation
A bad value here just makes for a bad alt-svc experience, not a security
problem.
Detected by OSS-Fuzz
Bug: https://issues.oss-fuzz.com/issues/383911309
Closes #15745
Conflict:context adapt
Reference:https://github.com/curl/curl/commit/c3857eca70e3bf293fff2fe0b3766cfcad1b1251
---
lib/altsvc.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/lib/altsvc.c b/lib/altsvc.c
index a3ab368c5014..62f2c545fe55 100644
--- a/lib/altsvc.c
+++ b/lib/altsvc.c
@@ -659,9 +659,13 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
srcalpnid, dstalpnid,
srcport, dstport);
if(as) {
- /* The expires time also needs to take the Age: value (if any) into
- account. [See RFC 7838 section 3.1] */
- as->expires = maxage + time(NULL);
+ time_t secs = time(NULL);
+ /* The expires time also needs to take the Age: value (if any)
+ into account. [See RFC 7838 section 3.1] */
+ if(maxage > (TIME_T_MAX - secs))
+ as->expires = TIME_T_MAX;
+ else
+ as->expires = maxage + secs;
as->persist = persist;
Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node);
infof(data, "Added alt-svc: %s:%d over %s", dsthost, dstport,

View File

@ -0,0 +1,62 @@
From 9919149aef67014150e2a1c75a7aa2c79204e30d Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Wed, 6 Nov 2024 11:26:25 +0100
Subject: [PATCH] cookie: treat cookie name case sensitively
Extend test 31 to verify
Reported-by: delogicsreal on github
Fixes #15492
Closes #15493
Conflict:context adapt
Reference:https://github.com/curl/curl/commit/9919149aef67014150e2a1c75a7aa2c79204e30d
---
lib/cookie.c | 2 +-
tests/data/test31 | 3 +++
2 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/lib/cookie.c b/lib/cookie.c
index ca8c3c596..e37d58f1d 100644
--- a/lib/cookie.c
+++ b/lib/cookie.c
@@ -989,7 +989,7 @@ replace_existing(struct Curl_easy *data,
clist = c->cookies[myhash];
replace_old = FALSE;
while(clist) {
- if(strcasecompare(clist->name, co->name)) {
+ if(!strcmp(clist->name, co->name)) {
/* the names are identical */
if(clist->domain && co->domain) {
diff --git a/tests/data/test31 b/tests/data/test31
index d9d073996..2d411b5cd 100644
--- a/tests/data/test31
+++ b/tests/data/test31
@@ -26,6 +26,7 @@ Set-Cookie: blankdomain=sure; domain=; path=/
%if !hyper
Set-Cookie: foobar=name; domain=anything.com; path=/ ; secure
Set-Cookie:ismatch=this ; domain=test31.curl; path=/silly/
+Set-Cookie:ISMATCH=this ; domain=test31.curl; path=/silly/
Set-Cookie: overwrite=this ; domain=test31.curl; path=/overwrite/
Set-Cookie: overwrite=this2 ; domain=test31.curl; path=/overwrite
Set-Cookie: sec1value=secure1 ; domain=test31.curl; path=/secure1/ ; secure
@@ -75,6 +76,7 @@ Set-Cookie: securewithspace=after ; secure =
%else
Set-Cookie: foobar=name; domain=anything.com; path=/ ; secure
Set-Cookie: ismatch=this ; domain=test31.curl; path=/silly/
+Set-Cookie:ISMATCH=this ; domain=test31.curl; path=/silly/
Set-Cookie: overwrite=this ; domain=test31.curl; path=/overwrite/
Set-Cookie: overwrite=this2 ; domain=test31.curl; path=/overwrite
Set-Cookie: sec1value=secure1 ; domain=test31.curl; path=/secure1/ ; secure
@@ -181,6 +183,7 @@ test31.curl FALSE /we/want/ FALSE 2118138987 nodomain value
#HttpOnly_.test31.curl TRUE /p2/ FALSE 0 httpo2 value2
#HttpOnly_.test31.curl TRUE /p1/ FALSE 0 httpo1 value1
.test31.curl TRUE /overwrite FALSE 0 overwrite this2
+.test31.curl TRUE /silly/ FALSE 0 ISMATCH this
.test31.curl TRUE /silly/ FALSE 0 ismatch this
</file>
</verify>
--
2.33.0

View File

@ -0,0 +1,176 @@
From 571e92f730831a860f8d2786674177ca08c0f592 Mon Sep 17 00:00:00 2001
From: Stefan Eissing <stefan@eissing.org>
Date: Mon, 10 Mar 2025 17:08:57 +0100
Subject: [PATCH] libssh: fix freeing of resources in disconnect
ssh's disconnect assumed that the session to the server could be shut
down successfully during disconnect. When this failed, e.g. timed out,
memory was leaked.
Closes #16659
Conflict:context adapt
Curl_dyn_free(&sshc->readdir_buf); => Curl_safefree(sshc->readdir_line);
Reference:https://github.com/curl/curl/commit/571e92f730831a860f8d2786674177ca08c0f592
---
lib/vssh/libssh.c | 95 ++++++++++++++++++++++++++---------------------
1 file changed, 53 insertions(+), 42 deletions(-)
diff --git a/lib/vssh/libssh.c b/lib/vssh/libssh.c
index 0467de041..8a08d8161 100644
--- a/lib/vssh/libssh.c
+++ b/lib/vssh/libssh.c
@@ -138,6 +138,7 @@ static void myssh_block2waitfor(struct connectdata *conn, bool block);
static CURLcode myssh_setup_connection(struct Curl_easy *data,
struct connectdata *conn);
+static void sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data);
/*
* SCP protocol handler.
@@ -1943,48 +1944,10 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
state(data, SSH_SESSION_FREE);
/* FALLTHROUGH */
case SSH_SESSION_FREE:
- if(sshc->ssh_session) {
- ssh_free(sshc->ssh_session);
- sshc->ssh_session = NULL;
- }
-
- /* worst-case scenario cleanup */
-
- DEBUGASSERT(sshc->ssh_session == NULL);
- DEBUGASSERT(sshc->scp_session == NULL);
-
- if(sshc->readdir_tmp) {
- ssh_string_free_char(sshc->readdir_tmp);
- sshc->readdir_tmp = NULL;
- }
-
- if(sshc->quote_attrs)
- sftp_attributes_free(sshc->quote_attrs);
-
- if(sshc->readdir_attrs)
- sftp_attributes_free(sshc->readdir_attrs);
-
- if(sshc->readdir_link_attrs)
- sftp_attributes_free(sshc->readdir_link_attrs);
-
- if(sshc->privkey)
- ssh_key_free(sshc->privkey);
- if(sshc->pubkey)
- ssh_key_free(sshc->pubkey);
-
- Curl_safefree(sshc->rsa_pub);
- Curl_safefree(sshc->rsa);
- Curl_safefree(sshc->quote_path1);
- Curl_safefree(sshc->quote_path2);
- Curl_safefree(sshc->readdir_line);
- Curl_safefree(sshc->readdir_linkPath);
- SSH_STRING_FREE_CHAR(sshc->homedir);
-
+ sshc_cleanup(sshc, data);
/* the code we are about to return */
result = sshc->actualcode;
-
memset(sshc, 0, sizeof(struct ssh_conn));
-
connclose(conn, "SSH session free");
sshc->state = SSH_SESSION_FREE; /* current */
sshc->nextstate = SSH_NO_STATE;
@@ -2328,6 +2291,52 @@ static CURLcode myssh_do_it(struct Curl_easy *data, bool *done)
return result;
}
+static void sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data)
+{
+ (void)data;
+ if(sshc->ssh_session) {
+ ssh_free(sshc->ssh_session);
+ sshc->ssh_session = NULL;
+ }
+
+ /* worst-case scenario cleanup */
+ DEBUGASSERT(sshc->ssh_session == NULL);
+ DEBUGASSERT(sshc->scp_session == NULL);
+
+ if(sshc->readdir_tmp) {
+ ssh_string_free_char(sshc->readdir_tmp);
+ sshc->readdir_tmp = NULL;
+ }
+ if(sshc->quote_attrs) {
+ sftp_attributes_free(sshc->quote_attrs);
+ sshc->quote_attrs = NULL;
+ }
+ if(sshc->readdir_attrs) {
+ sftp_attributes_free(sshc->readdir_attrs);
+ sshc->readdir_attrs = NULL;
+ }
+ if(sshc->readdir_link_attrs) {
+ sftp_attributes_free(sshc->readdir_link_attrs);
+ sshc->readdir_link_attrs = NULL;
+ }
+ if(sshc->privkey) {
+ ssh_key_free(sshc->privkey);
+ sshc->privkey = NULL;
+ }
+ if(sshc->pubkey) {
+ ssh_key_free(sshc->pubkey);
+ sshc->pubkey = NULL;
+ }
+
+ Curl_safefree(sshc->rsa_pub);
+ Curl_safefree(sshc->rsa);
+ Curl_safefree(sshc->quote_path1);
+ Curl_safefree(sshc->quote_path2);
+ Curl_safefree(sshc->readdir_line);
+ Curl_safefree(sshc->readdir_linkPath);
+ SSH_STRING_FREE_CHAR(sshc->homedir);
+}
+
/* BLOCKING, but the function is using the state machine so the only reason
this is still blocking is that the multi interface code has no support for
disconnecting operations that takes a while */
@@ -2336,10 +2345,10 @@ static CURLcode scp_disconnect(struct Curl_easy *data,
bool dead_connection)
{
CURLcode result = CURLE_OK;
- struct ssh_conn *ssh = &conn->proto.sshc;
+ struct ssh_conn *sshc = &conn->proto.sshc;
(void) dead_connection;
- if(ssh->ssh_session) {
+ if(sshc->ssh_session) {
/* only if there's a session still around to use! */
state(data, SSH_SESSION_DISCONNECT);
@@ -2347,6 +2356,7 @@ static CURLcode scp_disconnect(struct Curl_easy *data,
result = myssh_block_statemach(data, TRUE);
}
+ sshc_cleanup(sshc, data);
return result;
}
@@ -2500,6 +2510,7 @@ static CURLcode sftp_disconnect(struct Curl_easy *data,
struct connectdata *conn,
bool dead_connection)
{
+ struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result = CURLE_OK;
(void) dead_connection;
@@ -2512,9 +2523,9 @@ static CURLcode sftp_disconnect(struct Curl_easy *data,
}
DEBUGF(infof(data, "SSH DISCONNECT is done"));
+ sshc_cleanup(sshc, data);
return result;
-
}
static CURLcode sftp_done(struct Curl_easy *data, CURLcode status,
--
2.43.0

View File

@ -0,0 +1,48 @@
From e60166815448f1ce4cc27e59a16e5805e864113d Mon Sep 17 00:00:00 2001
From: Jay Satiro <raysatiro@yahoo.com>
Date: Mon, 24 Mar 2025 02:48:01 -0400
Subject: [PATCH] openssl: fix crash on missing cert password
- Return 0 for password length if OpenSSL is expecting a certificate
password but the user did not provide one.
Prior to this change libcurl would crash if OpenSSL called the certificate
password callback in libcurl but no password was provided (NULL).
Reported-by: Roman Zharkov
Fixes https://github.com/curl/curl/issues/16806
Closes https://github.com/curl/curl/pull/16807
Conflict:context adapt
Reference:https://github.com/curl/curl/commit/e60166815448f1ce4cc27e59a16e5805e864113d
---
lib/vtls/openssl.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
index 1beda3133..4d5e1be29 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
@@ -931,14 +931,14 @@ static char *ossl_strerror(unsigned long error, char *buf, size_t size)
}
static int passwd_callback(char *buf, int num, int encrypting,
- void *global_passwd)
+ void *password)
{
DEBUGASSERT(0 == encrypting);
- if(!encrypting) {
- int klen = curlx_uztosi(strlen((char *)global_passwd));
+ if(!encrypting && num >= 0 && password) {
+ int klen = curlx_uztosi(strlen((char *)password));
if(num > klen) {
- memcpy(buf, global_passwd, klen + 1);
+ memcpy(buf, password, klen + 1);
return klen;
}
}
--
2.43.0

View File

@ -0,0 +1,107 @@
From 5394cbf570cda0510d6f10bd875e9aba9f898ce4 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Tue, 7 Jun 2022 23:26:59 +0200
Subject: [PATCH] test391: verify --path-as-is with redirect
Conflict:context adapt
Reference:https://github.com/curl/curl/commit/5394cbf570cda0510d6f10bd875e9aba9f898ce4
---
tests/data/Makefile.inc | 2 +-
tests/data/test391 | 72 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 73 insertions(+), 1 deletion(-)
create mode 100644 tests/data/test391
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
index 2196e2fd9787..d41052e53907 100644
--- a/tests/data/Makefile.inc
+++ b/tests/data/Makefile.inc
@@ -64,7 +64,7 @@ test352 test353 test354 test355 test356 test357 test358 test359 test360 \
test361 test362 test363 test364 test365 test366 \
test387 test388 \
\
-test392 test393 test394 test395 test396 test397 \
+test391 test392 test393 test394 test395 test396 test397 \
\
test400 test401 test402 test403 test404 test405 test406 test407 test408 \
test409 test410 \
diff --git a/tests/data/test391 b/tests/data/test391
new file mode 100644
index 000000000..1eff2ef3e
--- /dev/null
+++ b/tests/data/test391
@@ -0,0 +1,72 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+--path-as-is
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 301 OK
+Content-Length: 6
+Content-Type: text/html
+Location: ../%TESTNUMBER0002
+
+-foo-
+</data>
+<data2>
+HTTP/1.1 200 OK
+Content-Length: 6
+Content-Type: text/html
+
+-muu-
+</data2>
+<datacheck>
+HTTP/1.1 301 OK
+Content-Length: 6
+Content-Type: text/html
+Location: ../%TESTNUMBER0002
+
+HTTP/1.1 200 OK
+Content-Length: 6
+Content-Type: text/html
+
+-muu-
+</datacheck>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+--path-as-is with redirect, keeping dotdots
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/../../%TESTNUMBER --path-as-is -L
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+GET /../../%TESTNUMBER HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+GET /../%TESTNUMBER0002 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+User-Agent: curl/%VERSION
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
--
2.33.0

View File

@ -0,0 +1,117 @@
From 654f8cb5f353905c6eb5b2a6ef7e5beafa7d0634 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Wed, 19 Feb 2025 23:55:31 +0100
Subject: [PATCH] tool_getparam: clear sensitive arguments better
curl attempts to clear some flags to hide them from snooping neighbors
(on platforms where it works). For example the credentials provided with
-u. Previously it would only do that if there was a space between the
option and the credentials as in "-u joe:s3cr3t" but not when done
without a separating space as in "-ujoe:s3cr3t".
This addresses that previous shortcoming.
Reported-by: kayrus on github
Fixes #16396
Closes #16401
Conflict:context adapt
Reference:https://github.com/curl/curl/commit/654f8cb5f353905c6eb5b2a6ef7e5beafa7d0634
---
src/tool_getparam.c | 19 ++++++++++++------
src/tool_getparam.h | 3 ++-
src/tool_parsecfg.c | 3 ++-
3 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/src/tool_getparam.c b/src/tool_getparam.c
index f66124d40a27..6944059df740 100644
--- a/src/tool_getparam.c
+++ b/src/tool_getparam.c
@@ -1564,7 +1564,8 @@ static ParameterError parse_time_cond(struct GlobalConfig *global,
ParameterError getparameter(const char *flag, /* f or -long-flag */
char *nextarg, /* NULL if unset */
- argv_item_t cleararg,
+ argv_item_t cleararg1,
+ argv_item_t cleararg2,
bool *usedarg, /* set to TRUE if the arg
has been used */
struct GlobalConfig *global,
@@ -1590,6 +1591,9 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
by using --OPTION or --no-OPTION */
#ifdef HAVE_WRITABLE_ARGV
argv_item_t clearthis = NULL;
+#else
+ (void)cleararg1;
+ (void)cleararg2;
#endif
*usedarg = FALSE; /* default is that we don't use the arg */
@@ -1669,6 +1671,9 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
if(!longopt && parse[1]) {
nextarg = (char *)&parse[1]; /* this is the actual extra parameter */
singleopt = TRUE; /* don't loop anymore after this */
+#ifdef HAVE_WRITABLE_ARGV
+ clearthis = &cleararg1[parse + 2 - flag];
+#endif
}
else if(!nextarg)
return PARAM_REQUIRES_PARAMETER;
@@ -1676,7 +1681,7 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
return PARAM_REQUIRES_PARAMETER;
else {
#ifdef HAVE_WRITABLE_ARGV
- clearthis = cleararg;
+ clearthis = cleararg2;
#endif
*usedarg = TRUE; /* mark it as used */
}
@@ -2889,8 +2894,8 @@ ParameterError parse_args(struct GlobalConfig *global, int argc,
}
}
- result = getparameter(orig_opt, nextarg, argv[i + 1], &passarg,
- global, config);
+ result = getparameter(orig_opt, nextarg, argv[i], argv[i + 1],
+ &passarg, global, config);
curlx_unicodefree(nextarg);
config = global->last;
if(result == PARAM_NEXT_OPERATION) {
@@ -2932,7 +2937,8 @@ ParameterError parse_args(struct GlobalConfig *global, int argc,
bool used;
/* Just add the URL please */
- result = getparameter("--url", orig_opt, argv[i], &used, global, config);
+ result = getparameter("--url", orig_opt, NULL, NULL,
+ &used, global, config);
}
if(!result)
diff --git a/src/tool_getparam.h b/src/tool_getparam.h
index beef191c66e8..bcfb35f0657e 100644
--- a/src/tool_getparam.h
+++ b/src/tool_getparam.h
@@ -361,7 +361,8 @@ const struct LongShort *findlongopt(const char *opt);
struct OperationConfig;
ParameterError getparameter(const char *flag, char *nextarg,
- argv_item_t cleararg,
+ argv_item_t cleararg1,
+ argv_item_t cleararg2,
bool *usedarg,
struct GlobalConfig *global,
struct OperationConfig *operation);
diff --git a/src/tool_parsecfg.c b/src/tool_parsecfg.c
index 651ec8e9f401..b9fd56b300ba 100644
--- a/src/tool_parsecfg.c
+++ b/src/tool_parsecfg.c
@@ -190,7 +190,8 @@ int parseconfig(const char *filename, struct GlobalConfig *global)
#ifdef DEBUG_CONFIG
fprintf(stderr, "PARAM: \"%s\"\n",(param ? param : "(null)"));
#endif
- res = getparameter(option, param, NULL, &usedarg, global, operation);
+ res = getparameter(option, param, NULL, NULL,
+ &usedarg, global, operation);
operation = global->last;
if(!res && param && *param && !usedarg)

View File

@ -0,0 +1,238 @@
From 66e5351e0adda5891b2ff17ccbafc81f620c0e01 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Sat, 28 Dec 2024 14:47:01 +0100
Subject: [PATCH] urlapi: fix redirect to a new fragment or query (only)
The redirect logic was broken when the redirect-to URL was a relative
URL only as a fragment or query (starting with '#' or '?').
Extended test 1560 to reproduce, then verify.
Reported-by: Jeroen Ooms
Fixes #15836
Closes #15848
Conflict:remove doc CURLOPT_PATH_AS_IS.md which is not exist
context adapt
Reference:https://github.com/curl/curl/commit/66e5351e0adda5891b2ff17ccbafc81f620c0e01
---
lib/urlapi.c | 102 ++++++------------------
tests/data/test391 | 2 +-
tests/libtest/lib1560.c | 32 +++++++
3 files changed, 60 insertions(+), 76 deletions(-)
diff --git a/lib/urlapi.c b/lib/urlapi.c
index b676c4d..0f8ffbf 100644
--- a/lib/urlapi.c
+++ b/lib/urlapi.c
@@ -275,8 +275,6 @@ static char *concat_url(const char *base, const char *relurl)
problems in the future...
*/
char *newest;
- char *protsep;
- char *pathsep;
size_t newlen;
bool host_changed = FALSE;
@@ -291,66 +289,35 @@ static char *concat_url(const char *base, const char *relurl)
return NULL; /* skip out of this NOW */
/* protsep points to the start of the host name */
- protsep = strstr(url_clone, "//");
+ char *protsep = strstr(url_clone, "//");
+ DEBUGASSERT(protsep);
if(!protsep)
protsep = url_clone;
else
protsep += 2; /* pass the slashes */
- if('/' != relurl[0]) {
- int level = 0;
-
- /* First we need to find out if there's a ?-letter in the URL,
+ if(('/' != relurl[0]) && ('#' != relurl[0])) {
+ /* First we need to find out if there is a ?-letter in the original URL,
and cut it and the right-side of that off */
- pathsep = strchr(protsep, '?');
+ char *pathsep = strchr(protsep, '?');
if(pathsep)
*pathsep = 0;
-
- /* we have a relative path to append to the last slash if there's one
- available, or if the new URL is just a query string (starts with a
- '?') we append the new one at the end of the entire currently worked
- out URL */
- if(useurl[0] != '?') {
- pathsep = strrchr(protsep, '/');
+ else {
+ /* if not, cut off the potential fragment */
+ pathsep = strchr(protsep, '#');
if(pathsep)
*pathsep = 0;
}
- /* Check if there's any slash after the host name, and if so, remember
- that position instead */
- pathsep = strchr(protsep, '/');
- if(pathsep)
- protsep = pathsep + 1;
- else
- protsep = NULL;
-
- /* now deal with one "./" or any amount of "../" in the newurl
- and act accordingly */
-
- if((useurl[0] == '.') && (useurl[1] == '/'))
- useurl += 2; /* just skip the "./" */
-
- while((useurl[0] == '.') &&
- (useurl[1] == '.') &&
- (useurl[2] == '/')) {
- level++;
- useurl += 3; /* pass the "../" */
- }
-
- if(protsep) {
- while(level--) {
- /* cut off one more level from the right of the original URL */
- pathsep = strrchr(protsep, '/');
- if(pathsep)
- *pathsep = 0;
- else {
- *protsep = 0;
- break;
- }
- }
+ /* if the redirect-to piece is not just a query, cut the path after the
+ last slash */
+ if(useurl[0] != '?') {
+ pathsep = strrchr(protsep, '/');
+ if(pathsep)
+ pathsep[1] = 0; /* leave the slash */
}
}
- else {
+ else if('/' == relurl[0]) {
/* We got a new absolute path for this server */
if(relurl[1] == '/') {
@@ -362,29 +329,20 @@ static char *concat_url(const char *base, const char *relurl)
host_changed = TRUE;
}
else {
- /* cut off the original URL from the first slash, or deal with URLs
- without slash */
- pathsep = strchr(protsep, '/');
- if(pathsep) {
- /* When people use badly formatted URLs, such as
- "http://www.url.com?dir=/home/daniel" we must not use the first
- slash, if there's a ?-letter before it! */
- char *sep = strchr(protsep, '?');
- if(sep && (sep < pathsep))
- pathsep = sep;
+ /* cut the original URL at first slash */
+ char *pathsep = strchr(protsep, '/');
+ if(pathsep)
*pathsep = 0;
- }
- else {
- /* There was no slash. Now, since we might be operating on a badly
- formatted URL, such as "http://www.url.com?id=2380" which doesn't
- use a slash separator as it is supposed to, we need to check for a
- ?-letter as well! */
- pathsep = strchr(protsep, '?');
- if(pathsep)
- *pathsep = 0;
- }
}
}
+ else {
+ /* the relative piece starts with '#' */
+
+ /* If there is a fragment in the original URL, cut it off */
+ char *pathsep = strchr(protsep, '#');
+ if(pathsep)
+ *pathsep = 0;
+ }
/* If the new part contains a space, this is a mighty stupid redirect
but we still make an effort to do "right". To the left of a '?'
@@ -406,12 +364,6 @@ static char *concat_url(const char *base, const char *relurl)
/* copy over the root url part */
memcpy(newest, url_clone, urllen);
- /* check if we need to append a slash */
- if(('/' == useurl[0]) || (protsep && !*protsep) || ('?' == useurl[0]))
- ;
- else
- newest[urllen++]='/';
-
/* then append the new piece on the right side */
strcpy_url(&newest[urllen], useurl, !host_changed);
@@ -1463,7 +1415,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
free(redired_url);
return CURLUE_OUT_OF_MEMORY;
}
- result = parseurl(redired_url, handle2, flags);
+ result = parseurl(redired_url, handle2, flags&~CURLU_PATH_AS_IS);
free(redired_url);
if(!result)
mv_urlhandle(handle2, u);
diff --git a/tests/data/test391 b/tests/data/test391
index 24428a08f0f2..279c562de317 100644
--- a/tests/data/test391
+++ b/tests/data/test391
@@ -62,7 +62,7 @@ Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*
-GET /../%TESTNUMBER0002 HTTP/1.1
+GET /%TESTNUMBER0002 HTTP/1.1
Host: %HOSTIP:%HTTPPORT
User-Agent: curl/%VERSION
Accept: */*
diff --git a/tests/libtest/lib1560.c b/tests/libtest/lib1560.c
index d5253a739a10..3103c69f2090 100644
--- a/tests/libtest/lib1560.c
+++ b/tests/libtest/lib1560.c
@@ -1143,6 +1143,38 @@ static CURLUcode updateurl(CURLU *u, const char *cmd, unsigned int setflags)
}
static struct redircase set_url_list[] = {
+ {"http://example.org#withs/ash", "/moo#frag",
+ "http://example.org/moo#frag",
+ 0, 0, CURLUE_OK},
+ {"http://example.org/", "../path/././../././../moo",
+ "http://example.org/moo",
+ 0, 0, CURLUE_OK},
+
+ {"http://example.org?bar/moo", "?weird",
+ "http://example.org/?weird", 0, 0, CURLUE_OK},
+ {"http://example.org/foo?bar", "?weird",
+ "http://example.org/foo?weird", 0, 0, CURLUE_OK},
+ {"http://example.org/foo", "?weird",
+ "http://example.org/foo?weird", 0, 0, CURLUE_OK},
+ {"http://example.org", "?weird",
+ "http://example.org/?weird", 0, 0, CURLUE_OK},
+ {"http://example.org/#original", "?weird#moo",
+ "http://example.org/?weird#moo", 0, 0, CURLUE_OK},
+
+ {"http://example.org?bar/moo#yes/path", "#new/slash",
+ "http://example.org/?bar/moo#new/slash", 0, 0, CURLUE_OK},
+ {"http://example.org/foo?bar", "#weird",
+ "http://example.org/foo?bar#weird", 0, 0, CURLUE_OK},
+ {"http://example.org/foo?bar#original", "#weird",
+ "http://example.org/foo?bar#weird", 0, 0, CURLUE_OK},
+ {"http://example.org/foo#original", "#weird",
+ "http://example.org/foo#weird", 0, 0, CURLUE_OK},
+ {"http://example.org/#original", "#weird",
+ "http://example.org/#weird", 0, 0, CURLUE_OK},
+ {"http://example.org#original", "#weird",
+ "http://example.org/#weird", 0, 0, CURLUE_OK},
+ {"http://example.org/foo?bar", "moo?hey#weird",
+ "http://example.org/moo?hey#weird", 0, 0, CURLUE_OK},
{"http://example.org/static/favicon/wikipedia.ico",
"//fake.example.com/licenses/by-sa/3.0/",
"http://fake.example.com/licenses/by-sa/3.0/",

View File

@ -6,7 +6,7 @@
Name: curl
Version: 7.79.1
Release: 34
Release: 39
Summary: Curl is used in command lines or scripts to transfer data
License: MIT
URL: https://curl.haxx.se/
@ -109,6 +109,16 @@ Patch95: backport-CVE-2024-8096-gtls-fix-OCSP-stapling-management.patch
Patch96: backport-url-allow-DoH-transfers-to-override-max-connection-limit.patch
Patch97: backport-CVE-2024-9681.patch
Patch98: backport-multi-check-that-the-multi-handle-is-valid-in-curl_m.patch
Patch99: backport-cookie-treat-cookie-name-case-sensitively.patch
Patch100: backport-CVE-2024-11053.patch
Patch101: backport-CVE-2025-0167.patch
Patch102: backport-CVE-2025-0725.patch
Patch103: backport-altsvc-avoid-integer-overflow-in-expire-calculation.patch
Patch104: backport-test391-verify-path-as-is-with-redirect.patch
Patch105: backport-urlapi-fix-redirect-to-a-new-fragment-or-query-only-adapt.patch
Patch106: backport-tool_getparam-clear-sensitive-arguments-better.patch
Patch107: backport-libssh-fix-freeing-of-resources-in-disconnect.patch
Patch108: backport-openssl-fix-crash-on-missing-cert-password.patch
BuildRequires: automake brotli-devel coreutils gcc groff krb5-devel
BuildRequires: libidn2-devel libnghttp2-devel libpsl-devel
@ -277,6 +287,40 @@ rm -rf ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la
%{_mandir}/man3/*
%changelog
* Tue May 06 2025 zhouyihang <zhouyihang3@h-partners.com> - 7.79.1-39
- Type:bugfix
- CVE:NA
- SUG:NA
- DESC:libssh: fix freeing of resources in disconnect
openssl: fix crash on missing cert password
* Tue Mar 25 2025 xingwei <xingwei14@h-partners.com> - 7.79.1-38
- Type:bugfix
- CVE:NA
- SUG:NA
- DESC:altsvc: avoid integer overflow in expire calculation
test391: verify --path-as-is with redirect
urlapi: fix redirect to a new fragment or query (only)
tool_getparam: clear sensitive arguments better
* Sat Feb 08 2025 zhouyihang <zhouyihang3@h-partners.com> - 7.79.1-37
- Type:CVE
- CVE:CVE-2025-0167 CVE-2025-0725
- SUG:NA
- DESC:fix CVE-2025-0167 CVE-2025-0725
* Fri Jan 03 2025 zhouyihang <zhouyihang3@h-partners.com> - 7.79.1-36
- Type:CVE
- CVE:CVE-2024-11053
- SUG:NA
- DESC:fix CVE-2024-11053
* Mon Dec 09 2024 zhouyihang <zhouyihang3@h-partners.com> - 7.79.1-35
- Type:bugfix
- CVE:NA
- SUG:NA
- DESC:cookie: treat cookie name case sensitively
* Sat Nov 30 2024 zhouyihang <zhouyihang3@h-partners.com> - 7.79.1-34
- Type:bugfix
- CVE:NA