From c1e254b55d930cccbae653320442fb7669be7692 Mon Sep 17 00:00:00 2001
From: dartraiden <wowemuh@gmail.com>
Date: Tue, 7 Jul 2020 22:32:37 +0300
Subject: libcurl: update to 7.71.1

---
 libs/libcurl/docs/CHANGES           | 441 ++++++++++++++++--------------------
 libs/libcurl/docs/THANKS            |   8 +
 libs/libcurl/include/curl/curl.h    |   6 +-
 libs/libcurl/include/curl/curlver.h |   8 +-
 libs/libcurl/include/curl/multi.h   |   2 +-
 libs/libcurl/src/config-win32.h     |   7 -
 libs/libcurl/src/cookie.c           |   2 +-
 libs/libcurl/src/curl_path.c        |   4 +-
 libs/libcurl/src/dict.c             |   3 +-
 libs/libcurl/src/dotdot.c           |  10 +-
 libs/libcurl/src/dynbuf.c           |   2 +-
 libs/libcurl/src/dynbuf.h           |   2 +-
 libs/libcurl/src/escape.c           |  24 +-
 libs/libcurl/src/escape.h           |  11 +-
 libs/libcurl/src/file.c             |   2 +-
 libs/libcurl/src/formdata.c         |   4 +-
 libs/libcurl/src/ftp.c              |  18 +-
 libs/libcurl/src/gopher.c           |   2 +-
 libs/libcurl/src/http.c             |  10 +-
 libs/libcurl/src/http2.c            |  44 ++++
 libs/libcurl/src/if2ip.c            |  13 +-
 libs/libcurl/src/imap.c             |  10 +-
 libs/libcurl/src/ldap.c             |   7 +-
 libs/libcurl/src/libcurl.plist      |   6 +-
 libs/libcurl/src/mime.c             |   2 +-
 libs/libcurl/src/mqtt.c             |   3 +-
 libs/libcurl/src/multi.c            | 122 +---------
 libs/libcurl/src/multihandle.h      |   4 -
 libs/libcurl/src/pingpong.c         |   4 +-
 libs/libcurl/src/pop3.c             |   4 +-
 libs/libcurl/src/sendf.c            |   2 +-
 libs/libcurl/src/smb.c              |   4 +-
 libs/libcurl/src/smtp.c             |   5 +-
 libs/libcurl/src/strerror.c         |   2 +-
 libs/libcurl/src/strtok.c           |   4 +-
 libs/libcurl/src/tftp.c             |   2 +-
 libs/libcurl/src/url.c              |  37 +--
 libs/libcurl/src/urlapi.c           |  13 +-
 libs/libcurl/src/urldata.h          |   5 +-
 libs/libcurl/src/vquic/ngtcp2.c     |   4 +-
 libs/libcurl/src/vtls/mbedtls.c     |  10 +
 libs/libcurl/src/vtls/openssl.c     |  11 +-
 libs/libcurl/src/vtls/vtls.c        |  48 +++-
 43 files changed, 461 insertions(+), 471 deletions(-)

(limited to 'libs/libcurl')

diff --git a/libs/libcurl/docs/CHANGES b/libs/libcurl/docs/CHANGES
index 5061b40139..5ee0cc6964 100644
--- a/libs/libcurl/docs/CHANGES
+++ b/libs/libcurl/docs/CHANGES
@@ -6,6 +6,205 @@
 
                                   Changelog
 
+Version 7.71.1 (30 Jun 2020)
+
+Daniel Stenberg (30 Jun 2020)
+- RELEASE-NOTES: curl 7.71.1
+
+- THANKS: add contributors to 7.71.1
+
+- scripts/copyright.pl: skip .dcignore
+
+- Revert "multi: implement wait using winsock events"
+  
+  This reverts commit 8bc25c590e530de87595d1bb3577f699eb1309b9.
+  
+  That commit (from #5397) introduced a regression in 7.71.0.
+  
+  Reported-by: tmkk on github
+  Fixes #5631
+  Closes #5632
+
+- TODO: Add flag to specify download directory
+
+- TODO: return code to CURLMOPT_PUSHFUNCTION to fail connection
+
+- cirrus-ci: disable FreeBSD 13 (again)
+  
+  It has been failing for a good while again. This time we better leave it
+  disabled until we have more reason to believe it behaves.
+  
+  Closes #5628
+
+- ngtcp2: sync with current master
+  
+  ngtcp2 added two new callbacks
+  
+  Reported-by: Lucien Zürcher
+  Fixes #5624
+  Closes #5627
+
+- examples/multithread.c: call curl_global_cleanup()
+  
+  Reported-by: qiandu2006 on github
+  Fixes #5622
+  Closes #5623
+
+- vtls: compare cert blob when finding a connection to reuse
+  
+  Reported-by: Gergely Nagy
+  Fixes #5617
+  Closes #5619
+
+- RELEASE-NOTES: synced
+
+- terminology: call them null-terminated strings
+  
+  Updated terminology in docs, comments and phrases to refer to C strings
+  as "null-terminated". Done to unify with how most other C oriented docs
+  refer of them and what users in general seem to prefer (based on a
+  single highly unscientific poll on twitter).
+  
+  Reported-by: coinhubs on github
+  Fixes #5598
+  Closes #5608
+
+- http: fix proxy auth with blank password
+  
+  Regression in 7.71.0
+  
+  Added test case 346 to verify.
+  
+  Reported-by: Kristoffer Gleditsch
+  Fixes #5613
+  Closes #5616
+
+- .dcignore: ignore tests and docs directories
+  
+  This is a config file for deepcode.ai, a static code analyzer.
+
+Jay Satiro (26 Jun 2020)
+- tool_cb_hdr: Fix etag warning output and return code
+  
+  - Return 'failure' on failure, to follow the existing style.
+  
+  - Put Warning: and the warning message on the same line.
+  
+  Ref: https://github.com/curl/curl/issues/5610
+  
+  Closes https://github.com/curl/curl/pull/5612
+
+Daniel Stenberg (26 Jun 2020)
+- CURLOPT_READFUNCTION.3: provide the upload data size up front
+  
+  Assisted-by: Jay Satiro
+  Closes #5607
+
+- test1539: do a HTTP 1.0 POST without a set size (fails)
+  
+  Attempt to reproduce #5593. Test case 1514 is very similar but uses
+  HTTP/1.1 and thus switches to chunked.
+  
+  Closes #5595
+
+- [Baruch Siach brought this change]
+
+  mbedtls: fix build with disabled proxy support
+  
+  Don't reference fields that do not exist. Fixes build failure:
+  
+  vtls/mbedtls.c: In function 'mbed_connect_step1':
+  vtls/mbedtls.c:249:54: error: 'struct connectdata' has no member named 'http_proxy'
+  
+  Closes #5615
+
+- codeql-analysis.yml: fix the 'languages' setting
+  
+  It needs a 'with:' in front of it.
+
+GitHub (26 Jun 2020)
+- [Daniel Stenberg brought this change]
+
+  gtihub: codeql-analysis.yml
+  
+  enables code security scanning with github actions
+
+Daniel Stenberg (25 Jun 2020)
+- tests: verify newline in username and password for HTTP
+  
+  test 1296 is a simply command line test
+  
+  test 1910 is a libcurl test including a redirect
+
+- url: allow user + password to contain "control codes" for HTTP(S)
+  
+  Reported-by: Jon Johnson Jr
+  Fixes #5582
+  Closes #5592
+
+- escape: make the URL decode able to reject only %00 bytes
+  
+  ... or all "control codes" or nothing.
+  
+  Assisted-by: Nicolas Sterchele
+
+- http2: set the correct URL in pushed transfers
+  
+  ...previously CURLINFO_EFFECTIVE_URL would report the URL of the
+  original "mother transfer", not the actually pushed resource.
+  
+  Reported-by: Jonathan Cardoso Machado
+  Fixes #5589
+  Closes #5591
+
+Jay Satiro (25 Jun 2020)
+- [Javier Blazquez brought this change]
+
+  openssl: Fix compilation on Windows when ngtcp2 is enabled
+  
+  - Include wincrypt before OpenSSL includes so that the latter can
+    properly handle any conflicts between the two.
+  
+  Closes https://github.com/curl/curl/pull/5606
+
+Daniel Stenberg (25 Jun 2020)
+- test543: extended to verify zero length input
+  
+  As was reported in #5601
+
+- escape: zero length input should return a zero length output
+  
+  Regression added in 7.71.0.
+  
+  Fixes #5601
+  Reported-by: Kristoffer Gleditsch
+  Closes #5602
+
+- Curl_inet_ntop: always check the return code
+  
+  Reported-by: Siva Sivaraman
+  Fixes #5412
+  Closes #5597
+
+- sendf: improve the message on client write errors
+  
+  Replace "Failed writing body (X != Y)" with
+  "Failure writing output to destination". Possibly slightly less cryptic.
+  
+  Reported-by: coinhubs on github
+  Fixes #5594
+  Closes #5596
+
+- RELEASE-NOTES: synced
+
+- curlver: start working on 7.71.1
+
+- [Denis Baručić brought this change]
+
+  DYNBUF.md: fix a typo: trail => tail
+  
+  Closes #5599
+
 Version 7.71.0 (23 Jun 2020)
 
 Daniel Stenberg (23 Jun 2020)
@@ -7261,245 +7460,3 @@ Daniel Stenberg (8 Nov 2019)
 - TODO: Run web-platform-tests url tests
   
   Closes #4477
-
-- TODO: 1.4 alt-svc sharing
-  
-  Closes #4476
-
-- test1560: require IPv6 for IPv6 aware URL parsing
-  
-  The URL parser function can't reject a bad IPv6 address properly when
-  curl was built without IPv6 support.
-  
-  Reported-by: Marcel Raad
-  Fixes #4556
-  Closes #4572
-
-- checksrc: repair the copyrightyear check
-  
-  - Consider a modified file to be committed this year.
-  
-  - Make the travis CHECKSRC also do COPYRIGHTYEAR scan in examples and
-    includes
-  
-  - Ignore 0 parents when getting latest commit date of file.
-  
-  since in the CI we're dealing with a truncated repo of last 50 commits,
-  the file's most recent commit may not be available. when this happens
-  git log and rev-list show the initial commit (ie first commit not to be
-  truncated) but that's incorrect so ignore it.
-  
-  Ref: https://github.com/curl/curl/pull/4547
-  
-  Closes https://github.com/curl/curl/pull/4549
-  
-  Co-authored-by: Jay Satiro
-
-- copyrights: fix copyright year range
-  
-  .. because checksrc's copyright year check stopped working.
-  
-  Ref: https://github.com/curl/curl/pull/4547
-  
-  Closes https://github.com/curl/curl/pull/4549
-
-- RELEASE-NOTES: synced
-
-- curlver: bump to 7.67.1
-
-- mailmap: fixup Massimiliano Fantuzzi
-
-- scripts/contributors: make committers get included too
-  
-  in addition to authors
-
-Jay Satiro (8 Nov 2019)
-- [Massimiliano Fantuzzi brought this change]
-
-  configure: fix typo in help text
-  
-  Closes https://github.com/curl/curl/pull/4570
-
-Daniel Stenberg (7 Nov 2019)
-- [Christian Schmitz brought this change]
-
-  ntlm: USE_WIN32_CRYPTO check removed to get USE_NTLM2SESSION set
-  
-  Closes #3704
-
-Jay Satiro (6 Nov 2019)
-- [Wyatt O'Day brought this change]
-
-  build: fix for CURL_DISABLE_DOH
-  
-  Fixes https://github.com/curl/curl/issues/4565
-  Closes https://github.com/curl/curl/pull/4566
-
-- [Leonardo Taccari brought this change]
-
-  configure: avoid unportable `==' test(1) operator
-  
-  Closes https://github.com/curl/curl/pull/4567
-
-Version 7.67.0 (5 Nov 2019)
-
-Daniel Stenberg (5 Nov 2019)
-- RELEASE-NOTES: synced
-  
-  The 7.67.0 release
-
-- THANKS: add new names from 7.67.0
-
-- configure: only say ipv6 enabled when the variable is set
-  
-  Previously it could say "IPv6: enabled" at the end of the configure run
-  but the define wasn't set because of a missing getaddrinfo().
-  
-  Reported-by: Marcel Raad
-  Fixes #4555
-  Closes #4560
-
-Marcel Raad (2 Nov 2019)
-- certs/Server-localhost-lastSAN-sv: regenerate with sha256
-  
-  All other certificates were regenerated in commit ba782baac30, but
-  this one was missed.
-  Fixes test3001 on modern systems.
-  
-  Closes https://github.com/curl/curl/pull/4551
-
-Daniel Stenberg (2 Nov 2019)
-- [Vilhelm Prytz brought this change]
-
-  copyrights: update all copyright notices to 2019 on files changed this year
-  
-  Closes #4547
-
-- [Bastien Bouclet brought this change]
-
-  mbedtls: add error message for cert validity starting in the future
-  
-  Closes #4552
-
-Jay Satiro (1 Nov 2019)
-- schannel_verify: Fix concurrent openings of CA file
-  
-  - Open the CA file using FILE_SHARE_READ mode so that others can read
-    from it as well.
-  
-  Prior to this change our schannel code opened the CA file without
-  sharing which meant concurrent openings (eg an attempt from another
-  thread or process) would fail during the time it was open without
-  sharing, which in curl's case would cause error:
-  "schannel: failed to open CA file".
-  
-  Bug: https://curl.haxx.se/mail/lib-2019-10/0104.html
-  Reported-by: Richard Alcock
-
-Daniel Stenberg (31 Oct 2019)
-- gtls: make gnutls_bye() not wait for response on shutdown
-  
-  ... as it can make it wait there for a long time for no good purpose.
-  
-  Patched-by: Jay Satiro
-  Reported-by: Bylon2 on github
-  Adviced-by: Nikos Mavrogiannopoulos
-  
-  Fixes #4487
-  Closes #4541
-
-- [Michał Janiszewski brought this change]
-
-  appveyor: publish artifacts on appveyor
-  
-  This allows obtaining upstream builds of curl directly from appveyor for
-  all the available configurations
-  
-  Closes #4509
-
-- url: make Curl_close() NULLify the pointer too
-  
-  This is the common pattern used in the code and by a unified approach we
-  avoid mistakes.
-  
-  Closes #4534
-
-- [Trivikram Kamat brought this change]
-
-  INSTALL: add missing space for configure commands
-  
-  Closes #4539
-
-- url: Curl_free_request_state() should also free doh handles
-  
-  ... or risk DoH memory leaks.
-  
-  Reported-by: Paul Dreik
-  Fixes #4463
-  Closes #4527
-
-- examples: remove the "this exact code has not been verified"
-  
-  ... as really confuses the reader to not know what to believe!
-
-- [Trivikram Kamat brought this change]
-
-  HTTP3: fix typo somehere1 > somewhere1
-  
-  Closes #4535
-
-Jay Satiro (28 Oct 2019)
-- [Javier Blazquez brought this change]
-
-  HTTP3: fix invalid use of sendto for connected UDP socket
-  
-  On macOS/BSD, trying to call sendto on a connected UDP socket fails
-  with a EISCONN error. Because the singleipconnect has already called
-  connect on the socket when we're trying to use it for QUIC transfers
-  we need to use plain send instead.
-  
-  Fixes #4529
-  Closes https://github.com/curl/curl/pull/4533
-
-Daniel Stenberg (28 Oct 2019)
-- RELEASE-NOTES: synced
-
-- [Javier Blazquez brought this change]
-
-  HTTP3: fix Windows build
-  
-  The ngtcp2 QUIC backend was using the MSG_DONTWAIT flag for send/recv
-  in order to perform nonblocking operations. On Windows this flag does
-  not exist. Instead, the socket must be set to nonblocking mode via
-  ioctlsocket.
-  
-  This change sets the nonblocking flag on UDP sockets used for QUIC on
-  all platforms so the use of MSG_DONTWAIT is not needed.
-  
-  Fixes #4531
-  Closes #4532
-
-Marcel Raad (27 Oct 2019)
-- appveyor: add --disable-proxy autotools build
-  
-  This would have caught issue #3926.
-  
-  Also make formatting more consistent.
-  
-  Closes https://github.com/curl/curl/pull/4526
-
-Daniel Stenberg (25 Oct 2019)
-- appveyor: make winbuilds with DEBUG=no/yes and VS 2015/2017
-  
-  ... and invoke "curl -V" once done
-  
-  Co-Authored-By: Jay Satiro
-  
-  Closes #4523
-
-- [Francois Rivard brought this change]
-
-  schannel: reverse the order of certinfo insertions
-  
-  Fixes #4518
-  Closes #4519
diff --git a/libs/libcurl/docs/THANKS b/libs/libcurl/docs/THANKS
index 11cd57fdda..76587bddfb 100644
--- a/libs/libcurl/docs/THANKS
+++ b/libs/libcurl/docs/THANKS
@@ -83,6 +83,7 @@ Alexander Sinditskiy
 Alexander Traud
 Alexander V. Tikhonov
 Alexander Zhuravlev
+Alexandre Pion
 Alexey Borzov
 Alexey Eremikhin
 Alexey Melnichuk
@@ -204,6 +205,7 @@ Balint Szilakszi
 Barry Abrahamson
 Barry Pollard
 Bart Whiteley
+Baruch Siach
 Bas Mevissen
 Bas van Schaik
 Bastien Bouclet
@@ -375,6 +377,7 @@ cmfrolick on github
 codesniffer13 on github
 Cody Jones
 Cody Mack
+coinhubs on github
 Colby Ranger
 Colin Blair
 Colin Hogben
@@ -501,6 +504,7 @@ David Yan
 davidedec on github
 dbrowndan on github
 Dengminwen
+Denis Baručić
 Denis Chaplygin
 Denis Feklushkin
 Denis Ollier
@@ -1014,6 +1018,7 @@ Johnny Luong
 Jojojov on github
 Jon DeVree
 Jon Grubbs
+Jon Johnson Jr
 Jon Nelson
 Jon Rumsey
 Jon Sargeant
@@ -1211,6 +1216,7 @@ Luca Boccassi
 Lucas Adamski
 Lucas Pardue
 Lucas Severo
+Lucien Zürcher
 Ludek Finstrle
 Ludovico Cavedon
 Ludwig Nussel
@@ -1661,6 +1667,7 @@ Przemysław Tomaszewski
 pszemus on github
 puckipedia on github
 Puneet Pawaia
+qiandu2006 on github
 Quagmire
 Quanah Gibson-Mount
 Quinn Slack
@@ -2026,6 +2033,7 @@ Timothe Litt
 Timothy Polich
 Tinus van den Berg
 TJ Saunders
+tmkk on github
 Tobias Blomberg
 Tobias Hieta
 Tobias Hintze
diff --git a/libs/libcurl/include/curl/curl.h b/libs/libcurl/include/curl/curl.h
index d5f8817d5f..e3531f5df8 100644
--- a/libs/libcurl/include/curl/curl.h
+++ b/libs/libcurl/include/curl/curl.h
@@ -774,7 +774,7 @@ enum curl_khtype {
 };
 
 struct curl_khkey {
-  const char *key; /* points to a zero-terminated string encoded with base64
+  const char *key; /* points to a null-terminated string encoded with base64
                       if len is zero, otherwise to the "raw" data */
   size_t len;
   enum curl_khtype keytype;
@@ -1446,7 +1446,7 @@ typedef enum {
   /* 132 OBSOLETE. Gone in 7.16.0 */
   /* 133 OBSOLETE. Gone in 7.16.0 */
 
-  /* zero terminated string for pass on to the FTP server when asked for
+  /* null-terminated string for pass on to the FTP server when asked for
      "account" info */
   CURLOPT(CURLOPT_FTP_ACCOUNT, CURLOPTTYPE_STRINGPOINT, 134),
 
@@ -2118,7 +2118,7 @@ typedef enum {
   CURL_TIMECOND_LAST
 } curl_TimeCond;
 
-/* Special size_t value signaling a zero-terminated string. */
+/* Special size_t value signaling a null-terminated string. */
 #define CURL_ZERO_TERMINATED ((size_t) -1)
 
 /* curl_strequal() and curl_strnequal() are subject for removal in a future
diff --git a/libs/libcurl/include/curl/curlver.h b/libs/libcurl/include/curl/curlver.h
index 62e0beeb80..48d1e46ac4 100644
--- a/libs/libcurl/include/curl/curlver.h
+++ b/libs/libcurl/include/curl/curlver.h
@@ -30,13 +30,13 @@
 
 /* This is the version number of the libcurl package from which this header
    file origins: */
-#define LIBCURL_VERSION "7.71.0"
+#define LIBCURL_VERSION "7.71.1"
 
 /* The numeric version number is also available "in parts" by using these
    defines: */
 #define LIBCURL_VERSION_MAJOR 7
 #define LIBCURL_VERSION_MINOR 71
-#define LIBCURL_VERSION_PATCH 0
+#define LIBCURL_VERSION_PATCH 1
 
 /* This is the numeric version of the libcurl version number, meant for easier
    parsing and comparisons by programs. The LIBCURL_VERSION_NUM define will
@@ -57,7 +57,7 @@
    CURL_VERSION_BITS() macro since curl's own configure script greps for it
    and needs it to contain the full number.
 */
-#define LIBCURL_VERSION_NUM 0x074700
+#define LIBCURL_VERSION_NUM 0x074701
 
 /*
  * This is the date and time when the full source package was created. The
@@ -68,7 +68,7 @@
  *
  * "2007-11-23"
  */
-#define LIBCURL_TIMESTAMP "2020-06-24"
+#define LIBCURL_TIMESTAMP "2020-07-01"
 
 #define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|(z))
 #define CURL_AT_LEAST_VERSION(x,y,z) \
diff --git a/libs/libcurl/include/curl/multi.h b/libs/libcurl/include/curl/multi.h
index 3039e787ea..2e6bb72d64 100644
--- a/libs/libcurl/include/curl/multi.h
+++ b/libs/libcurl/include/curl/multi.h
@@ -267,7 +267,7 @@ CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle,
  *          value into the equivalent human readable error string.  This is
  *          useful for printing meaningful error messages.
  *
- * Returns: A pointer to a zero-terminated error message.
+ * Returns: A pointer to a null-terminated error message.
  */
 CURL_EXTERN const char *curl_multi_strerror(CURLMcode);
 
diff --git a/libs/libcurl/src/config-win32.h b/libs/libcurl/src/config-win32.h
index 0463d14521..76ee6b1a77 100644
--- a/libs/libcurl/src/config-win32.h
+++ b/libs/libcurl/src/config-win32.h
@@ -246,10 +246,6 @@
 /* Define if you have the socket function. */
 #define HAVE_SOCKET 1
 
-/* Define if libSSH2 is in use */
-#define USE_LIBSSH2 1
-#define HAVE_LIBSSH2_H 1
-
 /* Define if you have the strcasecmp function. */
 /* #define HAVE_STRCASECMP 1 */
 
@@ -717,9 +713,6 @@ Vista
 #  define CURL_DISABLE_LDAP 1
 #endif
 
-/* if SSL is enabled */
-#define USE_OPENSSL 1
-
 /* Define to use the Windows crypto library. */
 #if !defined(CURL_WINDOWS_APP)
 #define USE_WIN32_CRYPTO
diff --git a/libs/libcurl/src/cookie.c b/libs/libcurl/src/cookie.c
index 68054e1c4c..cb7d94b102 100644
--- a/libs/libcurl/src/cookie.c
+++ b/libs/libcurl/src/cookie.c
@@ -755,7 +755,7 @@ Curl_cookie_add(struct Curl_easy *data,
         co->path = malloc(pathlen + 1); /* one extra for the zero byte */
         if(co->path) {
           memcpy(co->path, path, pathlen);
-          co->path[pathlen] = 0; /* zero terminate */
+          co->path[pathlen] = 0; /* null-terminate */
           co->spath = sanitize_cookie_path(co->path);
           if(!co->spath)
             badcookie = TRUE; /* out of memory bad */
diff --git a/libs/libcurl/src/curl_path.c b/libs/libcurl/src/curl_path.c
index f429634630..fbd98cb39b 100644
--- a/libs/libcurl/src/curl_path.c
+++ b/libs/libcurl/src/curl_path.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -42,7 +42,7 @@ CURLcode Curl_getworkingpath(struct connectdata *conn,
   size_t working_path_len;
   CURLcode result =
     Curl_urldecode(data, data->state.up.path, 0, &working_path,
-                   &working_path_len, FALSE);
+                   &working_path_len, REJECT_ZERO);
   if(result)
     return result;
 
diff --git a/libs/libcurl/src/dict.c b/libs/libcurl/src/dict.c
index c802deeff3..f529b48f71 100644
--- a/libs/libcurl/src/dict.c
+++ b/libs/libcurl/src/dict.c
@@ -99,7 +99,8 @@ static char *unescape_word(struct Curl_easy *data, const char *inputbuff)
   char *dictp;
   size_t len;
 
-  CURLcode result = Curl_urldecode(data, inputbuff, 0, &newp, &len, FALSE);
+  CURLcode result = Curl_urldecode(data, inputbuff, 0, &newp, &len,
+                                   REJECT_NADA);
   if(!newp || result)
     return NULL;
 
diff --git a/libs/libcurl/src/dotdot.c b/libs/libcurl/src/dotdot.c
index fe4f4971f1..ce9a052143 100644
--- a/libs/libcurl/src/dotdot.c
+++ b/libs/libcurl/src/dotdot.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -39,7 +39,7 @@
  * Curl_dedotdotify()
  * @unittest: 1395
  *
- * This function gets a zero-terminated path with dot and dotdot sequences
+ * This function gets a null-terminated path with dot and dotdot sequences
  * passed in and strips them off according to the rules in RFC 3986 section
  * 5.2.4.
  *
@@ -62,7 +62,7 @@ char *Curl_dedotdotify(const char *input)
   if(!out)
     return NULL; /* out of memory */
 
-  *out = 0; /* zero terminates, for inputs like "./" */
+  *out = 0; /* null-terminates, for inputs like "./" */
 
   /* get a cloned copy of the input */
   clone = strdup(input);
@@ -129,7 +129,7 @@ char *Curl_dedotdotify(const char *input)
         if(*outptr == '/')
           break;
       }
-      *outptr = 0; /* zero-terminate where it stops */
+      *outptr = 0; /* null-terminate where it stops */
     }
     else if(!strcmp("/..", clone)) {
       clone[2]='/';
@@ -141,7 +141,7 @@ char *Curl_dedotdotify(const char *input)
         if(*outptr == '/')
           break;
       }
-      *outptr = 0; /* zero-terminate where it stops */
+      *outptr = 0; /* null-terminate where it stops */
     }
 
     /*  D.  if the input buffer consists only of "." or "..", then remove
diff --git a/libs/libcurl/src/dynbuf.c b/libs/libcurl/src/dynbuf.c
index dfc1d05c64..38d370b078 100644
--- a/libs/libcurl/src/dynbuf.c
+++ b/libs/libcurl/src/dynbuf.c
@@ -161,7 +161,7 @@ CURLcode Curl_dyn_addn(struct dynbuf *s, const void *mem, size_t len)
 }
 
 /*
- * Append a zero terminated string at the end.
+ * Append a null-terminated string at the end.
  */
 CURLcode Curl_dyn_add(struct dynbuf *s, const char *str)
 {
diff --git a/libs/libcurl/src/dynbuf.h b/libs/libcurl/src/dynbuf.h
index 7809becfef..c80239e29c 100644
--- a/libs/libcurl/src/dynbuf.h
+++ b/libs/libcurl/src/dynbuf.h
@@ -23,7 +23,7 @@
  ***************************************************************************/
 
 struct dynbuf {
-  char *bufr;    /* point to a zero terminated allocated buffer */
+  char *bufr;    /* point to a null-terminated allocated buffer */
   size_t leng;   /* number of bytes *EXCLUDING* the zero terminator */
   size_t allc;   /* size of the current allocation */
   size_t toobig; /* size limit for the buffer */
diff --git a/libs/libcurl/src/escape.c b/libs/libcurl/src/escape.c
index f3c558ed0e..2bea145f46 100644
--- a/libs/libcurl/src/escape.c
+++ b/libs/libcurl/src/escape.c
@@ -89,6 +89,9 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string,
   Curl_dyn_init(&d, CURL_MAX_INPUT_LENGTH);
 
   length = (inlength?(size_t)inlength:strlen(string));
+  if(!length)
+    return strdup("");
+
   while(length--) {
     unsigned char in = *string; /* we need to treat the characters unsigned */
 
@@ -120,19 +123,26 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string,
 /*
  * Curl_urldecode() URL decodes the given string.
  *
- * Optionally detects control characters (byte codes lower than 32) in the
- * data and rejects such data.
- *
  * Returns a pointer to a malloced string in *ostring with length given in
  * *olen. If length == 0, the length is assumed to be strlen(string).
  *
  * 'data' can be set to NULL but then this function can't convert network
  * data to host for non-ascii.
+ *
+ * ctrl options:
+ * - REJECT_NADA: accept everything
+ * - REJECT_CTRL: rejects control characters (byte codes lower than 32) in
+ *                the data
+ * - REJECT_ZERO: rejects decoded zero bytes
+ *
+ * The values for the enum starts at 2, to make the assert detect legacy
+ * invokes that used TRUE/FALSE (0 and 1).
  */
+
 CURLcode Curl_urldecode(struct Curl_easy *data,
                         const char *string, size_t length,
                         char **ostring, size_t *olen,
-                        bool reject_ctrl)
+                        enum urlreject ctrl)
 {
   size_t alloc;
   char *ns;
@@ -141,6 +151,7 @@ CURLcode Curl_urldecode(struct Curl_easy *data,
   CURLcode result = CURLE_OK;
 
   DEBUGASSERT(string);
+  DEBUGASSERT(ctrl >= REJECT_NADA); /* crash on TRUE/FALSE */
 
   alloc = (length?length:strlen(string)) + 1;
   ns = malloc(alloc);
@@ -176,7 +187,8 @@ CURLcode Curl_urldecode(struct Curl_easy *data,
       alloc -= 2;
     }
 
-    if(reject_ctrl && (in < 0x20)) {
+    if(((ctrl == REJECT_CTRL) && (in < 0x20)) ||
+       ((ctrl == REJECT_ZERO) && (in == 0))) {
       free(ns);
       return CURLE_URL_MALFORMAT;
     }
@@ -210,7 +222,7 @@ char *curl_easy_unescape(struct Curl_easy *data, const char *string,
     size_t inputlen = length;
     size_t outputlen;
     CURLcode res = Curl_urldecode(data, string, inputlen, &str, &outputlen,
-                                  FALSE);
+                                  REJECT_NADA);
     if(res)
       return NULL;
 
diff --git a/libs/libcurl/src/escape.h b/libs/libcurl/src/escape.h
index d8bbe5cb0c..586db7e672 100644
--- a/libs/libcurl/src/escape.h
+++ b/libs/libcurl/src/escape.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -25,9 +25,16 @@
  * allocated string or NULL if an error occurred.  */
 
 bool Curl_isunreserved(unsigned char in);
+
+enum urlreject {
+  REJECT_NADA = 2,
+  REJECT_CTRL,
+  REJECT_ZERO
+};
+
 CURLcode Curl_urldecode(struct Curl_easy *data,
                         const char *string, size_t length,
                         char **ostring, size_t *olen,
-                        bool reject_crlf);
+                        enum urlreject ctrl);
 
 #endif /* HEADER_CURL_ESCAPE_H */
diff --git a/libs/libcurl/src/file.c b/libs/libcurl/src/file.c
index 576a794639..cd3e49c339 100644
--- a/libs/libcurl/src/file.c
+++ b/libs/libcurl/src/file.c
@@ -144,7 +144,7 @@ static CURLcode file_connect(struct connectdata *conn, bool *done)
   size_t real_path_len;
 
   CURLcode result = Curl_urldecode(data, data->state.up.path, 0, &real_path,
-                                   &real_path_len, FALSE);
+                                   &real_path_len, REJECT_ZERO);
   if(result)
     return result;
 
diff --git a/libs/libcurl/src/formdata.c b/libs/libcurl/src/formdata.c
index dfa44bc762..1cab2c5c25 100644
--- a/libs/libcurl/src/formdata.c
+++ b/libs/libcurl/src/formdata.c
@@ -602,7 +602,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
         /* Note that there's small risk that form->name is NULL here if the
            app passed in a bad combo, so we better check for that first. */
         if(form->name) {
-          /* copy name (without strdup; possibly not nul-terminated) */
+          /* copy name (without strdup; possibly not null-terminated) */
           form->name = Curl_memdup(form->name, form->namelength?
                                    form->namelength:
                                    strlen(form->name) + 1);
@@ -771,7 +771,7 @@ void curl_formfree(struct curl_httppost *form)
 }
 
 
-/* Set mime part name, taking care of non nul-terminated name string. */
+/* Set mime part name, taking care of non null-terminated name string. */
 static CURLcode setname(curl_mimepart *part, const char *name, size_t len)
 {
   char *zname;
diff --git a/libs/libcurl/src/ftp.c b/libs/libcurl/src/ftp.c
index 175d2eea78..20351ff865 100644
--- a/libs/libcurl/src/ftp.c
+++ b/libs/libcurl/src/ftp.c
@@ -1043,6 +1043,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
   } /* data->set.ftpport */
 
   if(!host) {
+    const char *r;
     /* not an interface and not a host name, get default by extracting
        the IP from the control connection */
     sslen = sizeof(ss);
@@ -1055,13 +1056,15 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
     switch(sa->sa_family) {
 #ifdef ENABLE_IPV6
     case AF_INET6:
-      Curl_inet_ntop(sa->sa_family, &sa6->sin6_addr, hbuf, sizeof(hbuf));
+      r = Curl_inet_ntop(sa->sa_family, &sa6->sin6_addr, hbuf, sizeof(hbuf));
       break;
 #endif
     default:
-      Curl_inet_ntop(sa->sa_family, &sa4->sin_addr, hbuf, sizeof(hbuf));
+      r = Curl_inet_ntop(sa->sa_family, &sa4->sin_addr, hbuf, sizeof(hbuf));
       break;
     }
+    if(!r)
+      return CURLE_FTP_PORT_FAILED;
     host = hbuf; /* use this host name */
     possibly_non_local = FALSE; /* we know it is local now */
   }
@@ -1449,7 +1452,7 @@ static CURLcode ftp_state_list(struct connectdata *conn)
     /* url-decode before evaluation: e.g. paths starting/ending with %2f */
     const char *slashPos = NULL;
     char *rawPath = NULL;
-    result = Curl_urldecode(data, ftp->path, 0, &rawPath, NULL, TRUE);
+    result = Curl_urldecode(data, ftp->path, 0, &rawPath, NULL, REJECT_CTRL);
     if(result)
       return result;
 
@@ -2824,7 +2827,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
             store++;
             ptr++;
           }
-          *store = '\0'; /* zero terminate */
+          *store = '\0'; /* null-terminate */
         }
         if(entry_extracted) {
           /* If the path name does not look like an absolute path (i.e.: it
@@ -2888,7 +2891,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
           ptr++;
         for(store = os; *ptr && *ptr != ' ';)
           *store++ = *ptr++;
-        *store = '\0'; /* zero terminate */
+        *store = '\0'; /* null-terminate */
 
         /* Check for special servers here. */
 
@@ -3191,7 +3194,8 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
 
   if(!result)
     /* get the url-decoded "raw" path */
-    result = Curl_urldecode(data, ftp->path, 0, &rawPath, &pathLen, TRUE);
+    result = Curl_urldecode(data, ftp->path, 0, &rawPath, &pathLen,
+                            REJECT_CTRL);
   if(result) {
     /* We can limp along anyway (and should try to since we may already be in
      * the error path) */
@@ -4107,7 +4111,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
   ftpc->cwdfail = FALSE;
 
   /* url-decode ftp path before further evaluation */
-  result = Curl_urldecode(data, ftp->path, 0, &rawPath, &pathLen, TRUE);
+  result = Curl_urldecode(data, ftp->path, 0, &rawPath, &pathLen, REJECT_CTRL);
   if(result)
     return result;
 
diff --git a/libs/libcurl/src/gopher.c b/libs/libcurl/src/gopher.c
index c48098f754..b4811b2894 100644
--- a/libs/libcurl/src/gopher.c
+++ b/libs/libcurl/src/gopher.c
@@ -116,7 +116,7 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
     newp += 2;
 
     /* ... and finally unescape */
-    result = Curl_urldecode(data, newp, 0, &sel, &len, FALSE);
+    result = Curl_urldecode(data, newp, 0, &sel, &len, REJECT_ZERO);
     free(gopherpath);
     if(result)
       return result;
diff --git a/libs/libcurl/src/http.c b/libs/libcurl/src/http.c
index 482f9ad0a5..28d66c287f 100644
--- a/libs/libcurl/src/http.c
+++ b/libs/libcurl/src/http.c
@@ -125,7 +125,8 @@ const struct Curl_handler Curl_handler_http = {
   ZERO_NULL,                            /* connection_check */
   PORT_HTTP,                            /* defport */
   CURLPROTO_HTTP,                       /* protocol */
-  PROTOPT_CREDSPERREQUEST               /* flags */
+  PROTOPT_CREDSPERREQUEST |             /* flags */
+  PROTOPT_USERPWDCTRL
 };
 
 #ifdef USE_SSL
@@ -150,7 +151,8 @@ const struct Curl_handler Curl_handler_https = {
   ZERO_NULL,                            /* connection_check */
   PORT_HTTPS,                           /* defport */
   CURLPROTO_HTTPS,                      /* protocol */
-  PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN_NPN /* flags */
+  PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN_NPN | /* flags */
+  PROTOPT_USERPWDCTRL
 };
 #endif
 
@@ -268,7 +270,7 @@ char *Curl_copy_header_value(const char *header)
     return NULL;
 
   memcpy(value, start, len);
-  value[len] = 0; /* zero terminate */
+  value[len] = 0; /* null-terminate */
 
   return value;
 }
@@ -306,7 +308,7 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
     pwd = conn->passwd;
   }
 
-  out = aprintf("%s:%s", user, pwd);
+  out = aprintf("%s:%s", user, pwd ? pwd : "");
   if(!out)
     return CURLE_OUT_OF_MEMORY;
 
diff --git a/libs/libcurl/src/http2.c b/libs/libcurl/src/http2.c
index 61990019e7..6cf651f0c0 100644
--- a/libs/libcurl/src/http2.c
+++ b/libs/libcurl/src/http2.c
@@ -469,6 +469,46 @@ static struct Curl_easy *duphandle(struct Curl_easy *data)
   return second;
 }
 
+static int set_transfer_url(struct Curl_easy *data,
+                            struct curl_pushheaders *hp)
+{
+  const char *v;
+  CURLU *u = curl_url();
+  CURLUcode uc;
+  char *url;
+
+  v = curl_pushheader_byname(hp, ":scheme");
+  if(v) {
+    uc = curl_url_set(u, CURLUPART_SCHEME, v, 0);
+    if(uc)
+      return 1;
+  }
+
+  v = curl_pushheader_byname(hp, ":authority");
+  if(v) {
+    uc = curl_url_set(u, CURLUPART_HOST, v, 0);
+    if(uc)
+      return 2;
+  }
+
+  v = curl_pushheader_byname(hp, ":path");
+  if(v) {
+    uc = curl_url_set(u, CURLUPART_PATH, v, 0);
+    if(uc)
+      return 3;
+  }
+
+  uc = curl_url_get(u, CURLUPART_URL, &url, 0);
+  if(uc)
+    return 4;
+  curl_url_cleanup(u);
+
+  if(data->change.url_alloc)
+    free(data->change.url);
+  data->change.url_alloc = TRUE;
+  data->change.url = url;
+  return 0;
+}
 
 static int push_promise(struct Curl_easy *data,
                         struct connectdata *conn,
@@ -505,6 +545,10 @@ static int push_promise(struct Curl_easy *data,
       goto fail;
     }
 
+    rv = set_transfer_url(newhandle, &heads);
+    if(rv)
+      goto fail;
+
     Curl_set_in_callback(data, true);
     rv = data->multi->push_cb(data, newhandle,
                               stream->push_headers_used, &heads,
diff --git a/libs/libcurl/src/if2ip.c b/libs/libcurl/src/if2ip.c
index b283f67f8b..39388692ef 100644
--- a/libs/libcurl/src/if2ip.c
+++ b/libs/libcurl/src/if2ip.c
@@ -118,7 +118,7 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
         if(iface->ifa_addr->sa_family == af) {
           if(strcasecompare(iface->ifa_name, interf)) {
             void *addr;
-            char *ip;
+            const char *ip;
             char scope[12] = "";
             char ipstr[64];
 #ifdef ENABLE_IPV6
@@ -153,15 +153,15 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
               }
 
               if(scopeid)
-                  msnprintf(scope, sizeof(scope), "%%%u", scopeid);
+                msnprintf(scope, sizeof(scope), "%%%u", scopeid);
 #endif
             }
             else
 #endif
               addr =
-                  &((struct sockaddr_in *)(void *)iface->ifa_addr)->sin_addr;
+                &((struct sockaddr_in *)(void *)iface->ifa_addr)->sin_addr;
             res = IF2IP_FOUND;
-            ip = (char *) Curl_inet_ntop(af, addr, ipstr, sizeof(ipstr));
+            ip = Curl_inet_ntop(af, addr, ipstr, sizeof(ipstr));
             msnprintf(buf, buf_size, "%s%s", ip, scope);
             break;
           }
@@ -190,6 +190,7 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
   struct sockaddr_in *s;
   curl_socket_t dummy;
   size_t len;
+  const char *r;
 
   (void)remote_scope;
   (void)local_scope_id;
@@ -219,9 +220,11 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
 
   s = (struct sockaddr_in *)(void *)&req.ifr_addr;
   memcpy(&in, &s->sin_addr, sizeof(in));
-  Curl_inet_ntop(s->sin_family, &in, buf, buf_size);
+  r = Curl_inet_ntop(s->sin_family, &in, buf, buf_size);
 
   sclose(dummy);
+  if(!r)
+    return IF2IP_NOT_FOUND;
   return IF2IP_FOUND;
 }
 
diff --git a/libs/libcurl/src/imap.c b/libs/libcurl/src/imap.c
index 14c76f08e7..cad0e5908d 100644
--- a/libs/libcurl/src/imap.c
+++ b/libs/libcurl/src/imap.c
@@ -1957,7 +1957,7 @@ static CURLcode imap_parse_url_path(struct connectdata *conn)
       end--;
 
     result = Curl_urldecode(data, begin, end - begin, &imap->mailbox, NULL,
-                            TRUE);
+                            REJECT_CTRL);
     if(result)
       return result;
   }
@@ -1979,7 +1979,8 @@ static CURLcode imap_parse_url_path(struct connectdata *conn)
       return CURLE_URL_MALFORMAT;
 
     /* Decode the name parameter */
-    result = Curl_urldecode(data, begin, ptr - begin, &name, NULL, TRUE);
+    result = Curl_urldecode(data, begin, ptr - begin, &name, NULL,
+                            REJECT_CTRL);
     if(result)
       return result;
 
@@ -1989,7 +1990,8 @@ static CURLcode imap_parse_url_path(struct connectdata *conn)
       ptr++;
 
     /* Decode the value parameter */
-    result = Curl_urldecode(data, begin, ptr - begin, &value, &valuelen, TRUE);
+    result = Curl_urldecode(data, begin, ptr - begin, &value, &valuelen,
+                            REJECT_CTRL);
     if(result) {
       free(name);
       return result;
@@ -2077,7 +2079,7 @@ static CURLcode imap_parse_custom_request(struct connectdata *conn)
 
   if(custom) {
     /* URL decode the custom request */
-    result = Curl_urldecode(data, custom, 0, &imap->custom, NULL, TRUE);
+    result = Curl_urldecode(data, custom, 0, &imap->custom, NULL, REJECT_CTRL);
 
     /* Extract the parameters if specified */
     if(!result) {
diff --git a/libs/libcurl/src/ldap.c b/libs/libcurl/src/ldap.c
index 27306580d9..512def659c 100644
--- a/libs/libcurl/src/ldap.c
+++ b/libs/libcurl/src/ldap.c
@@ -883,7 +883,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
     LDAP_TRACE(("DN '%s'\n", dn));
 
     /* Unescape the DN */
-    result = Curl_urldecode(conn->data, dn, 0, &unescaped, NULL, FALSE);
+    result = Curl_urldecode(conn->data, dn, 0, &unescaped, NULL, REJECT_ZERO);
     if(result) {
       rc = LDAP_NO_MEMORY;
 
@@ -949,7 +949,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
 
       /* Unescape the attribute */
       result = Curl_urldecode(conn->data, attributes[i], 0, &unescaped, NULL,
-                              FALSE);
+                              REJECT_ZERO);
       if(result) {
         free(attributes);
 
@@ -1018,7 +1018,8 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
     LDAP_TRACE(("filter '%s'\n", filter));
 
     /* Unescape the filter */
-    result = Curl_urldecode(conn->data, filter, 0, &unescaped, NULL, FALSE);
+    result = Curl_urldecode(conn->data, filter, 0, &unescaped, NULL,
+                            REJECT_ZERO);
     if(result) {
       rc = LDAP_NO_MEMORY;
 
diff --git a/libs/libcurl/src/libcurl.plist b/libs/libcurl/src/libcurl.plist
index 74dc728932..f206ea8f6f 100644
--- a/libs/libcurl/src/libcurl.plist
+++ b/libs/libcurl/src/libcurl.plist
@@ -15,7 +15,7 @@
 	<string>se.haxx.curl.libcurl</string>
 
 	<key>CFBundleVersion</key>
-	<string>7.71.0</string>
+	<string>7.71.1</string>
 
 	<key>CFBundleName</key>
 	<string>libcurl</string>
@@ -27,9 +27,9 @@
 	<string>????</string>
 
 	<key>CFBundleShortVersionString</key>
-	<string>libcurl 7.71.0</string>
+	<string>libcurl 7.71.1</string>
 
 	<key>CFBundleGetInfoString</key>
-	<string>libcurl.plist 7.71.0</string>
+	<string>libcurl.plist 7.71.1</string>
 </dict>
 </plist>
diff --git a/libs/libcurl/src/mime.c b/libs/libcurl/src/mime.c
index 4a87c4a3f3..6a9b64a2da 100644
--- a/libs/libcurl/src/mime.c
+++ b/libs/libcurl/src/mime.c
@@ -1419,7 +1419,7 @@ CURLcode curl_mime_data(curl_mimepart *part,
 
     if(datasize)
       memcpy(part->data, data, datasize);
-    part->data[datasize] = '\0';    /* Set a nul terminator as sentinel. */
+    part->data[datasize] = '\0';    /* Set a null terminator as sentinel. */
 
     part->readfunc = mime_mem_read;
     part->seekfunc = mime_mem_seek;
diff --git a/libs/libcurl/src/mqtt.c b/libs/libcurl/src/mqtt.c
index d09aab4eef..f6f4416140 100644
--- a/libs/libcurl/src/mqtt.c
+++ b/libs/libcurl/src/mqtt.c
@@ -211,7 +211,8 @@ static CURLcode mqtt_get_topic(struct connectdata *conn,
   char *path = conn->data->state.up.path;
 
   if(strlen(path) > 1) {
-    result = Curl_urldecode(conn->data, path + 1, 0, topic, topiclen, FALSE);
+    result = Curl_urldecode(conn->data, path + 1, 0, topic, topiclen,
+                            REJECT_NADA);
   }
   else {
     failf(conn->data, "Error: No topic specified.");
diff --git a/libs/libcurl/src/multi.c b/libs/libcurl/src/multi.c
index b106c94951..249e3607b7 100644
--- a/libs/libcurl/src/multi.c
+++ b/libs/libcurl/src/multi.c
@@ -374,11 +374,6 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
   multi->max_concurrent_streams = 100;
   multi->ipv6_works = Curl_ipv6works(NULL);
 
-#ifdef USE_WINSOCK
-  multi->wsa_event = WSACreateEvent();
-  if(multi->wsa_event == WSA_INVALID_EVENT)
-    goto error;
-#else
 #ifdef ENABLE_WAKEUP
   if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, multi->wakeup_pair) < 0) {
     multi->wakeup_pair[0] = CURL_SOCKET_BAD;
@@ -391,7 +386,6 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
     multi->wakeup_pair[0] = CURL_SOCKET_BAD;
     multi->wakeup_pair[1] = CURL_SOCKET_BAD;
   }
-#endif
 #endif
 
   return multi;
@@ -1073,15 +1067,11 @@ static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
   unsigned int i;
   unsigned int nfds = 0;
   unsigned int curlfds;
+  bool ufds_malloc = FALSE;
   long timeout_internal;
   int retcode = 0;
-#ifndef USE_WINSOCK
   struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK];
   struct pollfd *ufds = &a_few_on_stack[0];
-  bool ufds_malloc = FALSE;
-#else
-  DEBUGASSERT(multi->wsa_event != WSA_INVALID_EVENT);
-#endif
 
   if(!GOOD_MULTI_HANDLE(multi))
     return CURLM_BAD_HANDLE;
@@ -1127,16 +1117,11 @@ static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
   nfds += extra_nfds; /* add the externally provided ones */
 
 #ifdef ENABLE_WAKEUP
-#ifdef USE_WINSOCK
-  if(use_wakeup) {
-#else
   if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
-#endif
     ++nfds;
   }
 #endif
 
-#ifndef USE_WINSOCK
   if(nfds > NUM_POLLS_ON_STACK) {
     /* 'nfds' is a 32 bit value and 'struct pollfd' is typically 8 bytes
        big, so at 2^29 sockets this value might wrap. When a process gets
@@ -1147,9 +1132,7 @@ static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
       return CURLM_OUT_OF_MEMORY;
     ufds_malloc = TRUE;
   }
-
   nfds = 0;
-#endif
 
   /* only do the second loop if we found descriptors in the first stage run
      above */
@@ -1162,36 +1145,22 @@ static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
 
       for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
         curl_socket_t s = CURL_SOCKET_BAD;
-#ifdef USE_WINSOCK
-        long mask = 0;
-#endif
+
         if(bitmap & GETSOCK_READSOCK(i)) {
-#ifdef USE_WINSOCK
-          mask |= FD_READ;
-#else
           ufds[nfds].fd = sockbunch[i];
           ufds[nfds].events = POLLIN;
           ++nfds;
-#endif
           s = sockbunch[i];
         }
         if(bitmap & GETSOCK_WRITESOCK(i)) {
-#ifdef USE_WINSOCK
-          mask |= FD_WRITE;
-#else
           ufds[nfds].fd = sockbunch[i];
           ufds[nfds].events = POLLOUT;
           ++nfds;
-#endif
           s = sockbunch[i];
         }
         if(s == CURL_SOCKET_BAD) {
           break;
         }
-#ifdef USE_WINSOCK
-        if(WSAEventSelect(s, multi->wsa_event, mask) != 0)
-          return CURLM_INTERNAL_ERROR;
-#endif
       }
 
       data = data->next; /* check next handle */
@@ -1200,17 +1169,6 @@ static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
 
   /* Add external file descriptions from poll-like struct curl_waitfd */
   for(i = 0; i < extra_nfds; i++) {
-#ifdef USE_WINSOCK
-    long events = 0;
-    if(extra_fds[i].events & CURL_WAIT_POLLIN)
-      events |= FD_READ;
-    if(extra_fds[i].events & CURL_WAIT_POLLPRI)
-      events |= FD_OOB;
-    if(extra_fds[i].events & CURL_WAIT_POLLOUT)
-      events |= FD_WRITE;
-    if(WSAEventSelect(extra_fds[i].fd, multi->wsa_event, events) != 0)
-      return CURLM_INTERNAL_ERROR;
-#else
     ufds[nfds].fd = extra_fds[i].fd;
     ufds[nfds].events = 0;
     if(extra_fds[i].events & CURL_WAIT_POLLIN)
@@ -1220,61 +1178,28 @@ static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
     if(extra_fds[i].events & CURL_WAIT_POLLOUT)
       ufds[nfds].events |= POLLOUT;
     ++nfds;
-#endif
   }
 
 #ifdef ENABLE_WAKEUP
-#ifndef USE_WINSOCK
   if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
     ufds[nfds].fd = multi->wakeup_pair[0];
     ufds[nfds].events = POLLIN;
     ++nfds;
   }
-#endif
 #endif
 
   if(nfds) {
     int pollrc;
     /* wait... */
-#ifdef USE_WINSOCK
-    DWORD waitrc = WSAWaitForMultipleEvents(1, &multi->wsa_event, FALSE,
-                                            timeout_ms, FALSE);
-    /* WSA_WAIT_EVENT_0 is 0, so waitrc >= WSA_WAIT_EVENT_0 warns */
-    if(waitrc == WSA_WAIT_EVENT_0)
-      pollrc = 1;
-    else
-      pollrc = -1;
-#else
     pollrc = Curl_poll(ufds, nfds, timeout_ms);
-#endif
 
     if(pollrc > 0) {
-#ifdef USE_WINSOCK
-      retcode = 0;
-#else
       retcode = pollrc;
-#endif
       /* copy revents results from the poll to the curl_multi_wait poll
          struct, the bit values of the actual underlying poll() implementation
          may not be the same as the ones in the public libcurl API! */
       for(i = 0; i < extra_nfds; i++) {
         unsigned short mask = 0;
-#ifdef USE_WINSOCK
-        WSANETWORKEVENTS events = {0};
-        if(WSAEnumNetworkEvents(extra_fds[i].fd, multi->wsa_event,
-                                &events) == 0) {
-          if(events.lNetworkEvents & FD_READ)
-            mask |= CURL_WAIT_POLLIN;
-          if(events.lNetworkEvents & FD_WRITE)
-            mask |= CURL_WAIT_POLLOUT;
-          if(events.lNetworkEvents & FD_OOB)
-            mask |= CURL_WAIT_POLLPRI;
-
-          if(events.lNetworkEvents != 0)
-            retcode++;
-        }
-        WSAEventSelect(extra_fds[i].fd, multi->wsa_event, 0);
-#else
         unsigned r = ufds[curlfds + i].revents;
 
         if(r & POLLIN)
@@ -1283,39 +1208,10 @@ static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
           mask |= CURL_WAIT_POLLOUT;
         if(r & POLLPRI)
           mask |= CURL_WAIT_POLLPRI;
-#endif
 
         extra_fds[i].revents = mask;
       }
 
-#ifdef USE_WINSOCK
-      /* Count up all our own sockets that had activity,
-         and remove them from the event. */
-      if(curlfds) {
-        data = multi->easyp;
-        while(data) {
-          bitmap = multi_getsock(data, sockbunch);
-
-          for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
-            if(bitmap & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i))) {
-              WSANETWORKEVENTS events = {0};
-              if(WSAEnumNetworkEvents(sockbunch[i], multi->wsa_event,
-                                      &events) == 0) {
-                if(events.lNetworkEvents != 0)
-                  retcode++;
-              }
-              WSAEventSelect(sockbunch[i], multi->wsa_event, 0);
-            }
-            else
-              break;
-          }
-
-          data = data->next;
-        }
-      }
-
-      WSAResetEvent(multi->wsa_event);
-#else
 #ifdef ENABLE_WAKEUP
       if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
         if(ufds[curlfds + extra_nfds].revents & POLLIN) {
@@ -1328,8 +1224,10 @@ static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
                when there is no more data, breaking the loop. */
             nread = sread(multi->wakeup_pair[0], buf, sizeof(buf));
             if(nread <= 0) {
+#ifndef USE_WINSOCK
               if(nread < 0 && EINTR == SOCKERRNO)
                 continue;
+#endif
               break;
             }
           }
@@ -1337,15 +1235,12 @@ static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
           retcode--;
         }
       }
-#endif
 #endif
     }
   }
 
-#ifndef USE_WINSOCK
   if(ufds_malloc)
     free(ufds);
-#endif
   if(ret)
     *ret = retcode;
   if(!extrawait || nfds)
@@ -1400,10 +1295,6 @@ CURLMcode curl_multi_wakeup(struct Curl_multi *multi)
     return CURLM_BAD_HANDLE;
 
 #ifdef ENABLE_WAKEUP
-#ifdef USE_WINSOCK
-  if(WSASetEvent(multi->wsa_event))
-    return CURLM_OK;
-#else
   /* the wakeup_pair variable is only written during init and cleanup,
      making it safe to access from another thread after the init part
      and before cleanup */
@@ -1436,7 +1327,6 @@ CURLMcode curl_multi_wakeup(struct Curl_multi *multi)
       return CURLM_OK;
     }
   }
-#endif
 #endif
   return CURLM_WAKEUP_FAILURE;
 }
@@ -2596,13 +2486,9 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
     Curl_hash_destroy(&multi->hostcache);
     Curl_psl_destroy(&multi->psl);
 
-#ifdef USE_WINSOCK
-    WSACloseEvent(multi->wsa_event);
-#else
 #ifdef ENABLE_WAKEUP
     sclose(multi->wakeup_pair[0]);
     sclose(multi->wakeup_pair[1]);
-#endif
 #endif
     free(multi);
 
diff --git a/libs/libcurl/src/multihandle.h b/libs/libcurl/src/multihandle.h
index 94bbad77a0..91eca16c4a 100644
--- a/libs/libcurl/src/multihandle.h
+++ b/libs/libcurl/src/multihandle.h
@@ -138,13 +138,9 @@ struct Curl_multi {
                                     previous callback */
   unsigned int max_concurrent_streams;
 
-#ifdef USE_WINSOCK
-  WSAEVENT wsa_event; /* winsock event used for waits */
-#else
 #ifdef ENABLE_WAKEUP
   curl_socket_t wakeup_pair[2]; /* socketpair() used for wakeup
                                    0 is used for read, 1 is used for write */
-#endif
 #endif
   /* multiplexing wanted */
   bool multiplexing;
diff --git a/libs/libcurl/src/pingpong.c b/libs/libcurl/src/pingpong.c
index ced832ecf5..3143315219 100644
--- a/libs/libcurl/src/pingpong.c
+++ b/libs/libcurl/src/pingpong.c
@@ -384,10 +384,10 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
 
           if(pp->endofresp(conn, pp->linestart_resp, perline, code)) {
             /* This is the end of the last line, copy the last line to the
-               start of the buffer and zero terminate, for old times sake */
+               start of the buffer and null-terminate, for old times sake */
             size_t n = ptr - pp->linestart_resp;
             memmove(buf, pp->linestart_resp, n);
-            buf[n] = 0; /* zero terminate */
+            buf[n] = 0; /* null-terminate */
             keepon = FALSE;
             pp->linestart_resp = ptr + 1; /* advance pointer */
             i++; /* skip this before getting out */
diff --git a/libs/libcurl/src/pop3.c b/libs/libcurl/src/pop3.c
index 2f490b2f12..9ff5c78fd0 100644
--- a/libs/libcurl/src/pop3.c
+++ b/libs/libcurl/src/pop3.c
@@ -1390,7 +1390,7 @@ static CURLcode pop3_parse_url_path(struct connectdata *conn)
   const char *path = &data->state.up.path[1]; /* skip leading path */
 
   /* URL decode the path for the message ID */
-  return Curl_urldecode(data, path, 0, &pop3->id, NULL, TRUE);
+  return Curl_urldecode(data, path, 0, &pop3->id, NULL, REJECT_CTRL);
 }
 
 /***********************************************************************
@@ -1408,7 +1408,7 @@ static CURLcode pop3_parse_custom_request(struct connectdata *conn)
 
   /* URL decode the custom request */
   if(custom)
-    result = Curl_urldecode(data, custom, 0, &pop3->custom, NULL, TRUE);
+    result = Curl_urldecode(data, custom, 0, &pop3->custom, NULL, REJECT_CTRL);
 
   return result;
 }
diff --git a/libs/libcurl/src/sendf.c b/libs/libcurl/src/sendf.c
index 147ecbfa53..6943fa84e0 100644
--- a/libs/libcurl/src/sendf.c
+++ b/libs/libcurl/src/sendf.c
@@ -593,7 +593,7 @@ static CURLcode chop_write(struct connectdata *conn,
         return pausewrite(data, type, ptr, len);
       }
       if(wrote != chunklen) {
-        failf(data, "Failed writing body (%zu != %zu)", wrote, chunklen);
+        failf(data, "Failure writing output to destination");
         return CURLE_WRITE_ERROR;
       }
     }
diff --git a/libs/libcurl/src/smb.c b/libs/libcurl/src/smb.c
index 12f99257fc..d493adcc03 100644
--- a/libs/libcurl/src/smb.c
+++ b/libs/libcurl/src/smb.c
@@ -6,7 +6,7 @@
  *                             \___|\___/|_| \_\_____|
  *
  * Copyright (C) 2014, Bill Nagel <wnagel@tycoint.com>, Exacq Technologies
- * Copyright (C) 2016-2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2016-2020, 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
@@ -964,7 +964,7 @@ static CURLcode smb_parse_url_path(struct connectdata *conn)
 
   /* URL decode the path */
   CURLcode result = Curl_urldecode(data, data->state.up.path, 0, &path, NULL,
-                                   TRUE);
+                                   REJECT_CTRL);
   if(result)
     return result;
 
diff --git a/libs/libcurl/src/smtp.c b/libs/libcurl/src/smtp.c
index ec936480e8..685513b3b1 100644
--- a/libs/libcurl/src/smtp.c
+++ b/libs/libcurl/src/smtp.c
@@ -1689,7 +1689,8 @@ static CURLcode smtp_parse_url_path(struct connectdata *conn)
   }
 
   /* URL decode the path and use it as the domain in our EHLO */
-  return Curl_urldecode(conn->data, path, 0, &smtpc->domain, NULL, TRUE);
+  return Curl_urldecode(conn->data, path, 0, &smtpc->domain, NULL,
+                        REJECT_CTRL);
 }
 
 /***********************************************************************
@@ -1707,7 +1708,7 @@ static CURLcode smtp_parse_custom_request(struct connectdata *conn)
 
   /* URL decode the custom request */
   if(custom)
-    result = Curl_urldecode(data, custom, 0, &smtp->custom, NULL, TRUE);
+    result = Curl_urldecode(data, custom, 0, &smtp->custom, NULL, REJECT_CTRL);
 
   return result;
 }
diff --git a/libs/libcurl/src/strerror.c b/libs/libcurl/src/strerror.c
index 1a166bf019..015e588cf7 100644
--- a/libs/libcurl/src/strerror.c
+++ b/libs/libcurl/src/strerror.c
@@ -795,7 +795,7 @@ const char *Curl_strerror(int err, char *buf, size_t buflen)
 
 #endif /* end of not Windows */
 
-  buf[max] = '\0'; /* make sure the string is zero terminated */
+  buf[max] = '\0'; /* make sure the string is null-terminated */
 
   /* strip trailing '\r\n' or '\n'. */
   p = strrchr(buf, '\n');
diff --git a/libs/libcurl/src/strtok.c b/libs/libcurl/src/strtok.c
index be8f481282..ba6e0258a6 100644
--- a/libs/libcurl/src/strtok.c
+++ b/libs/libcurl/src/strtok.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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 @@ Curl_strtok_r(char *ptr, const char *sep, char **end)
 
     if(**end) {
       /* the end is not a null byte */
-      **end = '\0';  /* zero terminate it! */
+      **end = '\0';  /* null-terminate it! */
       ++*end;        /* advance the last pointer to beyond the null byte */
     }
 
diff --git a/libs/libcurl/src/tftp.c b/libs/libcurl/src/tftp.c
index 4f2f973a8e..378d956081 100644
--- a/libs/libcurl/src/tftp.c
+++ b/libs/libcurl/src/tftp.c
@@ -487,7 +487,7 @@ static CURLcode tftp_send_first(struct tftp_state_data *state,
        file name so we skip the always-present first letter of the path
        string. */
     result = Curl_urldecode(data, &state->conn->data->state.up.path[1], 0,
-                            &filename, NULL, FALSE);
+                            &filename, NULL, REJECT_ZERO);
     if(result)
       return result;
 
diff --git a/libs/libcurl/src/url.c b/libs/libcurl/src/url.c
index 8225e617a8..a1a6b69103 100644
--- a/libs/libcurl/src/url.c
+++ b/libs/libcurl/src/url.c
@@ -1894,23 +1894,32 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
   if(result)
     return result;
 
-  uc = curl_url_get(uh, CURLUPART_USER, &data->state.up.user,
-                    CURLU_URLDECODE);
+  /* we don't use the URL API's URL decoder option here since it rejects
+     control codes and we want to allow them for some schemes in the user and
+     password fields */
+  uc = curl_url_get(uh, CURLUPART_USER, &data->state.up.user, 0);
   if(!uc) {
-    conn->user = strdup(data->state.up.user);
-    if(!conn->user)
-      return CURLE_OUT_OF_MEMORY;
+    char *decoded;
+    result = Curl_urldecode(NULL, data->state.up.user, 0, &decoded, NULL,
+                            conn->handler->flags&PROTOPT_USERPWDCTRL ?
+                            REJECT_ZERO : REJECT_CTRL);
+    if(result)
+      return result;
+    conn->user = decoded;
     conn->bits.user_passwd = TRUE;
   }
   else if(uc != CURLUE_NO_USER)
     return Curl_uc_to_curlcode(uc);
 
-  uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password,
-                    CURLU_URLDECODE);
+  uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password, 0);
   if(!uc) {
-    conn->passwd = strdup(data->state.up.password);
-    if(!conn->passwd)
-      return CURLE_OUT_OF_MEMORY;
+    char *decoded;
+    result = Curl_urldecode(NULL, data->state.up.password, 0, &decoded, NULL,
+                            conn->handler->flags&PROTOPT_USERPWDCTRL ?
+                            REJECT_ZERO : REJECT_CTRL);
+    if(result)
+      return result;
+    conn->passwd = decoded;
     conn->bits.user_passwd = TRUE;
   }
   else if(uc != CURLUE_NO_PASSWORD)
@@ -2373,10 +2382,10 @@ static CURLcode parse_proxy_auth(struct Curl_easy *data,
 
   if(proxyuser)
     result = Curl_urldecode(data, proxyuser, 0, &conn->http_proxy.user, NULL,
-                            FALSE);
+                            REJECT_ZERO);
   if(!result && proxypasswd)
     result = Curl_urldecode(data, proxypasswd, 0, &conn->http_proxy.passwd,
-                            NULL, FALSE);
+                            NULL, REJECT_ZERO);
   return result;
 }
 
@@ -3600,6 +3609,7 @@ static CURLcode create_conn(struct Curl_easy *data,
     data->set.str[STRING_SSL_CIPHER13_LIST_ORIG];
   data->set.ssl.primary.pinned_key =
     data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+  data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_ORIG];
 
 #ifndef CURL_DISABLE_PROXY
   data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
@@ -3613,6 +3623,7 @@ static CURLcode create_conn(struct Curl_easy *data,
     data->set.str[STRING_SSL_CIPHER13_LIST_PROXY];
   data->set.proxy_ssl.primary.pinned_key =
     data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY];
+  data->set.proxy_ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY];
   data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY];
   data->set.proxy_ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_PROXY];
   data->set.proxy_ssl.cert = data->set.str[STRING_CERT_PROXY];
@@ -3646,7 +3657,7 @@ static CURLcode create_conn(struct Curl_easy *data,
   data->set.ssl.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT_ORIG];
 
   if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary,
-     &conn->ssl_config)) {
+                                    &conn->ssl_config)) {
     result = CURLE_OUT_OF_MEMORY;
     goto out;
   }
diff --git a/libs/libcurl/src/urlapi.c b/libs/libcurl/src/urlapi.c
index 37937fbca7..acbfb82875 100644
--- a/libs/libcurl/src/urlapi.c
+++ b/libs/libcurl/src/urlapi.c
@@ -225,7 +225,7 @@ static void strcpy_url(char *output, const char *url, bool relative)
       break;
     }
   }
-  *optr = 0; /* zero terminate output buffer */
+  *optr = 0; /* null-terminate output buffer */
 
 }
 
@@ -584,7 +584,7 @@ static CURLUcode junkscan(const char *part)
       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
       0x7f,
-      0x00 /* zero terminate */
+      0x00 /* null-terminate */
     };
     size_t n = strlen(part);
     size_t nfine = strcspn(part, badbytes);
@@ -1185,7 +1185,10 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what,
     if(urldecode) {
       char *decoded;
       size_t dlen;
-      CURLcode res = Curl_urldecode(NULL, *part, 0, &decoded, &dlen, TRUE);
+      /* this unconditional rejection of control bytes is documented
+         API behavior */
+      CURLcode res = Curl_urldecode(NULL, *part, 0, &decoded, &dlen,
+                                    REJECT_CTRL);
       free(*part);
       if(res) {
         *part = NULL;
@@ -1395,7 +1398,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
         i = (const unsigned char *)part;
         for(o = enc; *i; ++o, ++i)
           *o = (*i == ' ') ? '+' : *i;
-        *o = 0; /* zero terminate */
+        *o = 0; /* null-terminate */
         part = strdup(enc);
         if(!part) {
           free(enc);
@@ -1419,7 +1422,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
           o += 3;
         }
       }
-      *o = 0; /* zero terminate */
+      *o = 0; /* null-terminate */
       newp = enc;
       if(free_part)
         free((char *)part);
diff --git a/libs/libcurl/src/urldata.h b/libs/libcurl/src/urldata.h
index 74b43abaa8..f80a02defc 100644
--- a/libs/libcurl/src/urldata.h
+++ b/libs/libcurl/src/urldata.h
@@ -229,6 +229,7 @@ struct ssl_primary_config {
   char *cipher_list;     /* list of ciphers to use */
   char *cipher_list13;   /* list of TLS 1.3 cipher suites to use */
   char *pinned_key;
+  struct curl_blob *cert_blob;
   BIT(verifypeer);       /* set TRUE if this is desired */
   BIT(verifyhost);       /* set TRUE if CN/SAN must match hostname */
   BIT(verifystatus);     /* set TRUE if certificate status must be checked */
@@ -766,6 +767,8 @@ struct Curl_handler {
                                          HTTP proxy as HTTP proxies may know
                                          this protocol and act as a gateway */
 #define PROTOPT_WILDCARD (1<<12) /* protocol supports wildcard matching */
+#define PROTOPT_USERPWDCTRL (1<<13) /* Allow "control bytes" (< 32 ascii) in
+                                       user name and password */
 
 #define CONNCHECK_NONE 0                 /* No checks */
 #define CONNCHECK_ISDEAD (1<<0)          /* Check if the connection is dead. */
@@ -1562,7 +1565,7 @@ enum dupstring {
   STRING_DNS_LOCAL_IP4,
   STRING_DNS_LOCAL_IP6,
 
-  /* -- end of zero-terminated strings -- */
+  /* -- end of null-terminated strings -- */
 
   STRING_LASTZEROTERMINATED,
 
diff --git a/libs/libcurl/src/vquic/ngtcp2.c b/libs/libcurl/src/vquic/ngtcp2.c
index e5528231c8..d29cb378de 100644
--- a/libs/libcurl/src/vquic/ngtcp2.c
+++ b/libs/libcurl/src/vquic/ngtcp2.c
@@ -757,7 +757,9 @@ static ngtcp2_conn_callbacks ng_callbacks = {
   cb_extend_max_stream_data,
   NULL, /* dcid_status */
   NULL, /* handshake_confirmed */
-  NULL  /* recv_new_token */
+  NULL, /* recv_new_token */
+  ngtcp2_crypto_delete_crypto_aead_ctx_cb,
+  ngtcp2_crypto_delete_crypto_cipher_ctx_cb
 };
 
 /*
diff --git a/libs/libcurl/src/vtls/mbedtls.c b/libs/libcurl/src/vtls/mbedtls.c
index ba31b8e788..545f824c62 100644
--- a/libs/libcurl/src/vtls/mbedtls.c
+++ b/libs/libcurl/src/vtls/mbedtls.c
@@ -246,9 +246,14 @@ mbed_connect_step1(struct connectdata *conn,
   const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
   char * const ssl_cert = SSL_SET_OPTION(cert);
   const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile);
+#ifndef CURL_DISABLE_PROXY
   const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
     conn->host.name;
   const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
+#else
+  const char * const hostname = conn->host.name;
+  const long int port = conn->remote_port;
+#endif
   int ret = -1;
   char errorbuf[128];
   errorbuf[0] = 0;
@@ -538,9 +543,14 @@ mbed_connect_step2(struct connectdata *conn,
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   struct ssl_backend_data *backend = connssl->backend;
   const mbedtls_x509_crt *peercert;
+#ifndef CURL_DISABLE_PROXY
   const char * const pinnedpubkey = SSL_IS_PROXY() ?
     data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
     data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+#else
+  const char * const pinnedpubkey =
+    data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+#endif
 
   conn->recv[sockindex] = mbed_recv;
   conn->send[sockindex] = mbed_send;
diff --git a/libs/libcurl/src/vtls/openssl.c b/libs/libcurl/src/vtls/openssl.c
index 790d35862a..2e9f900da3 100644
--- a/libs/libcurl/src/vtls/openssl.c
+++ b/libs/libcurl/src/vtls/openssl.c
@@ -31,6 +31,11 @@
 
 #include <limits.h>
 
+/* Wincrypt must be included before anything that could include OpenSSL. */
+#if defined(USE_WIN32_CRYPTO)
+#include <wincrypt.h>
+#endif
+
 #include "urldata.h"
 #include "sendf.h"
 #include "formdata.h" /* for the boundary function */
@@ -48,10 +53,6 @@
 #include "strerror.h"
 #include "curl_printf.h"
 
-#if defined(USE_WIN32_CRYPTO)
-#include <wincrypt.h>
-#endif
-
 #include <openssl/ssl.h>
 #include <openssl/rand.h>
 #include <openssl/x509v3.h>
@@ -1635,7 +1636,7 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
              type itself: for example for an IA5String the data will be ASCII"
 
              It has been however verified that in 0.9.6 and 0.9.7, IA5String
-             is always zero-terminated.
+             is always null-terminated.
           */
           if((altlen == strlen(altptr)) &&
              /* if this isn't true, there was an embedded zero in the name
diff --git a/libs/libcurl/src/vtls/vtls.c b/libs/libcurl/src/vtls/vtls.c
index dfe2601393..c3a55fb1cb 100644
--- a/libs/libcurl/src/vtls/vtls.c
+++ b/libs/libcurl/src/vtls/vtls.c
@@ -63,6 +63,7 @@
 #include "warnless.h"
 #include "curl_base64.h"
 #include "curl_printf.h"
+#include "strdup.h"
 
 /* The last #include files should be: */
 #include "curl_memory.h"
@@ -82,6 +83,44 @@
   else                                       \
     dest->var = NULL;
 
+#define CLONE_BLOB(var)                         \
+  if(blobdup(&dest->var, source->var))         \
+    return FALSE;
+
+static CURLcode blobdup(struct curl_blob **dest,
+                        struct curl_blob *src)
+{
+  DEBUGASSERT(dest);
+  DEBUGASSERT(!*dest);
+  if(src) {
+    /* only if there's data to dupe! */
+    struct curl_blob *d;
+    d = malloc(sizeof(struct curl_blob) + src->len);
+    if(!d)
+      return CURLE_OUT_OF_MEMORY;
+    d->len = src->len;
+    /* Always duplicate because the connection may survive longer than the
+       handle that passed in the blob. */
+    d->flags = CURL_BLOB_COPY;
+    d->data = (void *)((char *)d + sizeof(struct curl_blob));
+    memcpy(d->data, src->data, src->len);
+    *dest = d;
+  }
+  return CURLE_OK;
+}
+
+/* returns TRUE if the blobs are identical */
+static bool blobcmp(struct curl_blob *first, struct curl_blob *second)
+{
+  if(!first && !second) /* both are NULL */
+    return TRUE;
+  if(!first || !second) /* one is NULL */
+    return FALSE;
+  if(first->len != second->len) /* different sizes */
+    return FALSE;
+  return !memcmp(first->data, second->data, first->len); /* same data */
+}
+
 bool
 Curl_ssl_config_matches(struct ssl_primary_config *data,
                         struct ssl_primary_config *needle)
@@ -91,6 +130,7 @@ Curl_ssl_config_matches(struct ssl_primary_config *data,
      (data->verifypeer == needle->verifypeer) &&
      (data->verifyhost == needle->verifyhost) &&
      (data->verifystatus == needle->verifystatus) &&
+     blobcmp(data->cert_blob, needle->cert_blob) &&
      Curl_safe_strcasecompare(data->CApath, needle->CApath) &&
      Curl_safe_strcasecompare(data->CAfile, needle->CAfile) &&
      Curl_safe_strcasecompare(data->clientcert, needle->clientcert) &&
@@ -115,6 +155,7 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
   dest->verifystatus = source->verifystatus;
   dest->sessionid = source->sessionid;
 
+  CLONE_BLOB(cert_blob);
   CLONE_STRING(CApath);
   CLONE_STRING(CAfile);
   CLONE_STRING(clientcert);
@@ -137,6 +178,7 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc)
   Curl_safefree(sslc->cipher_list);
   Curl_safefree(sslc->cipher_list13);
   Curl_safefree(sslc->pinned_key);
+  Curl_safefree(sslc->cert_blob);
 }
 
 #ifdef USE_SSL
@@ -706,7 +748,7 @@ CURLcode Curl_ssl_init_certinfo(struct Curl_easy *data, int num)
 }
 
 /*
- * 'value' is NOT a zero terminated string
+ * 'value' is NOT a null-terminated string
  */
 CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data,
                                     int certnum,
@@ -728,10 +770,10 @@ CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data,
   /* sprintf the label and colon */
   msnprintf(output, outlen, "%s:", label);
 
-  /* memcpy the value (it might not be zero terminated) */
+  /* memcpy the value (it might not be null-terminated) */
   memcpy(&output[labellen + 1], value, valuelen);
 
-  /* zero terminate the output */
+  /* null-terminate the output */
   output[labellen + 1 + valuelen] = 0;
 
   nl = Curl_slist_append_nodup(ci->certinfo[certnum], output);
-- 
cgit v1.2.3