Compare commits

...

19 Commits
master ... f24

Author SHA1 Message Date
Kamil Dudka a612826260 Resolves: CVE-2016-9586 - fix floating point buffer overflow issues 2016-12-23 12:45:36 +01:00
Kamil Dudka 3226149d73 Resolves: CVE-2016-8615 - fix cookie injection for other servers 2016-11-02 18:10:51 +01:00
Kamil Dudka b9022e2512 Resolves: CVE-2016-8616 - compare user/passwd case-sensitively while reusing connections 2016-11-02 18:10:51 +01:00
Kamil Dudka aab38786d3 Resolves: CVE-2016-8617 - base64: check for integer overflow on large input 2016-11-02 18:10:50 +01:00
Kamil Dudka 48891bfbad Resolves: CVE-2016-8619 - fix double-free in krb5 code 2016-11-02 18:10:50 +01:00
Kamil Dudka a9c0e68d9c Resolves: CVE-2016-8618 - fix double-free in curl_maprintf() 2016-11-02 18:10:49 +01:00
Kamil Dudka b8f34f331c Resolves: CVE-2016-8620 - fix glob parser write/read out of bounds 2016-11-02 18:10:21 +01:00
Kamil Dudka f4a6154810 Resolves: CVE-2016-8621 - fix out-of-bounds read in curl_getdate() 2016-11-02 17:21:38 +01:00
Kamil Dudka 7c7cf92ea9 Resolves: CVE-2016-8622 - fix URL unescape heap overflow via integer truncation 2016-11-02 17:16:59 +01:00
Kamil Dudka 6e32112b9a Resolves: CVE-2016-8623 - fix use-after-free via shared cookies 2016-11-02 16:56:45 +01:00
Kamil Dudka 8cc82f17a1 Resolves: CVE-2016-8624 - urlparse: accept '#' as end of host name 2016-11-02 16:50:01 +01:00
Kamil Dudka 6c0c913605 run autoreconf in %prep to avoid patching Makefile.in files from now on 2016-11-02 16:47:42 +01:00
Kamil Dudka d178d238e4 Resolves: CVE-2016-7167 - reject negative string lengths in curl_easy_[un]escape() 2016-09-14 11:59:13 +02:00
Kamil Dudka c1383a09aa work around race condition in PK11_FindSlotByName()
Bug: https://bugzilla.mozilla.org/1297397
2016-08-26 15:46:58 +02:00
Kamil Dudka 4207564392 Related: CVE-2016-5420 - fix incorrect use of a previously loaded certificate from file 2016-08-26 15:43:09 +02:00
Kamil Dudka 8ef834caac Resolves: CVE-2016-5420 - fix re-using connections with wrong client cert 2016-08-03 17:01:07 +02:00
Kamil Dudka 22a15a2535 Resolves: CVE-2016-5419 - fix TLS session resumption client cert bypass 2016-08-03 17:00:57 +02:00
Kamil Dudka 8288db1fc2 Resolves: CVE-2016-5421 - fix use of connection struct after free 2016-08-03 17:00:44 +02:00
Kamil Dudka fb0bc4b8e6 Resolves: #1340757 - fix SIGSEGV of the curl tool
... while parsing URL with too many globs
2016-06-03 13:34:39 +02:00
18 changed files with 2713 additions and 1 deletions

View File

@ -0,0 +1,35 @@
From 5a3eddc9c327dcc20620d8ae47b27f5085811c7e Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Fri, 3 Jun 2016 11:26:20 +0200
Subject: [PATCH] tool_urlglob: fix off-by-one error in glob_parse()
... causing SIGSEGV while parsing URL with too many globs.
Minimal example:
$ curl $(for i in $(seq 101); do printf '{a}'; done)
Reported-by: Romain Coltel
Bug: https://bugzilla.redhat.com/1340757
Upstream-commit: 584d0121c353ed855115c39f6cbc009854018029
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
src/tool_urlglob.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/tool_urlglob.c b/src/tool_urlglob.c
index 70d17fe..a357b8b 100644
--- a/src/tool_urlglob.c
+++ b/src/tool_urlglob.c
@@ -402,7 +402,7 @@ static CURLcode glob_parse(URLGlob *glob, char *pattern,
}
}
- if(++glob->size > GLOB_PATTERN_NUM)
+ if(++glob->size >= GLOB_PATTERN_NUM)
return GLOBERROR("too many globs", pos, CURLE_URL_MALFORMAT);
}
return res;
--
2.5.5

View File

@ -0,0 +1,34 @@
From 93b8ffb630b62fedaef04a0d7674a89fe367bb22 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Sun, 31 Jul 2016 01:09:04 +0200
Subject: [PATCH] curl_multi_cleanup: clear connection pointer for easy handles
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
CVE-2016-5421
Bug: https://curl.haxx.se/docs/adv_20160803C.html
Reported-by: Marcelo Echeverria and Fernando Muñoz
Upstream-commit: 75dc096e01ef1e21b6c57690d99371dedb2c0b80
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/multi.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/lib/multi.c b/lib/multi.c
index 069412d..89ea625 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -1869,6 +1869,8 @@ static void close_all_connections(struct Curl_multi *multi)
conn->data = multi->closure_handle;
sigpipe_ignore(conn->data, &pipe_st);
+ conn->data->easy_conn = NULL; /* clear the easy handle's connection
+ pointer */
/* This will remove the connection from the cache */
(void)Curl_disconnect(conn, FALSE);
sigpipe_restore(&pipe_st);
--
2.5.5

View File

@ -0,0 +1,73 @@
From 86eef63a05eaabd60e4a10d0fc173bab0e7dbf9e Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Fri, 1 Jul 2016 13:32:31 +0200
Subject: [PATCH] TLS: switch off SSL session id when client cert is used
CVE-2016-5419
Bug: https://curl.haxx.se/docs/adv_20160803A.html
Reported-by: Bru Rom
Contributions-by: Eric Rescorla and Ray Satiro
Upstream-commit: 247d890da88f9ee817079e246c59f3d7d12fde5f
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/url.c | 1 +
lib/urldata.h | 1 +
lib/vtls/vtls.c | 10 ++++++++++
3 files changed, 12 insertions(+)
diff --git a/lib/url.c b/lib/url.c
index 576b8e8..ff99c58 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -5781,6 +5781,7 @@ static CURLcode create_conn(struct SessionHandle *data,
data->set.ssl.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
data->set.ssl.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
data->set.ssl.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST];
+ data->set.ssl.clientcert = data->set.str[STRING_CERT];
#ifdef USE_TLS_SRP
data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME];
data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD];
diff --git a/lib/urldata.h b/lib/urldata.h
index e7341ac..c96dfd4 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -354,6 +354,7 @@ struct ssl_config_data {
char *CAfile; /* certificate to verify peer against */
const char *CRLfile; /* CRL to check certificate revocation */
const char *issuercert;/* optional issuer certificate filename */
+ char *clientcert;
char *random_file; /* path to file containing "random" data */
char *egdsocket; /* path to file containing the EGD daemon socket */
char *cipher_list; /* list of ciphers to use */
diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
index 36465a7..697560d 100644
--- a/lib/vtls/vtls.c
+++ b/lib/vtls/vtls.c
@@ -156,6 +156,15 @@ Curl_clone_ssl_config(struct ssl_config_data *source,
else
dest->random_file = NULL;
+ if(source->clientcert) {
+ dest->clientcert = strdup(source->clientcert);
+ if(!dest->clientcert)
+ return FALSE;
+ dest->sessionid = FALSE;
+ }
+ else
+ dest->clientcert = NULL;
+
return TRUE;
}
@@ -166,6 +175,7 @@ void Curl_free_ssl_config(struct ssl_config_data* sslc)
Curl_safefree(sslc->cipher_list);
Curl_safefree(sslc->egdsocket);
Curl_safefree(sslc->random_file);
+ Curl_safefree(sslc->clientcert);
}
--
2.5.5

View File

@ -0,0 +1,75 @@
From d684e3b136fb77339864d5e48223dea95e7f9ce5 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Sun, 31 Jul 2016 00:51:48 +0200
Subject: [PATCH 1/2] TLS: only reuse connections with the same client cert
CVE-2016-5420
Bug: https://curl.haxx.se/docs/adv_20160803B.html
Upstream-commit: 11ec5ad4352bba384404c56e77c7fab9382fd22d
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/vtls/vtls.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
index 36465a7..7a3ba71 100644
--- a/lib/vtls/vtls.c
+++ b/lib/vtls/vtls.c
@@ -99,6 +99,7 @@ Curl_ssl_config_matches(struct ssl_config_data* data,
(data->verifyhost == needle->verifyhost) &&
safe_strequal(data->CApath, needle->CApath) &&
safe_strequal(data->CAfile, needle->CAfile) &&
+ safe_strequal(data->clientcert, needle->clientcert) &&
safe_strequal(data->random_file, needle->random_file) &&
safe_strequal(data->egdsocket, needle->egdsocket) &&
safe_strequal(data->cipher_list, needle->cipher_list))
--
2.5.5
From 2430e5ed89222f09e6042c9da89472a4e54b0af7 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Mon, 22 Aug 2016 10:24:35 +0200
Subject: [PATCH 2/2] nss: refuse previously loaded certificate from file
... when we are not asked to use a certificate from file
Upstream-commit: 7700fcba64bf5806de28f6c1c7da3b4f0b38567d
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/vtls/nss.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c
index 722ea88..35fa50d 100644
--- a/lib/vtls/nss.c
+++ b/lib/vtls/nss.c
@@ -1010,10 +1010,10 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock,
struct ssl_connect_data *connssl = (struct ssl_connect_data *)arg;
struct SessionHandle *data = connssl->data;
const char *nickname = connssl->client_nickname;
+ static const char pem_slotname[] = "PEM Token #1";
if(connssl->obj_clicert) {
/* use the cert/key provided by PEM reader */
- static const char pem_slotname[] = "PEM Token #1";
SECItem cert_der = { 0, NULL, 0 };
void *proto_win = SSL_RevealPinArg(sock);
struct CERTCertificateStr *cert;
@@ -1075,6 +1075,12 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock,
if(NULL == nickname)
nickname = "[unknown]";
+ if(!strncmp(nickname, pem_slotname, sizeof(pem_slotname) - 1U)) {
+ failf(data, "NSS: refusing previously loaded certificate from file: %s",
+ nickname);
+ return SECFailure;
+ }
+
if(NULL == *pRetKey) {
failf(data, "NSS: private key not found for certificate: %s", nickname);
return SECFailure;
--
2.7.4

View File

@ -0,0 +1,97 @@
From 5812a71c283936b85a77bd2745d4c6bb673cb55f Mon Sep 17 00:00:00 2001
From: Peter Wang <novalazy@gmail.com>
Date: Fri, 26 Aug 2016 16:28:39 +1000
Subject: [PATCH] nss: work around race condition in PK11_FindSlotByName()
Serialise the call to PK11_FindSlotByName() to avoid spurious errors in
a multi-threaded environment. The underlying cause is a race condition
in nssSlot_IsTokenPresent().
Bug: https://bugzilla.mozilla.org/1297397
Closes #985
Upstream-commit: 3a5d5de9ef52ebe8ca2bda2165edc1b34c242e54
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/vtls/nss.c | 22 +++++++++++++++++++---
1 file changed, 19 insertions(+), 3 deletions(-)
diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c
index e467360..1465c03 100644
--- a/lib/vtls/nss.c
+++ b/lib/vtls/nss.c
@@ -81,6 +81,7 @@ PRFileDesc *PR_ImportTCPSocket(PRInt32 osfd);
PRLock * nss_initlock = NULL;
PRLock * nss_crllock = NULL;
+PRLock *nss_findslot_lock = NULL;
struct curl_llist *nss_crl_list = NULL;
NSSInitContext * nss_context = NULL;
@@ -340,6 +341,19 @@ static char* dup_nickname(struct SessionHandle *data, enum dupstring cert_kind)
return NULL;
}
+/* Lock/unlock wrapper for PK11_FindSlotByName() to work around race condition
+ * in nssSlot_IsTokenPresent() causing spurious SEC_ERROR_NO_TOKEN. For more
+ * details, go to <https://bugzilla.mozilla.org/1297397>.
+ */
+static PK11SlotInfo* nss_find_slot_by_name(const char *slot_name)
+{
+ PK11SlotInfo *slot;
+ PR_Lock(nss_initlock);
+ slot = PK11_FindSlotByName(slot_name);
+ PR_Unlock(nss_initlock);
+ return slot;
+}
+
/* Call PK11_CreateGenericObject() with the given obj_class and filename. If
* the call succeeds, append the object handle to the list of objects so that
* the object can be destroyed in Curl_nss_close(). */
@@ -362,7 +376,7 @@ static CURLcode nss_create_object(struct ssl_connect_data *ssl,
if(!slot_name)
return CURLE_OUT_OF_MEMORY;
- slot = PK11_FindSlotByName(slot_name);
+ slot = nss_find_slot_by_name(slot_name);
free(slot_name);
if(!slot)
return result;
@@ -563,7 +577,7 @@ static CURLcode nss_load_key(struct connectdata *conn, int sockindex,
return result;
}
- slot = PK11_FindSlotByName("PEM Token #1");
+ slot = nss_find_slot_by_name("PEM Token #1");
if(!slot)
return CURLE_SSL_CERTPROBLEM;
@@ -1019,7 +1033,7 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock,
struct CERTCertificateStr *cert;
struct SECKEYPrivateKeyStr *key;
- PK11SlotInfo *slot = PK11_FindSlotByName(pem_slotname);
+ PK11SlotInfo *slot = nss_find_slot_by_name(pem_slotname);
if(NULL == slot) {
failf(data, "NSS: PK11 slot not found: %s", pem_slotname);
return SECFailure;
@@ -1255,6 +1269,7 @@ int Curl_nss_init(void)
PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 256);
nss_initlock = PR_NewLock();
nss_crllock = PR_NewLock();
+ nss_findslot_lock = PR_NewLock();
}
/* We will actually initialize NSS later */
@@ -1309,6 +1324,7 @@ void Curl_nss_cleanup(void)
PR_DestroyLock(nss_initlock);
PR_DestroyLock(nss_crllock);
+ PR_DestroyLock(nss_findslot_lock);
nss_initlock = NULL;
initialized = 0;
--
2.7.4

View File

@ -0,0 +1,94 @@
From 7959c5713bbec03c9284a14b1fdd7379520199bc Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Thu, 8 Sep 2016 22:59:54 +0200
Subject: [PATCH 1/2] curl_easy_escape: deny negative string lengths as input
CVE-2016-7167
Bug: https://curl.haxx.se/docs/adv_20160914.html
Upstream-commit: 826a9ced2bed217155e34065ef4048931f327b1e
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/escape.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/lib/escape.c b/lib/escape.c
index 40338a9..c6aa3b9 100644
--- a/lib/escape.c
+++ b/lib/escape.c
@@ -78,15 +78,21 @@ char *curl_unescape(const char *string, int length)
char *curl_easy_escape(CURL *handle, const char *string, int inlength)
{
- size_t alloc = (inlength?(size_t)inlength:strlen(string))+1;
+ size_t alloc;
char *ns;
char *testing_ptr = NULL;
unsigned char in; /* we need to treat the characters unsigned */
- size_t newlen = alloc;
+ size_t newlen;
size_t strindex=0;
size_t length;
CURLcode result;
+ if(inlength < 0)
+ return NULL;
+
+ alloc = (inlength?(size_t)inlength:strlen(string))+1;
+ newlen = alloc;
+
ns = malloc(alloc);
if(!ns)
return NULL;
--
2.7.4
From 6a280152e3893938e5d26f5d535613eefab80b5a Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Tue, 13 Sep 2016 23:00:50 +0200
Subject: [PATCH 2/2] curl_easy_unescape: deny negative string lengths as input
CVE-2016-7167
Bug: https://curl.haxx.se/docs/adv_20160914.html
Upstream-commit: 01cf1308ee2e792c77bb1d2c9218c56a30fd40ae
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/escape.c | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/lib/escape.c b/lib/escape.c
index c6aa3b9..808ac6c 100644
--- a/lib/escape.c
+++ b/lib/escape.c
@@ -217,14 +217,16 @@ char *curl_easy_unescape(CURL *handle, const char *string, int length,
int *olen)
{
char *str = NULL;
- size_t inputlen = length;
- size_t outputlen;
- CURLcode res = Curl_urldecode(handle, string, inputlen, &str, &outputlen,
- FALSE);
- if(res)
- return NULL;
- if(olen)
- *olen = curlx_uztosi(outputlen);
+ if(length >= 0) {
+ size_t inputlen = length;
+ size_t outputlen;
+ CURLcode res = Curl_urldecode(handle, string, inputlen, &str, &outputlen,
+ FALSE);
+ if(res)
+ return NULL;
+ if(olen)
+ *olen = curlx_uztosi(outputlen);
+ }
return str;
}
--
2.7.4

View File

@ -0,0 +1,162 @@
From 0eefde2bae1576ec5a4eca30bd1abbe0fc1be3ea Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Tue, 11 Oct 2016 00:48:35 +0200
Subject: [PATCH 1/2] urlparse: accept '#' as end of host name
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
'http://example.com#@127.0.0.1/x.txt' equals a request to example.com
for the '/' document with the rest of the URL being a fragment.
CVE-2016-8624
Bug: https://curl.haxx.se/docs/adv_20161102J.html
Reported-by: Fernando Muñoz
Upstream-commit: 3bb273db7e40ebc284cff45f3ce3f0475c8339c2
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/url.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/lib/url.c b/lib/url.c
index ff99c58..ff14dad 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -4086,7 +4086,7 @@ static CURLcode parseurlandfillconn(struct SessionHandle *data,
path[0]=0;
if(2 > sscanf(data->change.url,
- "%15[^\n:]://%[^\n/?]%[^\n]",
+ "%15[^\n:]://%[^\n/?#]%[^\n]",
protobuf,
conn->host.name, path)) {
@@ -4094,7 +4094,7 @@ static CURLcode parseurlandfillconn(struct SessionHandle *data,
* The URL was badly formatted, let's try the browser-style _without_
* protocol specified like 'http://'.
*/
- rc = sscanf(data->change.url, "%[^\n/?]%[^\n]", conn->host.name, path);
+ rc = sscanf(data->change.url, "%[^\n/?#]%[^\n]", conn->host.name, path);
if(1 > rc) {
/*
* We couldn't even get this format.
@@ -4184,10 +4184,10 @@ static CURLcode parseurlandfillconn(struct SessionHandle *data,
}
/* If the URL is malformatted (missing a '/' after hostname before path) we
- * insert a slash here. The only letter except '/' we accept to start a path
- * is '?'.
+ * insert a slash here. The only letters except '/' that can start a path is
+ * '?' and '#' - as controlled by the two sscanf() patterns above.
*/
- if(path[0] == '?') {
+ if(path[0] != '/') {
/* We need this function to deal with overlapping memory areas. We know
that the memory area 'path' points to is 'urllen' bytes big and that
is bigger than the path. Use +1 to move the zero byte too. */
--
2.7.4
From c0304cbed088744f3c72a93b29bb58c8bc92d48a Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Tue, 11 Oct 2016 00:54:51 +0200
Subject: [PATCH 2/2] test1246: verify URL parsing with host name ending with
'#'
Upstream-commit: 42b650b9ea5f26b2f5347af3072eaf690658ed62
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
tests/data/Makefile.inc | 2 +-
tests/data/test1246 | 64 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 65 insertions(+), 1 deletion(-)
create mode 100644 tests/data/test1246
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
index 7321ad5..b4bec03 100644
--- a/tests/data/Makefile.inc
+++ b/tests/data/Makefile.inc
@@ -126,7 +126,7 @@ test1208 test1209 test1210 test1211 test1212 test1213 test1214 test1215 \
test1216 test1217 test1218 test1219 \
test1220 test1221 test1222 test1223 test1224 test1225 test1226 test1227 \
test1228 test1229 test1230 test1231 test1232 test1233 test1234 test1235 \
-test1236 test1237 test1238 test1239 test1240 test1241 \
+test1236 test1237 test1238 test1239 test1240 test1241 test1246 \
\
test1300 test1301 test1302 test1303 test1304 test1305 test1306 test1307 \
test1308 test1309 test1310 test1311 test1312 test1313 test1314 test1315 \
diff --git a/tests/data/test1246 b/tests/data/test1246
new file mode 100644
index 0000000..6565929
--- /dev/null
+++ b/tests/data/test1246
@@ -0,0 +1,64 @@
+<testcase>
+<info>
+# verify URL with hostname ending in pound sign
+<keywords>
+HTTP
+HTTP GET
+HTTP proxy
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 200 OK
+Content-Length: 6
+Connection: close
+
+-foo-
+</data>
+
+<data1>
+HTTP/1.1 200 OK
+Content-Length: 7
+Connection: close
+
+-cool-
+</data1>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+URL with '#' at end of host name instead of '/'
+ </name>
+ <command>
+--proxy http://%HOSTIP:%HTTPPORT http://test.remote.haxx.se.1246:%HTTPPORT#@127.0.0.1/tricked.html no-scheme-url.com.1246:%HTTPPORT#@127.127.127.127/again.html
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+GET http://test.remote.haxx.se.1246:%HTTPPORT/ HTTP/1.1
+Host: test.remote.haxx.se.1246:%HTTPPORT
+Accept: */*
+Proxy-Connection: Keep-Alive
+
+GET http://no-scheme-url.com.1246:%HTTPPORT/ HTTP/1.1
+Host: no-scheme-url.com.1246:%HTTPPORT
+Accept: */*
+Proxy-Connection: Keep-Alive
+
+</protocol>
+</verify>
+</testcase>
--
2.7.4

View File

@ -0,0 +1,174 @@
From 86936c59e634a4662912a3b40bcc01d214249e55 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Tue, 4 Oct 2016 23:26:13 +0200
Subject: [PATCH] cookies: getlist() now holds deep copies of all cookies
Previously it only held references to them, which was reckless as the
thread lock was released so the cookies could get modified by other
handles that share the same cookie jar over the share interface.
CVE-2016-8623
Bug: https://curl.haxx.se/docs/adv_20161102I.html
Reported-by: Cure53
Upstream-commit: c5be3d7267c725dbd093ff3a883e07ee8cf2a1d5
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/cookie.c | 61 +++++++++++++++++++++++++++++++++++++++---------------------
lib/cookie.h | 4 ++--
lib/http.c | 2 +-
3 files changed, 43 insertions(+), 24 deletions(-)
diff --git a/lib/cookie.c b/lib/cookie.c
index e5c7b7e..7a60411 100644
--- a/lib/cookie.c
+++ b/lib/cookie.c
@@ -1013,6 +1013,40 @@ static int cookie_sort(const void *p1, const void *p2)
return 0;
}
+#define CLONE(field) \
+ do { \
+ if(src->field) { \
+ dup->field = strdup(src->field); \
+ if(!dup->field) \
+ goto fail; \
+ } \
+ } while(0)
+
+static struct Cookie *dup_cookie(struct Cookie *src)
+{
+ struct Cookie *dup = calloc(sizeof(struct Cookie), 1);
+ if(dup) {
+ CLONE(expirestr);
+ CLONE(domain);
+ CLONE(path);
+ CLONE(spath);
+ CLONE(name);
+ CLONE(value);
+ CLONE(maxage);
+ CLONE(version);
+ dup->expires = src->expires;
+ dup->tailmatch = src->tailmatch;
+ dup->secure = src->secure;
+ dup->livecookie = src->livecookie;
+ dup->httponly = src->httponly;
+ }
+ return dup;
+
+ fail:
+ freecookie(dup);
+ return NULL;
+}
+
/*****************************************************************************
*
* Curl_cookie_getlist()
@@ -1068,11 +1102,8 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
/* and now, we know this is a match and we should create an
entry for the return-linked-list */
- newco = malloc(sizeof(struct Cookie));
+ newco = dup_cookie(co);
if(newco) {
- /* first, copy the whole source cookie: */
- memcpy(newco, co, sizeof(struct Cookie));
-
/* then modify our next */
newco->next = mainco;
@@ -1084,12 +1115,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
else {
fail:
/* failure, clear up the allocated chain and return NULL */
- while(mainco) {
- co = mainco->next;
- free(mainco);
- mainco = co;
- }
-
+ Curl_cookie_freelist(mainco);
return NULL;
}
}
@@ -1141,7 +1167,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
void Curl_cookie_clearall(struct CookieInfo *cookies)
{
if(cookies) {
- Curl_cookie_freelist(cookies->cookies, TRUE);
+ Curl_cookie_freelist(cookies->cookies);
cookies->cookies = NULL;
cookies->numcookies = 0;
}
@@ -1153,21 +1179,14 @@ void Curl_cookie_clearall(struct CookieInfo *cookies)
*
* Free a list of cookies previously returned by Curl_cookie_getlist();
*
- * The 'cookiestoo' argument tells this function whether to just free the
- * list or actually also free all cookies within the list as well.
- *
****************************************************************************/
-void Curl_cookie_freelist(struct Cookie *co, bool cookiestoo)
+void Curl_cookie_freelist(struct Cookie *co)
{
struct Cookie *next;
while(co) {
next = co->next;
- if(cookiestoo)
- freecookie(co);
- else
- free(co); /* we only free the struct since the "members" are all just
- pointed out in the main cookie list! */
+ freecookie(co);
co = next;
}
}
@@ -1222,7 +1241,7 @@ void Curl_cookie_cleanup(struct CookieInfo *c)
{
if(c) {
free(c->filename);
- Curl_cookie_freelist(c->cookies, TRUE);
+ Curl_cookie_freelist(c->cookies);
free(c); /* free the base struct as well */
}
}
diff --git a/lib/cookie.h b/lib/cookie.h
index 74a9224..ecfece2 100644
--- a/lib/cookie.h
+++ b/lib/cookie.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -82,7 +82,7 @@ struct Cookie *Curl_cookie_add(struct SessionHandle *data,
struct Cookie *Curl_cookie_getlist(struct CookieInfo *, const char *,
const char *, bool);
-void Curl_cookie_freelist(struct Cookie *cookies, bool cookiestoo);
+void Curl_cookie_freelist(struct Cookie *cookies);
void Curl_cookie_clearall(struct CookieInfo *cookies);
void Curl_cookie_clearsess(struct CookieInfo *cookies);
diff --git a/lib/http.c b/lib/http.c
index 53c6cf8..f9a82c8 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -2384,7 +2384,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
co = co->next; /* next cookie please */
}
- Curl_cookie_freelist(store, FALSE); /* free the cookie list */
+ Curl_cookie_freelist(store);
}
if(addcookies && !result) {
if(!count)
--
2.7.4

View File

@ -0,0 +1,539 @@
From 76f91d8b2da6501558cd92620c9656c283db8adf Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Tue, 4 Oct 2016 18:56:45 +0200
Subject: [PATCH 1/2] unescape: avoid integer overflow
CVE-2016-8622
Bug: https://curl.haxx.se/docs/adv_20161102H.html
Reported-by: Cure53
Upstream-commit: 53e71e47d6b81650d26ec33a58d0dca24c7ffb2c
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
docs/libcurl/curl_easy_unescape.3 | 7 +++++--
lib/dict.c | 10 +++++-----
lib/escape.c | 10 ++++++++--
3 files changed, 18 insertions(+), 9 deletions(-)
diff --git a/docs/libcurl/curl_easy_unescape.3 b/docs/libcurl/curl_easy_unescape.3
index 06fd6fc..50ce97d 100644
--- a/docs/libcurl/curl_easy_unescape.3
+++ b/docs/libcurl/curl_easy_unescape.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -40,7 +40,10 @@ will use strlen() on the input \fIurl\fP string to find out the size.
If \fBoutlength\fP is non-NULL, the function will write the length of the
returned string in the integer it points to. This allows an escaped string
-containing %00 to still get used properly after unescaping.
+containing %00 to still get used properly after unescaping. Since this is a
+pointer to an \fIint\fP type, it can only return a value up to INT_MAX so no
+longer string can be unescaped if the string length is returned in this
+parameter.
You must \fIcurl_free(3)\fP the returned string when you're done with it.
.SH AVAILABILITY
diff --git a/lib/dict.c b/lib/dict.c
index 2e7cb47..e1475ca 100644
--- a/lib/dict.c
+++ b/lib/dict.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -52,7 +52,7 @@
#include <curl/curl.h>
#include "transfer.h"
#include "sendf.h"
-
+#include "escape.h"
#include "progress.h"
#include "strequal.h"
#include "dict.h"
@@ -96,12 +96,12 @@ static char *unescape_word(struct SessionHandle *data, const char *inputbuff)
char *newp;
char *dictp;
char *ptr;
- int len;
+ size_t len;
char ch;
int olen=0;
- newp = curl_easy_unescape(data, inputbuff, 0, &len);
- if(!newp)
+ CURLcode result = Curl_urldecode(data, inputbuff, 0, &newp, &len, FALSE);
+ if(!newp || result)
return NULL;
dictp = malloc(((size_t)len)*2 + 1); /* add one for terminating zero */
diff --git a/lib/escape.c b/lib/escape.c
index 808ac6c..4091097 100644
--- a/lib/escape.c
+++ b/lib/escape.c
@@ -224,8 +224,14 @@ char *curl_easy_unescape(CURL *handle, const char *string, int length,
FALSE);
if(res)
return NULL;
- if(olen)
- *olen = curlx_uztosi(outputlen);
+
+ if(olen) {
+ if(outputlen <= (size_t) INT_MAX)
+ *olen = curlx_uztosi(outputlen);
+ else
+ /* too large to return in an int, fail! */
+ Curl_safefree(str);
+ }
}
return str;
}
--
2.7.4
From e24b3f19b11fa4bf01ae4bce34d6aa96b27ec6ab Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Sat, 8 Oct 2016 11:21:38 +0200
Subject: [PATCH 2/2] escape: avoid using curl_easy_unescape() internally
Since the internal Curl_urldecode() function has a better API.
Upstream-commit: 46133aa536f7f5bf552b83369e3851b6f811299e
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/file.c | 9 +++++----
lib/ftp.c | 60 +++++++++++++++++++++++++++++-------------------------------
lib/gopher.c | 5 +++--
lib/ldap.c | 26 +++++++++++++++-----------
lib/ssh.c | 12 ++++++------
lib/tftp.c | 9 +++++----
lib/url.c | 55 +++++++++++++++++++++++++++----------------------------
7 files changed, 90 insertions(+), 86 deletions(-)
diff --git a/lib/file.c b/lib/file.c
index d47bda1..1afdb7b 100644
--- a/lib/file.c
+++ b/lib/file.c
@@ -194,11 +194,12 @@ static CURLcode file_connect(struct connectdata *conn, bool *done)
int i;
char *actual_path;
#endif
- int real_path_len;
+ size_t real_path_len;
- real_path = curl_easy_unescape(data, data->state.path, 0, &real_path_len);
- if(!real_path)
- return CURLE_OUT_OF_MEMORY;
+ CURLcode result = Curl_urldecode(data, data->state.path, 0, &real_path,
+ &real_path_len, FALSE);
+ if(result)
+ return result;
#ifdef DOS_FILESYSTEM
/* If the first character is a slash, and there's
diff --git a/lib/ftp.c b/lib/ftp.c
index b5a7f55..d7e3dbb 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -3298,8 +3298,8 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
}
/* get the "raw" path */
- path = curl_easy_unescape(data, path_to_use, 0, NULL);
- if(!path) {
+ result = Curl_urldecode(data, path_to_use, 0, &path, NULL, FALSE);
+ if(result) {
/* out of memory, but we can limp along anyway (and should try to
* since we may already be in the out of memory cleanup path) */
if(!result)
@@ -4291,6 +4291,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
slash_pos=strrchr(cur_pos, '/');
if(slash_pos || !*cur_pos) {
size_t dirlen = slash_pos-cur_pos;
+ CURLcode result;
ftpc->dirs = calloc(1, sizeof(ftpc->dirs[0]));
if(!ftpc->dirs)
@@ -4299,12 +4300,13 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
if(!dirlen)
dirlen++;
- ftpc->dirs[0] = curl_easy_unescape(conn->data, slash_pos ? cur_pos : "/",
- slash_pos ? curlx_uztosi(dirlen) : 1,
- NULL);
- if(!ftpc->dirs[0]) {
+ result = Curl_urldecode(conn->data, slash_pos ? cur_pos : "/",
+ slash_pos ? dirlen : 1,
+ &ftpc->dirs[0], NULL,
+ FALSE);
+ if(result) {
freedirs(ftpc);
- return CURLE_OUT_OF_MEMORY;
+ return result;
}
ftpc->dirdepth = 1; /* we consider it to be a single dir */
filename = slash_pos ? slash_pos+1 : cur_pos; /* rest is file name */
@@ -4339,18 +4341,15 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
/* we skip empty path components, like "x//y" since the FTP command
CWD requires a parameter and a non-existent parameter a) doesn't
work on many servers and b) has no effect on the others. */
- int len = curlx_sztosi(slash_pos - cur_pos + absolute_dir);
- ftpc->dirs[ftpc->dirdepth] =
- curl_easy_unescape(conn->data, cur_pos - absolute_dir, len, NULL);
- if(!ftpc->dirs[ftpc->dirdepth]) { /* run out of memory ... */
- failf(data, "no memory");
- freedirs(ftpc);
- return CURLE_OUT_OF_MEMORY;
- }
- if(isBadFtpString(ftpc->dirs[ftpc->dirdepth])) {
+ size_t len = slash_pos - cur_pos + absolute_dir;
+ CURLcode result =
+ Curl_urldecode(conn->data, cur_pos - absolute_dir, len,
+ &ftpc->dirs[ftpc->dirdepth], NULL,
+ TRUE);
+ if(result) {
free(ftpc->dirs[ftpc->dirdepth]);
freedirs(ftpc);
- return CURLE_URL_MALFORMAT;
+ return result;
}
}
else {
@@ -4386,15 +4385,12 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
} /* switch */
if(filename && *filename) {
- ftpc->file = curl_easy_unescape(conn->data, filename, 0, NULL);
- if(NULL == ftpc->file) {
- freedirs(ftpc);
- failf(data, "no memory");
- return CURLE_OUT_OF_MEMORY;
- }
- if(isBadFtpString(ftpc->file)) {
+ CURLcode result =
+ Curl_urldecode(conn->data, filename, 0, &ftpc->file, NULL, TRUE);
+
+ if(result) {
freedirs(ftpc);
- return CURLE_URL_MALFORMAT;
+ return result;
}
}
else
@@ -4412,15 +4408,17 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
if(ftpc->prevpath) {
/* prevpath is "raw" so we convert the input path before we compare the
strings */
- int dlen;
- char *path = curl_easy_unescape(conn->data, data->state.path, 0, &dlen);
- if(!path) {
+ size_t dlen;
+ char *path;
+ CURLcode result =
+ Curl_urldecode(conn->data, data->state.path, 0, &path, &dlen, FALSE);
+ if(result) {
freedirs(ftpc);
- return CURLE_OUT_OF_MEMORY;
+ return result;
}
- dlen -= ftpc->file?curlx_uztosi(strlen(ftpc->file)):0;
- if((dlen == curlx_uztosi(strlen(ftpc->prevpath))) &&
+ dlen -= ftpc->file?strlen(ftpc->file):0;
+ if((dlen == strlen(ftpc->prevpath)) &&
strnequal(path, ftpc->prevpath, dlen)) {
infof(data, "Request has same path as previous transfer\n");
ftpc->cwddone = TRUE;
diff --git a/lib/gopher.c b/lib/gopher.c
index 19f2f5a..03c79f7 100644
--- a/lib/gopher.c
+++ b/lib/gopher.c
@@ -35,6 +35,7 @@
#include "rawstr.h"
#include "select.h"
#include "url.h"
+#include "escape.h"
#include "warnless.h"
#include "curl_memory.h"
/* The last #include file should be: */
@@ -83,7 +84,7 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
char *sel;
char *sel_org = NULL;
ssize_t amount, k;
- int len;
+ size_t len;
*done = TRUE; /* unconditionally */
@@ -107,7 +108,7 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
newp[i] = '\x09';
/* ... and finally unescape */
- sel = curl_easy_unescape(data, newp, 0, &len);
+ result = Curl_urldecode(data, newp, 0, &sel, &len, FALSE);
if(!sel)
return CURLE_OUT_OF_MEMORY;
sel_org = sel;
diff --git a/lib/ldap.c b/lib/ldap.c
index 4f4c707..57061bb 100644
--- a/lib/ldap.c
+++ b/lib/ldap.c
@@ -768,7 +768,7 @@ static bool split_str(char *str, char ***out, size_t *count)
*
* Defined in RFC4516 section 2.
*/
-static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
+static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
{
int rc = LDAP_SUCCESS;
char *path;
@@ -799,12 +799,13 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
if(*p) {
char *dn = p;
char *unescaped;
+ CURLcode result;
LDAP_TRACE (("DN '%s'\n", dn));
/* Unescape the DN */
- unescaped = curl_easy_unescape(conn->data, dn, 0, NULL);
- if(!unescaped) {
+ result = Curl_urldecode(conn->data, dn, 0, &unescaped, NULL, FALSE);
+ if(result) {
rc = LDAP_NO_MEMORY;
goto quit;
@@ -863,12 +864,14 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
for(i = 0; i < count; i++) {
char *unescaped;
+ CURLcode result;
LDAP_TRACE (("attr[%d] '%s'\n", i, attributes[i]));
/* Unescape the attribute */
- unescaped = curl_easy_unescape(conn->data, attributes[i], 0, NULL);
- if(!unescaped) {
+ result = Curl_urldecode(conn->data, attributes[i], 0, &unescaped, NULL,
+ FALSE);
+ if(result) {
free(attributes);
rc = LDAP_NO_MEMORY;
@@ -931,12 +934,13 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
if(*p) {
char *filter = p;
char *unescaped;
+ CURLcode result;
LDAP_TRACE (("filter '%s'\n", filter));
/* Unescape the filter */
- unescaped = curl_easy_unescape(conn->data, filter, 0, NULL);
- if(!unescaped) {
+ result = Curl_urldecode(conn->data, filter, 0, &unescaped, NULL, FALSE);
+ if(result) {
rc = LDAP_NO_MEMORY;
goto quit;
@@ -972,8 +976,8 @@ quit:
return rc;
}
-static int _ldap_url_parse (const struct connectdata *conn,
- LDAPURLDesc **ludpp)
+static int _ldap_url_parse(const struct connectdata *conn,
+ LDAPURLDesc **ludpp)
{
LDAPURLDesc *ludp = calloc(1, sizeof(*ludp));
int rc;
@@ -982,7 +986,7 @@ static int _ldap_url_parse (const struct connectdata *conn,
if(!ludp)
return LDAP_NO_MEMORY;
- rc = _ldap_url_parse2 (conn, ludp);
+ rc = _ldap_url_parse2(conn, ludp);
if(rc != LDAP_SUCCESS) {
_ldap_free_urldesc(ludp);
ludp = NULL;
@@ -991,7 +995,7 @@ static int _ldap_url_parse (const struct connectdata *conn,
return (rc);
}
-static void _ldap_free_urldesc (LDAPURLDesc *ludp)
+static void _ldap_free_urldesc(LDAPURLDesc *ludp)
{
size_t i;
diff --git a/lib/ssh.c b/lib/ssh.c
index 10bf546..2d9b6a2 100644
--- a/lib/ssh.c
+++ b/lib/ssh.c
@@ -407,12 +407,12 @@ static CURLcode ssh_getworkingpath(struct connectdata *conn,
struct SessionHandle *data = conn->data;
char *real_path = NULL;
char *working_path;
- int working_path_len;
-
- working_path = curl_easy_unescape(data, data->state.path, 0,
- &working_path_len);
- if(!working_path)
- return CURLE_OUT_OF_MEMORY;
+ size_t working_path_len;
+ CURLcode result =
+ Curl_urldecode(data, data->state.path, 0, &working_path,
+ &working_path_len, FALSE);
+ if(result)
+ return result;
/* Check for /~/ , indicating relative to the user's home directory */
if(conn->handler->protocol & CURLPROTO_SCP) {
diff --git a/lib/tftp.c b/lib/tftp.c
index 040d967..274a724 100644
--- a/lib/tftp.c
+++ b/lib/tftp.c
@@ -59,6 +59,7 @@
#include "speedcheck.h"
#include "curl_printf.h"
#include "select.h"
+#include "escape.h"
/* The last #include files should be: */
#include "curl_memory.h"
@@ -484,10 +485,10 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
/* As RFC3617 describes the separator slash is not actually part of the
file name so we skip the always-present first letter of the path
string. */
- filename = curl_easy_unescape(data, &state->conn->data->state.path[1], 0,
- NULL);
- if(!filename)
- return CURLE_OUT_OF_MEMORY;
+ result = Curl_urldecode(data, &state->conn->data->state.path[1], 0,
+ &filename, NULL, FALSE);
+ if(result)
+ return result;
snprintf((char *)state->spacket.data+2,
state->blksize,
diff --git a/lib/url.c b/lib/url.c
index ff14dad..a88903c 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -4652,21 +4652,24 @@ static CURLcode parse_proxy(struct SessionHandle *data,
them. */
Curl_safefree(conn->proxyuser);
if(proxyuser && strlen(proxyuser) < MAX_CURL_USER_LENGTH)
- conn->proxyuser = curl_easy_unescape(data, proxyuser, 0, NULL);
- else
+ result = Curl_urldecode(data, proxyuser, 0, &conn->proxyuser, NULL,
+ FALSE);
+ else {
conn->proxyuser = strdup("");
+ if(!conn->proxyuser)
+ result = CURLE_OUT_OF_MEMORY;
+ }
- if(!conn->proxyuser)
- result = CURLE_OUT_OF_MEMORY;
- else {
+ if(!result) {
Curl_safefree(conn->proxypasswd);
if(proxypasswd && strlen(proxypasswd) < MAX_CURL_PASSWORD_LENGTH)
- conn->proxypasswd = curl_easy_unescape(data, proxypasswd, 0, NULL);
- else
+ result = Curl_urldecode(data, proxypasswd, 0,
+ &conn->proxypasswd, NULL, FALSE);
+ else {
conn->proxypasswd = strdup("");
-
- if(!conn->proxypasswd)
- result = CURLE_OUT_OF_MEMORY;
+ if(!conn->proxypasswd)
+ result = CURLE_OUT_OF_MEMORY;
+ }
}
if(!result) {
@@ -4773,6 +4776,7 @@ static CURLcode parse_proxy_auth(struct SessionHandle *data,
{
char proxyuser[MAX_CURL_USER_LENGTH]="";
char proxypasswd[MAX_CURL_PASSWORD_LENGTH]="";
+ CURLcode result;
if(data->set.str[STRING_PROXYUSERNAME] != NULL) {
strncpy(proxyuser, data->set.str[STRING_PROXYUSERNAME],
@@ -4785,15 +4789,11 @@ static CURLcode parse_proxy_auth(struct SessionHandle *data,
proxypasswd[MAX_CURL_PASSWORD_LENGTH-1] = '\0'; /*To be on safe side*/
}
- conn->proxyuser = curl_easy_unescape(data, proxyuser, 0, NULL);
- if(!conn->proxyuser)
- return CURLE_OUT_OF_MEMORY;
-
- conn->proxypasswd = curl_easy_unescape(data, proxypasswd, 0, NULL);
- if(!conn->proxypasswd)
- return CURLE_OUT_OF_MEMORY;
-
- return CURLE_OK;
+ result = Curl_urldecode(data, proxyuser, 0, &conn->proxyuser, NULL, FALSE);
+ if(!result)
+ result = Curl_urldecode(data, proxypasswd, 0, &conn->proxypasswd, NULL,
+ FALSE);
+ return result;
}
#endif /* CURL_DISABLE_PROXY */
@@ -4867,9 +4867,8 @@ static CURLcode parse_url_login(struct SessionHandle *data,
conn->bits.user_passwd = TRUE; /* enable user+password */
/* Decode the user */
- newname = curl_easy_unescape(data, userp, 0, NULL);
- if(!newname) {
- result = CURLE_OUT_OF_MEMORY;
+ result = Curl_urldecode(data, userp, 0, &newname, NULL, FALSE);
+ if(result) {
goto out;
}
@@ -4879,9 +4878,9 @@ static CURLcode parse_url_login(struct SessionHandle *data,
if(passwdp) {
/* We have a password in the URL so decode it */
- char *newpasswd = curl_easy_unescape(data, passwdp, 0, NULL);
- if(!newpasswd) {
- result = CURLE_OUT_OF_MEMORY;
+ char *newpasswd;
+ result = Curl_urldecode(data, passwdp, 0, &newpasswd, NULL, FALSE);
+ if(result) {
goto out;
}
@@ -4891,9 +4890,9 @@ static CURLcode parse_url_login(struct SessionHandle *data,
if(optionsp) {
/* We have an options list in the URL so decode it */
- char *newoptions = curl_easy_unescape(data, optionsp, 0, NULL);
- if(!newoptions) {
- result = CURLE_OUT_OF_MEMORY;
+ char *newoptions;
+ result = Curl_urldecode(data, optionsp, 0, &newoptions, NULL, FALSE);
+ if(result) {
goto out;
}
--
2.7.4

View File

@ -0,0 +1,104 @@
From 97c3fb871f3284bb0063e531f17e12dea14bfda8 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Tue, 4 Oct 2016 16:59:38 +0200
Subject: [PATCH] parsedate: handle cut off numbers better
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
... and don't read outside of the given buffer!
CVE-2016-8621
bug: https://curl.haxx.se/docs/adv_20161102G.html
Reported-by: Luật Nguyễn
Upstream-commit: 96a80b5a262fb6dd2ddcea7987296f3b9a405618
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/parsedate.c | 12 +++++++-----
tests/data/test517 | 6 ++++++
tests/libtest/lib517.c | 8 +++++++-
3 files changed, 20 insertions(+), 6 deletions(-)
diff --git a/lib/parsedate.c b/lib/parsedate.c
index dfcf855..8e932f4 100644
--- a/lib/parsedate.c
+++ b/lib/parsedate.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -386,15 +386,17 @@ static int parsedate(const char *date, time_t *output)
/* a digit */
int val;
char *end;
+ int len=0;
if((secnum == -1) &&
- (3 == sscanf(date, "%02d:%02d:%02d", &hournum, &minnum, &secnum))) {
+ (3 == sscanf(date, "%02d:%02d:%02d%n",
+ &hournum, &minnum, &secnum, &len))) {
/* time stamp! */
- date += 8;
+ date += len;
}
else if((secnum == -1) &&
- (2 == sscanf(date, "%02d:%02d", &hournum, &minnum))) {
+ (2 == sscanf(date, "%02d:%02d%n", &hournum, &minnum, &len))) {
/* time stamp without seconds */
- date += 5;
+ date += len;
secnum = 0;
}
else {
diff --git a/tests/data/test517 b/tests/data/test517
index c81a45e..513634f 100644
--- a/tests/data/test517
+++ b/tests/data/test517
@@ -116,6 +116,12 @@ nothing
81: 20111323 12:34:56 => -1
82: 20110623 12:34:79 => -1
83: Wed, 31 Dec 2008 23:59:60 GMT => 1230768000
+84: 20110623 12:3 => 1308830580
+85: 20110623 1:3 => 1308790980
+86: 20110623 1:30 => 1308792600
+87: 20110623 12:12:3 => 1308831123
+88: 20110623 01:12:3 => 1308791523
+89: 20110623 01:99:30 => -1
</stdout>
# This test case previously tested an overflow case ("2094 Nov 6 =>
diff --git a/tests/libtest/lib517.c b/tests/libtest/lib517.c
index 2f68ebd..22162ff 100644
--- a/tests/libtest/lib517.c
+++ b/tests/libtest/lib517.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -116,6 +116,12 @@ static const char * const dates[]={
"20111323 12:34:56",
"20110623 12:34:79",
"Wed, 31 Dec 2008 23:59:60 GMT", /* leap second */
+ "20110623 12:3",
+ "20110623 1:3",
+ "20110623 1:30",
+ "20110623 12:12:3",
+ "20110623 01:12:3",
+ "20110623 01:99:30",
NULL
};
--
2.7.4

View File

@ -0,0 +1,192 @@
From 899d4f898f2b1b2cc910ca994e23e2d55347c22d Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Mon, 3 Oct 2016 17:27:16 +0200
Subject: [PATCH 1/3] range: prevent negative end number in a glob range
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
CVE-2016-8620
Bug: https://curl.haxx.se/docs/adv_20161102F.html
Reported-by: Luật Nguyễn
Upstream-commit: fbb5f1aa0326d485d5a7ac643b48481897ca667f
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
src/tool_urlglob.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/tool_urlglob.c b/src/tool_urlglob.c
index 6a4ff76..49bbe4b 100644
--- a/src/tool_urlglob.c
+++ b/src/tool_urlglob.c
@@ -257,6 +257,12 @@ static CURLcode glob_range(URLGlob *glob, char **patternp,
endp = NULL;
else {
pattern = endp+1;
+ while(*pattern && ISBLANK(*pattern))
+ pattern++;
+ if(!ISDIGIT(*pattern)) {
+ endp = NULL;
+ goto fail;
+ }
errno = 0;
max_n = strtoul(pattern, &endp, 10);
if(errno || (*endp == ':')) {
@@ -277,6 +283,7 @@ static CURLcode glob_range(URLGlob *glob, char **patternp,
}
}
+ fail:
*posp += (pattern - *patternp);
if(!endp || (min_n > max_n) || (step_n > (max_n - min_n)) ||
--
2.7.4
From 2897ecbeaf174a4f665e4b7ff9aea7fdd85f3d80 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Mon, 3 Oct 2016 18:23:22 +0200
Subject: [PATCH 2/3] glob_next_url: make sure to stay within the given output
buffer
Upstream-commit: 269a88910436d730ac212f4dc01cbe6961338061
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
src/tool_urlglob.c | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/src/tool_urlglob.c b/src/tool_urlglob.c
index 49bbe4b..3a3aba9 100644
--- a/src/tool_urlglob.c
+++ b/src/tool_urlglob.c
@@ -432,6 +432,7 @@ CURLcode glob_url(URLGlob** glob, char* url, unsigned long *urlnum,
glob_buffer = malloc(strlen(url) + 1);
if(!glob_buffer)
return CURLE_OUT_OF_MEMORY;
+ glob_buffer[0]=0;
glob_expand = calloc(1, sizeof(URLGlob));
if(!glob_expand) {
@@ -549,20 +550,25 @@ CURLcode glob_next_url(char **globbed, URLGlob *glob)
switch(pat->type) {
case UPTSet:
if(pat->content.Set.elements) {
- len = strlen(pat->content.Set.elements[pat->content.Set.ptr_s]);
snprintf(buf, buflen, "%s",
pat->content.Set.elements[pat->content.Set.ptr_s]);
+ len = strlen(buf);
buf += len;
buflen -= len;
}
break;
case UPTCharRange:
- *buf++ = pat->content.CharRange.ptr_c;
+ if(buflen) {
+ *buf++ = pat->content.CharRange.ptr_c;
+ *buf = '\0';
+ buflen--;
+ }
break;
case UPTNumRange:
- len = snprintf(buf, buflen, "%0*ld",
- pat->content.NumRange.padlength,
- pat->content.NumRange.ptr_n);
+ snprintf(buf, buflen, "%0*ld",
+ pat->content.NumRange.padlength,
+ pat->content.NumRange.ptr_n);
+ len = strlen(buf);
buf += len;
buflen -= len;
break;
@@ -571,7 +577,6 @@ CURLcode glob_next_url(char **globbed, URLGlob *glob)
return CURLE_FAILED_INIT;
}
}
- *buf = '\0';
*globbed = strdup(glob->glob_buffer);
if(!*globbed)
--
2.7.4
From 46475c97a6970a644239c542bc6a2a653020c87b Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Tue, 4 Oct 2016 17:25:09 +0200
Subject: [PATCH 3/3] range: reject char globs with missing end like '[L-]'
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
... which previously would lead to out of boundary reads.
Reported-by: Luật Nguyễn
Upstream-commit: ee4f76606cfa4ee068bf28edd37c8dae7e8db317
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
src/tool_urlglob.c | 34 +++++++++++++++++++---------------
1 file changed, 19 insertions(+), 15 deletions(-)
diff --git a/src/tool_urlglob.c b/src/tool_urlglob.c
index 3a3aba9..3b17a68 100644
--- a/src/tool_urlglob.c
+++ b/src/tool_urlglob.c
@@ -188,32 +188,36 @@ static CURLcode glob_range(URLGlob *glob, char **patternp,
/* character range detected */
char min_c;
char max_c;
+ char end_c;
int step=1;
pat->type = UPTCharRange;
- rc = sscanf(pattern, "%c-%c", &min_c, &max_c);
+ rc = sscanf(pattern, "%c-%c%c", &min_c, &max_c, &end_c);
- if((rc == 2) && (pattern[3] == ':')) {
- char *endp;
- unsigned long lstep;
- errno = 0;
- lstep = strtoul(&pattern[4], &endp, 10);
- if(errno || (*endp != ']'))
- step = -1;
- else {
- pattern = endp+1;
- step = (int)lstep;
- if(step > (max_c - min_c))
+ if(rc == 3) {
+ if(end_c == ':') {
+ char *endp;
+ unsigned long lstep;
+ errno = 0;
+ lstep = strtoul(&pattern[4], &endp, 10);
+ if(errno || (*endp != ']'))
step = -1;
+ else {
+ pattern = endp+1;
+ step = (int)lstep;
+ if(step > (max_c - min_c))
+ step = -1;
+ }
}
+ else if(end_c != ']')
+ /* then this is wrong */
+ rc = 0;
}
- else
- pattern += 4;
*posp += (pattern - *patternp);
- if((rc != 2) || (min_c >= max_c) || ((max_c - min_c) > ('z' - 'a')) ||
+ if((rc != 3) || (min_c >= max_c) || ((max_c - min_c) > ('z' - 'a')) ||
(step <= 0) )
/* the pattern is not well-formed */
return GLOBERROR("bad range", *posp, CURLE_URL_MALFORMAT);
--
2.7.4

View File

@ -0,0 +1,49 @@
From 086eed9d97b860b2c3484038d225a16e406c757d Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Wed, 28 Sep 2016 10:15:34 +0200
Subject: [PATCH] aprintf: detect wrap-around when growing allocation
On 32bit systems we could otherwise wrap around after 2GB and allocate 0
bytes and crash.
CVE-2016-8618
Bug: https://curl.haxx.se/docs/adv_20161102D.html
Reported-by: Cure53
Upstream-commit: 8732ec40db652c53fa58cd13e2acb8eab6e40874
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/mprintf.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/lib/mprintf.c b/lib/mprintf.c
index b6d9a9c..e47c10a 100644
--- a/lib/mprintf.c
+++ b/lib/mprintf.c
@@ -1011,16 +1011,19 @@ static int alloc_addbyter(int output, FILE *data)
infop->len =0;
}
else if(infop->len+1 >= infop->alloc) {
- char *newptr;
+ char *newptr = NULL;
+ size_t newsize = infop->alloc*2;
- newptr = realloc(infop->buffer, infop->alloc*2);
+ /* detect wrap-around or other overflow problems */
+ if(newsize > infop->alloc)
+ newptr = realloc(infop->buffer, newsize);
if(!newptr) {
infop->fail = 1;
return -1; /* fail */
}
infop->buffer = newptr;
- infop->alloc *= 2;
+ infop->alloc = newsize;
}
infop->buffer[ infop->len ] = outc;
--
2.7.4

View File

@ -0,0 +1,49 @@
From 47736feee3eb92b3527237316f60c880421bbce4 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Wed, 28 Sep 2016 12:56:02 +0200
Subject: [PATCH] krb5: avoid realloc(0)
If the requested size is zero, bail out with error instead of doing a
realloc() that would cause a double-free: realloc(0) acts as a free()
and then there's a second free in the cleanup path.
CVE-2016-8619
Bug: https://curl.haxx.se/docs/adv_20161102E.html
Reported-by: Cure53
Upstream-commit: 3d6460edeee21d7d790ec570d0887bed1f4366dd
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/security.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/lib/security.c b/lib/security.c
index 014bbf1..74d924c 100644
--- a/lib/security.c
+++ b/lib/security.c
@@ -192,15 +192,18 @@ static CURLcode read_data(struct connectdata *conn,
struct krb5buffer *buf)
{
int len;
- void* tmp;
+ void *tmp = NULL;
CURLcode result;
result = socket_read(fd, &len, sizeof(len));
if(result)
return result;
- len = ntohl(len);
- tmp = realloc(buf->data, len);
+ if(len) {
+ /* only realloc if there was a length */
+ len = ntohl(len);
+ tmp = realloc(buf->data, len);
+ }
if(tmp == NULL)
return CURLE_OUT_OF_MEMORY;
--
2.7.4

View File

@ -0,0 +1,35 @@
From f4145e2024d0785d6e72f5963585e7a43cace9cd Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Wed, 28 Sep 2016 00:05:12 +0200
Subject: [PATCH] base64: check for integer overflow on large input
CVE-2016-8617
Bug: https://curl.haxx.se/docs/adv_20161102C.html
Reported-by: Cure53
Upstream-commit: efd24d57426bd77c9b5860e6b297904703750412
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/base64.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/lib/base64.c b/lib/base64.c
index 2212115..8db578c 100644
--- a/lib/base64.c
+++ b/lib/base64.c
@@ -190,6 +190,11 @@ static CURLcode base64_encode(const char *table64,
if(0 == insize)
insize = strlen(indata);
+#if SIZEOF_SIZE_T == 4
+ if(insize > UINT_MAX/4)
+ return CURLE_OUT_OF_MEMORY;
+#endif
+
base64data = output = malloc(insize*4/3+4);
if(NULL == output)
return CURLE_OUT_OF_MEMORY;
--
2.7.4

View File

@ -0,0 +1,57 @@
From 5bc491031e5fb48a3d09762c1cebd690b8aa4d46 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Tue, 27 Sep 2016 18:01:53 +0200
Subject: [PATCH] connectionexists: use case sensitive user/password
comparisons
CVE-2016-8616
Bug: https://curl.haxx.se/docs/adv_20161102B.html
Reported-by: Cure53
Upstream-commit: b3ee26c5df75d97f6895e6ec4538894ebaf76e48
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/url.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/lib/url.c b/lib/url.c
index a88903c..b6ad5a6 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -3305,8 +3305,8 @@ ConnectionExists(struct SessionHandle *data,
if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) {
/* This protocol requires credentials per connection,
so verify that we're using the same name and password as well */
- if(!strequal(needle->user, check->user) ||
- !strequal(needle->passwd, check->passwd)) {
+ if(strcmp(needle->user, check->user) ||
+ strcmp(needle->passwd, check->passwd)) {
/* one of them was different */
continue;
}
@@ -3369,8 +3369,8 @@ ConnectionExists(struct SessionHandle *data,
possible. (Especially we must not reuse the same connection if
partway through a handshake!) */
if(wantNTLMhttp) {
- if(!strequal(needle->user, check->user) ||
- !strequal(needle->passwd, check->passwd))
+ if(strcmp(needle->user, check->user) ||
+ strcmp(needle->passwd, check->passwd))
continue;
}
else if(check->ntlm.state != NTLMSTATE_NONE) {
@@ -3380,8 +3380,8 @@ ConnectionExists(struct SessionHandle *data,
/* Same for Proxy NTLM authentication */
if(wantProxyNTLMhttp) {
- if(!strequal(needle->proxyuser, check->proxyuser) ||
- !strequal(needle->proxypasswd, check->proxypasswd))
+ if(strcmp(needle->proxyuser, check->proxyuser) ||
+ strcmp(needle->proxypasswd, check->proxypasswd))
continue;
}
else if(check->proxyntlm.state != NTLMSTATE_NONE) {
--
2.7.4

View File

@ -0,0 +1,70 @@
From 1ac97e5d7a54fd50543977a861fac2ab2ed84d43 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Tue, 27 Sep 2016 17:36:19 +0200
Subject: [PATCH] cookie: replace use of fgets() with custom version
... that will ignore lines that are too long to fit in the buffer.
CVE-2016-8615
Bug: https://curl.haxx.se/docs/adv_20161102A.html
Reported-by: Cure53
Upstream-commit: cff89bc088b7884098ea0c5378bbda3d49c437bc
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/cookie.c | 31 ++++++++++++++++++++++++++++++-
1 file changed, 30 insertions(+), 1 deletion(-)
diff --git a/lib/cookie.c b/lib/cookie.c
index 7a60411..f5a8846 100644
--- a/lib/cookie.c
+++ b/lib/cookie.c
@@ -892,6 +892,35 @@ Curl_cookie_add(struct SessionHandle *data,
return co;
}
+/*
+ * get_line() makes sure to only return complete whole lines that fit in 'len'
+ * bytes and end with a newline.
+ */
+static char *get_line(char *buf, int len, FILE *input)
+{
+ bool partial = FALSE;
+ while(1) {
+ char *b = fgets(buf, len, input);
+ if(b) {
+ size_t rlen = strlen(b);
+ if(rlen && (b[rlen-1] == '\n')) {
+ if(partial) {
+ partial = FALSE;
+ continue;
+ }
+ return b;
+ }
+ else
+ /* read a partial, discard the next piece that ends with newline */
+ partial = TRUE;
+ }
+ else
+ break;
+ }
+ return NULL;
+}
+
+
/*****************************************************************************
*
* Curl_cookie_init()
@@ -948,7 +977,7 @@ struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
line = malloc(MAX_COOKIE_LINE);
if(!line)
goto fail;
- while(fgets(line, MAX_COOKIE_LINE, fp)) {
+ while(get_line(line, MAX_COOKIE_LINE, fp)) {
if(checkprefix("Set-Cookie:", line)) {
/* This is a cookie line, get it! */
lineptr=&line[11];
--
2.7.4

View File

@ -0,0 +1,768 @@
From 5cc964e88bc34721a1e718004c450ce20a9fb428 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Sun, 3 Apr 2016 16:04:20 +0200
Subject: [PATCH 1/6] lib557: allow too long lines
Upstream-commit: adeaf95e2058a842badaddeae5501c0f5133dbea
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
tests/libtest/lib557.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/tests/libtest/lib557.c b/tests/libtest/lib557.c
index 2c0d5e0..2e72489 100644
--- a/tests/libtest/lib557.c
+++ b/tests/libtest/lib557.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -453,6 +453,7 @@ static int test_unsigned_int_formatting(void)
#elif (SIZEOF_INT == 8)
+ /* !checksrc! disable LONGLINE all */
i=1; ui_test[i].num = 0xFFFFFFFFFFFFFFFFU; ui_test[i].expected = "18446744073709551615";
i++; ui_test[i].num = 0xFFFFFFFF00000000U; ui_test[i].expected = "18446744069414584320";
i++; ui_test[i].num = 0x00000000FFFFFFFFU; ui_test[i].expected = "4294967295";
@@ -1344,6 +1345,7 @@ static int test_curl_off_t_formatting(void)
num_cofft_tests = i;
#endif
+ /* !checksrc! enable LONGLINE */
for(i=1; i<=num_cofft_tests; i++) {
@@ -1351,11 +1353,12 @@ static int test_curl_off_t_formatting(void)
co_test[i].result[j] = 'X';
co_test[i].result[BUFSZ-1] = '\0';
- (void)curl_msprintf(co_test[i].result, "%" CURL_FORMAT_CURL_OFF_T, co_test[i].num);
+ (void)curl_msprintf(co_test[i].result, "%" CURL_FORMAT_CURL_OFF_T,
+ co_test[i].num);
if(memcmp(co_test[i].result,
- co_test[i].expected,
- strlen(co_test[i].expected))) {
+ co_test[i].expected,
+ strlen(co_test[i].expected))) {
printf("curl_off_t test #%.2d: Failed (Expected: %s Got: %s)\n",
i, co_test[i].expected, co_test[i].result);
failed++;
--
2.7.4
From 1e8206bd84b5bd2a41ea80631b6815d00c4ed813 Mon Sep 17 00:00:00 2001
From: Jay Satiro <raysatiro@yahoo.com>
Date: Wed, 9 Mar 2016 02:59:05 -0500
Subject: [PATCH 2/6] mprintf: Fix processing of width and prec args
Prior to this change a width arg could be erroneously output, and also
width and precision args could not be used together without crashing.
"%0*d%s", 2, 9, "foo"
Before: "092"
After: "09foo"
"%*.*s", 5, 2, "foo"
Before: crash
After: " fo"
Test 557 is updated to verify this and more
Upstream-commit: 68701e51c1f794df59d9f70bcddbf714ee91b868
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/mprintf.c | 60 +++++++++++++++++++++++++++++++++-----------------
tests/data/test557 | 1 +
tests/libtest/lib557.c | 49 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 90 insertions(+), 20 deletions(-)
diff --git a/lib/mprintf.c b/lib/mprintf.c
index e47c10a..a110785 100644
--- a/lib/mprintf.c
+++ b/lib/mprintf.c
@@ -465,22 +465,24 @@ static long dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
if(flags & FLAGS_WIDTHPARAM) {
/* we have the width specified from a parameter, so we make that
parameter's info setup properly */
- vto[i].width = width - 1;
- i = width - 1;
- vto[i].type = FORMAT_WIDTH;
- vto[i].flags = FLAGS_NEW;
- vto[i].precision = vto[i].width = 0; /* can't use width or precision
- of width! */
+ long k = width - 1;
+ vto[i].width = k;
+ vto[k].type = FORMAT_WIDTH;
+ vto[k].flags = FLAGS_NEW;
+ /* can't use width or precision of width! */
+ vto[k].width = 0;
+ vto[k].precision = 0;
}
if(flags & FLAGS_PRECPARAM) {
/* we have the precision specified from a parameter, so we make that
parameter's info setup properly */
- vto[i].precision = precision - 1;
- i = precision - 1;
- vto[i].type = FORMAT_WIDTH;
- vto[i].flags = FLAGS_NEW;
- vto[i].precision = vto[i].width = 0; /* can't use width or precision
- of width! */
+ long k = precision - 1;
+ vto[i].precision = k;
+ vto[k].type = FORMAT_WIDTH;
+ vto[k].flags = FLAGS_NEW;
+ /* can't use width or precision of width! */
+ vto[k].width = 0;
+ vto[k].precision = 0;
}
*endpos++ = fmt + 1; /* end of this sequence */
}
@@ -488,11 +490,15 @@ static long dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
/* Read the arg list parameters into our data list */
for(i=0; i<max_param; i++) {
- if((i + 1 < max_param) && (vto[i + 1].type == FORMAT_WIDTH)) {
- /* Width/precision arguments must be read before the main argument
- * they are attached to
- */
- vto[i + 1].data.num.as_signed = (mp_intmax_t)va_arg(arglist, int);
+ /* Width/precision arguments must be read before the main argument
+ they are attached to */
+ if(vto[i].flags & FLAGS_WIDTHPARAM) {
+ vto[vto[i].width].data.num.as_signed =
+ (mp_intmax_t)va_arg(arglist, int);
+ }
+ if(vto[i].flags & FLAGS_PRECPARAM) {
+ vto[vto[i].precision].data.num.as_signed =
+ (mp_intmax_t)va_arg(arglist, int);
}
switch (vto[i].type) {
@@ -645,16 +651,30 @@ static int dprintf_formatf(
p = &vto[param];
/* pick up the specified width */
- if(p->flags & FLAGS_WIDTHPARAM)
+ if(p->flags & FLAGS_WIDTHPARAM) {
width = (long)vto[p->width].data.num.as_signed;
+ param_num++; /* since the width is extracted from a parameter, we
+ must skip that to get to the next one properly */
+ if(width < 0) {
+ /* "A negative field width is taken as a '-' flag followed by a
+ positive field width." */
+ width = -width;
+ p->flags |= FLAGS_LEFT;
+ p->flags &= ~FLAGS_PAD_NIL;
+ }
+ }
else
width = p->width;
/* pick up the specified precision */
if(p->flags & FLAGS_PRECPARAM) {
prec = (long)vto[p->precision].data.num.as_signed;
- param_num++; /* since the precision is extraced from a parameter, we
+ param_num++; /* since the precision is extracted from a parameter, we
must skip that to get to the next one properly */
+ if(prec < 0)
+ /* "A negative precision is taken as if the precision were
+ omitted." */
+ prec = -1;
}
else if(p->flags & FLAGS_PREC)
prec = p->precision;
@@ -809,7 +829,7 @@ static int dprintf_formatf(
else
len = strlen(str);
- width -= (long)len;
+ width -= (len > LONG_MAX) ? LONG_MAX : (long)len;
if(p->flags & FLAGS_ALT)
OUTCHAR('"');
diff --git a/tests/data/test557 b/tests/data/test557
index ee2793f..8d0944a 100644
--- a/tests/data/test557
+++ b/tests/data/test557
@@ -39,6 +39,7 @@ All curl_mprintf() signed int tests OK!
All curl_mprintf() unsigned long tests OK!
All curl_mprintf() signed long tests OK!
All curl_mprintf() curl_off_t tests OK!
+All curl_mprintf() strings tests OK!
</stdout>
</verify>
diff --git a/tests/libtest/lib557.c b/tests/libtest/lib557.c
index 2e72489..5bdb8ab 100644
--- a/tests/libtest/lib557.c
+++ b/tests/libtest/lib557.c
@@ -1374,6 +1374,53 @@ static int test_curl_off_t_formatting(void)
return failed;
}
+static int string_check(char *buf, const char *buf2)
+{
+ if(strcmp(buf, buf2)) {
+ /* they shouldn't differ */
+ printf("sprintf failed:\nwe '%s'\nsystem: '%s'\n",
+ buf, buf2);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * The output strings in this test need to have been verified with a system
+ * sprintf() before used here.
+ */
+static int test_string_formatting(void)
+{
+ int errors = 0;
+ char buf[256];
+ curl_msnprintf(buf, sizeof(buf), "%0*d%s", 2, 9, "foo");
+ errors += string_check(buf, "09foo");
+
+ curl_msnprintf(buf, sizeof(buf), "%*.*s", 5, 2, "foo");
+ errors += string_check(buf, " fo");
+
+ curl_msnprintf(buf, sizeof(buf), "%*.*s", 2, 5, "foo");
+ errors += string_check(buf, "foo");
+
+ curl_msnprintf(buf, sizeof(buf), "%*.*s", 0, 10, "foo");
+ errors += string_check(buf, "foo");
+
+ curl_msnprintf(buf, sizeof(buf), "%-10s", "foo");
+ errors += string_check(buf, "foo ");
+
+ curl_msnprintf(buf, sizeof(buf), "%10s", "foo");
+ errors += string_check(buf, " foo");
+
+ curl_msnprintf(buf, sizeof(buf), "%*.*s", -10, -10, "foo");
+ errors += string_check(buf, "foo ");
+
+ if(!errors)
+ printf("All curl_mprintf() strings tests OK!\n");
+ else
+ printf("Some curl_mprintf() string tests Failed!\n");
+
+ return errors;
+}
int test(char *URL)
{
@@ -1394,6 +1441,8 @@ int test(char *URL)
errors += test_curl_off_t_formatting();
+ errors += test_string_formatting();
+
if(errors)
return TEST_ERR_MAJOR_BAD;
else
--
2.7.4
From cf803e5d0041aaf77b95506a49895b7fa78c9541 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Sat, 8 Oct 2016 20:47:04 +0200
Subject: [PATCH 3/6] mprintf: return error on too many arguments
128 arguments should be enough for everyone
Upstream-commit: 71588c9aef8112025c7525d20f57eb367a947344
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/mprintf.c | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/lib/mprintf.c b/lib/mprintf.c
index a110785..f51fe6d 100644
--- a/lib/mprintf.c
+++ b/lib/mprintf.c
@@ -232,10 +232,12 @@ static bool dprintf_IsQualifierNoDollar(const char *fmt)
* Create an index with the type of each parameter entry and its
* value (may vary in size)
*
+ * Returns zero on success.
+ *
******************************************************************/
-static long dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
- va_list arglist)
+static int dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
+ va_list arglist)
{
char *fmt = (char *)format;
int param_num = 0;
@@ -398,6 +400,10 @@ static long dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
i = this_param - 1;
+ if((i < 0) || (i >= MAX_PARAMETERS))
+ /* out of allowed range */
+ return 1;
+
switch (*fmt) {
case 'S':
flags |= FLAGS_ALT;
@@ -554,7 +560,7 @@ static long dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
}
}
- return max_param;
+ return 0;
}
@@ -587,7 +593,8 @@ static int dprintf_formatf(
va_stack_t *p;
/* Do the actual %-code parsing */
- dprintf_Pass1(format, vto, endpos, ap_save);
+ if(dprintf_Pass1(format, vto, endpos, ap_save))
+ return -1;
end = &endpos[0]; /* the initial end-position from the list dprintf_Pass1()
created for us */
@@ -994,7 +1001,7 @@ int curl_mvsnprintf(char *buffer, size_t maxlength, const char *format,
info.max = maxlength;
retcode = dprintf_formatf(&info, addbyter, format, ap_save);
- if(info.max) {
+ if((retcode != -1) && info.max) {
/* we terminate this with a zero byte */
if(info.max == info.length)
/* we're at maximum, scrap the last letter */
--
2.7.4
From 329eb5d7f36049fa294dac1f89125ae5dd41fd84 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Sat, 8 Oct 2016 20:47:44 +0200
Subject: [PATCH 4/6] test557: verify printf() with 128 and 129 arguments
Upstream-commit: ac8a3149133fd3420770baf37190e47f5f7a46c7
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
tests/libtest/lib557.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 104 insertions(+)
diff --git a/tests/libtest/lib557.c b/tests/libtest/lib557.c
index 5bdb8ab..683ca08 100644
--- a/tests/libtest/lib557.c
+++ b/tests/libtest/lib557.c
@@ -1422,11 +1422,115 @@ static int test_string_formatting(void)
return errors;
}
+static int test_weird_arguments(void)
+{
+ int errors = 0;
+ char buf[256];
+ int rc;
+
+ /* MAX_PARAMETERS is 128, try exact 128! */
+ rc = curl_msnprintf(buf, sizeof(buf),
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 1 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 2 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 3 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 4 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 5 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 6 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 7 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 8 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 9 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 10 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 11 */
+ "%d%d%d%d%d%d%d%d" /* 8 */
+ ,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 1 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 2 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 3 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 4 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 5 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 6 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 7 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 8 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 9 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 10 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 11 */
+ 0, 1, 2, 3, 4, 5, 6, 7); /* 8 */
+
+ if(rc != 128) {
+ printf("curl_mprintf() returned %d and not 128!\n", rc);
+ errors++;
+ }
+
+ errors += string_check(buf,
+ "0123456789" /* 10 */
+ "0123456789" /* 10 1 */
+ "0123456789" /* 10 2 */
+ "0123456789" /* 10 3 */
+ "0123456789" /* 10 4 */
+ "0123456789" /* 10 5 */
+ "0123456789" /* 10 6 */
+ "0123456789" /* 10 7 */
+ "0123456789" /* 10 8 */
+ "0123456789" /* 10 9 */
+ "0123456789" /* 10 10*/
+ "0123456789" /* 10 11 */
+ "01234567" /* 8 */
+ );
+
+ /* MAX_PARAMETERS is 128, try more! */
+ buf[0] = 0;
+ rc = curl_msnprintf(buf, sizeof(buf),
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 1 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 2 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 3 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 4 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 5 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 6 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 7 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 8 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 9 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 10 */
+ "%d%d%d%d%d%d%d%d%d%d" /* 10 11 */
+ "%d%d%d%d%d%d%d%d%d" /* 9 */
+ ,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 1 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 2 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 3 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 4 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 5 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 6 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 7 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 8 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 9 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 10 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 10 11 */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8); /* 9 */
+
+ if(rc != -1) {
+ printf("curl_mprintf() returned %d and not -1!\n", rc);
+ errors++;
+ }
+
+ errors += string_check(buf, "");
+
+ if(errors)
+ printf("Some curl_mprintf() weird arguments tests failed!\n");
+
+ return errors;
+}
+
+
int test(char *URL)
{
int errors = 0;
(void)URL; /* not used */
+ errors += test_weird_arguments();
+
errors += test_unsigned_short_formatting();
errors += test_signed_short_formatting();
--
2.7.4
From 7ad1cdfb256f7e1b84fc960a8ca1403cca5d930f Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Tue, 8 Nov 2016 15:30:33 +0100
Subject: [PATCH 5/6] printf: fix ".*f" handling
It would always use precision 1 instead of reading it from the argument
list as intended.
Reported-by: Ray Satiro
Bug: #1113
Upstream-commit: 5dd1b65f79bc6dc75b752c53f3fa853b2a3b6d69
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/mprintf.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/lib/mprintf.c b/lib/mprintf.c
index f51fe6d..07830db 100644
--- a/lib/mprintf.c
+++ b/lib/mprintf.c
@@ -308,7 +308,6 @@ static int dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
flags |= FLAGS_ALT;
break;
case '.':
- flags |= FLAGS_PREC;
if('*' == *fmt) {
/* The precision is picked from a specified parameter */
--
2.7.4
From 3162df571802b2c94d9969b6b269cd0d50c6650d Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Tue, 8 Nov 2016 15:32:37 +0100
Subject: [PATCH 6/6] printf: fix floating point buffer overflow issues
... and add a bunch of floating point printf tests
Upstream-commit: 3ab3c16db6a5674f53cf23d56512a405fde0b2c9
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
lib/mprintf.c | 20 +++++++-
tests/data/test557 | 1 +
tests/libtest/lib557.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 152 insertions(+), 5 deletions(-)
diff --git a/lib/mprintf.c b/lib/mprintf.c
index e1ad537..e3a690b 100644
--- a/lib/mprintf.c
+++ b/lib/mprintf.c
@@ -97,7 +97,8 @@
# define mp_uintmax_t unsigned long
#endif
-#define BUFFSIZE 256 /* buffer for long-to-str and float-to-str calcs */
+#define BUFFSIZE 326 /* buffer for long-to-str and float-to-str calcs, should
+ fit negative DBL_MAX (317 letters) */
#define MAX_PARAMETERS 128 /* lame static limit */
#ifdef __AMIGA__
@@ -918,12 +919,25 @@ static int dprintf_formatf(
*fptr = 0;
if(width >= 0) {
+ if(width >= (long)sizeof(work))
+ width = sizeof(work)-1;
/* RECURSIVE USAGE */
len = curl_msnprintf(fptr, left, "%ld", width);
fptr += len;
left -= len;
}
if(prec >= 0) {
+ /* for each digit in the integer part, we can have one less
+ precision */
+ size_t maxprec = sizeof(work) - 2;
+ double val = p->data.dnum;
+ while(val >= 10.0) {
+ val /= 10;
+ maxprec--;
+ }
+
+ if(prec > (long)maxprec)
+ prec = maxprec-1;
/* RECURSIVE USAGE */
len = curl_msnprintf(fptr, left, ".%ld", prec);
fptr += len;
@@ -943,7 +957,9 @@ static int dprintf_formatf(
/* NOTE NOTE NOTE!! Not all sprintf implementations return number of
output characters */
(sprintf)(work, formatbuf, p->data.dnum);
-
+#ifdef CURLDEBUG
+ assert(strlen(work) <= sizeof(work));
+#endif
for(fptr=work; *fptr; fptr++)
OUTCHAR(*fptr);
}
diff --git a/tests/data/test557 b/tests/data/test557
index 8d0944a..ad9350f 100644
--- a/tests/data/test557
+++ b/tests/data/test557
@@ -40,6 +40,7 @@ All curl_mprintf() unsigned long tests OK!
All curl_mprintf() signed long tests OK!
All curl_mprintf() curl_off_t tests OK!
All curl_mprintf() strings tests OK!
+All float strings tests OK!
</stdout>
</verify>
diff --git a/tests/libtest/lib557.c b/tests/libtest/lib557.c
index 683ca08..8c62a0e 100644
--- a/tests/libtest/lib557.c
+++ b/tests/libtest/lib557.c
@@ -1374,16 +1374,31 @@ static int test_curl_off_t_formatting(void)
return failed;
}
-static int string_check(char *buf, const char *buf2)
+static int _string_check(int linenumber, char *buf, const char *buf2)
{
if(strcmp(buf, buf2)) {
/* they shouldn't differ */
- printf("sprintf failed:\nwe '%s'\nsystem: '%s'\n",
- buf, buf2);
+ printf("sprintf line %d failed:\nwe '%s'\nsystem: '%s'\n",
+ linenumber, buf, buf2);
return 1;
}
return 0;
}
+#define string_check(x,y) _string_check(__LINE__, x, y)
+
+static int _strlen_check(int linenumber, char *buf, size_t len)
+{
+ size_t buflen = strlen(buf);
+ if(len != buflen) {
+ /* they shouldn't differ */
+ printf("sprintf strlen:%d failed:\nwe '%d'\nsystem: '%d'\n",
+ linenumber, buflen, len);
+ return 1;
+ }
+ return 0;
+}
+
+#define strlen_check(x,y) _strlen_check(__LINE__, x, y)
/*
* The output strings in this test need to have been verified with a system
@@ -1523,6 +1538,119 @@ static int test_weird_arguments(void)
return errors;
}
+/* DBL_MAX value from Linux */
+#define MAXIMIZE -179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000
+
+static int test_float_formatting(void)
+{
+ int errors = 0;
+ char buf[512]; /* larger than max float size */
+ curl_msnprintf(buf, sizeof(buf), "%f", 9.0);
+ errors += string_check(buf, "9.000000");
+
+ curl_msnprintf(buf, sizeof(buf), "%.1f", 9.1);
+ errors += string_check(buf, "9.1");
+
+ curl_msnprintf(buf, sizeof(buf), "%.2f", 9.1);
+ errors += string_check(buf, "9.10");
+
+ curl_msnprintf(buf, sizeof(buf), "%.0f", 9.1);
+ errors += string_check(buf, "9");
+
+ curl_msnprintf(buf, sizeof(buf), "%0f", 9.1);
+ errors += string_check(buf, "9.100000");
+
+ curl_msnprintf(buf, sizeof(buf), "%10f", 9.1);
+ errors += string_check(buf, " 9.100000");
+
+ curl_msnprintf(buf, sizeof(buf), "%10.3f", 9.1);
+ errors += string_check(buf, " 9.100");
+
+ curl_msnprintf(buf, sizeof(buf), "%-10.3f", 9.1);
+ errors += string_check(buf, "9.100 ");
+
+ curl_msnprintf(buf, sizeof(buf), "%-10.3f", 9.123456);
+ errors += string_check(buf, "9.123 ");
+
+ curl_msnprintf(buf, sizeof(buf), "%.-2f", 9.1);
+ errors += string_check(buf, "9.100000");
+
+ curl_msnprintf(buf, sizeof(buf), "%*f", 10, 9.1);
+ errors += string_check(buf, " 9.100000");
+
+ curl_msnprintf(buf, sizeof(buf), "%*f", 3, 9.1);
+ errors += string_check(buf, "9.100000");
+
+ curl_msnprintf(buf, sizeof(buf), "%*f", 6, 9.2987654);
+ errors += string_check(buf, "9.298765");
+
+ curl_msnprintf(buf, sizeof(buf), "%*f", 6, 9.298765);
+ errors += string_check(buf, "9.298765");
+
+ curl_msnprintf(buf, sizeof(buf), "%*f", 6, 9.29876);
+ errors += string_check(buf, "9.298760");
+
+ curl_msnprintf(buf, sizeof(buf), "%.*f", 6, 9.2987654);
+ errors += string_check(buf, "9.298765");
+ curl_msnprintf(buf, sizeof(buf), "%.*f", 5, 9.2987654);
+ errors += string_check(buf, "9.29877");
+ curl_msnprintf(buf, sizeof(buf), "%.*f", 4, 9.2987654);
+ errors += string_check(buf, "9.2988");
+ curl_msnprintf(buf, sizeof(buf), "%.*f", 3, 9.2987654);
+ errors += string_check(buf, "9.299");
+ curl_msnprintf(buf, sizeof(buf), "%.*f", 2, 9.2987654);
+ errors += string_check(buf, "9.30");
+ curl_msnprintf(buf, sizeof(buf), "%.*f", 1, 9.2987654);
+ errors += string_check(buf, "9.3");
+ curl_msnprintf(buf, sizeof(buf), "%.*f", 0, 9.2987654);
+ errors += string_check(buf, "9");
+
+ /* very large precisions easily turn into system specific outputs so we only
+ check the output buffer length here as we know the internal limit */
+
+ curl_msnprintf(buf, sizeof(buf), "%.*f", (1<<30), 9.2987654);
+ errors += strlen_check(buf, 325);
+
+ curl_msnprintf(buf, sizeof(buf), "%10000.10000f", 9.2987654);
+ errors += strlen_check(buf, 325);
+
+ curl_msnprintf(buf, sizeof(buf), "%240.10000f",
+ 123456789123456789123456789.2987654);
+ errors += strlen_check(buf, 325);
+
+ /* 1<<31 turns negative (-2147483648) when used signed */
+ curl_msnprintf(buf, sizeof(buf), "%*f", (1<<31), 9.1);
+ errors += string_check(buf, "9.100000");
+
+ /* curl_msnprintf() limits a single float output to 325 bytes maximum
+ width */
+ curl_msnprintf(buf, sizeof(buf), "%*f", (1<<30), 9.1);
+ errors += string_check(buf, " 9.100000");
+ curl_msnprintf(buf, sizeof(buf), "%100000f", 9.1);
+ errors += string_check(buf, " 9.100000");
+
+ curl_msnprintf(buf, sizeof(buf), "%f", MAXIMIZE);
+ errors += strlen_check(buf, 317);
+
+ curl_msnprintf(buf, 2, "%f", MAXIMIZE);
+ errors += strlen_check(buf, 1);
+ curl_msnprintf(buf, 3, "%f", MAXIMIZE);
+ errors += strlen_check(buf, 2);
+ curl_msnprintf(buf, 4, "%f", MAXIMIZE);
+ errors += strlen_check(buf, 3);
+ curl_msnprintf(buf, 5, "%f", MAXIMIZE);
+ errors += strlen_check(buf, 4);
+ curl_msnprintf(buf, 6, "%f", MAXIMIZE);
+ errors += strlen_check(buf, 5);
+
+ if(!errors)
+ printf("All float strings tests OK!\n");
+ else
+ printf("test_float_formatting Failed!\n");
+
+ return errors;
+}
+
int test(char *URL)
{
@@ -1547,6 +1675,8 @@ int test(char *URL)
errors += test_string_formatting();
+ errors += test_float_formatting();
+
if(errors)
return TEST_ERR_MAJOR_BAD;
else
--
2.7.4

107
curl.spec
View File

@ -1,7 +1,7 @@
Summary: A utility for getting files from remote servers (FTP, HTTP, and others)
Name: curl
Version: 7.47.1
Release: 4%{?dist}
Release: 10%{?dist}
License: MIT
Group: Applications/Internet
Source: http://curl.haxx.se/download/%{name}-%{version}.tar.lzma
@ -10,6 +10,57 @@ Source2: curlbuild.h
# do not refuse cookies for localhost (#1308791)
Patch1: 0001-curl-7.47.1-psl-localhost.patch
# fix SIGSEGV of the curl tool while parsing URL with too many globs (#1340757)
Patch7: 0007-curl-7.49.1-urlglob.patch
# fix use of connection struct after free (CVE-2016-5421)
Patch8: 0008-curl-7.47.1-CVE-2016-5421.patch
# fix TLS session resumption client cert bypass (CVE-2016-5419)
Patch9: 0009-curl-7.47.1-CVE-2016-5419.patch
# fix re-using connections with wrong client cert (CVE-2016-5420)
Patch10: 0010-curl-7.47.1-CVE-2016-5420.patch
# work around race condition in PK11_FindSlotByName()
Patch11: 0011-curl-7.47.1-find-slot-race.patch
# reject negative string lengths in curl_easy_[un]escape() (CVE-2016-7167)
Patch12: 0012-curl-7.47.1-CVE-2016-7167.patch
# urlparse: accept '#' as end of host name (CVE-2016-8624)
Patch13: 0013-curl-7.47.1-CVE-2016-8624.patch
# fix use-after-free via shared cookies (CVE-2016-8623)
Patch14: 0014-curl-7.47.1-CVE-2016-8623.patch
# fix URL unescape heap overflow via integer truncation (CVE-2016-8622)
Patch15: 0015-curl-7.47.1-CVE-2016-8622.patch
# fix out-of-bounds read in curl_getdate() (CVE-2016-8621)
Patch16: 0016-curl-7.47.1-CVE-2016-8621.patch
# fix glob parser write/read out of bounds (CVE-2016-8620)
Patch17: 0017-curl-7.47.1-CVE-2016-8620.patch
# fix double-free in curl_maprintf() (CVE-2016-8618)
Patch18: 0018-curl-7.47.1-CVE-2016-8618.patch
# fix double-free in krb5 code (CVE-2016-8619)
Patch19: 0019-curl-7.47.1-CVE-2016-8619.patch
# base64: check for integer overflow on large input (CVE-2016-8617)
Patch20: 0020-curl-7.47.1-CVE-2016-8617.patch
# compare user/passwd case-sensitively while reusing connections (CVE-2016-8616)
Patch21: 0021-curl-7.47.1-CVE-2016-8616.patch
# fix cookie injection for other servers (CVE-2016-8615)
Patch22: 0022-curl-7.47.1-CVE-2016-8615.patch
# fix floating point buffer overflow issues (CVE-2016-9586)
Patch23: 0023-curl-7.47.1-CVE-2016-9586.patch
# patch making libcurl multilib ready
Patch101: 0101-curl-7.32.0-multilib.patch
@ -25,6 +76,7 @@ Patch107: 0107-curl-7.21.4-libidn-valgrind.patch
Provides: webclient
URL: http://curl.haxx.se/
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(id -nu)
BuildRequires: automake
BuildRequires: groff
BuildRequires: krb5-devel
BuildRequires: libidn-devel
@ -32,6 +84,7 @@ BuildRequires: libmetalink-devel
BuildRequires: libnghttp2-devel
BuildRequires: libpsl-devel
BuildRequires: libssh2-devel
BuildRequires: libtool
BuildRequires: nss-devel
BuildRequires: openldap-devel
BuildRequires: openssh-clients
@ -122,6 +175,23 @@ documentation of the library, too.
# upstream patches
%patch1 -p1
%patch7 -p1
%patch8 -p1
%patch9 -p1
%patch10 -p1
%patch11 -p1
%patch12 -p1
%patch13 -p1
%patch14 -p1
%patch15 -p1
%patch16 -p1
%patch17 -p1
%patch18 -p1
%patch19 -p1
%patch20 -p1
%patch21 -p1
%patch22 -p1
%patch23 -p1
# Fedora patches
%patch101 -p1
@ -142,6 +212,9 @@ printf "1112\n1801\n" >> tests/data/DISABLED
echo "1319" >> tests/data/DISABLED
%endif
# we need to regenerate Makefile.in files because of patching
autoreconf -fiv
%build
[ -x /usr/kerberos/bin/krb5-config ] && KRB5_PREFIX="=/usr/kerberos"
%configure --disable-static \
@ -234,6 +307,38 @@ rm -rf $RPM_BUILD_ROOT
%{_datadir}/aclocal/libcurl.m4
%changelog
* Fri Dec 23 2016 Kamil Dudka <kdudka@redhat.com> 7.47.1-10
- fix floating point buffer overflow issues (CVE-2016-9586)
* Wed Nov 02 2016 Kamil Dudka <kdudka@redhat.com> 7.47.1-9
- fix cookie injection for other servers (CVE-2016-8615)
- compare user/passwd case-sensitively while reusing connections (CVE-2016-8616)
- base64: check for integer overflow on large input (CVE-2016-8617)
- fix double-free in krb5 code (CVE-2016-8619)
- fix double-free in curl_maprintf() (CVE-2016-8618)
- fix glob parser write/read out of bounds (CVE-2016-8620)
- fix out-of-bounds read in curl_getdate() (CVE-2016-8621)
- fix URL unescape heap overflow via integer truncation (CVE-2016-8622)
- fix use-after-free via shared cookies (CVE-2016-8623)
- urlparse: accept '#' as end of host name (CVE-2016-8624)
- run autoreconf in %%prep to avoid patching Makefile.in files from now on
* Wed Sep 14 2016 Kamil Dudka <kdudka@redhat.com> 7.47.1-8
- reject negative string lengths in curl_easy_[un]escape() (CVE-2016-7167)
* Fri Aug 26 2016 Kamil Dudka <kdudka@redhat.com> 7.47.1-7
- work around race condition in PK11_FindSlotByName()
- fix incorrect use of a previously loaded certificate from file
(related to CVE-2016-5420)
* Wed Aug 03 2016 Kamil Dudka <kdudka@redhat.com> 7.47.1-6
- fix re-using connections with wrong client cert (CVE-2016-5420)
- fix TLS session resumption client cert bypass (CVE-2016-5419)
- fix use of connection struct after free (CVE-2016-5421)
* Fri Jun 03 2016 Kamil Dudka <kdudka@redhat.com> 7.47.1-5
- fix SIGSEGV of the curl tool while parsing URL with too many globs (#1340757)
* Wed Mar 02 2016 Kamil Dudka <kdudka@redhat.com> 7.47.1-4
- do not refuse cookies for localhost (#1308791)