Merge topic 'try_compile-project-platform-vars'

a6562ff579 try_compile: Add option to skip passing platform variables
4843a37676 try_compile: Propagate platform variables in project-mode too

Acked-by: Kitware Robot <kwrobot@kitware.com>
Tested-by: buildbot <buildbot@kitware.com>
Merge-request: !7265
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 09afcb3..7917803 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -530,6 +530,13 @@
         CMAKE_CI_BUILD_NAME: intel2021.5.0_makefiles
         CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2022.0.2-el8
 
+t:intel2021.6.0-makefiles:
+    extends:
+        - .cmake_test_linux_intelclassic_makefiles
+    variables:
+        CMAKE_CI_BUILD_NAME: intel2021.6.0_makefiles
+        CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2022.1.0-el8
+
 t:oneapi2021.1.1-makefiles:
     extends:
         - .cmake_test_linux_inteloneapi_makefiles
@@ -572,6 +579,13 @@
         CMAKE_CI_BUILD_NAME: oneapi2022.0.2_makefiles
         CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2022.0.2-el8
 
+t:oneapi2022.1.0-makefiles:
+    extends:
+        - .cmake_test_linux_inteloneapi_makefiles
+    variables:
+        CMAKE_CI_BUILD_NAME: oneapi2022.1.0_makefiles
+        CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2022.1.0-el8
+
 b:linux-x86_64-package:
     extends:
         - .linux_package
diff --git a/.gitlab/os-windows.yml b/.gitlab/os-windows.yml
index 3532765..4b4656a 100644
--- a/.gitlab/os-windows.yml
+++ b/.gitlab/os-windows.yml
@@ -35,7 +35,7 @@
     variables:
         VCVARSALL: "${VS170COMNTOOLS}\\..\\..\\VC\\Auxiliary\\Build\\vcvarsall.bat"
         VCVARSPLATFORM: "x64"
-        VCVARSVERSION: "14.31.31103"
+        VCVARSVERSION: "14.32.31326"
 
 .windows_vs2022_x64_ninja:
     extends:
@@ -54,7 +54,7 @@
         CMAKE_CONFIGURATION: windows_vs2022_x64
         CMAKE_GENERATOR: "Visual Studio 17 2022"
         CMAKE_GENERATOR_PLATFORM: "x64"
-        CMAKE_GENERATOR_TOOLSET: "v143,version=14.31.31103"
+        CMAKE_GENERATOR_TOOLSET: "v143,version=14.32.31326"
         CMAKE_CI_NIGHTLY_IGNORE_DEPS: "true"
 
 .windows_vs2019_x64:
@@ -173,7 +173,7 @@
         - windows
         - shell
         - vs2022
-        - msvc-19.31
+        - msvc-19.32
         - nonconcurrent
 
 .windows_tags_concurrent_vs2022:
@@ -182,7 +182,7 @@
         - windows
         - shell
         - vs2022
-        - msvc-19.31
+        - msvc-19.32
         - concurrent
 
 .windows_tags_concurrent_vs2019:
diff --git a/Copyright.txt b/Copyright.txt
index 4b6a7f5..2cf1769 100644
--- a/Copyright.txt
+++ b/Copyright.txt
@@ -78,6 +78,7 @@
 * Michael Hirsch, Ph.D. <www.scivision.co>
 * Michael Stürmer
 * Miguel A. Figueroa-Villanueva
+* Mike Durso <rbprogrammer@gmail.com>
 * Mike Jackson
 * Mike McQuaid <mike@mikemcquaid.com>
 * Nicolas Bock <nicolasbock@gmail.com>
diff --git a/Help/command/install.rst b/Help/command/install.rst
index 1a9dfd7..973aa31 100644
--- a/Help/command/install.rst
+++ b/Help/command/install.rst
@@ -85,7 +85,7 @@
 
 ``COMPONENT``
   Specify an installation component name with which the install rule
-  is associated, such as "runtime" or "development".  During
+  is associated, such as ``Runtime`` or ``Development``.  During
   component-specific installation only install rules associated with
   the given component name will be executed.  During a full installation
   all components are installed unless marked with ``EXCLUDE_FROM_ALL``.
diff --git a/Help/command/project.rst b/Help/command/project.rst
index 2a9dcfe..8f32fa3 100644
--- a/Help/command/project.rst
+++ b/Help/command/project.rst
@@ -123,28 +123,56 @@
 The variables set through the ``VERSION``, ``DESCRIPTION`` and ``HOMEPAGE_URL``
 options are intended for use as default values in package metadata and documentation.
 
+.. _`Code Injection`:
+
 Code Injection
 ^^^^^^^^^^^^^^
 
-If the :variable:`CMAKE_PROJECT_INCLUDE_BEFORE` or
-:variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE_BEFORE` variables are set,
-the files they point to will be included as the first step of the
-``project()`` command.
-If both are set, then :variable:`CMAKE_PROJECT_INCLUDE_BEFORE` will be
-included before :variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE_BEFORE`.
+A number of variables can be defined by the user to specify files to include
+at different points during the execution of the ``project()`` command.
+The following outlines the steps performed during a ``project()`` call:
 
-If the :variable:`CMAKE_PROJECT_INCLUDE` or
-:variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE` variables are set, the files
-they point to will be included as the last step of the ``project()`` command.
-If both are set, then :variable:`CMAKE_PROJECT_INCLUDE` will be included before
-:variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE`.
+* .. versionadded:: 3.15
+    For every ``project()`` call regardless of the project
+    name, include the file named by :variable:`CMAKE_PROJECT_INCLUDE_BEFORE`,
+    if set.
 
-.. versionadded:: 3.15
-  Added the ``CMAKE_PROJECT_INCLUDE`` and ``CMAKE_PROJECT_INCLUDE_BEFORE``
-  variables.
+* .. versionadded:: 3.17
+    If the ``project()`` command specifies ``<PROJECT-NAME>`` as its project
+    name, include the file named by
+    :variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE_BEFORE`, if set.
 
-.. versionadded:: 3.17
-  Added the ``CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE_BEFORE`` variable.
+* Set the various project-specific variables detailed in the `Synopsis`_
+  and `Options`_ sections above.
+
+* For the very first ``project()`` call only:
+
+  * If :variable:`CMAKE_TOOLCHAIN_FILE` is set, read it at least once.
+    It may be read multiple times and it may also be read again when
+    enabling languages later (see below).
+
+  * Set the variables describing the host and target platforms.
+    Language-specific variables might or might not be set at this point.
+    On the first run, the only language-specific variables that might be
+    defined are those a toolchain file may have set. On subsequent runs,
+    language-specific variables cached from a previous run may be set.
+
+  * .. versionadded:: 3.24
+      Include each file listed in :variable:`CMAKE_PROJECT_TOP_LEVEL_INCLUDES`,
+      if set. The variable is ignored by CMake thereafter.
+
+* Enable any languages specified in the call, or the default languages if
+  none were provided. The toolchain file may be re-read when enabling a
+  language for the first time.
+
+* .. versionadded:: 3.15
+    For every ``project()`` call regardless of the project
+    name, include the file named by :variable:`CMAKE_PROJECT_INCLUDE`,
+    if set.
+
+* If the ``project()`` command specifies ``<PROJECT-NAME>`` as its project
+  name, include the file named by
+  :variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE`, if set.
 
 Usage
 ^^^^^
diff --git a/Help/manual/cmake-presets.7.rst b/Help/manual/cmake-presets.7.rst
index c8d24f2..948d87a 100644
--- a/Help/manual/cmake-presets.7.rst
+++ b/Help/manual/cmake-presets.7.rst
@@ -1068,6 +1068,17 @@
 
   A literal dollar sign (``$``).
 
+``${pathListSep}``
+
+  Native character for separating lists of paths, such as ``:`` or ``;``.
+
+  For example, by setting ``PATH`` to
+  ``/path/to/ninja/bin${pathListSep}$env{PATH}``, ``${pathListSep}`` will
+  expand to the underlying operating system's character used for
+  concatenation in ``PATH``.
+
+  This is allowed in preset files specifying version ``5`` or above.
+
 ``$env{<variable-name>}``
 
   Environment variable with name ``<variable-name>``. The variable name may
diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst
index 41f2f30..ff431ad 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -243,6 +243,7 @@
    /variable/CMAKE_PROJECT_INCLUDE_BEFORE
    /variable/CMAKE_PROJECT_PROJECT-NAME_INCLUDE
    /variable/CMAKE_PROJECT_PROJECT-NAME_INCLUDE_BEFORE
+   /variable/CMAKE_PROJECT_TOP_LEVEL_INCLUDES
    /variable/CMAKE_REQUIRE_FIND_PACKAGE_PackageName
    /variable/CMAKE_SKIP_INSTALL_ALL_DEPENDENCY
    /variable/CMAKE_STAGING_PREFIX
diff --git a/Help/release/dev/CMAKE_PROJECT_TOP_LEVEL_INCLUDES.rst b/Help/release/dev/CMAKE_PROJECT_TOP_LEVEL_INCLUDES.rst
new file mode 100644
index 0000000..ca2d223
--- /dev/null
+++ b/Help/release/dev/CMAKE_PROJECT_TOP_LEVEL_INCLUDES.rst
@@ -0,0 +1,6 @@
+CMAKE_PROJECT_TOP_LEVEL_INCLUDES
+--------------------------------
+
+* The :variable:`CMAKE_PROJECT_TOP_LEVEL_INCLUDES` variable was added to allow
+  injecting custom code at the site of the first :command:`project` call,
+  after the host and target platform details have been determined.
diff --git a/Help/release/dev/presets-pathListSep.rst b/Help/release/dev/presets-pathListSep.rst
new file mode 100644
index 0000000..84b129f
--- /dev/null
+++ b/Help/release/dev/presets-pathListSep.rst
@@ -0,0 +1,5 @@
+presets-pathListSep
+-------------------
+
+* :manual:`cmake-presets(7)` files now support a ``${pathListSep}`` macro,
+  which expands to ``:`` or ``;`` based on the platform.
diff --git a/Help/variable/CMAKE_PROJECT_INCLUDE.rst b/Help/variable/CMAKE_PROJECT_INCLUDE.rst
index 41d9e5d..76b9d92 100644
--- a/Help/variable/CMAKE_PROJECT_INCLUDE.rst
+++ b/Help/variable/CMAKE_PROJECT_INCLUDE.rst
@@ -5,8 +5,11 @@
 
 A CMake language file or module to be included as the last step of all
 :command:`project` command calls.  This is intended for injecting custom code
-into project builds without modifying their source.
+into project builds without modifying their source.  See :ref:`Code Injection`
+for a more detailed discussion of files potentially included during a
+:command:`project` call.
 
 See also the :variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE`,
-:variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE_BEFORE` and
-:variable:`CMAKE_PROJECT_INCLUDE_BEFORE` variables.
+:variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE_BEFORE`,
+:variable:`CMAKE_PROJECT_INCLUDE_BEFORE`, and
+:variable:`CMAKE_PROJECT_TOP_LEVEL_INCLUDES` variables.
diff --git a/Help/variable/CMAKE_PROJECT_INCLUDE_BEFORE.rst b/Help/variable/CMAKE_PROJECT_INCLUDE_BEFORE.rst
index c2fd0f8..9a8c4b5 100644
--- a/Help/variable/CMAKE_PROJECT_INCLUDE_BEFORE.rst
+++ b/Help/variable/CMAKE_PROJECT_INCLUDE_BEFORE.rst
@@ -5,8 +5,11 @@
 
 A CMake language file or module to be included as the first step of all
 :command:`project` command calls.  This is intended for injecting custom code
-into project builds without modifying their source.
+into project builds without modifying their source.  See :ref:`Code Injection`
+for a more detailed discussion of files potentially included during a
+:command:`project` call.
 
 See also the :variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE`,
-:variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE_BEFORE` and
-:variable:`CMAKE_PROJECT_INCLUDE` variables.
+:variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE_BEFORE`,
+:variable:`CMAKE_PROJECT_INCLUDE`, and
+:variable:`CMAKE_PROJECT_TOP_LEVEL_INCLUDES` variables.
diff --git a/Help/variable/CMAKE_PROJECT_PROJECT-NAME_INCLUDE.rst b/Help/variable/CMAKE_PROJECT_PROJECT-NAME_INCLUDE.rst
index 74247f1..3bb5cd8 100644
--- a/Help/variable/CMAKE_PROJECT_PROJECT-NAME_INCLUDE.rst
+++ b/Help/variable/CMAKE_PROJECT_PROJECT-NAME_INCLUDE.rst
@@ -4,8 +4,9 @@
 A CMake language file or module to be included as the last step of any
 :command:`project` command calls that specify ``<PROJECT-NAME>`` as the project
 name.  This is intended for injecting custom code into project builds without
-modifying their source.
+modifying their source.  See :ref:`Code Injection` for a more detailed
+discussion of files potentially included during a :command:`project` call.
 
 See also the :variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE_BEFORE`,
-:variable:`CMAKE_PROJECT_INCLUDE` and
-:variable:`CMAKE_PROJECT_INCLUDE_BEFORE` variables.
+:variable:`CMAKE_PROJECT_INCLUDE`, :variable:`CMAKE_PROJECT_INCLUDE_BEFORE`,
+and :variable:`CMAKE_PROJECT_TOP_LEVEL_INCLUDES` variables.
diff --git a/Help/variable/CMAKE_PROJECT_PROJECT-NAME_INCLUDE_BEFORE.rst b/Help/variable/CMAKE_PROJECT_PROJECT-NAME_INCLUDE_BEFORE.rst
index 39abb12..ca584c1 100644
--- a/Help/variable/CMAKE_PROJECT_PROJECT-NAME_INCLUDE_BEFORE.rst
+++ b/Help/variable/CMAKE_PROJECT_PROJECT-NAME_INCLUDE_BEFORE.rst
@@ -6,8 +6,9 @@
 A CMake language file or module to be included as the first step of any
 :command:`project` command calls that specify ``<PROJECT-NAME>`` as the project
 name.  This is intended for injecting custom code into project builds without
-modifying their source.
+modifying their source.  See :ref:`Code Injection` for a more detailed
+discussion of files potentially included during a :command:`project` call.
 
 See also the :variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE`,
-:variable:`CMAKE_PROJECT_INCLUDE` and
-:variable:`CMAKE_PROJECT_INCLUDE_BEFORE` variables.
+:variable:`CMAKE_PROJECT_INCLUDE`, :variable:`CMAKE_PROJECT_INCLUDE_BEFORE`,
+and :variable:`CMAKE_PROJECT_TOP_LEVEL_INCLUDES` variables.
diff --git a/Help/variable/CMAKE_PROJECT_TOP_LEVEL_INCLUDES.rst b/Help/variable/CMAKE_PROJECT_TOP_LEVEL_INCLUDES.rst
new file mode 100644
index 0000000..2010b08
--- /dev/null
+++ b/Help/variable/CMAKE_PROJECT_TOP_LEVEL_INCLUDES.rst
@@ -0,0 +1,27 @@
+CMAKE_PROJECT_TOP_LEVEL_INCLUDES
+--------------------------------
+
+.. versionadded:: 3.24
+
+:ref:`Semicolon-separated list <CMake Language Lists>` of CMake language
+files to include as part of the very first :command:`project` call.
+The files will be included immediately after the toolchain file has been read
+(if one is specified) and platform variables have been set, but before any
+languages have been enabled. Therefore, language-specific variables,
+including things like :variable:`CMAKE_<LANG>_COMPILER`, might not be set.
+See :ref:`Code Injection` for a more detailed discussion of files potentially
+included during a :command:`project` call.
+
+This variable is intended for specifying files that perform one-time setup
+for the build. It provides an injection point for things like configuring
+package managers, adding logic the user shares between projects (e.g. defining
+their own custom build types), and so on. It is primarily for users to add
+things specific to their environment, but not for specifying the toolchain
+details (use :variable:`CMAKE_TOOLCHAIN_FILE` for that).
+
+By default, this variable is empty.  It is intended to be set by the user.
+
+See also the :variable:`CMAKE_PROJECT_INCLUDE`,
+:variable:`CMAKE_PROJECT_INCLUDE_BEFORE`,
+:variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE`, and
+:variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE_BEFORE` variables.
diff --git a/Help/variable/CMAKE_TOOLCHAIN_FILE.rst b/Help/variable/CMAKE_TOOLCHAIN_FILE.rst
index ff8d59a..1117c1f 100644
--- a/Help/variable/CMAKE_TOOLCHAIN_FILE.rst
+++ b/Help/variable/CMAKE_TOOLCHAIN_FILE.rst
@@ -13,3 +13,6 @@
 
 This is initialized by the :envvar:`CMAKE_TOOLCHAIN_FILE` environment
 variable if it is set when a new build tree is first created.
+
+See the :variable:`CMAKE_PROJECT_TOP_LEVEL_INCLUDES` variable for setting
+other things not directly related to the toolchain.
diff --git a/Modules/CMakeDetermineSystem.cmake b/Modules/CMakeDetermineSystem.cmake
index 8c7af06..2c2c2ac 100644
--- a/Modules/CMakeDetermineSystem.cmake
+++ b/Modules/CMakeDetermineSystem.cmake
@@ -128,7 +128,6 @@
     set(CMAKE_TOOLCHAIN_FILE "${_INCLUDED_TOOLCHAIN_FILE}" CACHE FILEPATH "The CMake toolchain file" FORCE)
   else()
     message(FATAL_ERROR "Could not find toolchain file: ${CMAKE_TOOLCHAIN_FILE}")
-    set(CMAKE_TOOLCHAIN_FILE "NOTFOUND" CACHE FILEPATH "The CMake toolchain file" FORCE)
   endif()
 endif()
 
diff --git a/Modules/CMakePackageConfigHelpers.cmake b/Modules/CMakePackageConfigHelpers.cmake
index 5813956..6f5702a 100644
--- a/Modules/CMakePackageConfigHelpers.cmake
+++ b/Modules/CMakePackageConfigHelpers.cmake
@@ -177,9 +177,9 @@
   packages with no binaries.
 
 .. versionadded:: 3.19
-  ``COMPATIBILITY_MODE`` ``AnyNewerVersion``, ``SameMajorVersion`` and
-  ``SameMinorVersion`` handle the version range if any is specified
-  (see :command:`find_package` command for the details).
+  The version file generated by ``AnyNewerVersion``, ``SameMajorVersion`` and
+  ``SameMinorVersion`` arguments of ``COMPATIBILITY`` handle the version range
+  if any is specified (see :command:`find_package` command for the details).
   ``ExactVersion`` mode is incompatible with version ranges and will display an
   author warning if one is specified.
 
diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake
index 5c37be2..707de88 100644
--- a/Modules/ExternalProject.cmake
+++ b/Modules/ExternalProject.cmake
@@ -2530,6 +2530,12 @@
     get_property(svn_username TARGET ${name} PROPERTY _EP_SVN_USERNAME)
     get_property(svn_password TARGET ${name} PROPERTY _EP_SVN_PASSWORD)
     get_property(svn_trust_cert TARGET ${name} PROPERTY _EP_SVN_TRUST_CERT)
+    get_property(uses_terminal TARGET ${name} PROPERTY _EP_USES_TERMINAL_DOWNLOAD)
+    if(uses_terminal)
+      set(svn_interactive_args "")
+    else()
+      set(svn_interactive_args "--non-interactive")
+    endif()
 
     get_filename_component(src_name "${source_dir}" NAME)
     get_filename_component(work_dir "${source_dir}" PATH)
@@ -2545,7 +2551,8 @@
       set(svn_trust_cert_args --trust-server-cert)
     endif()
     set(cmd ${Subversion_SVN_EXECUTABLE} co ${svn_repository} ${svn_revision}
-      --non-interactive ${svn_trust_cert_args} ${svn_user_pw_args} ${src_name})
+      ${svn_interactive_args} ${svn_trust_cert_args} ${svn_user_pw_args}
+      ${src_name})
 
   elseif(git_repository)
     set(method git)
@@ -2934,6 +2941,12 @@
     get_property(svn_username TARGET ${name} PROPERTY _EP_SVN_USERNAME)
     get_property(svn_password TARGET ${name} PROPERTY _EP_SVN_PASSWORD)
     get_property(svn_trust_cert TARGET ${name} PROPERTY _EP_SVN_TRUST_CERT)
+    get_property(uses_terminal TARGET ${name} PROPERTY _EP_USES_TERMINAL_UPDATE)
+    if(uses_terminal)
+      set(svn_interactive_args "")
+    else()
+      set(svn_interactive_args "--non-interactive")
+    endif()
     set(svn_user_pw_args "")
     if(DEFINED svn_username)
       set(svn_user_pw_args ${svn_user_pw_args} "--username=${svn_username}")
@@ -2945,7 +2958,7 @@
       set(svn_trust_cert_args --trust-server-cert)
     endif()
     set(cmd ${Subversion_SVN_EXECUTABLE} up ${svn_revision}
-      --non-interactive ${svn_trust_cert_args} ${svn_user_pw_args})
+      ${svn_interactive_args} ${svn_trust_cert_args} ${svn_user_pw_args})
     set(always 1)
   elseif(git_repository)
     # FetchContent gives us these directly, so don't try to recompute them
diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake
index 1b81778..b92c679 100644
--- a/Modules/FetchContent.cmake
+++ b/Modules/FetchContent.cmake
@@ -1351,6 +1351,14 @@
       list(APPEND subCMakeOpts "-DCMAKE_MAKE_PROGRAM:FILEPATH=${CMAKE_MAKE_PROGRAM}")
     endif()
 
+    # Override the sub-build's configuration types for multi-config generators.
+    # This ensures we are not affected by any custom setting from the project
+    # and can always request a known configuration further below.
+    get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+    if(is_multi_config)
+      list(APPEND subCMakeOpts "-DCMAKE_CONFIGURATION_TYPES:STRING=Release")
+    endif()
+
   else()
     # Likely we've been invoked via CMake's script mode where no
     # generator is set (and hence CMAKE_MAKE_PROGRAM could not be
@@ -1395,7 +1403,8 @@
   # If we've already previously done these steps, they will not cause
   # anything to be updated, so extra rebuilds of the project won't occur.
   # Make sure to pass through CMAKE_MAKE_PROGRAM in case the main project
-  # has this set to something not findable on the PATH.
+  # has this set to something not findable on the PATH. We also ensured above
+  # that the Release config will be defined for multi-config generators.
   configure_file("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/FetchContent/CMakeLists.cmake.in"
                  "${ARG_SUBBUILD_DIR}/CMakeLists.txt")
   execute_process(
@@ -1411,7 +1420,7 @@
     message(FATAL_ERROR "CMake step for ${contentName} failed: ${result}")
   endif()
   execute_process(
-    COMMAND ${CMAKE_COMMAND} --build .
+    COMMAND ${CMAKE_COMMAND} --build . --config Release
     RESULT_VARIABLE result
     ${outputOptions}
     WORKING_DIRECTORY "${ARG_SUBBUILD_DIR}"
diff --git a/Modules/FindGLUT.cmake b/Modules/FindGLUT.cmake
index 43041c5..72d4db5 100644
--- a/Modules/FindGLUT.cmake
+++ b/Modules/FindGLUT.cmake
@@ -96,7 +96,21 @@
 
 find_package(PkgConfig QUIET)
 if(PKG_CONFIG_FOUND)
+  # Tell pkg-config not to strip any -I flags to make sure GLUT_INCLUDE_DIRS
+  # will be defined.
+  if(DEFINED ENV{PKG_CONFIG_ALLOW_SYSTEM_CFLAGS})
+    set(_pkgconfig_allow_system_cflags_old "$ENV{PKG_CONFIG_ALLOW_SYSTEM_CFLAGS}")
+  else()
+    unset(_pkgconfig_allow_system_cflags_old)
+  endif()
+  set(ENV{PKG_CONFIG_ALLOW_SYSTEM_CFLAGS} 1)
   pkg_check_modules(GLUT QUIET glut)
+  if(DEFINED _pkgconfig_allow_system_cflags_old)
+    set(ENV{PKG_CONFIG_ALLOW_SYSTEM_CFLAGS} "${_pkgconfig_allow_system_cflags_old}")
+    unset(_pkgconfig_allow_system_cflags_old)
+  else()
+    unset(ENV{PKG_CONFIG_ALLOW_SYSTEM_CFLAGS})
+  endif()
   if(NOT GLUT_FOUND)
     pkg_check_modules(GLUT QUIET freeglut)
   endif()
diff --git a/Modules/FindOpenCL.cmake b/Modules/FindOpenCL.cmake
index 1b4662b..5c7aa22 100644
--- a/Modules/FindOpenCL.cmake
+++ b/Modules/FindOpenCL.cmake
@@ -45,7 +45,7 @@
   set(CMAKE_REQUIRED_QUIET ${OpenCL_FIND_QUIETLY})
 
   CMAKE_PUSH_CHECK_STATE()
-  foreach(VERSION "2_2" "2_1" "2_0" "1_2" "1_1" "1_0")
+  foreach(VERSION "3_0" "2_2" "2_1" "2_0" "1_2" "1_1" "1_0")
     set(CMAKE_REQUIRED_INCLUDES "${OpenCL_INCLUDE_DIR}")
 
     if(APPLE)
diff --git a/Modules/FindPkgConfig.cmake b/Modules/FindPkgConfig.cmake
index 547bc52..ab8af3e 100644
--- a/Modules/FindPkgConfig.cmake
+++ b/Modules/FindPkgConfig.cmake
@@ -429,7 +429,7 @@
   else()
     unset(_pkgconfig_allow_system_libs_old)
   endif()
-  set(ENV{PKG_CONFIG_ALLOW_SYSTEM_LIBS} 0)
+  set(ENV{PKG_CONFIG_ALLOW_SYSTEM_LIBS} 1)
 endmacro()
 
 macro(_pkg_restore_path_internal)
@@ -440,6 +440,8 @@
   if(DEFINED _pkgconfig_allow_system_libs_old)
     set(ENV{PKG_CONFIG_ALLOW_SYSTEM_LIBS} "${_pkgconfig_allow_system_libs_old}")
     unset(_pkgconfig_allow_system_libs_old)
+  else()
+    unset(ENV{PKG_CONFIG_ALLOW_SYSTEM_LIBS})
   endif()
 
   unset(_extra_paths)
diff --git a/Modules/FindPython/Support.cmake b/Modules/FindPython/Support.cmake
index 6edfbea..cbb6c1c 100644
--- a/Modules/FindPython/Support.cmake
+++ b/Modules/FindPython/Support.cmake
@@ -22,7 +22,7 @@
   message (FATAL_ERROR "FindPython: INTERNAL ERROR")
 endif()
 if (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR EQUAL "3")
-  set(_${_PYTHON_PREFIX}_VERSIONS 3.11 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0)
+  set(_${_PYTHON_PREFIX}_VERSIONS 3.12 3.11 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0)
 elseif (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR EQUAL "2")
   set(_${_PYTHON_PREFIX}_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0)
 else()
diff --git a/Modules/FindPythonInterp.cmake b/Modules/FindPythonInterp.cmake
index 4fc40c8..7ad3587 100644
--- a/Modules/FindPythonInterp.cmake
+++ b/Modules/FindPythonInterp.cmake
@@ -54,7 +54,7 @@
 
 set(_PYTHON1_VERSIONS 1.6 1.5)
 set(_PYTHON2_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0)
-set(_PYTHON3_VERSIONS 3.11 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0)
+set(_PYTHON3_VERSIONS 3.12 3.11 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0)
 
 if(PythonInterp_FIND_VERSION)
     if(PythonInterp_FIND_VERSION_COUNT GREATER 1)
diff --git a/Modules/FindPythonLibs.cmake b/Modules/FindPythonLibs.cmake
index c0caf34..43a84dd 100644
--- a/Modules/FindPythonLibs.cmake
+++ b/Modules/FindPythonLibs.cmake
@@ -79,7 +79,7 @@
 
 set(_PYTHON1_VERSIONS 1.6 1.5)
 set(_PYTHON2_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0)
-set(_PYTHON3_VERSIONS 3.11 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0)
+set(_PYTHON3_VERSIONS 3.12 3.11 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0)
 
 if(PythonLibs_FIND_VERSION)
     if(PythonLibs_FIND_VERSION_COUNT GREATER 1)
diff --git a/Modules/FindZLIB.cmake b/Modules/FindZLIB.cmake
index 4af842a..f50116f 100644
--- a/Modules/FindZLIB.cmake
+++ b/Modules/FindZLIB.cmake
@@ -77,8 +77,13 @@
 unset(_ZLIB_x86)
 list(APPEND _ZLIB_SEARCHES _ZLIB_SEARCH_NORMAL)
 
-set(ZLIB_NAMES z zlib zdll zlib1 zlibstatic zlibstat zlibvc)
-set(ZLIB_NAMES_DEBUG zd zlibd zdlld zlibd1 zlib1d zlibstaticd zlibstatd zlibvcd)
+if(ZLIB_USE_STATIC_LIBS)
+  set(ZLIB_NAMES zlibstatic zlibstat zlib z)
+  set(ZLIB_NAMES_DEBUG zlibstaticd zlibstatd zlibd zd)
+else()
+  set(ZLIB_NAMES z zlib zdll zlib1 zlibstatic zlibwapi zlibvc zlibstat)
+  set(ZLIB_NAMES_DEBUG zd zlibd zdlld zlibd1 zlib1d zlibstaticd zlibwapid zlibvcd zlibstatd)
+endif()
 
 # Try each search configuration.
 foreach(search ${_ZLIB_SEARCHES})
@@ -87,9 +92,15 @@
 
 # Allow ZLIB_LIBRARY to be set manually, as the location of the zlib library
 if(NOT ZLIB_LIBRARY)
+  set(_zlib_ORIG_CMAKE_FIND_LIBRARY_PREFIXES ${CMAKE_FIND_LIBRARY_PREFIXES})
+  set(_zlib_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
+  # Prefix/suffix of the win32/Makefile.gcc build
+  if(WIN32)
+    list(APPEND CMAKE_FIND_LIBRARY_PREFIXES "" "lib")
+    list(APPEND CMAKE_FIND_LIBRARY_SUFFIXES ".dll.a")
+  endif()
   # Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES
   if(ZLIB_USE_STATIC_LIBS)
-    set(_zlib_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
     if(WIN32)
       set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
     else()
@@ -103,9 +114,8 @@
   endforeach()
 
   # Restore the original find library ordering
-  if(ZLIB_USE_STATIC_LIBS)
-    set(CMAKE_FIND_LIBRARY_SUFFIXES ${_zlib_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES})
-  endif()
+  set(CMAKE_FIND_LIBRARY_SUFFIXES ${_zlib_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES})
+  set(CMAKE_FIND_LIBRARY_PREFIXES ${_zlib_ORIG_CMAKE_FIND_LIBRARY_PREFIXES})
 
   include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
   select_library_configurations(ZLIB)
diff --git a/Modules/FortranCInterface/CMakeLists.txt b/Modules/FortranCInterface/CMakeLists.txt
index ce0bc10..fb35ff0 100644
--- a/Modules/FortranCInterface/CMakeLists.txt
+++ b/Modules/FortranCInterface/CMakeLists.txt
@@ -112,6 +112,9 @@
   CMAKE_Fortran_COMPILER_VERSION VERSION_GREATER_EQUAL 12)
   target_compile_options(FortranCInterface PRIVATE "-fno-lto")
   target_compile_options(myfort PRIVATE "-flto=auto" "-ffat-lto-objects")
+endif()
+if(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND
+  CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 12)
   target_compile_options(symbols PRIVATE "-flto=auto" "-ffat-lto-objects")
 endif()
 
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index db444ba..66590af 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,7 +1,7 @@
 # CMake version number components.
 set(CMake_VERSION_MAJOR 3)
 set(CMake_VERSION_MINOR 23)
-set(CMake_VERSION_PATCH 20220511)
+set(CMake_VERSION_PATCH 20220517)
 #set(CMake_VERSION_RC 0)
 set(CMake_VERSION_IS_DIRTY 0)
 
diff --git a/Source/CursesDialog/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx
index 11b3b35..3e254e0 100644
--- a/Source/CursesDialog/cmCursesMainForm.cxx
+++ b/Source/CursesDialog/cmCursesMainForm.cxx
@@ -35,11 +35,6 @@
   : Args(std::move(args))
   , InitialWidth(initWidth)
 {
-  this->HasNonStatusOutputs = false;
-  this->NumberOfPages = 0;
-  this->AdvancedMode = false;
-  this->NumberOfVisibleEntries = 0;
-  this->OkToGenerate = false;
   this->HelpMessage.emplace_back(
     "Welcome to ccmake, curses based user interface for CMake.");
   this->HelpMessage.emplace_back();
@@ -54,7 +49,6 @@
     cmStrCat(cmSystemTools::GetProgramPath(this->Args[0]), "/cmake");
   this->Args[0] = whereCMake;
   this->CMakeInstance->SetArgs(this->Args);
-  this->SearchMode = false;
 }
 
 cmCursesMainForm::~cmCursesMainForm()
@@ -99,13 +93,13 @@
 
   int entrywidth = this->InitialWidth - 35;
 
-  if (count == 0) {
-    // If cache is empty, display a label saying so and a
-    // dummy entry widget (does not respond to input)
-    cmCursesCacheEntryComposite comp("EMPTY CACHE", 30, 30);
-    comp.Entry = cm::make_unique<cmCursesDummyWidget>(1, 1, 1, 1);
-    newEntries.emplace_back(std::move(comp));
-  } else {
+  // Add a label to display when cache is empty
+  // dummy entry widget (does not respond to input)
+  cmCursesCacheEntryComposite comp("EMPTY CACHE", 30, 30);
+  comp.Entry = cm::make_unique<cmCursesDummyWidget>(1, 1, 1, 1);
+  newEntries.emplace_back(std::move(comp));
+
+  if (count > 0) {
     // Create the composites.
 
     // First add entries which are new
@@ -196,7 +190,8 @@
     this->Fields.push_back(entry.Entry->Field);
   }
   // if no cache entries there should still be one dummy field
-  if (this->Fields.empty()) {
+  this->IsEmpty = this->Fields.empty();
+  if (this->IsEmpty) {
     const auto& front = this->Entries.front();
     this->Fields.push_back(front.Label->Field);
     this->Fields.push_back(front.IsNewLabel->Field);
@@ -875,7 +870,7 @@
         }
       }
       // delete cache entry
-      else if (key == 'd' && this->NumberOfVisibleEntries) {
+      else if (key == 'd' && this->NumberOfVisibleEntries && !this->IsEmpty) {
         this->OkToGenerate = false;
         FIELD* cur = current_field(this->Form);
         size_t findex = field_index(cur);
diff --git a/Source/CursesDialog/cmCursesMainForm.h b/Source/CursesDialog/cmCursesMainForm.h
index c6db66f..fb44a45 100644
--- a/Source/CursesDialog/cmCursesMainForm.h
+++ b/Source/CursesDialog/cmCursesMainForm.h
@@ -138,7 +138,7 @@
   // Output produced by the last pass
   std::vector<std::string> Outputs;
   // Did the last pass produced outputs of interest (errors, warnings, ...)
-  bool HasNonStatusOutputs;
+  bool HasNonStatusOutputs = false;
   // Last progress bar
   std::string LastProgress;
 
@@ -155,17 +155,18 @@
   // Fields displayed. Includes labels, new entry markers, entries
   std::vector<FIELD*> Fields;
   // Number of entries shown (depends on mode -normal or advanced-)
-  size_t NumberOfVisibleEntries;
-  bool AdvancedMode;
+  size_t NumberOfVisibleEntries = 0;
+  bool AdvancedMode = false;
   // Did the iteration converge (no new entries) ?
-  bool OkToGenerate;
+  bool OkToGenerate = false;
   // Number of pages displayed
-  int NumberOfPages;
+  int NumberOfPages = 0;
+  bool IsEmpty = false;
 
   int InitialWidth;
   std::unique_ptr<cmake> CMakeInstance;
 
   std::string SearchString;
   std::string OldSearchString;
-  bool SearchMode;
+  bool SearchMode = false;
 };
diff --git a/Source/cmCMakePresetsGraph.cxx b/Source/cmCMakePresetsGraph.cxx
index 478c175..b737c1f 100644
--- a/Source/cmCMakePresetsGraph.cxx
+++ b/Source/cmCMakePresetsGraph.cxx
@@ -361,6 +361,13 @@
           cmSystemTools::GetParentDirectory(preset.OriginFile->Filename);
         return ExpandMacroResult::Ok;
       }
+      if (macroName == "pathListSep") {
+        if (version < 5) {
+          return ExpandMacroResult::Error;
+        }
+        macroOut += cmSystemTools::GetSystemPathlistSeparator();
+        return ExpandMacroResult::Ok;
+      }
     }
 
     return ExpandMacroResult::Ignore;
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 09e2abe..3831546 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -688,6 +688,33 @@
     if (!this->FindMakeProgram(mf)) {
       return;
     }
+
+    // One-time includes of user-provided project setup files
+    std::string includes =
+      mf->GetSafeDefinition("CMAKE_PROJECT_TOP_LEVEL_INCLUDES");
+    std::vector<std::string> includesList = cmExpandedList(includes);
+    for (std::string const& setupFile : includesList) {
+      std::string absSetupFile = cmSystemTools::CollapseFullPath(
+        setupFile, mf->GetCurrentSourceDirectory());
+      if (!cmSystemTools::FileExists(absSetupFile)) {
+        cmSystemTools::Error(
+          "CMAKE_PROJECT_TOP_LEVEL_INCLUDES file does not exist: " +
+          setupFile);
+        return;
+      }
+      if (cmSystemTools::FileIsDirectory(absSetupFile)) {
+        cmSystemTools::Error(
+          "CMAKE_PROJECT_TOP_LEVEL_INCLUDES file is a directory: " +
+          setupFile);
+        return;
+      }
+      if (!mf->ReadListFile(absSetupFile)) {
+        cmSystemTools::Error(
+          "Failed reading CMAKE_PROJECT_TOP_LEVEL_INCLUDES file: " +
+          setupFile);
+        return;
+      }
+    }
   }
 
   // Check that the languages are supported by the generator and its
diff --git a/Source/cmInstallGenerator.cxx b/Source/cmInstallGenerator.cxx
index 87110a9..93abd45 100644
--- a/Source/cmInstallGenerator.cxx
+++ b/Source/cmInstallGenerator.cxx
@@ -165,14 +165,22 @@
 }
 
 std::string cmInstallGenerator::CreateComponentTest(
-  const std::string& component, bool exclude_from_all)
+  const std::string& component, bool exclude_from_all, bool all_components)
 {
+  if (all_components) {
+    if (exclude_from_all) {
+      return "CMAKE_INSTALL_COMPONENT";
+    }
+    return {};
+  }
+
   std::string result = "CMAKE_INSTALL_COMPONENT STREQUAL \"";
   result += component;
   result += "\"";
   if (!exclude_from_all) {
     result += " OR NOT CMAKE_INSTALL_COMPONENT";
   }
+
   return result;
 }
 
@@ -181,10 +189,11 @@
   // Track indentation.
   Indent indent;
 
+  std::string component_test = this->CreateComponentTest(
+    this->Component, this->ExcludeFromAll, this->AllComponents);
+
   // Begin this block of installation.
-  if (!this->AllComponents) {
-    std::string component_test =
-      this->CreateComponentTest(this->Component, this->ExcludeFromAll);
+  if (!component_test.empty()) {
     os << indent << "if(" << component_test << ")\n";
   }
 
@@ -193,7 +202,7 @@
                               this->AllComponents ? indent : indent.Next());
 
   // End this block of installation.
-  if (!this->AllComponents) {
+  if (!component_test.empty()) {
     os << indent << "endif()\n\n";
   }
 }
diff --git a/Source/cmInstallGenerator.h b/Source/cmInstallGenerator.h
index d342c99..9fcd284 100644
--- a/Source/cmInstallGenerator.h
+++ b/Source/cmInstallGenerator.h
@@ -78,7 +78,8 @@
   void GenerateScript(std::ostream& os) override;
 
   std::string CreateComponentTest(const std::string& component,
-                                  bool exclude_from_all);
+                                  bool exclude_from_all,
+                                  bool all_components = false);
 
   using TweakMethod =
     std::function<void(std::ostream& os, Indent indent,
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index cb32172..527175d 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -3429,3 +3429,12 @@
   return "";
 #endif
 }
+
+char cmSystemTools::GetSystemPathlistSeparator()
+{
+#if defined(_WIN32)
+  return ';';
+#else
+  return ':';
+#endif
+}
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index c17ecbd..4865a4b 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -535,6 +535,9 @@
   /** Get the system name. */
   static cm::string_view GetSystemName();
 
+  /** Get the system path separator character */
+  static char GetSystemPathlistSeparator();
+
 private:
   static bool s_ForceUnixPaths;
   static bool s_RunCommandHideConsole;
diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx
index d5d08b8..00c65ed 100644
--- a/Source/cmVisualStudioGeneratorOptions.cxx
+++ b/Source/cmVisualStudioGeneratorOptions.cxx
@@ -171,14 +171,15 @@
     code.clear();
   }
 
-  if (arch.empty() && gencode.empty()) {
-    return;
-  }
-
   // Create a CodeGeneration field with [arch],[code] syntax in each entry.
   // CUDA will convert it to `-gencode=arch=[arch],code="[code],[arch]"`.
   FlagValue& result = this->FlagMap["CodeGeneration"];
 
+  // If there are no flags, leave the CodeGeneration field empty.
+  if (arch.empty() && gencode.empty()) {
+    return;
+  }
+
   // First entries for the -arch=<arch> [-code=<code>,...] pair.
   if (!arch.empty()) {
     std::string arch_name = arch[0];
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 9cee144..7fdfaea 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -431,8 +431,10 @@
 
   if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^9]|[9][0-9])")
     ADD_TEST_MACRO(CSharpOnly CSharpOnly)
-    ADD_TEST_MACRO(CSharpLinkToCxx CSharpLinkToCxx)
-    ADD_TEST_MACRO(CSharpLinkFromCxx CSharpLinkFromCxx)
+    if(NOT CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64")
+      ADD_TEST_MACRO(CSharpLinkToCxx CSharpLinkToCxx)
+      ADD_TEST_MACRO(CSharpLinkFromCxx CSharpLinkFromCxx)
+    endif()
     ADD_TEST_MACRO(CSharpWin32GenEx CSharpWin32GenEx)
     set_tests_properties(CSharpWin32GenEx PROPERTIES
       PASS_REGULAR_EXPRESSION "Target \"CSharpWin32GenEx\" has a generator expression in its\n  WIN32_EXECUTABLE property\\.  This is not supported on managed executables\\."
@@ -2113,6 +2115,7 @@
   if(MSVC AND NOT MSVC_VERSION LESS 1310
      AND (NOT CMAKE_GENERATOR MATCHES "Visual Studio 9 "
           OR CMAKE_SIZEOF_VOID_P EQUAL 4)
+     AND (NOT CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64")
       )
     ADD_TEST_MACRO(VSMASM VSMASM)
   endif()
@@ -2123,7 +2126,8 @@
     endif()
 
     if(NOT "${CMAKE_GENERATOR}" MATCHES "Visual Studio 9 "
-        AND NOT CMAKE_GENERATOR_TOOLSET STREQUAL "v90")
+        AND NOT CMAKE_GENERATOR_TOOLSET STREQUAL "v90"
+        AND NOT CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64")
       ADD_TEST_MACRO(VSWindowsFormsResx VSWindowsFormsResx)
       ADD_TEST_MACRO(VSManagedCustomCommand)
     endif()
diff --git a/Tests/ExportImport/Import/A/imp_testExe1.c b/Tests/ExportImport/Import/A/imp_testExe1.c
index 7490a80..d3b0e9e 100644
--- a/Tests/ExportImport/Import/A/imp_testExe1.c
+++ b/Tests/ExportImport/Import/A/imp_testExe1.c
@@ -19,7 +19,7 @@
 #else
 #  define testLib4libcfg testLib4libopt
 #endif
-extern testLib4libcfg(void);
+extern int testLib4libcfg(void);
 
 int main()
 {
diff --git a/Tests/RunCMake/AutoExportDll/AutoExport.cmake b/Tests/RunCMake/AutoExportDll/AutoExport.cmake
index 85eff7e..dbcf4b8 100644
--- a/Tests/RunCMake/AutoExportDll/AutoExport.cmake
+++ b/Tests/RunCMake/AutoExportDll/AutoExport.cmake
@@ -6,7 +6,8 @@
 set_property(TARGET objlib PROPERTY POSITION_INDEPENDENT_CODE 1)
 add_library(autoexport SHARED hello.cxx world.cxx foo.c $<TARGET_OBJECTS:objlib>)
 add_library(autoexport3 SHARED cppCLI.cxx)
-if(MSVC AND NOT MSVC_VERSION VERSION_LESS 1600)
+if(MSVC AND NOT MSVC_VERSION VERSION_LESS 1600
+  AND NOT CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64")
   set_property(TARGET autoexport3 PROPERTY COMMON_LANGUAGE_RUNTIME "")
 endif()
 
@@ -15,7 +16,8 @@
   set_target_properties(say PROPERTIES ENABLE_EXPORTS ON)
   add_library(autoexport_for_exec SHARED hello2.c)
   target_link_libraries(autoexport_for_exec say)
-  if(NOT MSVC_VERSION VERSION_LESS 1600)
+  if(NOT MSVC_VERSION VERSION_LESS 1600 AND
+    NOT CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64")
     enable_language(ASM_MASM)
     target_sources(autoexport PRIVATE nop.asm)
     set_property(SOURCE nop.asm PROPERTY COMPILE_FLAGS /safeseh)
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 07b256c..4fe6ac1 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -960,7 +960,9 @@
 
 if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^9]|9[0-9])")
   add_RunCMake_test(CSharpCustomCommand)
-  add_RunCMake_test(CSharpReferenceImport)
+  if(NOT CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64")
+    add_RunCMake_test(CSharpReferenceImport)
+  endif()
 endif()
 
 add_RunCMake_test("CTestCommandExpandLists")
diff --git a/Tests/RunCMake/CMakePresets/PathListSep.cmake b/Tests/RunCMake/CMakePresets/PathListSep.cmake
new file mode 100644
index 0000000..52c225b
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/PathListSep.cmake
@@ -0,0 +1,7 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+if(CMAKE_HOST_WIN32)
+    test_variable(TEST_PATH_LIST_SEP "" "${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR}")
+else()
+    test_variable(TEST_PATH_LIST_SEP "" "${CMAKE_CURRENT_SOURCE_DIR}:${CMAKE_CURRENT_SOURCE_DIR}")
+endif()
diff --git a/Tests/RunCMake/CMakePresets/PathListSep.json.in b/Tests/RunCMake/CMakePresets/PathListSep.json.in
new file mode 100644
index 0000000..4c25029
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/PathListSep.json.in
@@ -0,0 +1,13 @@
+{
+    "version": 5,
+    "configurePresets": [
+        {
+            "name": "PathListSep",
+            "generator": "@RunCMake_GENERATOR@",
+            "binaryDir": "${sourceDir}/build",
+            "cacheVariables": {
+                "TEST_PATH_LIST_SEP": "${sourceDir}${pathListSep}${sourceDir}"
+            }
+        }
+    ]
+}
diff --git a/Tests/RunCMake/CMakePresets/PathListSepFuture-result.txt b/Tests/RunCMake/CMakePresets/PathListSepFuture-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/PathListSepFuture-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/PathListSepFuture-stderr.txt b/Tests/RunCMake/CMakePresets/PathListSepFuture-stderr.txt
new file mode 100644
index 0000000..b961aaf
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/PathListSepFuture-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/PathListSepFuture: Invalid macro expansion$
diff --git a/Tests/RunCMake/CMakePresets/PathListSepFuture.json.in b/Tests/RunCMake/CMakePresets/PathListSepFuture.json.in
new file mode 100644
index 0000000..2fd6b7e
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/PathListSepFuture.json.in
@@ -0,0 +1,13 @@
+{
+    "version": 4,
+    "configurePresets": [
+        {
+            "name": "PathListSepFuture",
+            "generator": "@RunCMake_GENERATOR@",
+            "binaryDir": "${sourceDir}/build",
+            "cacheVariables": {
+                "TEST_PATH_LIST_SEP": "${sourceDir}${pathListSep}${sourceDir}"
+            }
+        }
+    ]
+}
diff --git a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake
index 5867efd..d097086 100644
--- a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake
@@ -335,6 +335,12 @@
 set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/FileDirFuture.json.in")
 run_cmake_presets(FileDirFuture)
 
+# Test ${pathListSep} macro
+set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/PathListSep.json.in")
+run_cmake_presets(PathListSep)
+set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/PathListSepFuture.json.in")
+run_cmake_presets(PathListSepFuture)
+
 # Test conditions
 set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/Conditions.json.in")
 run_cmake_presets(ListConditions --list-presets)
diff --git a/Tests/RunCMake/CommandLine/Envgen-G-implicit-platform-stdout.txt b/Tests/RunCMake/CommandLine/Envgen-G-implicit-platform-stdout.txt
index 4dd6be1..a182e1c 100644
--- a/Tests/RunCMake/CommandLine/Envgen-G-implicit-platform-stdout.txt
+++ b/Tests/RunCMake/CommandLine/Envgen-G-implicit-platform-stdout.txt
@@ -1 +1 @@
--- CMAKE_VS_PLATFORM_NAME='(x64|Win32)'
+-- CMAKE_VS_PLATFORM_NAME='(x64|Win32|ARM64)'
diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetHostArchNone.cmake b/Tests/RunCMake/GeneratorToolset/TestToolsetHostArchNone.cmake
index 854f3dc..5ea02a5 100644
--- a/Tests/RunCMake/GeneratorToolset/TestToolsetHostArchNone.cmake
+++ b/Tests/RunCMake/GeneratorToolset/TestToolsetHostArchNone.cmake
@@ -1,10 +1,15 @@
 message(STATUS "CMAKE_VS_PLATFORM_TOOLSET='${CMAKE_VS_PLATFORM_TOOLSET}'")
 message(STATUS "CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE='${CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE}'")
+message(STATUS "CMAKE_HOST_SYSTEM_PROCESSOR='${CMAKE_HOST_SYSTEM_PROCESSOR}'")
 
 if(CMAKE_GENERATOR MATCHES "Visual Studio 1[67]")
   cmake_host_system_information(RESULT is_64_bit QUERY IS_64BIT)
   if(is_64_bit)
-    if(NOT "${CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE}" STREQUAL "x64")
+    if("${CMAKE_HOST_SYSTEM_PROCESSOR}" STREQUAL "ARM64")
+      if(NOT "${CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE}" STREQUAL "")
+        message(FATAL_ERROR "CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE is not empty as expected.")
+      endif()
+    elseif(NOT "${CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE}" STREQUAL "x64")
       message(FATAL_ERROR "CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE is not 'x64' as expected.")
     endif()
   endif()
diff --git a/Tests/RunCMake/VS10Project/VsCSharpCompilerOpts-check.cmake b/Tests/RunCMake/VS10Project/VsCSharpCompilerOpts-check.cmake
index 3e418c3..2ba8c3b 100644
--- a/Tests/RunCMake/VS10Project/VsCSharpCompilerOpts-check.cmake
+++ b/Tests/RunCMake/VS10Project/VsCSharpCompilerOpts-check.cmake
@@ -17,9 +17,9 @@
 file(STRINGS "${csProjectFile}" lines)
 foreach(line IN LISTS lines)
   #message(STATUS ${line})
-  if(line MATCHES "^ *<PropertyGroup .*Debug\\|(Win32|x64).*")
+  if(line MATCHES "^ *<PropertyGroup .*Debug\\|(Win32|x64|ARM64).*")
     set(inDebug TRUE)
-  elseif(line MATCHES "^ *<PropertyGroup .*Release\\|(Win32|x64).*")
+  elseif(line MATCHES "^ *<PropertyGroup .*Release\\|(Win32|x64|ARM64).*")
     set(inRelease TRUE)
   elseif(line MATCHES "^ *</PropertyGroup> *$")
     set(inRelease FALSE)
diff --git a/Tests/RunCMake/VS10Project/VsCSharpDefines-check.cmake b/Tests/RunCMake/VS10Project/VsCSharpDefines-check.cmake
index 631abac..d47bac9 100644
--- a/Tests/RunCMake/VS10Project/VsCSharpDefines-check.cmake
+++ b/Tests/RunCMake/VS10Project/VsCSharpDefines-check.cmake
@@ -17,9 +17,9 @@
 file(STRINGS "${csProjectFile}" lines)
 foreach(line IN LISTS lines)
   #message(STATUS ${line})
-  if(line MATCHES "^ *<PropertyGroup .*Debug\\|(Win32|x64).*")
+  if(line MATCHES "^ *<PropertyGroup .*Debug\\|(Win32|x64|ARM64).*")
     set(inDebug TRUE)
-  elseif(line MATCHES "^ *<PropertyGroup .*Release\\|(Win32|x64).*")
+  elseif(line MATCHES "^ *<PropertyGroup .*Release\\|(Win32|x64|ARM64).*")
     set(inRelease TRUE)
   elseif(line MATCHES "^ *</PropertyGroup> *$")
     set(inRelease FALSE)
diff --git a/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-all-check.cmake b/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-all-check.cmake
index 48d8e1a..0b5fb8d 100644
--- a/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-all-check.cmake
+++ b/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-all-check.cmake
@@ -1 +1 @@
-check_installed([[^empty1.txt;empty2.txt$]])
+check_installed([[^empty1.txt;empty3.txt$]])
diff --git a/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-dev-check.cmake b/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-dev-check.cmake
index 48d8e1a..88e57e3 100644
--- a/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-dev-check.cmake
+++ b/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-dev-check.cmake
@@ -1 +1 @@
-check_installed([[^empty1.txt;empty2.txt$]])
+check_installed([[^empty1.txt;empty2.txt;empty3.txt$]])
diff --git a/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-uns-check.cmake b/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-uns-check.cmake
index 48d8e1a..88e57e3 100644
--- a/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-uns-check.cmake
+++ b/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS-uns-check.cmake
@@ -1 +1 @@
-check_installed([[^empty1.txt;empty2.txt$]])
+check_installed([[^empty1.txt;empty2.txt;empty3.txt$]])
diff --git a/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS.cmake b/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS.cmake
index aa3f9d1..73c4e35 100644
--- a/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS.cmake
+++ b/Tests/RunCMake/install/SCRIPT-ALL_COMPONENTS.cmake
@@ -1,5 +1,16 @@
+
 install(
   SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/install_script.cmake"
+  ALL_COMPONENTS
+)
+
+install(
   CODE "write_empty_file(empty2.txt)"
   ALL_COMPONENTS
-  )
+  EXCLUDE_FROM_ALL
+)
+
+install(
+  CODE "write_empty_file(empty3.txt)"
+  ALL_COMPONENTS
+)
diff --git a/Tests/RunCMake/project/CodeInjection-stdout.txt b/Tests/RunCMake/project/CodeInjection-stdout.txt
new file mode 100644
index 0000000..88ac966
--- /dev/null
+++ b/Tests/RunCMake/project/CodeInjection-stdout.txt
@@ -0,0 +1,10 @@
+(-- )?Included CMAKE_PROJECT_INCLUDE_BEFORE
+(-- )?Included CMAKE_TOOLCHAIN_FILE
+.*Included CMAKE_PROJECT_TOP_LEVEL_INCLUDES first file
+(-- )?Included CMAKE_PROJECT_TOP_LEVEL_INCLUDES second file
+(-- )?Included CMAKE_PROJECT_INCLUDE
+(-- )?Calling sub-project
+(-- )?Included CMAKE_PROJECT_INCLUDE_BEFORE
+(-- )?Included CMAKE_PROJECT_SubProj_INCLUDE_BEFORE
+(-- )?Included CMAKE_PROJECT_INCLUDE
+(-- )?Included CMAKE_PROJECT_SubProj_INCLUDE
diff --git a/Tests/RunCMake/project/CodeInjection.cmake b/Tests/RunCMake/project/CodeInjection.cmake
new file mode 100644
index 0000000..dcf56a1
--- /dev/null
+++ b/Tests/RunCMake/project/CodeInjection.cmake
@@ -0,0 +1 @@
+add_subdirectory(CodeInjection)
diff --git a/Tests/RunCMake/project/CodeInjection/CMakeLists.txt b/Tests/RunCMake/project/CodeInjection/CMakeLists.txt
new file mode 100644
index 0000000..8ee99d0
--- /dev/null
+++ b/Tests/RunCMake/project/CodeInjection/CMakeLists.txt
@@ -0,0 +1,2 @@
+message(STATUS "Calling sub-project")
+project(SubProj LANGUAGES NONE)
diff --git a/Tests/RunCMake/project/CodeInjection/cmake_project_include.cmake b/Tests/RunCMake/project/CodeInjection/cmake_project_include.cmake
new file mode 100644
index 0000000..f3f0a7e
--- /dev/null
+++ b/Tests/RunCMake/project/CodeInjection/cmake_project_include.cmake
@@ -0,0 +1 @@
+message(STATUS "Included CMAKE_PROJECT_INCLUDE")
diff --git a/Tests/RunCMake/project/CodeInjection/cmake_project_include_before.cmake b/Tests/RunCMake/project/CodeInjection/cmake_project_include_before.cmake
new file mode 100644
index 0000000..01d53c9
--- /dev/null
+++ b/Tests/RunCMake/project/CodeInjection/cmake_project_include_before.cmake
@@ -0,0 +1 @@
+message(STATUS "Included CMAKE_PROJECT_INCLUDE_BEFORE")
diff --git a/Tests/RunCMake/project/CodeInjection/cmake_project_subproj_include.cmake b/Tests/RunCMake/project/CodeInjection/cmake_project_subproj_include.cmake
new file mode 100644
index 0000000..d68de6a
--- /dev/null
+++ b/Tests/RunCMake/project/CodeInjection/cmake_project_subproj_include.cmake
@@ -0,0 +1 @@
+message(STATUS "Included CMAKE_PROJECT_SubProj_INCLUDE")
diff --git a/Tests/RunCMake/project/CodeInjection/cmake_project_subproj_include_before.cmake b/Tests/RunCMake/project/CodeInjection/cmake_project_subproj_include_before.cmake
new file mode 100644
index 0000000..ef3bfc0
--- /dev/null
+++ b/Tests/RunCMake/project/CodeInjection/cmake_project_subproj_include_before.cmake
@@ -0,0 +1 @@
+message(STATUS "Included CMAKE_PROJECT_SubProj_INCLUDE_BEFORE")
diff --git a/Tests/RunCMake/project/CodeInjection/cmake_project_top_level_includes_1.cmake b/Tests/RunCMake/project/CodeInjection/cmake_project_top_level_includes_1.cmake
new file mode 100644
index 0000000..73ad037
--- /dev/null
+++ b/Tests/RunCMake/project/CodeInjection/cmake_project_top_level_includes_1.cmake
@@ -0,0 +1 @@
+message(STATUS "Included CMAKE_PROJECT_TOP_LEVEL_INCLUDES first file")
diff --git a/Tests/RunCMake/project/CodeInjection/cmake_project_top_level_includes_2.cmake b/Tests/RunCMake/project/CodeInjection/cmake_project_top_level_includes_2.cmake
new file mode 100644
index 0000000..80f9705
--- /dev/null
+++ b/Tests/RunCMake/project/CodeInjection/cmake_project_top_level_includes_2.cmake
@@ -0,0 +1 @@
+message(STATUS "Included CMAKE_PROJECT_TOP_LEVEL_INCLUDES second file")
diff --git a/Tests/RunCMake/project/CodeInjection/initial_cache.cmake b/Tests/RunCMake/project/CodeInjection/initial_cache.cmake
new file mode 100644
index 0000000..6c8995b
--- /dev/null
+++ b/Tests/RunCMake/project/CodeInjection/initial_cache.cmake
@@ -0,0 +1,10 @@
+set(CMAKE_TOOLCHAIN_FILE                 "${CMAKE_CURRENT_LIST_DIR}/passthrough_toolchain_file.cmake" CACHE FILEPATH "")
+set(CMAKE_PROJECT_INCLUDE                "${CMAKE_CURRENT_LIST_DIR}/cmake_project_include.cmake" CACHE FILEPATH "")
+set(CMAKE_PROJECT_INCLUDE_BEFORE         "${CMAKE_CURRENT_LIST_DIR}/cmake_project_include_before.cmake" CACHE FILEPATH "")
+set(CMAKE_PROJECT_SubProj_INCLUDE        "${CMAKE_CURRENT_LIST_DIR}/cmake_project_subproj_include.cmake" CACHE FILEPATH "")
+set(CMAKE_PROJECT_SubProj_INCLUDE_BEFORE "${CMAKE_CURRENT_LIST_DIR}/cmake_project_subproj_include_before.cmake" CACHE FILEPATH "")
+set(CMAKE_PROJECT_TOP_LEVEL_INCLUDES
+  "${CMAKE_CURRENT_LIST_DIR}/cmake_project_top_level_includes_1.cmake"
+  "${CMAKE_CURRENT_LIST_DIR}/cmake_project_top_level_includes_2.cmake"
+  CACHE STRING ""
+)
diff --git a/Tests/RunCMake/project/CodeInjection/passthrough_toolchain_file.cmake b/Tests/RunCMake/project/CodeInjection/passthrough_toolchain_file.cmake
new file mode 100644
index 0000000..d045712
--- /dev/null
+++ b/Tests/RunCMake/project/CodeInjection/passthrough_toolchain_file.cmake
@@ -0,0 +1 @@
+message(STATUS "Included CMAKE_TOOLCHAIN_FILE")
diff --git a/Tests/RunCMake/project/RunCMakeTest.cmake b/Tests/RunCMake/project/RunCMakeTest.cmake
index d7dab12..945d9ed 100644
--- a/Tests/RunCMake/project/RunCMakeTest.cmake
+++ b/Tests/RunCMake/project/RunCMakeTest.cmake
@@ -1,5 +1,14 @@
 include(RunCMake)
 
+# Use an initial cache file to define the project() variables
+# to avoid long command lines. Also see the CMakeOnly test case
+# which tests some of the individual variables one at a time.
+# Here, we are focused on testing that the variables are all injected
+# at the expected points in the expected order.
+run_cmake_with_options(CodeInjection
+  -C "${CMAKE_CURRENT_LIST_DIR}/CodeInjection/initial_cache.cmake"
+)
+
 if(CMake_TEST_RESOURCES)
   run_cmake(ExplicitRC)
 endif()
diff --git a/Tests/TargetName/executables/hello_world.c b/Tests/TargetName/executables/hello_world.c
index 5b6eaf8..71d71f5 100644
--- a/Tests/TargetName/executables/hello_world.c
+++ b/Tests/TargetName/executables/hello_world.c
@@ -1,5 +1,6 @@
 #include <stdio.h>
-main()
+int main(void)
 {
   printf("hello, world\n");
+  return 0;
 }
diff --git a/Utilities/Scripts/update-curl.bash b/Utilities/Scripts/update-curl.bash
index 64cb659..9715e07 100755
--- a/Utilities/Scripts/update-curl.bash
+++ b/Utilities/Scripts/update-curl.bash
@@ -8,7 +8,7 @@
 readonly ownership="Curl Upstream <curl-library@lists.haxx.se>"
 readonly subtree="Utilities/cmcurl"
 readonly repo="https://github.com/curl/curl.git"
-readonly tag="curl-7_83_0"
+readonly tag="curl-7_83_1"
 readonly shortlog=false
 readonly paths="
   CMake/*
diff --git a/Utilities/cmcurl/include/curl/curlver.h b/Utilities/cmcurl/include/curl/curlver.h
index 3081115..718d58c 100644
--- a/Utilities/cmcurl/include/curl/curlver.h
+++ b/Utilities/cmcurl/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.83.0"
+#define LIBCURL_VERSION "7.83.1"
 
 /* The numeric version number is also available "in parts" by using these
    defines: */
 #define LIBCURL_VERSION_MAJOR 7
 #define LIBCURL_VERSION_MINOR 83
-#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 0x075300
+#define LIBCURL_VERSION_NUM 0x075301
 
 /*
  * This is the date and time when the full source package was created. The
diff --git a/Utilities/cmcurl/lib/altsvc.c b/Utilities/cmcurl/lib/altsvc.c
index 45929a5..dd2d0eb 100644
--- a/Utilities/cmcurl/lib/altsvc.c
+++ b/Utilities/cmcurl/lib/altsvc.c
@@ -102,12 +102,17 @@
                                       unsigned int dstport)
 {
   struct altsvc *as = calloc(sizeof(struct altsvc), 1);
+  size_t hlen;
   if(!as)
     return NULL;
-
+  hlen = strlen(srchost);
+  DEBUGASSERT(hlen);
   as->src.host = strdup(srchost);
   if(!as->src.host)
     goto error;
+  if(hlen && (srchost[hlen - 1] == '.'))
+    /* strip off trailing any dot */
+    as->src.host[--hlen] = 0;
   as->dst.host = strdup(dsthost);
   if(!as->dst.host)
     goto error;
@@ -398,6 +403,22 @@
   return CURLE_OK;
 }
 
+/* hostcompare() returns true if 'host' matches 'check'. The first host
+ * argument may have a trailing dot present that will be ignored.
+ */
+static bool hostcompare(const char *host, const char *check)
+{
+  size_t hlen = strlen(host);
+  size_t clen = strlen(check);
+
+  if(hlen && (host[hlen - 1] == '.'))
+    hlen--;
+  if(hlen != clen)
+    /* they can't match if they have different lengths */
+    return FALSE;
+  return strncasecompare(host, check, hlen);
+}
+
 /* altsvc_flush() removes all alternatives for this source origin from the
    list */
 static void altsvc_flush(struct altsvcinfo *asi, enum alpnid srcalpnid,
@@ -410,7 +431,7 @@
     n = e->next;
     if((srcalpnid == as->src.alpnid) &&
        (srcport == as->src.port) &&
-       strcasecompare(srchost, as->src.host)) {
+       hostcompare(srchost, as->src.host)) {
       Curl_llist_remove(&asi->list, e, NULL);
       altsvc_free(as);
     }
@@ -635,7 +656,7 @@
       continue;
     }
     if((as->src.alpnid == srcalpnid) &&
-       strcasecompare(as->src.host, srchost) &&
+       hostcompare(srchost, as->src.host) &&
        (as->src.port == srcport) &&
        (versions & as->dst.alpnid)) {
       /* match */
diff --git a/Utilities/cmcurl/lib/c-hyper.c b/Utilities/cmcurl/lib/c-hyper.c
index de09568..6908298 100644
--- a/Utilities/cmcurl/lib/c-hyper.c
+++ b/Utilities/cmcurl/lib/c-hyper.c
@@ -439,6 +439,13 @@
     reasonp = hyper_response_reason_phrase(resp);
     reason_len = hyper_response_reason_phrase_len(resp);
 
+    if(http_status == 417 && data->state.expect100header) {
+      infof(data, "Got 417 while waiting for a 100");
+      data->state.disableexpect = TRUE;
+      data->req.newurl = strdup(data->state.url);
+      Curl_done_sending(data, k);
+    }
+
     result = status_line(data, conn,
                          http_status, http_version, reasonp, reason_len);
     if(result)
@@ -951,6 +958,11 @@
       goto error;
     }
   }
+  else {
+    if(!h2 && !data->state.disableexpect) {
+      data->state.expect100header = TRUE;
+    }
+  }
 
   if(hyper_request_set_method(req, (uint8_t *)method, strlen(method))) {
     failf(data, "error setting method");
diff --git a/Utilities/cmcurl/lib/cookie.c b/Utilities/cmcurl/lib/cookie.c
index 451881f..0c2d49b 100644
--- a/Utilities/cmcurl/lib/cookie.c
+++ b/Utilities/cmcurl/lib/cookie.c
@@ -427,7 +427,15 @@
 /* Make sure domain contains a dot or is localhost. */
 static bool bad_domain(const char *domain)
 {
-  return !strchr(domain, '.') && !strcasecompare(domain, "localhost");
+  if(strcasecompare(domain, "localhost"))
+    return FALSE;
+  else {
+    /* there must be a dot present, but that dot must not be a trailing dot */
+    char *dot = strchr(domain, '.');
+    if(dot)
+      return dot[1] ? FALSE : TRUE;
+  }
+  return TRUE;
 }
 
 /*
diff --git a/Utilities/cmcurl/lib/easy.c b/Utilities/cmcurl/lib/easy.c
index 65d7464..bd9d695 100644
--- a/Utilities/cmcurl/lib/easy.c
+++ b/Utilities/cmcurl/lib/easy.c
@@ -1139,7 +1139,7 @@
   if(!data->conn)
     /* on first invoke, the transfer has been detached from the connection and
        needs to be reattached */
-    Curl_attach_connnection(data, c);
+    Curl_attach_connection(data, c);
 
   *n = 0;
   result = Curl_read(data, sfd, buffer, buflen, &n1);
@@ -1175,7 +1175,7 @@
   if(!data->conn)
     /* on first invoke, the transfer has been detached from the connection and
        needs to be reattached */
-    Curl_attach_connnection(data, c);
+    Curl_attach_connection(data, c);
 
   *n = 0;
   sigpipe_ignore(data, &pipe_st);
@@ -1209,12 +1209,12 @@
   if(conn->handler->connection_check) {
     /* briefly attach the connection to this transfer for the purpose of
        checking it */
-    Curl_attach_connnection(data, conn);
+    Curl_attach_connection(data, conn);
 
     /* Do a protocol-specific keepalive check on the connection. */
     conn->handler->connection_check(data, conn, CONNCHECK_KEEPALIVE);
     /* detach the connection again */
-    Curl_detach_connnection(data);
+    Curl_detach_connection(data);
   }
 
   return 0; /* continue iteration */
diff --git a/Utilities/cmcurl/lib/hostip.c b/Utilities/cmcurl/lib/hostip.c
index 7f6bbac..7000b85 100644
--- a/Utilities/cmcurl/lib/hostip.c
+++ b/Utilities/cmcurl/lib/hostip.c
@@ -1268,7 +1268,7 @@
   result = Curl_setup_conn(data, protocol_done);
 
   if(result) {
-    Curl_detach_connnection(data);
+    Curl_detach_connection(data);
     Curl_conncache_remove_conn(data, conn, TRUE);
     Curl_disconnect(data, conn, TRUE);
   }
diff --git a/Utilities/cmcurl/lib/hsts.c b/Utilities/cmcurl/lib/hsts.c
index 03fcc9e..b9fa6f7 100644
--- a/Utilities/cmcurl/lib/hsts.c
+++ b/Utilities/cmcurl/lib/hsts.c
@@ -114,16 +114,25 @@
                             curl_off_t expires)
 {
   struct stsentry *sts = hsts_entry();
+  char *duphost;
+  size_t hlen;
   if(!sts)
     return CURLE_OUT_OF_MEMORY;
 
-  sts->expires = expires;
-  sts->includeSubDomains = subdomains;
-  sts->host = strdup(hostname);
-  if(!sts->host) {
+  duphost = strdup(hostname);
+  if(!duphost) {
     free(sts);
     return CURLE_OUT_OF_MEMORY;
   }
+
+  hlen = strlen(duphost);
+  if(duphost[hlen - 1] == '.')
+    /* strip off trailing any dot */
+    duphost[--hlen] = 0;
+
+  sts->host = duphost;
+  sts->expires = expires;
+  sts->includeSubDomains = subdomains;
   Curl_llist_insert_next(&h->list, h->list.tail, sts, &sts->node);
   return CURLE_OK;
 }
@@ -238,10 +247,21 @@
                            bool subdomain)
 {
   if(h) {
+    char buffer[MAX_HSTS_HOSTLEN + 1];
     time_t now = time(NULL);
     size_t hlen = strlen(hostname);
     struct Curl_llist_element *e;
     struct Curl_llist_element *n;
+
+    if((hlen > MAX_HSTS_HOSTLEN) || !hlen)
+      return NULL;
+    memcpy(buffer, hostname, hlen);
+    if(hostname[hlen-1] == '.')
+      /* remove the trailing dot */
+      --hlen;
+    buffer[hlen] = 0;
+    hostname = buffer;
+
     for(e = h->list.head; e; e = n) {
       struct stsentry *sts = e->ptr;
       n = e->next;
@@ -440,7 +460,7 @@
     CURLSTScode sc;
     DEBUGASSERT(h);
     do {
-      char buffer[257];
+      char buffer[MAX_HSTS_HOSTLEN + 1];
       struct curl_hstsentry e;
       e.name = buffer;
       e.namelen = sizeof(buffer)-1;
diff --git a/Utilities/cmcurl/lib/http.c b/Utilities/cmcurl/lib/http.c
index 0d5c449..b215307 100644
--- a/Utilities/cmcurl/lib/http.c
+++ b/Utilities/cmcurl/lib/http.c
@@ -651,6 +651,21 @@
   return result;
 }
 
+/*
+ * Curl_allow_auth_to_host() tells if authentication, cookies or other
+ * "sensitive data" can (still) be sent to this host.
+ */
+bool Curl_allow_auth_to_host(struct Curl_easy *data)
+{
+  struct connectdata *conn = data->conn;
+  return (!data->state.this_is_a_follow ||
+          data->set.allow_auth_to_other_hosts ||
+          (data->state.first_host &&
+           strcasecompare(data->state.first_host, conn->host.name) &&
+           (data->state.first_remote_port == conn->remote_port) &&
+           (data->state.first_remote_protocol == conn->handler->protocol)));
+}
+
 #ifndef CURL_DISABLE_HTTP_AUTH
 /*
  * Output the correct authentication header depending on the auth type
@@ -775,21 +790,6 @@
   return CURLE_OK;
 }
 
-/*
- * Curl_allow_auth_to_host() tells if authentication, cookies or other
- * "sensitive data" can (still) be sent to this host.
- */
-bool Curl_allow_auth_to_host(struct Curl_easy *data)
-{
-  struct connectdata *conn = data->conn;
-  return (!data->state.this_is_a_follow ||
-          data->set.allow_auth_to_other_hosts ||
-          (data->state.first_host &&
-           strcasecompare(data->state.first_host, conn->host.name) &&
-           (data->state.first_remote_port == conn->remote_port) &&
-           (data->state.first_remote_protocol == conn->handler->protocol)));
-}
-
 /**
  * Curl_http_output_auth() setups the authentication headers for the
  * host/proxy and the correct authentication
diff --git a/Utilities/cmcurl/lib/http_proxy.c b/Utilities/cmcurl/lib/http_proxy.c
index 863cbbb..ed08193 100644
--- a/Utilities/cmcurl/lib/http_proxy.c
+++ b/Utilities/cmcurl/lib/http_proxy.c
@@ -967,6 +967,13 @@
       break;
     }
 
+    if(conn->bits.close && data->req.newurl) {
+      /* Connection closed by server. Don't use it anymore */
+      Curl_closesocket(data, conn, conn->sock[sockindex]);
+      conn->sock[sockindex] = CURL_SOCKET_BAD;
+      break;
+    }
+
     /* If we are supposed to continue and request a new URL, which basically
      * means the HTTP authentication is still going on so if the tunnel
      * is complete we start over in INIT state */
diff --git a/Utilities/cmcurl/lib/multi.c b/Utilities/cmcurl/lib/multi.c
index 466425d..8e58d78 100644
--- a/Utilities/cmcurl/lib/multi.c
+++ b/Utilities/cmcurl/lib/multi.c
@@ -118,7 +118,7 @@
 
   /* Important: reset the conn pointer so that we don't point to memory
      that could be freed anytime */
-  Curl_detach_connnection(data);
+  Curl_detach_connection(data);
   Curl_expire_clear(data); /* stop all timers */
 }
 
@@ -635,7 +635,7 @@
   process_pending_handles(data->multi); /* connection / multiplex */
 
   CONNCACHE_LOCK(data);
-  Curl_detach_connnection(data);
+  Curl_detach_connection(data);
   if(CONN_INUSE(conn)) {
     /* Stop if still used. */
     CONNCACHE_UNLOCK(data);
@@ -824,7 +824,7 @@
                                       that vanish with this handle */
 
   /* Remove the association between the connection and the handle */
-  Curl_detach_connnection(data);
+  Curl_detach_connection(data);
 
   if(data->state.lastconnect_id != -1) {
     /* Mark any connect-only connection for closure */
@@ -899,12 +899,12 @@
 }
 
 /*
- * Curl_detach_connnection() removes the given transfer from the connection.
+ * Curl_detach_connection() removes the given transfer from the connection.
  *
  * This is the only function that should clear data->conn. This will
  * occasionally be called with the data->conn pointer already cleared.
  */
-void Curl_detach_connnection(struct Curl_easy *data)
+void Curl_detach_connection(struct Curl_easy *data)
 {
   struct connectdata *conn = data->conn;
   if(conn) {
@@ -916,11 +916,11 @@
 }
 
 /*
- * Curl_attach_connnection() attaches this transfer to this connection.
+ * Curl_attach_connection() attaches this transfer to this connection.
  *
  * This is the only function that should assign data->conn
  */
-void Curl_attach_connnection(struct Curl_easy *data,
+void Curl_attach_connection(struct Curl_easy *data,
                              struct connectdata *conn)
 {
   DEBUGASSERT(!data->conn);
@@ -1540,7 +1540,7 @@
 
     /* take this handle to the perform state right away */
     multistate(data, MSTATE_PERFORMING);
-    Curl_attach_connnection(data, conn);
+    Curl_attach_connection(data, conn);
     k->keepon |= KEEP_RECV; /* setup to receive! */
   }
   return rc;
@@ -2558,7 +2558,7 @@
             /* This is where we make sure that the conn pointer is reset.
                We don't have to do this in every case block above where a
                failure is detected */
-            Curl_detach_connnection(data);
+            Curl_detach_connection(data);
 
             /* remove connection from cache */
             Curl_conncache_remove_conn(data, conn, TRUE);
diff --git a/Utilities/cmcurl/lib/multiif.h b/Utilities/cmcurl/lib/multiif.h
index f4d0ada..5a8c358 100644
--- a/Utilities/cmcurl/lib/multiif.h
+++ b/Utilities/cmcurl/lib/multiif.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, 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
@@ -31,9 +31,9 @@
 void Curl_expire_clear(struct Curl_easy *data);
 void Curl_expire_done(struct Curl_easy *data, expire_id id);
 CURLMcode Curl_update_timer(struct Curl_multi *multi) WARN_UNUSED_RESULT;
-void Curl_attach_connnection(struct Curl_easy *data,
+void Curl_attach_connection(struct Curl_easy *data,
                              struct connectdata *conn);
-void Curl_detach_connnection(struct Curl_easy *data);
+void Curl_detach_connection(struct Curl_easy *data);
 bool Curl_multiplex_wanted(const struct Curl_multi *multi);
 void Curl_set_in_callback(struct Curl_easy *data, bool value);
 bool Curl_is_in_callback(struct Curl_easy *easy);
diff --git a/Utilities/cmcurl/lib/setopt.c b/Utilities/cmcurl/lib/setopt.c
index 0df1afa..05e1a54 100644
--- a/Utilities/cmcurl/lib/setopt.c
+++ b/Utilities/cmcurl/lib/setopt.c
@@ -2294,6 +2294,7 @@
 
   case CURLOPT_SSL_OPTIONS:
     arg = va_arg(param, long);
+    data->set.ssl.primary.ssl_options = (unsigned char)(arg & 0xff);
     data->set.ssl.enable_beast = !!(arg & CURLSSLOPT_ALLOW_BEAST);
     data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
     data->set.ssl.no_partialchain = !!(arg & CURLSSLOPT_NO_PARTIALCHAIN);
@@ -2307,6 +2308,7 @@
 #ifndef CURL_DISABLE_PROXY
   case CURLOPT_PROXY_SSL_OPTIONS:
     arg = va_arg(param, long);
+    data->set.proxy_ssl.primary.ssl_options = (unsigned char)(arg & 0xff);
     data->set.proxy_ssl.enable_beast = !!(arg & CURLSSLOPT_ALLOW_BEAST);
     data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
     data->set.proxy_ssl.no_partialchain = !!(arg & CURLSSLOPT_NO_PARTIALCHAIN);
@@ -2745,49 +2747,52 @@
   case CURLOPT_TLSAUTH_USERNAME:
     result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME],
                             va_arg(param, char *));
-    if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype)
-      data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
+    if(data->set.str[STRING_TLSAUTH_USERNAME] &&
+       !data->set.ssl.primary.authtype)
+      data->set.ssl.primary.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
     break;
 #ifndef CURL_DISABLE_PROXY
   case CURLOPT_PROXY_TLSAUTH_USERNAME:
     result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_PROXY],
                             va_arg(param, char *));
     if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
-       !data->set.proxy_ssl.authtype)
-      data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
+       !data->set.proxy_ssl.primary.authtype)
+      data->set.proxy_ssl.primary.authtype = CURL_TLSAUTH_SRP; /* default to
+                                                                  SRP */
     break;
 #endif
   case CURLOPT_TLSAUTH_PASSWORD:
     result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD],
                             va_arg(param, char *));
-    if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype)
-      data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
+    if(data->set.str[STRING_TLSAUTH_USERNAME] &&
+       !data->set.ssl.primary.authtype)
+      data->set.ssl.primary.authtype = CURL_TLSAUTH_SRP; /* default */
     break;
 #ifndef CURL_DISABLE_PROXY
   case CURLOPT_PROXY_TLSAUTH_PASSWORD:
     result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_PROXY],
                             va_arg(param, char *));
     if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
-       !data->set.proxy_ssl.authtype)
-      data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
+       !data->set.proxy_ssl.primary.authtype)
+      data->set.proxy_ssl.primary.authtype = CURL_TLSAUTH_SRP; /* default */
     break;
 #endif
   case CURLOPT_TLSAUTH_TYPE:
     argptr = va_arg(param, char *);
     if(!argptr ||
        strncasecompare(argptr, "SRP", strlen("SRP")))
-      data->set.ssl.authtype = CURL_TLSAUTH_SRP;
+      data->set.ssl.primary.authtype = CURL_TLSAUTH_SRP;
     else
-      data->set.ssl.authtype = CURL_TLSAUTH_NONE;
+      data->set.ssl.primary.authtype = CURL_TLSAUTH_NONE;
     break;
 #ifndef CURL_DISABLE_PROXY
   case CURLOPT_PROXY_TLSAUTH_TYPE:
     argptr = va_arg(param, char *);
     if(!argptr ||
        strncasecompare(argptr, "SRP", strlen("SRP")))
-      data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP;
+      data->set.proxy_ssl.primary.authtype = CURL_TLSAUTH_SRP;
     else
-      data->set.proxy_ssl.authtype = CURL_TLSAUTH_NONE;
+      data->set.proxy_ssl.primary.authtype = CURL_TLSAUTH_NONE;
     break;
 #endif
 #endif
diff --git a/Utilities/cmcurl/lib/url.c b/Utilities/cmcurl/lib/url.c
index ef48ed6..6b31d4b 100644
--- a/Utilities/cmcurl/lib/url.c
+++ b/Utilities/cmcurl/lib/url.c
@@ -372,7 +372,7 @@
 
   /* Detach connection if any is left. This should not be normal, but can be
      the case for example with CONNECT_ONLY + recv/send (test 556) */
-  Curl_detach_connnection(data);
+  Curl_detach_connection(data);
   m = data->multi;
   if(m)
     /* This handle is still part of a multi handle, take care of this first
@@ -542,7 +542,7 @@
   set->ssl.primary.verifypeer = TRUE;
   set->ssl.primary.verifyhost = TRUE;
 #ifdef USE_TLS_SRP
-  set->ssl.authtype = CURL_TLSAUTH_NONE;
+  set->ssl.primary.authtype = CURL_TLSAUTH_NONE;
 #endif
   set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth
                                                       type */
@@ -859,7 +859,7 @@
 
   /* temporarily attach the connection to this transfer handle for the
      disconnect and shutdown */
-  Curl_attach_connnection(data, conn);
+  Curl_attach_connection(data, conn);
 
   if(conn->handler->disconnect)
     /* This is set if protocol-specific cleanups should be made */
@@ -868,7 +868,7 @@
   conn_shutdown(data, conn);
 
   /* detach it again */
-  Curl_detach_connnection(data);
+  Curl_detach_connection(data);
 
   conn_free(conn);
 }
@@ -1020,12 +1020,12 @@
 
       /* briefly attach the connection to this transfer for the purpose of
          checking it */
-      Curl_attach_connnection(data, conn);
+      Curl_attach_connection(data, conn);
 
       state = conn->handler->connection_check(data, conn, CONNCHECK_ISDEAD);
       dead = (state & CONNRESULT_DEAD);
       /* detach the connection again */
-      Curl_detach_connnection(data);
+      Curl_detach_connection(data);
 
     }
     else {
@@ -1100,6 +1100,12 @@
   }
 }
 
+static bool ssh_config_matches(struct connectdata *one,
+                               struct connectdata *two)
+{
+  return (Curl_safecmp(one->proto.sshc.rsa, two->proto.sshc.rsa) &&
+          Curl_safecmp(one->proto.sshc.rsa_pub, two->proto.sshc.rsa_pub));
+}
 /*
  * Given one filled in connection struct (named needle), this function should
  * detect if there already is one that has all the significant details
@@ -1356,6 +1362,11 @@
          (data->state.httpwant < CURL_HTTP_VERSION_2_0))
         continue;
 
+      if(get_protocol_family(needle->handler) == PROTO_FAMILY_SSH) {
+        if(!ssh_config_matches(needle, check))
+          continue;
+      }
+
       if((needle->handler->flags&PROTOPT_SSL)
 #ifndef CURL_DISABLE_PROXY
          || !needle->bits.httpproxy || needle->bits.tunnel_proxy
@@ -1508,7 +1519,7 @@
 
   if(chosen) {
     /* mark it as used before releasing the lock */
-    Curl_attach_connnection(data, chosen);
+    Curl_attach_connection(data, chosen);
     CONNCACHE_UNLOCK(data);
     *usethis = chosen;
     return TRUE; /* yes, we found one to use! */
@@ -1758,11 +1769,17 @@
   conn->ssl_config.verifystatus = data->set.ssl.primary.verifystatus;
   conn->ssl_config.verifypeer = data->set.ssl.primary.verifypeer;
   conn->ssl_config.verifyhost = data->set.ssl.primary.verifyhost;
+  conn->ssl_config.ssl_options = data->set.ssl.primary.ssl_options;
+#ifdef USE_TLS_SRP
+#endif
 #ifndef CURL_DISABLE_PROXY
   conn->proxy_ssl_config.verifystatus =
     data->set.proxy_ssl.primary.verifystatus;
   conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer;
   conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost;
+  conn->proxy_ssl_config.ssl_options = data->set.proxy_ssl.primary.ssl_options;
+#ifdef USE_TLS_SRP
+#endif
 #endif
   conn->ip_version = data->set.ipver;
   conn->bits.connect_only = data->set.connect_only;
@@ -3779,7 +3796,7 @@
     if(!result) {
       conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; /* we are "connected */
 
-      Curl_attach_connnection(data, conn);
+      Curl_attach_connection(data, conn);
       result = Curl_conncache_add_conn(data);
       if(result)
         goto out;
@@ -3848,7 +3865,8 @@
     data->set.str[STRING_SSL_ISSUERCERT_PROXY];
   data->set.proxy_ssl.primary.issuercert_blob =
     data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY];
-  data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY];
+  data->set.proxy_ssl.primary.CRLfile =
+    data->set.str[STRING_SSL_CRLFILE_PROXY];
   data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
   data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY];
   data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY];
@@ -3856,18 +3874,20 @@
   data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY];
   data->set.proxy_ssl.key_blob = data->set.blobs[BLOB_KEY_PROXY];
 #endif
-  data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE];
+  data->set.ssl.primary.CRLfile = data->set.str[STRING_SSL_CRLFILE];
   data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE];
   data->set.ssl.key = data->set.str[STRING_KEY];
   data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE];
   data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD];
   data->set.ssl.primary.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];
+  data->set.ssl.primary.username = data->set.str[STRING_TLSAUTH_USERNAME];
+  data->set.ssl.primary.password = data->set.str[STRING_TLSAUTH_PASSWORD];
 #ifndef CURL_DISABLE_PROXY
-  data->set.proxy_ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
-  data->set.proxy_ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
+  data->set.proxy_ssl.primary.username =
+    data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
+  data->set.proxy_ssl.primary.password =
+    data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
 #endif
 #endif
   data->set.ssl.key_blob = data->set.blobs[BLOB_KEY];
@@ -4006,7 +4026,7 @@
        * This is a brand new connection, so let's store it in the connection
        * cache of ours!
        */
-      Curl_attach_connnection(data, conn);
+      Curl_attach_connection(data, conn);
       result = Curl_conncache_add_conn(data);
       if(result)
         goto out;
@@ -4153,7 +4173,7 @@
   else if(result && conn) {
     /* We're not allowed to return failure with memory left allocated in the
        connectdata struct, free those here */
-    Curl_detach_connnection(data);
+    Curl_detach_connection(data);
     Curl_conncache_remove_conn(data, conn, TRUE);
     Curl_disconnect(data, conn, TRUE);
   }
diff --git a/Utilities/cmcurl/lib/urlapi.c b/Utilities/cmcurl/lib/urlapi.c
index 99a0f69..2a36de6 100644
--- a/Utilities/cmcurl/lib/urlapi.c
+++ b/Utilities/cmcurl/lib/urlapi.c
@@ -228,7 +228,7 @@
  */
 bool Curl_is_absolute_url(const char *url, char *buf, size_t buflen)
 {
-  size_t i;
+  int i;
   DEBUGASSERT(!buf || (buflen > MAX_SCHEME_LEN));
   (void)buflen; /* only used in debug-builds */
   if(buf)
@@ -678,8 +678,8 @@
 #endif
   }
   else {
-    /* letters from the second string is not ok */
-    len = strcspn(hostname, " \r\n");
+    /* letters from the second string are not ok */
+    len = strcspn(hostname, " \r\n\t/:#?!@");
     if(hlen != len)
       /* hostname with bad content */
       return CURLUE_BAD_HOSTNAME;
diff --git a/Utilities/cmcurl/lib/urldata.h b/Utilities/cmcurl/lib/urldata.h
index 9c34ec4..584434d 100644
--- a/Utilities/cmcurl/lib/urldata.h
+++ b/Utilities/cmcurl/lib/urldata.h
@@ -253,10 +253,17 @@
   char *cipher_list;     /* list of ciphers to use */
   char *cipher_list13;   /* list of TLS 1.3 cipher suites to use */
   char *pinned_key;
+  char *CRLfile;         /* CRL to check certificate revocation */
   struct curl_blob *cert_blob;
   struct curl_blob *ca_info_blob;
   struct curl_blob *issuercert_blob;
+#ifdef USE_TLS_SRP
+  char *username; /* TLS username (for, e.g., SRP) */
+  char *password; /* TLS password (for, e.g., SRP) */
+  enum CURL_TLSAUTH authtype; /* TLS authentication type (default SRP) */
+#endif
   char *curves;          /* list of curves to use */
+  unsigned char ssl_options;  /* the CURLOPT_SSL_OPTIONS bitmask */
   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 */
@@ -266,7 +273,6 @@
 struct ssl_config_data {
   struct ssl_primary_config primary;
   long certverifyresult; /* result from the certificate verification */
-  char *CRLfile;   /* CRL to check certificate revocation */
   curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */
   void *fsslctxp;        /* parameter for call back */
   char *cert_type; /* format for certificate (default: PEM)*/
@@ -274,11 +280,6 @@
   struct curl_blob *key_blob;
   char *key_type; /* format for private key (default: PEM) */
   char *key_passwd; /* plain text private key password */
-#ifdef USE_TLS_SRP
-  char *username; /* TLS username (for, e.g., SRP) */
-  char *password; /* TLS password (for, e.g., SRP) */
-  enum CURL_TLSAUTH authtype; /* TLS authentication type (default SRP) */
-#endif
   BIT(certinfo);     /* gather lots of certificate info */
   BIT(falsestart);
   BIT(enable_beast); /* allow this flaw for interoperability's sake*/
diff --git a/Utilities/cmcurl/lib/vquic/msh3.c b/Utilities/cmcurl/lib/vquic/msh3.c
index be18e6e..f7bd315 100644
--- a/Utilities/cmcurl/lib/vquic/msh3.c
+++ b/Utilities/cmcurl/lib/vquic/msh3.c
@@ -95,7 +95,9 @@
 
 void Curl_quic_ver(char *p, size_t len)
 {
-  (void)msnprintf(p, len, "msh3/%s", "0.0.1");
+  uint32_t v[4];
+  MsH3Version(v);
+  (void)msnprintf(p, len, "msh3/%d.%d.%d.%d", v[0], v[1], v[2], v[3]);
 }
 
 CURLcode Curl_quic_connect(struct Curl_easy *data,
@@ -121,7 +123,10 @@
     return CURLE_FAILED_INIT;
   }
 
-  qs->conn = MsH3ConnectionOpen(qs->api, conn->host.name, unsecure);
+  qs->conn = MsH3ConnectionOpen(qs->api,
+                                conn->host.name,
+                                (uint16_t)conn->remote_port,
+                                unsecure);
   if(!qs->conn) {
     failf(data, "can't create msh3 connection");
     if(qs->api) {
@@ -357,7 +362,7 @@
   struct HTTP *stream = IfContext;
   (void)Request;
   (void)AbortError;
-  H3BUGF(printf("* msh3_complete, aborted=%hhu\n", Aborted));
+  H3BUGF(printf("* msh3_complete, aborted=%s\n", Aborted ? "true" : "false"));
   msh3_lock_acquire(&stream->recv_lock);
   if(Aborted) {
     stream->recv_error = CURLE_HTTP3; /* TODO - how do we pass AbortError? */
diff --git a/Utilities/cmcurl/lib/vquic/ngtcp2.c b/Utilities/cmcurl/lib/vquic/ngtcp2.c
index abce631..f1a64ee 100644
--- a/Utilities/cmcurl/lib/vquic/ngtcp2.c
+++ b/Utilities/cmcurl/lib/vquic/ngtcp2.c
@@ -264,6 +264,7 @@
 
 static SSL_CTX *quic_ssl_ctx(struct Curl_easy *data)
 {
+  struct connectdata *conn = data->conn;
   SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_method());
 
   SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_3_VERSION);
@@ -291,12 +292,11 @@
     SSL_CTX_set_keylog_callback(ssl_ctx, keylog_callback);
   }
 
-  {
-    struct connectdata *conn = data->conn;
+  if(conn->ssl_config.verifypeer) {
     const char * const ssl_cafile = conn->ssl_config.CAfile;
     const char * const ssl_capath = conn->ssl_config.CApath;
 
-    if(conn->ssl_config.verifypeer) {
+    if(ssl_cafile || ssl_capath) {
       SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
       /* tell OpenSSL where to find CA certificates that are used to verify
          the server's certificate. */
@@ -311,6 +311,13 @@
       infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
       infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
     }
+#ifdef CURL_CA_FALLBACK
+    else {
+      /* verifying the peer without any CA certificates won't work so
+         use openssl's built-in default as fallback */
+      SSL_CTX_set_default_verify_paths(ssl_ctx);
+    }
+#endif
   }
   return ssl_ctx;
 }
diff --git a/Utilities/cmcurl/lib/vssh/ssh.h b/Utilities/cmcurl/lib/vssh/ssh.h
index 7972081..30d82e5 100644
--- a/Utilities/cmcurl/lib/vssh/ssh.h
+++ b/Utilities/cmcurl/lib/vssh/ssh.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2022, 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
@@ -131,8 +131,8 @@
 
   /* common */
   const char *passphrase;     /* pass-phrase to use */
-  char *rsa_pub;              /* path name */
-  char *rsa;                  /* path name */
+  char *rsa_pub;              /* strdup'ed public key file */
+  char *rsa;                  /* strdup'ed private key file */
   bool authed;                /* the connection has been authenticated fine */
   bool acceptfail;            /* used by the SFTP_QUOTE (continue if
                                  quote command fails) */
diff --git a/Utilities/cmcurl/lib/vtls/gskit.c b/Utilities/cmcurl/lib/vtls/gskit.c
index 9b5fbe4..7a65f92 100644
--- a/Utilities/cmcurl/lib/vtls/gskit.c
+++ b/Utilities/cmcurl/lib/vtls/gskit.c
@@ -293,27 +293,6 @@
 }
 
 
-static CURLcode set_callback(struct Curl_easy *data,
-                             gsk_handle h, GSK_CALLBACK_ID id, void *info)
-{
-  char buffer[STRERROR_LEN];
-  int rc = gsk_attribute_set_callback(h, id, info);
-
-  switch(rc) {
-  case GSK_OK:
-    return CURLE_OK;
-  case GSK_ERROR_IO:
-    failf(data, "gsk_attribute_set_callback() I/O error: %s",
-          Curl_strerror(errno, buffer, sizeof(buffer)));
-    break;
-  default:
-    failf(data, "gsk_attribute_set_callback(): %s", gsk_strerror(rc));
-    break;
-  }
-  return CURLE_SSL_CONNECT_ERROR;
-}
-
-
 static CURLcode set_ciphers(struct Curl_easy *data,
                             gsk_handle h, unsigned int *protoflags)
 {
@@ -796,13 +775,13 @@
     BACKEND->localfd = sockpair[0];
     BACKEND->remotefd = sockpair[1];
     setsockopt(BACKEND->localfd, SOL_SOCKET, SO_RCVBUF,
-               (void *) sobufsize, sizeof(sobufsize));
+               (void *) &sobufsize, sizeof(sobufsize));
     setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_RCVBUF,
-               (void *) sobufsize, sizeof(sobufsize));
+               (void *) &sobufsize, sizeof(sobufsize));
     setsockopt(BACKEND->localfd, SOL_SOCKET, SO_SNDBUF,
-               (void *) sobufsize, sizeof(sobufsize));
+               (void *) &sobufsize, sizeof(sobufsize));
     setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_SNDBUF,
-               (void *) sobufsize, sizeof(sobufsize));
+               (void *) &sobufsize, sizeof(sobufsize));
     curlx_nonblock(BACKEND->localfd, TRUE);
     curlx_nonblock(BACKEND->remotefd, TRUE);
   }
diff --git a/Utilities/cmcurl/lib/vtls/gtls.c b/Utilities/cmcurl/lib/vtls/gtls.c
index 0535011..dd82755 100644
--- a/Utilities/cmcurl/lib/vtls/gtls.c
+++ b/Utilities/cmcurl/lib/vtls/gtls.c
@@ -445,9 +445,10 @@
   }
 
 #ifdef USE_GNUTLS_SRP
-  if((SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) &&
+  if((SSL_SET_OPTION(primary.authtype) == CURL_TLSAUTH_SRP) &&
      Curl_allow_auth_to_host(data)) {
-    infof(data, "Using TLS-SRP username: %s", SSL_SET_OPTION(username));
+    infof(data, "Using TLS-SRP username: %s",
+          SSL_SET_OPTION(primary.username));
 
     rc = gnutls_srp_allocate_client_credentials(&backend->srp_client_cred);
     if(rc != GNUTLS_E_SUCCESS) {
@@ -457,8 +458,8 @@
     }
 
     rc = gnutls_srp_set_client_credentials(backend->srp_client_cred,
-                                           SSL_SET_OPTION(username),
-                                           SSL_SET_OPTION(password));
+                                           SSL_SET_OPTION(primary.username),
+                                           SSL_SET_OPTION(primary.password));
     if(rc != GNUTLS_E_SUCCESS) {
       failf(data, "gnutls_srp_set_client_cred() failed: %s",
             gnutls_strerror(rc));
@@ -515,19 +516,19 @@
   }
 #endif
 
-  if(SSL_SET_OPTION(CRLfile)) {
+  if(SSL_SET_OPTION(primary.CRLfile)) {
     /* set the CRL list file */
     rc = gnutls_certificate_set_x509_crl_file(backend->cred,
-                                              SSL_SET_OPTION(CRLfile),
+                                              SSL_SET_OPTION(primary.CRLfile),
                                               GNUTLS_X509_FMT_PEM);
     if(rc < 0) {
       failf(data, "error reading crl file %s (%s)",
-            SSL_SET_OPTION(CRLfile), gnutls_strerror(rc));
+            SSL_SET_OPTION(primary.CRLfile), gnutls_strerror(rc));
       return CURLE_SSL_CRL_BADFILE;
     }
     else
       infof(data, "found %d CRL in %s",
-            rc, SSL_SET_OPTION(CRLfile));
+            rc, SSL_SET_OPTION(primary.CRLfile));
   }
 
   /* Initialize TLS session as a client */
@@ -598,7 +599,7 @@
 #ifdef USE_GNUTLS_SRP
   /* Only add SRP to the cipher list if SRP is requested. Otherwise
    * GnuTLS will disable TLS 1.3 support. */
-  if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
+  if(SSL_SET_OPTION(primary.authtype) == CURL_TLSAUTH_SRP) {
     size_t len = strlen(prioritylist);
 
     char *prioritysrp = malloc(len + sizeof(GNUTLS_SRP) + 1);
@@ -693,7 +694,7 @@
 
 #ifdef USE_GNUTLS_SRP
   /* put the credentials to the current session */
-  if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
+  if(SSL_SET_OPTION(primary.authtype) == CURL_TLSAUTH_SRP) {
     rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
                                 backend->srp_client_cred);
     if(rc != GNUTLS_E_SUCCESS) {
@@ -875,8 +876,8 @@
        SSL_CONN_CONFIG(verifyhost) ||
        SSL_CONN_CONFIG(issuercert)) {
 #ifdef USE_GNUTLS_SRP
-      if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
-         && SSL_SET_OPTION(username) != NULL
+      if(SSL_SET_OPTION(primary.authtype) == CURL_TLSAUTH_SRP
+         && SSL_SET_OPTION(primary.username)
          && !SSL_CONN_CONFIG(verifypeer)
          && gnutls_cipher_get(session)) {
         /* no peer cert, but auth is ok if we have SRP user and cipher and no
@@ -934,7 +935,8 @@
         failf(data, "server certificate verification failed. CAfile: %s "
               "CRLfile: %s", SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile):
               "none",
-              SSL_SET_OPTION(CRLfile)?SSL_SET_OPTION(CRLfile):"none");
+              SSL_SET_OPTION(primary.CRLfile) ?
+              SSL_SET_OPTION(primary.CRLfile) : "none");
         return CURLE_PEER_FAILED_VERIFICATION;
       }
       else
@@ -1564,8 +1566,8 @@
   gnutls_certificate_free_credentials(backend->cred);
 
 #ifdef USE_GNUTLS_SRP
-  if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
-     && SSL_SET_OPTION(username) != NULL)
+  if(SSL_SET_OPTION(primary.authtype) == CURL_TLSAUTH_SRP
+     && SSL_SET_OPTION(primary.username) != NULL)
     gnutls_srp_free_client_credentials(backend->srp_client_cred);
 #endif
 
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls.c b/Utilities/cmcurl/lib/vtls/mbedtls.c
index 64f57c5..b60b9ca 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls.c
+++ b/Utilities/cmcurl/lib/vtls/mbedtls.c
@@ -279,7 +279,7 @@
   const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
   char * const ssl_cert = SSL_SET_OPTION(primary.clientcert);
   const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(primary.cert_blob);
-  const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile);
+  const char * const ssl_crlfile = SSL_SET_OPTION(primary.CRLfile);
   const char * const hostname = SSL_HOST_NAME();
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
   const long int port = SSL_HOST_PORT();
@@ -303,8 +303,9 @@
                               &ts_entropy, NULL, 0);
   if(ret) {
     mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
-    failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s",
+    failf(data, "mbedtls_ctr_drbg_seed returned (-0x%04X) %s",
           -ret, errorbuf);
+    return CURLE_FAILED_INIT;
   }
 #else
   mbedtls_entropy_init(&backend->entropy);
@@ -314,8 +315,9 @@
                               &backend->entropy, NULL, 0);
   if(ret) {
     mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
-    failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s",
+    failf(data, "mbedtls_ctr_drbg_seed returned (-0x%04X) %s",
           -ret, errorbuf);
+    return CURLE_FAILED_INIT;
   }
 #endif /* THREADING_SUPPORT */
 
@@ -815,8 +817,8 @@
     if(next_protocol) {
       infof(data, VTLS_INFOF_ALPN_ACCEPTED_1STR, next_protocol);
 #ifdef USE_HTTP2
-      if(!strncmp(next_protocol, ALPN_H2, ALPN_H2_LEN) &&
-         !next_protocol[ALPN_H2_LEN]) {
+      if(!strncmp(next_protocol, ALPN_H2, ALPN_H2_LENGTH) &&
+         !next_protocol[ALPN_H2_LENGTH]) {
         conn->negnpn = CURL_HTTP_VERSION_2;
       }
       else
@@ -1015,7 +1017,7 @@
 
   if(ret) {
     mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
-    failf(data, "Failed - mbedTLS: ctr_drbg_seed returned (-0x%04X) %s",
+    failf(data, "mbedtls_ctr_drbg_seed returned (-0x%04X) %s",
           -ret, errorbuf);
   }
   else {
@@ -1023,7 +1025,7 @@
 
     if(ret) {
       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
-      failf(data, "mbedTLS: ctr_drbg_init returned (-0x%04X) %s",
+      failf(data, "mbedtls_ctr_drbg_random returned (-0x%04X) %s",
             -ret, errorbuf);
     }
   }
diff --git a/Utilities/cmcurl/lib/vtls/nss.c b/Utilities/cmcurl/lib/vtls/nss.c
index 5b7de9f..cb0509f 100644
--- a/Utilities/cmcurl/lib/vtls/nss.c
+++ b/Utilities/cmcurl/lib/vtls/nss.c
@@ -983,6 +983,9 @@
   PR_Free(common_name);
 }
 
+/* A number of certs that will never occur in a real server handshake */
+#define TOO_MANY_CERTS 300
+
 static CURLcode display_conn_info(struct Curl_easy *data, PRFileDesc *sock)
 {
   CURLcode result = CURLE_OK;
@@ -1018,6 +1021,11 @@
         cert2 = CERT_FindCertIssuer(cert, now, certUsageSSLCA);
         while(cert2) {
           i++;
+          if(i >= TOO_MANY_CERTS) {
+            CERT_DestroyCertificate(cert2);
+            failf(data, "certificate loop");
+            return CURLE_SSL_CERTPROBLEM;
+          }
           if(cert2->isRoot) {
             CERT_DestroyCertificate(cert2);
             break;
@@ -2027,13 +2035,13 @@
     }
   }
 
-  if(SSL_SET_OPTION(CRLfile)) {
-    const CURLcode rv = nss_load_crl(SSL_SET_OPTION(CRLfile));
+  if(SSL_SET_OPTION(primary.CRLfile)) {
+    const CURLcode rv = nss_load_crl(SSL_SET_OPTION(primary.CRLfile));
     if(rv) {
       result = rv;
       goto error;
     }
-    infof(data, "  CRLfile: %s", SSL_SET_OPTION(CRLfile));
+    infof(data, "  CRLfile: %s", SSL_SET_OPTION(primary.CRLfile));
   }
 
   if(SSL_SET_OPTION(primary.clientcert)) {
diff --git a/Utilities/cmcurl/lib/vtls/openssl.c b/Utilities/cmcurl/lib/vtls/openssl.c
index 3722005..635e9c1 100644
--- a/Utilities/cmcurl/lib/vtls/openssl.c
+++ b/Utilities/cmcurl/lib/vtls/openssl.c
@@ -215,11 +215,10 @@
  * OpenSSL: supported since 1.0.2, see
  *   https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set1_groups.html
  * BoringSSL: supported since 5fd1807d95f7 (committed 2016-09-30)
- * LibreSSL: not tested.
+ * LibreSSL: since 2.5.3 (April 12, 2017)
  */
-#if ((OPENSSL_VERSION_NUMBER >= 0x10002000L) && \
-     !defined(LIBRESSL_VERSION_NUMBER)) || \
-    defined(OPENSSL_IS_BORINGSSL)
+#if (OPENSSL_VERSION_NUMBER >= 0x10002000L) ||  \
+  defined(OPENSSL_IS_BORINGSSL)
 #define HAVE_SSL_CTX_SET_EC_CURVES
 #endif
 
@@ -2663,7 +2662,7 @@
 #endif
   const long int ssl_version = SSL_CONN_CONFIG(version);
 #ifdef USE_OPENSSL_SRP
-  const enum CURL_TLSAUTH ssl_authtype = SSL_SET_OPTION(authtype);
+  const enum CURL_TLSAUTH ssl_authtype = SSL_SET_OPTION(primary.authtype);
 #endif
   char * const ssl_cert = SSL_SET_OPTION(primary.clientcert);
   const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(primary.cert_blob);
@@ -2674,7 +2673,7 @@
     (ca_info_blob ? NULL : SSL_CONN_CONFIG(CAfile));
   const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
   const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
-  const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile);
+  const char * const ssl_crlfile = SSL_SET_OPTION(primary.CRLfile);
   char error_buffer[256];
   struct ssl_backend_data *backend = connssl->backend;
   bool imported_native_ca = false;
@@ -2926,15 +2925,15 @@
 #ifdef USE_OPENSSL_SRP
   if((ssl_authtype == CURL_TLSAUTH_SRP) &&
      Curl_allow_auth_to_host(data)) {
-    char * const ssl_username = SSL_SET_OPTION(username);
-
+    char * const ssl_username = SSL_SET_OPTION(primary.username);
+    char * const ssl_password = SSL_SET_OPTION(primary.password);
     infof(data, "Using TLS-SRP username: %s", ssl_username);
 
     if(!SSL_CTX_set_srp_username(backend->ctx, ssl_username)) {
       failf(data, "Unable to set SRP user name");
       return CURLE_BAD_FUNCTION_ARGUMENT;
     }
-    if(!SSL_CTX_set_srp_password(backend->ctx, SSL_SET_OPTION(password))) {
+    if(!SSL_CTX_set_srp_password(backend->ctx, ssl_password)) {
       failf(data, "failed setting SRP password");
       return CURLE_BAD_FUNCTION_ARGUMENT;
     }
diff --git a/Utilities/cmcurl/lib/vtls/sectransp.c b/Utilities/cmcurl/lib/vtls/sectransp.c
index 8ee8fe9..2e57d83 100644
--- a/Utilities/cmcurl/lib/vtls/sectransp.c
+++ b/Utilities/cmcurl/lib/vtls/sectransp.c
@@ -2045,8 +2045,9 @@
     err = SSLSetPeerDomainName(backend->ssl_ctx, snihost, snilen);
 
     if(err != noErr) {
-      infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d",
+      failf(data, "SSL: SSLSetPeerDomainName() failed: OSStatus %d",
             err);
+      return CURLE_SSL_CONNECT_ERROR;
     }
 
     if((Curl_inet_pton(AF_INET, hostname, &addr))
diff --git a/Utilities/cmcurl/lib/vtls/vtls.c b/Utilities/cmcurl/lib/vtls/vtls.c
index a40ac06..e2d3438 100644
--- a/Utilities/cmcurl/lib/vtls/vtls.c
+++ b/Utilities/cmcurl/lib/vtls/vtls.c
@@ -132,6 +132,7 @@
 {
   if((data->version == needle->version) &&
      (data->version_max == needle->version_max) &&
+     (data->ssl_options == needle->ssl_options) &&
      (data->verifypeer == needle->verifypeer) &&
      (data->verifyhost == needle->verifyhost) &&
      (data->verifystatus == needle->verifystatus) &&
@@ -144,9 +145,15 @@
      Curl_safecmp(data->clientcert, needle->clientcert) &&
      Curl_safecmp(data->random_file, needle->random_file) &&
      Curl_safecmp(data->egdsocket, needle->egdsocket) &&
+#ifdef USE_TLS_SRP
+     Curl_safecmp(data->username, needle->username) &&
+     Curl_safecmp(data->password, needle->password) &&
+     (data->authtype == needle->authtype) &&
+#endif
      Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list) &&
      Curl_safe_strcasecompare(data->cipher_list13, needle->cipher_list13) &&
      Curl_safe_strcasecompare(data->curves, needle->curves) &&
+     Curl_safe_strcasecompare(data->CRLfile, needle->CRLfile) &&
      Curl_safe_strcasecompare(data->pinned_key, needle->pinned_key))
     return TRUE;
 
@@ -163,6 +170,10 @@
   dest->verifyhost = source->verifyhost;
   dest->verifystatus = source->verifystatus;
   dest->sessionid = source->sessionid;
+  dest->ssl_options = source->ssl_options;
+#ifdef USE_TLS_SRP
+  dest->authtype = source->authtype;
+#endif
 
   CLONE_BLOB(cert_blob);
   CLONE_BLOB(ca_info_blob);
@@ -177,6 +188,11 @@
   CLONE_STRING(cipher_list13);
   CLONE_STRING(pinned_key);
   CLONE_STRING(curves);
+  CLONE_STRING(CRLfile);
+#ifdef USE_TLS_SRP
+  CLONE_STRING(username);
+  CLONE_STRING(password);
+#endif
 
   return TRUE;
 }
@@ -196,6 +212,11 @@
   Curl_safefree(sslc->ca_info_blob);
   Curl_safefree(sslc->issuercert_blob);
   Curl_safefree(sslc->curves);
+  Curl_safefree(sslc->CRLfile);
+#ifdef USE_TLS_SRP
+  Curl_safefree(sslc->username);
+  Curl_safefree(sslc->password);
+#endif
 }
 
 #ifdef USE_SSL
diff --git a/Utilities/cmcurl/lib/vtls/x509asn1.c b/Utilities/cmcurl/lib/vtls/x509asn1.c
index f64acb8..dfb9386 100644
--- a/Utilities/cmcurl/lib/vtls/x509asn1.c
+++ b/Utilities/cmcurl/lib/vtls/x509asn1.c
@@ -945,6 +945,24 @@
 
   /* Generate all information records for the public key. */
 
+  if(strcasecompare(algo, "ecPublicKey")) {
+    /*
+     * ECC public key is all the data, a value of type BIT STRING mapped to
+     * OCTET STRING and should not be parsed as an ASN.1 value.
+     */
+    const unsigned long len =
+      (unsigned long)((pubkey->end - pubkey->beg - 2) * 4);
+    if(!certnum)
+      infof(data, "   ECC Public Key (%lu bits)", len);
+    if(data->set.ssl.certinfo) {
+      char q[sizeof(len) * 8 / 3 + 1];
+      msnprintf(q, sizeof(q), "%lu", len);
+      if(Curl_ssl_push_certinfo(data, certnum, "ECC Public Key", q))
+        return 1;
+    }
+    return do_pubkey_field(data, certnum, "ecPublicKey", pubkey);
+  }
+
   /* Get the public key (single element). */
   if(!getASN1Element(&pk, pubkey->beg + 1, pubkey->end))
     return 1;
@@ -971,14 +989,10 @@
     if(!certnum)
       infof(data, "   RSA Public Key (%lu bits)", len);
     if(data->set.ssl.certinfo) {
-      q = curl_maprintf("%lu", len);
-      if(q) {
-        CURLcode result =
-          Curl_ssl_push_certinfo(data, certnum, "RSA Public Key", q);
-        free((char *) q);
-        if(result)
-          return 1;
-      }
+      char r[sizeof(len) * 8 / 3 + 1];
+      msnprintf(r, sizeof(r), "%lu", len);
+      if(Curl_ssl_push_certinfo(data, certnum, "RSA Public Key", r))
+        return 1;
     }
     /* Generate coefficients. */
     if(do_pubkey_field(data, certnum, "rsa(n)", &elem))