diff options
134 files changed, 1564 insertions, 558 deletions
diff --git a/Help/command/file.rst b/Help/command/file.rst index 2cf938b..953172b 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -449,7 +449,7 @@ modified. file(GENERATE OUTPUT output-file <INPUT input-file|CONTENT content> - [CONDITION expression]) + [CONDITION expression] [TARGET target]) Generate an output file for each build configuration supported by the current :manual:`CMake Generator <cmake-generators(7)>`. Evaluate @@ -479,6 +479,10 @@ from the input content to produce the output content. The options are: with respect to the value of :variable:`CMAKE_CURRENT_BINARY_DIR`. See policy :policy:`CMP0070`. +``TARGET <target>`` + Specify target which to use when evaluating generator expressions. Enables + use of generator expressions requiring a target. + Exactly one ``CONTENT`` or ``INPUT`` option must be given. A specific ``OUTPUT`` file may be named by at most one invocation of ``file(GENERATE)``. Generated files are modified and their timestamp updated on subsequent cmake diff --git a/Help/generator/Visual Studio 14 2015.rst b/Help/generator/Visual Studio 14 2015.rst index 401845d..5b319bb 100644 --- a/Help/generator/Visual Studio 14 2015.rst +++ b/Help/generator/Visual Studio 14 2015.rst @@ -45,3 +45,19 @@ via the :manual:`cmake(1)` ``-T`` option, to specify another toolset. By default this generator uses the 32-bit variant even on a 64-bit host. .. include:: VS_TOOLSET_HOST_ARCH.txt + +.. _`Windows 10 SDK Maximum Version for VS 2015`: + +Windows 10 SDK Maximum Version for VS 2015 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Microsoft stated in a "Windows 10 October 2018 Update" blog post that Windows +10 SDK versions (15063, 16299, 17134, 17763) are not supported by VS 2015 and +are only supported by VS 2017 and later. Therefore by default CMake +automatically ignores Windows 10 SDKs beyond ``10.0.14393.0``. + +However, there are other recommendations for certain driver/Win32 builds that +indicate otherwise. A user can override this behavior by either setting the +:variable:`CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM` to a false value +or setting the :variable:`CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM` to +the string value of the required maximum (e.g. ``10.0.15063.0``). diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index 2627e0c..ce8969b 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -57,6 +57,7 @@ Policies Introduced by CMake 3.19 .. toctree:: :maxdepth: 1 + CMP0111: An imported target with a missing location fails during generation. </policy/CMP0111> CMP0110: add_test() supports arbitrary characters in test names. </policy/CMP0110> CMP0109: find_program() requires permission to execute but not to read. </policy/CMP0109> diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 4b40917..53cdd0b 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -124,6 +124,7 @@ Variables that Provide Information /variable/CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE /variable/CMAKE_VS_PLATFORM_TOOLSET_VERSION /variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION + /variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM /variable/CMAKE_XCODE_GENERATE_SCHEME /variable/CMAKE_XCODE_PLATFORM_TOOLSET /variable/PROJECT-NAME_BINARY_DIR diff --git a/Help/policy/CMP0111.rst b/Help/policy/CMP0111.rst new file mode 100644 index 0000000..37e5ad5 --- /dev/null +++ b/Help/policy/CMP0111.rst @@ -0,0 +1,20 @@ +CMP0111 +------- + +.. versionadded:: 3.19 + +An imported target with a missing location fails during generation. + +Prior to this the location would be generated as ``<TARGET_NAME>-NOTFOUND``, +which would result in build failures. + +The ``OLD`` behavior of this policy is to generate the location of an imported +unknown, static or shared library target as ``<TARGET_NAME>-NOTFOUND`` if not +set. +The ``NEW`` behavior is to raise an error. + +This policy was introduced in CMake version 3.19. CMake version |release| +warns when the policy is not set and uses ``OLD`` behavior. Use the +:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly. + +.. include:: DEPRECATED.txt diff --git a/Help/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.rst b/Help/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.rst index 9b53282..bac3274 100644 --- a/Help/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.rst +++ b/Help/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.rst @@ -13,8 +13,14 @@ The features listed here may be used with the :command:`target_compile_features` command. See the :manual:`cmake-compile-features(7)` manual for information on compile features and a list of supported compilers. +The features known to this version of CMake are listed below. -The features known to this version of CMake are: +High level meta features indicating C++ standard support +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following meta features indicate general support for the associated +language standard. It reflects the language support claimed by the compiler, +but it does not necessarily imply complete conformance to that standard. ``cxx_std_98`` Compiler mode is at least C++ 98. @@ -31,10 +37,29 @@ The features known to this version of CMake are: ``cxx_std_20`` Compiler mode is at least C++ 20. -``cxx_aggregate_default_initializers`` - Aggregate default initializers, as defined in N3605_. - .. _N3605: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3605.html +Low level individual compile features +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For C++ 11 and C++ 14, compilers were sometimes slow to implement certain +language features. CMake provided some individual compile features to help +projects determine whether specific features were available. These individual +features are now less relevant and projects should generally prefer to use the +high level meta features instead. Individual compile features are not provided +for C++ 17 or later. + +See the :manual:`cmake-compile-features(7)` manual for further discussion of +the use of individual compile features. + +Individual features from C++ 98 +""""""""""""""""""""""""""""""" + +``cxx_template_template_parameters`` + Template template parameters, as defined in ``ISO/IEC 14882:1998``. + + +Individual features from C++ 11 +""""""""""""""""""""""""""""""" ``cxx_alias_templates`` Template aliases, as defined in N2258_. @@ -56,30 +81,16 @@ The features known to this version of CMake are: .. _N2761: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2761.pdf -``cxx_attribute_deprecated`` - ``[[deprecated]]`` attribute, as defined in N3760_. - - .. _N3760: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3760.html - ``cxx_auto_type`` Automatic type deduction, as defined in N1984_. .. _N1984: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1984.pdf -``cxx_binary_literals`` - Binary literals, as defined in N3472_. - - .. _N3472: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3472.pdf - ``cxx_constexpr`` Constant expressions, as defined in N2235_. .. _N2235: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf -``cxx_contextual_conversions`` - Contextual conversions, as defined in N3323_. - - .. _N3323: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3323.pdf ``cxx_decltype_incomplete_return_types`` Decltype on incomplete return types, as defined in N3276_. @@ -91,11 +102,6 @@ The features known to this version of CMake are: .. _N2343: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2343.pdf -``cxx_decltype_auto`` - ``decltype(auto)`` semantics, as defined in N3638_. - - .. _N3638: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3638.html - ``cxx_default_function_template_args`` Default template arguments for function templates, as defined in DR226_ @@ -121,11 +127,6 @@ The features known to this version of CMake are: .. _N2346: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm -``cxx_digit_separators`` - Digit separators, as defined in N3781_. - - .. _N3781: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3781.pdf - ``cxx_enum_forward_declarations`` Enum forward declarations, as defined in N2764_. @@ -163,11 +164,6 @@ The features known to this version of CMake are: .. _N2672: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2672.htm -``cxx_generic_lambdas`` - Generic lambdas, as defined in N3649_. - - .. _N3649: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3649.html - ``cxx_inheriting_constructors`` Inheriting constructors, as defined in N2540_. @@ -183,11 +179,6 @@ The features known to this version of CMake are: .. _N2927: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2927.pdf -``cxx_lambda_init_captures`` - Initialized lambda captures, as defined in N3648_. - - .. _N3648: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3648.html - ``cxx_local_type_template_args`` Local and unnamed types as template arguments, as defined in N2657_. @@ -236,16 +227,6 @@ The features known to this version of CMake are: .. _N2439: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2439.htm -``cxx_relaxed_constexpr`` - Relaxed constexpr, as defined in N3652_. - - .. _N3652: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3652.html - -``cxx_return_type_deduction`` - Return type deduction on normal functions, as defined in N3386_. - - .. _N3386: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3386.html - ``cxx_right_angle_brackets`` Right angle bracket parsing, as defined in N1757_. @@ -301,11 +282,6 @@ The features known to this version of CMake are: .. _N2765: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2765.pdf -``cxx_variable_templates`` - Variable templates, as defined in N3651_. - - .. _N3651: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3651.pdf - ``cxx_variadic_macros`` Variadic macros, as defined in N1653_. @@ -316,5 +292,61 @@ The features known to this version of CMake are: .. _N2242: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2242.pdf -``cxx_template_template_parameters`` - Template template parameters, as defined in ``ISO/IEC 14882:1998``. + +Individual features from C++ 14 +""""""""""""""""""""""""""""""" + +``cxx_aggregate_default_initializers`` + Aggregate default initializers, as defined in N3605_. + + .. _N3605: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3605.html + +``cxx_attribute_deprecated`` + ``[[deprecated]]`` attribute, as defined in N3760_. + + .. _N3760: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3760.html + +``cxx_binary_literals`` + Binary literals, as defined in N3472_. + + .. _N3472: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3472.pdf + +``cxx_contextual_conversions`` + Contextual conversions, as defined in N3323_. + + .. _N3323: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3323.pdf + +``cxx_decltype_auto`` + ``decltype(auto)`` semantics, as defined in N3638_. + + .. _N3638: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3638.html + +``cxx_digit_separators`` + Digit separators, as defined in N3781_. + + .. _N3781: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3781.pdf + +``cxx_generic_lambdas`` + Generic lambdas, as defined in N3649_. + + .. _N3649: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3649.html + +``cxx_lambda_init_captures`` + Initialized lambda captures, as defined in N3648_. + + .. _N3648: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3648.html + +``cxx_relaxed_constexpr`` + Relaxed constexpr, as defined in N3652_. + + .. _N3652: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3652.html + +``cxx_return_type_deduction`` + Return type deduction on normal functions, as defined in N3386_. + + .. _N3386: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3386.html + +``cxx_variable_templates`` + Variable templates, as defined in N3651_. + + .. _N3651: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3651.pdf diff --git a/Help/prop_tgt/WIN32_EXECUTABLE.rst b/Help/prop_tgt/WIN32_EXECUTABLE.rst index 060d166..eac28ae 100644 --- a/Help/prop_tgt/WIN32_EXECUTABLE.rst +++ b/Help/prop_tgt/WIN32_EXECUTABLE.rst @@ -11,3 +11,7 @@ configure use of the Microsoft Foundation Classes (MFC) for WinMain executables. This property is initialized by the value of the :variable:`CMAKE_WIN32_EXECUTABLE` variable if it is set when a target is created. + +This property supports +:manual:`generator expressions <cmake-generator-expressions(7)>`, except if the +target is managed (contains C# code.) diff --git a/Help/release/3.18.rst b/Help/release/3.18.rst index f199244..099e9b5 100644 --- a/Help/release/3.18.rst +++ b/Help/release/3.18.rst @@ -265,8 +265,9 @@ Other environment variable to customize colors. * The :manual:`Compile Features <cmake-compile-features(7)>` functionality - is now aware of the availability of C11 features in MSVC 19.27 and above, - including support for the ``c_restrict`` feature and the ``-std:c11`` flag. + is now aware of the availability of C11 features in MSVC 19.27 and 19.28, + including support for the ``c_restrict``, ``c_static_assert`` features and + the ``-std:c11`` flag. Deprecated and Removed Features =============================== @@ -353,4 +354,10 @@ Changes made since CMake 3.18.0 include the following. This restores compatibility with behavior of CMake 3.15 and below. * The :manual:`Compile Features <cmake-compile-features(7)>` functionality - was updated for MSVC 19.27 as mentioned above. + was updated for MSVC 19.27 as mentioned above (``c_restrict``). + +3.18.3 +------ + +* The :manual:`Compile Features <cmake-compile-features(7)>` functionality + was updated for MSVC 19.28 as mentioned above (``c_static_assert``). diff --git a/Help/release/dev/asm-osx-architectures.rst b/Help/release/dev/asm-osx-architectures.rst new file mode 100644 index 0000000..d8d0660 --- /dev/null +++ b/Help/release/dev/asm-osx-architectures.rst @@ -0,0 +1,5 @@ +asm-osx-architectures +--------------------- + +* The :prop_tgt:`OSX_ARCHITECTURES` target property is now respected for the + ``ASM`` language. diff --git a/Help/release/dev/file-generate-target.rst b/Help/release/dev/file-generate-target.rst new file mode 100644 index 0000000..09fb460 --- /dev/null +++ b/Help/release/dev/file-generate-target.rst @@ -0,0 +1,5 @@ +file-generate-target +-------------------- + +* The :command:`file(GENERATE)` command gained a new ``TARGET`` keyword to + support resolving target-dependent generator expressions. diff --git a/Help/release/dev/imported-target-location-required.rst b/Help/release/dev/imported-target-location-required.rst new file mode 100644 index 0000000..3625242 --- /dev/null +++ b/Help/release/dev/imported-target-location-required.rst @@ -0,0 +1,5 @@ +imported-target-location-required +--------------------------------- + +* An imported target with a missing location now fails during generation if the + location is used. See policy :policy:`CMP0111`. diff --git a/Help/release/dev/vs-win-sdk-custom-max.rst b/Help/release/dev/vs-win-sdk-custom-max.rst new file mode 100644 index 0000000..bd19fc8 --- /dev/null +++ b/Help/release/dev/vs-win-sdk-custom-max.rst @@ -0,0 +1,6 @@ +vs-win-sdk-custom-max +--------------------- + +* A :variable:`CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM` variable + was added to tell the :ref:`Visual Studio Generators` what maximumm + version of the Windows SDK to choose. diff --git a/Help/release/dev/win32-executable-genex.rst b/Help/release/dev/win32-executable-genex.rst new file mode 100644 index 0000000..f03203d --- /dev/null +++ b/Help/release/dev/win32-executable-genex.rst @@ -0,0 +1,5 @@ +win32-executable-genex +---------------------- + +* The :prop_tgt:`WIN32_EXECUTABLE` target property now supports + :manual:`generator expressions <cmake-generator-expressions(7)>`. diff --git a/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION.rst b/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION.rst index cb55bc2..eb71049 100644 --- a/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION.rst +++ b/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION.rst @@ -17,3 +17,5 @@ One may set a ``CMAKE_WINDOWS_KITS_10_DIR`` *environment variable* to an absolute path to tell CMake to look for Windows 10 SDKs in a custom location. The specified directory is expected to contain ``Include/10.0.*`` directories. + +See also :variable:`CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM`. diff --git a/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM.rst b/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM.rst new file mode 100644 index 0000000..591ea91 --- /dev/null +++ b/Help/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM.rst @@ -0,0 +1,14 @@ +CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM +------------------------------------------------ + +.. versionadded:: 3.19 + +Override the :ref:`Windows 10 SDK Maximum Version for VS 2015`. + +The :variable:`CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM` variable may +be set to a false value (e.g. ``OFF``, ``FALSE``, or ``0``) or the SDK version +to use as the maximum (e.g. ``10.0.14393.0``). If unset, the default depends +on which version of Visual Studio is targeted by the current generator. + +This can be used in conjunction with :variable:`CMAKE_SYSTEM_VERSION`, which +CMake uses to select :variable:`CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION`. diff --git a/Modules/Compiler/MSVC-C-FeatureTests.cmake b/Modules/Compiler/MSVC-C-FeatureTests.cmake index 862bff3..4024c12 100644 --- a/Modules/Compiler/MSVC-C-FeatureTests.cmake +++ b/Modules/Compiler/MSVC-C-FeatureTests.cmake @@ -1,9 +1,7 @@ set(_cmake_oldestSupported "_MSC_VER >= 1600") -# Not yet supported: -#set(_cmake_feature_test_c_static_assert "") - set(_cmake_feature_test_c_restrict "_MSC_VER >= 1927") +set(_cmake_feature_test_c_static_assert "_MSC_VER >= 1928") set(_cmake_feature_test_c_variadic_macros "${_cmake_oldestSupported}") set(_cmake_feature_test_c_function_prototypes "${_cmake_oldestSupported}") diff --git a/Modules/Compiler/MSVC-C.cmake b/Modules/Compiler/MSVC-C.cmake index a05e6a0..31ae7fd 100644 --- a/Modules/Compiler/MSVC-C.cmake +++ b/Modules/Compiler/MSVC-C.cmake @@ -51,6 +51,10 @@ macro(cmake_record_c_compile_features) list(APPEND CMAKE_C_COMPILE_FEATURES c_restrict) list(APPEND CMAKE_C99_COMPILE_FEATURES c_restrict) endif() + if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.28) + list(APPEND CMAKE_C_COMPILE_FEATURES c_static_assert) + list(APPEND CMAKE_C11_COMPILE_FEATURES c_static_assert) + endif() set(_result 0) # expected by cmake_determine_compile_features endmacro() diff --git a/Modules/Compiler/NVIDIA-CUDA.cmake b/Modules/Compiler/NVIDIA-CUDA.cmake index feb5ecc..3187294 100644 --- a/Modules/Compiler/NVIDIA-CUDA.cmake +++ b/Modules/Compiler/NVIDIA-CUDA.cmake @@ -68,20 +68,22 @@ if(UNIX) endif() if("x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC") + # MSVC requires c++14 as the minimum level set(CMAKE_CUDA03_STANDARD_COMPILE_OPTION "") set(CMAKE_CUDA03_EXTENSION_COMPILE_OPTION "") + # MSVC requires c++14 as the minimum level set(CMAKE_CUDA11_STANDARD_COMPILE_OPTION "") set(CMAKE_CUDA11_EXTENSION_COMPILE_OPTION "") if (NOT CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 9.0) - set(CMAKE_CUDA14_STANDARD_COMPILE_OPTION "") - set(CMAKE_CUDA14_EXTENSION_COMPILE_OPTION "") + set(CMAKE_CUDA14_STANDARD_COMPILE_OPTION "-std=c++14") + set(CMAKE_CUDA14_EXTENSION_COMPILE_OPTION "-std=c++14") endif() if (NOT CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 11.0) - set(CMAKE_CUDA17_STANDARD_COMPILE_OPTION "") - set(CMAKE_CUDA17_EXTENSION_COMPILE_OPTION "") + set(CMAKE_CUDA17_STANDARD_COMPILE_OPTION "-std=c++17") + set(CMAKE_CUDA17_EXTENSION_COMPILE_OPTION "-std=c++17") endif() else() diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake index c85e2d8..acf2a94 100644 --- a/Modules/FetchContent.cmake +++ b/Modules/FetchContent.cmake @@ -1038,6 +1038,11 @@ function(FetchContent_Populate contentName) message(FATAL_ERROR "Content ${contentName} already populated in ${${contentNameLower}_SOURCE_DIR}") endif() + __FetchContent_getSavedDetails(${contentName} contentDetails) + if("${contentDetails}" STREQUAL "") + message(FATAL_ERROR "No details have been set for content: ${contentName}") + endif() + string(TOUPPER ${contentName} contentNameUpper) set(FETCHCONTENT_SOURCE_DIR_${contentNameUpper} "${FETCHCONTENT_SOURCE_DIR_${contentNameUpper}}" @@ -1045,14 +1050,35 @@ function(FetchContent_Populate contentName) if(FETCHCONTENT_SOURCE_DIR_${contentNameUpper}) # The source directory has been explicitly provided in the cache, - # so no population is required + # so no population is required. The build directory may still be specified + # by the declared details though. set(${contentNameLower}_SOURCE_DIR "${FETCHCONTENT_SOURCE_DIR_${contentNameUpper}}") - set(${contentNameLower}_BINARY_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-build") + + cmake_parse_arguments(savedDetails "" "BINARY_DIR" "" ${contentDetails}) + + if(savedDetails_BINARY_DIR) + set(${contentNameLower}_BINARY_DIR ${savedDetails_BINARY_DIR}) + else() + set(${contentNameLower}_BINARY_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-build") + endif() elseif(FETCHCONTENT_FULLY_DISCONNECTED) - # Bypass population and assume source is already there from a previous run - set(${contentNameLower}_SOURCE_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-src") - set(${contentNameLower}_BINARY_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-build") + # Bypass population and assume source is already there from a previous run. + # Declared details may override the default source or build directories. + + cmake_parse_arguments(savedDetails "" "SOURCE_DIR;BINARY_DIR" "" ${contentDetails}) + + if(savedDetails_SOURCE_DIR) + set(${contentNameLower}_SOURCE_DIR ${savedDetails_SOURCE_DIR}) + else() + set(${contentNameLower}_SOURCE_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-src") + endif() + + if(savedDetails_BINARY_DIR) + set(${contentNameLower}_BINARY_DIR ${savedDetails_BINARY_DIR}) + else() + set(${contentNameLower}_BINARY_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-build") + endif() else() # Support both a global "disconnect all updates" and a per-content @@ -1072,11 +1098,6 @@ function(FetchContent_Populate contentName) unset(quietFlag) endif() - __FetchContent_getSavedDetails(${contentName} contentDetails) - if("${contentDetails}" STREQUAL "") - message(FATAL_ERROR "No details have been set for content: ${contentName}") - endif() - set(__detailsQuoted) foreach(__item IN LISTS contentDetails) string(APPEND __detailsQuoted " [==[${__item}]==]") diff --git a/Modules/FindJNI.cmake b/Modules/FindJNI.cmake index 3a5bd31..eff815d 100644 --- a/Modules/FindJNI.cmake +++ b/Modules/FindJNI.cmake @@ -59,6 +59,8 @@ macro(java_append_library_directories _var) endif() elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^i.86$") set(_java_libarch "i386") + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64") + set(_java_libarch "arm64") elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^alpha") set(_java_libarch "alpha") elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm") diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 11555e7..439e483 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 18) -set(CMake_VERSION_PATCH 20200821) +set(CMake_VERSION_PATCH 20200827) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx index 511168b..df68033 100644 --- a/Source/cmExtraCodeBlocksGenerator.cxx +++ b/Source/cmExtraCodeBlocksGenerator.cxx @@ -689,7 +689,8 @@ int cmExtraCodeBlocksGenerator::GetCBTargetType(cmGeneratorTarget* target) { switch (target->GetType()) { case cmStateEnums::EXECUTABLE: - if ((target->GetPropertyAsBool("WIN32_EXECUTABLE")) || + if ((target->IsWin32Executable( + target->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"))) || (target->GetPropertyAsBool("MACOSX_BUNDLE"))) { return 0; } diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 8d20d35..550ad6e 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -2240,6 +2240,7 @@ bool HandleUploadCommand(std::vector<std::string> const& args, } void AddEvaluationFile(const std::string& inputName, + const std::string& targetName, const std::string& outputExpr, const std::string& condition, bool inputIsContent, cmExecutionStatus& status) @@ -2255,7 +2256,8 @@ void AddEvaluationFile(const std::string& inputName, conditionGe.Parse(condition); status.GetMakefile().AddEvaluationFile( - inputName, std::move(outputCge), std::move(conditionCge), inputIsContent); + inputName, targetName, std::move(outputCge), std::move(conditionCge), + inputIsContent); } bool HandleGenerateCommand(std::vector<std::string> const& args, @@ -2269,23 +2271,36 @@ bool HandleGenerateCommand(std::vector<std::string> const& args, status.SetError("Incorrect arguments to GENERATE subcommand."); return false; } + std::string condition; - if (args.size() > 5) { - if (args[5] != "CONDITION") { + std::string target; + + for (std::size_t i = 5; i < args.size();) { + const std::string& arg = args[i++]; + + if (args.size() - i == 0) { status.SetError("Incorrect arguments to GENERATE subcommand."); return false; } - if (args.size() != 7) { - status.SetError("Incorrect arguments to GENERATE subcommand."); + + const std::string& value = args[i++]; + + if (value.empty()) { + status.SetError( + arg + " of sub-command GENERATE must not be empty if specified."); return false; } - condition = args[6]; - if (condition.empty()) { - status.SetError("CONDITION of sub-command GENERATE must not be empty if " - "specified."); + + if (arg == "CONDITION") { + condition = value; + } else if (arg == "TARGET") { + target = value; + } else { + status.SetError("Unknown argument to GENERATE subcommand."); return false; } } + std::string output = args[2]; const bool inputIsContent = args[3] != "INPUT"; if (inputIsContent && args[3] != "CONTENT") { @@ -2294,7 +2309,7 @@ bool HandleGenerateCommand(std::vector<std::string> const& args, } std::string input = args[4]; - AddEvaluationFile(input, output, condition, inputIsContent, status); + AddEvaluationFile(input, target, output, condition, inputIsContent, status); return true; } diff --git a/Source/cmGeneratorExpressionEvaluationFile.cxx b/Source/cmGeneratorExpressionEvaluationFile.cxx index 6647e62..9e5023d 100644 --- a/Source/cmGeneratorExpressionEvaluationFile.cxx +++ b/Source/cmGeneratorExpressionEvaluationFile.cxx @@ -19,11 +19,12 @@ #include "cmSystemTools.h" cmGeneratorExpressionEvaluationFile::cmGeneratorExpressionEvaluationFile( - std::string input, + std::string input, std::string target, std::unique_ptr<cmCompiledGeneratorExpression> outputFileExpr, std::unique_ptr<cmCompiledGeneratorExpression> condition, bool inputIsContent, cmPolicies::PolicyStatus policyStatusCMP0070) : Input(std::move(input)) + , Target(std::move(target)) , OutputFileExpr(std::move(outputFileExpr)) , Condition(std::move(condition)) , InputIsContent(inputIsContent) @@ -37,9 +38,10 @@ void cmGeneratorExpressionEvaluationFile::Generate( std::map<std::string, std::string>& outputFiles, mode_t perm) { std::string rawCondition = this->Condition->GetInput(); + cmGeneratorTarget* target = lg->FindGeneratorTargetToUse(Target); if (!rawCondition.empty()) { std::string condResult = - this->Condition->Evaluate(lg, config, nullptr, nullptr, nullptr, lang); + this->Condition->Evaluate(lg, config, target, nullptr, nullptr, lang); if (condResult == "0") { return; } @@ -54,9 +56,10 @@ void cmGeneratorExpressionEvaluationFile::Generate( } } - const std::string outputFileName = this->GetOutputFileName(lg, config, lang); + const std::string outputFileName = + this->GetOutputFileName(lg, target, config, lang); const std::string& outputContent = - inputExpression->Evaluate(lg, config, nullptr, nullptr, nullptr, lang); + inputExpression->Evaluate(lg, config, target, nullptr, nullptr, lang); auto it = outputFiles.find(outputFileName); @@ -91,10 +94,11 @@ void cmGeneratorExpressionEvaluationFile::CreateOutputFile( { std::vector<std::string> enabledLanguages; cmGlobalGenerator* gg = lg->GetGlobalGenerator(); + cmGeneratorTarget* target = lg->FindGeneratorTargetToUse(Target); gg->GetEnabledLanguages(enabledLanguages); for (std::string const& le : enabledLanguages) { - std::string const name = this->GetOutputFileName(lg, config, le); + std::string const name = this->GetOutputFileName(lg, target, config, le); cmSourceFile* sf = lg->GetMakefile()->GetOrCreateSource( name, false, cmSourceFileLocationKind::Known); // Tell TraceDependencies that the file is not expected to exist @@ -176,10 +180,11 @@ std::string cmGeneratorExpressionEvaluationFile::GetInputFileName( } std::string cmGeneratorExpressionEvaluationFile::GetOutputFileName( - cmLocalGenerator* lg, const std::string& config, const std::string& lang) + cmLocalGenerator* lg, cmGeneratorTarget* target, const std::string& config, + const std::string& lang) { - std::string outputFileName = this->OutputFileExpr->Evaluate( - lg, config, nullptr, nullptr, nullptr, lang); + std::string outputFileName = + this->OutputFileExpr->Evaluate(lg, config, target, nullptr, nullptr, lang); if (cmSystemTools::FileIsFullPath(outputFileName)) { outputFileName = cmSystemTools::CollapseFullPath(outputFileName); diff --git a/Source/cmGeneratorExpressionEvaluationFile.h b/Source/cmGeneratorExpressionEvaluationFile.h index a258a2d..caa8064 100644 --- a/Source/cmGeneratorExpressionEvaluationFile.h +++ b/Source/cmGeneratorExpressionEvaluationFile.h @@ -15,13 +15,14 @@ #include "cmGeneratorExpression.h" #include "cmPolicies.h" +class cmGeneratorTarget; class cmLocalGenerator; class cmGeneratorExpressionEvaluationFile { public: cmGeneratorExpressionEvaluationFile( - std::string input, + std::string input, std::string target, std::unique_ptr<cmCompiledGeneratorExpression> outputFileExpr, std::unique_ptr<cmCompiledGeneratorExpression> condition, bool inputIsContent, cmPolicies::PolicyStatus policyStatusCMP0070); @@ -40,6 +41,7 @@ private: std::string GetInputFileName(cmLocalGenerator* lg); std::string GetOutputFileName(cmLocalGenerator* lg, + cmGeneratorTarget* target, const std::string& config, const std::string& lang); enum PathRole @@ -52,6 +54,7 @@ private: private: const std::string Input; + const std::string Target; const std::unique_ptr<cmCompiledGeneratorExpression> OutputFileExpr; const std::unique_ptr<cmCompiledGeneratorExpression> Condition; std::vector<std::string> Files; diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 9611e14..7c526a0 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -2266,6 +2266,12 @@ bool cmGeneratorTarget::IsBundleOnApple() const this->IsCFBundleOnApple(); } +bool cmGeneratorTarget::IsWin32Executable(const std::string& config) const +{ + return cmIsOn(cmGeneratorExpression::Evaluate( + this->GetSafeProperty("WIN32_EXECUTABLE"), this->LocalGenerator, config)); +} + std::string cmGeneratorTarget::GetCFBundleDirectory( const std::string& config, BundleDirectoryLevel level) const { diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 69c5faf..544b27a 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -284,6 +284,9 @@ public: or CFBundle on Apple. */ bool IsBundleOnApple() const; + /** Return whether this target is a Win32 executable */ + bool IsWin32Executable(const std::string& config) const; + /** Get the full name of the target according to the settings in its makefile. */ std::string GetFullName(const std::string& config, diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index cad5d1f..a192ffd 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -335,13 +335,13 @@ bool cmGlobalGenerator::CheckTargetsForType() const bool failed = false; for (const auto& generator : this->LocalGenerators) { for (const auto& target : generator->GetGeneratorTargets()) { - if (target->GetType() == cmStateEnums::EXECUTABLE && - target->GetPropertyAsBool("WIN32_EXECUTABLE")) { + if (target->GetType() == cmStateEnums::EXECUTABLE) { std::vector<std::string> const& configs = target->Makefile->GetGeneratorConfigs( cmMakefile::IncludeEmptyConfig); for (std::string const& config : configs) { - if (target->GetLinkerLanguage(config) == "Swift") { + if (target->IsWin32Executable(config) && + target->GetLinkerLanguage(config) == "Swift") { this->GetCMakeInstance()->IssueMessage( MessageType::FATAL_ERROR, "WIN32_EXECUTABLE property is not supported on Swift " diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx index 451d448..aa1b7ad 100644 --- a/Source/cmGlobalVisualStudio14Generator.cxx +++ b/Source/cmGlobalVisualStudio14Generator.cxx @@ -169,7 +169,8 @@ bool cmGlobalVisualStudio14Generator::SelectWindows10SDK(cmMakefile* mf, bool required) { // Find the default version of the Windows 10 SDK. - std::string const version = this->GetWindows10SDKVersion(); + std::string const version = this->GetWindows10SDKVersion(mf); + if (required && version.empty()) { std::ostringstream e; e << "Could not find an appropriate version of the Windows 10 SDK" @@ -233,8 +234,25 @@ bool cmGlobalVisualStudio14Generator::IsWindowsStoreToolsetInstalled() const cmSystemTools::KeyWOW64_32); } -std::string cmGlobalVisualStudio14Generator::GetWindows10SDKMaxVersion() const +std::string cmGlobalVisualStudio14Generator::GetWindows10SDKMaxVersion( + cmMakefile* mf) const { + // if the given value is set, it can either be OFF/FALSE or a valid SDK + // string + if (std::string const* value = + mf->GetDef("CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM")) { + + // If the value is some off/false value, then there is NO maximum set. + if (cmIsOff(value)) { + return std::string(); + } + // If the value is something else, trust that it is a valid SDK value. + else if (value) { + return *value; + } + // If value is an invalid pointer, leave result unchanged. + } + // The last Windows 10 SDK version that VS 2015 can target is 10.0.14393.0. // // "VS 2015 Users: The Windows 10 SDK (15063, 16299, 17134, 17763) is @@ -267,7 +285,8 @@ public: }; #endif -std::string cmGlobalVisualStudio14Generator::GetWindows10SDKVersion() +std::string cmGlobalVisualStudio14Generator::GetWindows10SDKVersion( + cmMakefile* mf) { #if defined(_WIN32) && !defined(__CYGWIN__) std::vector<std::string> win10Roots; @@ -317,8 +336,10 @@ std::string cmGlobalVisualStudio14Generator::GetWindows10SDKVersion() i = cmSystemTools::GetFilenameName(i); } - // Skip SDKs that cannot be used with our toolset. - std::string maxVersion = this->GetWindows10SDKMaxVersion(); + // Skip SDKs that cannot be used with our toolset, unless the user does not + // want to limit the highest supported SDK according to the Microsoft + // documentation. + std::string maxVersion = this->GetWindows10SDKMaxVersion(mf); if (!maxVersion.empty()) { cm::erase_if(sdks, WindowsSDKTooRecent(maxVersion)); } diff --git a/Source/cmGlobalVisualStudio14Generator.h b/Source/cmGlobalVisualStudio14Generator.h index 39353f2..2b9a649 100644 --- a/Source/cmGlobalVisualStudio14Generator.h +++ b/Source/cmGlobalVisualStudio14Generator.h @@ -43,7 +43,7 @@ protected: // Used to make sure that the Windows 10 SDK selected can work with the // version of the toolset. - virtual std::string GetWindows10SDKMaxVersion() const; + virtual std::string GetWindows10SDKMaxVersion(cmMakefile* mf) const; virtual bool SelectWindows10SDK(cmMakefile* mf, bool required); @@ -54,7 +54,7 @@ protected: // installed on the machine. bool IsWindowsDesktopToolsetInstalled() const override; - std::string GetWindows10SDKVersion(); + std::string GetWindows10SDKVersion(cmMakefile* mf); private: class Factory; diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index e2e045c..4b877ce 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -540,8 +540,8 @@ bool cmGlobalVisualStudioVersionedGenerator::IsWin81SDKInstalled() const return false; } -std::string cmGlobalVisualStudioVersionedGenerator::GetWindows10SDKMaxVersion() - const +std::string cmGlobalVisualStudioVersionedGenerator::GetWindows10SDKMaxVersion( + cmMakefile*) const { return std::string(); } diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.h b/Source/cmGlobalVisualStudioVersionedGenerator.h index d5b8337..289c35c 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.h +++ b/Source/cmGlobalVisualStudioVersionedGenerator.h @@ -57,7 +57,7 @@ protected: // Check for a Win 8 SDK known to the registry or VS installer tool. bool IsWin81SDKInstalled() const; - std::string GetWindows10SDKMaxVersion() const override; + std::string GetWindows10SDKMaxVersion(cmMakefile*) const override; std::string FindMSBuildCommand() override; std::string FindDevEnvCommand() override; diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 2380cce..40010fc 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1520,7 +1520,7 @@ void cmLocalGenerator::GetTargetFlags( return; } - if (target->GetPropertyAsBool("WIN32_EXECUTABLE")) { + if (target->IsWin32Executable(config)) { exeFlags += this->Makefile->GetSafeDefinition("CMAKE_CREATE_WIN32_EXE"); exeFlags += " "; @@ -1875,8 +1875,9 @@ void cmLocalGenerator::AddArchitectureFlags(std::string& flags, if (this->Makefile->IsOn("APPLE") && this->EmitUniversalBinaryFlags) { std::vector<std::string> archs; target->GetAppleArchs(config, archs); - if (!archs.empty() && !lang.empty() && - (lang[0] == 'C' || lang[0] == 'F' || lang[0] == 'O')) { + if (!archs.empty() && + (lang == "C" || lang == "CXX" || lang == "OBJ" || lang == "OBJCXX" || + cmHasLiteralPrefix(lang, "ASM"))) { for (std::string const& arch : archs) { if (filterArch.empty() || filterArch == arch) { flags += " -arch "; diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 50ffe8d..ee7f74c 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -1113,7 +1113,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( cmComputeLinkInformation& cli = *pcli; std::string linkLanguage = cli.GetLinkLanguage(); - bool isWin32Executable = target->GetPropertyAsBool("WIN32_EXECUTABLE"); + bool isWin32Executable = target->IsWin32Executable(configName); // Compute the variable name to lookup standard libraries for this // language. diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 5cfe5f1..d9d4ae8 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -801,15 +801,15 @@ void cmMakefile::EnforceDirectoryLevelRules() const } void cmMakefile::AddEvaluationFile( - const std::string& inputFile, + const std::string& inputFile, const std::string& targetName, std::unique_ptr<cmCompiledGeneratorExpression> outputName, std::unique_ptr<cmCompiledGeneratorExpression> condition, bool inputIsContent) { this->EvaluationFiles.push_back( cm::make_unique<cmGeneratorExpressionEvaluationFile>( - inputFile, std::move(outputName), std::move(condition), inputIsContent, - this->GetPolicyStatus(cmPolicies::CMP0070))); + inputFile, targetName, std::move(outputName), std::move(condition), + inputIsContent, this->GetPolicyStatus(cmPolicies::CMP0070))); } const std::vector<std::unique_ptr<cmGeneratorExpressionEvaluationFile>>& diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 80d80d3..69894b1 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -949,7 +949,7 @@ public: void EnforceDirectoryLevelRules() const; void AddEvaluationFile( - const std::string& inputFile, + const std::string& inputFile, const std::string& targetName, std::unique_ptr<cmCompiledGeneratorExpression> outputName, std::unique_ptr<cmCompiledGeneratorExpression> condition, bool inputIsContent); diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index bc288ac..9b5c6e6 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -371,7 +371,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) this->LocalGenerator->AddConfigVariableFlags( linkFlags, "CMAKE_EXE_LINKER_FLAGS", this->GetConfigName()); - if (this->GeneratorTarget->GetPropertyAsBool("WIN32_EXECUTABLE")) { + if (this->GeneratorTarget->IsWin32Executable( + this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"))) { this->LocalGenerator->AppendFlags( linkFlags, this->Makefile->GetSafeDefinition("CMAKE_CREATE_WIN32_EXE")); } else { diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 0c00ffb..1a12dab 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -326,7 +326,11 @@ class cmMakefile; 19, 0, cmPolicies::WARN) \ SELECT(POLICY, CMP0110, \ "add_test() supports arbitrary characters in test names.", 3, 19, 0, \ - cmPolicies::WARN) + cmPolicies::WARN) \ + SELECT(POLICY, CMP0111, \ + "An imported target with a missing location fails during " \ + "generation.", \ + 3, 19, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 06957b0..8c2cacd 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -1223,9 +1223,13 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() if (this->Moc.ExecutableTarget != nullptr) { dependencies.push_back(this->Moc.ExecutableTarget->Target->GetName()); + } else if (!this->Moc.Executable.empty()) { + dependencies.push_back(this->Moc.Executable); } if (this->Uic.ExecutableTarget != nullptr) { dependencies.push_back(this->Uic.ExecutableTarget->Target->GetName()); + } else if (!this->Uic.Executable.empty()) { + dependencies.push_back(this->Uic.Executable); } // Create the custom command that outputs the timestamp file. diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 60416a3..bea9001 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -2039,6 +2039,37 @@ std::string cmTarget::ImportedGetFullPath( } if (result.empty()) { + auto message = [&]() -> std::string { + std::string unset; + std::string configuration; + + if (artifact == cmStateEnums::RuntimeBinaryArtifact) { + unset = "IMPORTED_LOCATION"; + } else if (artifact == cmStateEnums::ImportLibraryArtifact) { + unset = "IMPORTED_IMPLIB"; + } + + if (!config.empty()) { + configuration = cmStrCat(" configuration \"", config, "\""); + } + + return cmStrCat(unset, " not set for imported target \"", + this->GetName(), "\"", configuration, "."); + }; + + switch (this->GetPolicyStatus(cmPolicies::CMP0111)) { + case cmPolicies::WARN: + impl->Makefile->IssueMessage( + MessageType::AUTHOR_WARNING, + cmPolicies::GetPolicyWarning(cmPolicies::CMP0111) + "\n" + + message()); + CM_FALLTHROUGH; + case cmPolicies::OLD: + break; + default: + impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, message()); + } + result = cmStrCat(this->GetName(), "-NOTFOUND"); } return result; diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index db9dc53..fa6ad47 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -595,14 +595,24 @@ void cmVisualStudio10TargetGenerator::Generate() case cmStateEnums::MODULE_LIBRARY: outputType = "Module"; break; - case cmStateEnums::EXECUTABLE: - if (this->GeneratorTarget->Target->GetPropertyAsBool( - "WIN32_EXECUTABLE")) { + case cmStateEnums::EXECUTABLE: { + auto const win32 = + this->GeneratorTarget->GetSafeProperty("WIN32_EXECUTABLE"); + if (win32.find("$<") != std::string::npos) { + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat( + "Target \"", this->GeneratorTarget->GetName(), + "\" has a generator expression in its WIN32_EXECUTABLE " + "property. This is not supported on managed executables.")); + return; + } + if (cmIsOn(win32)) { outputType = "WinExe"; } else { outputType = "Exe"; } - break; + } break; case cmStateEnums::UTILITY: case cmStateEnums::INTERFACE_LIBRARY: case cmStateEnums::GLOBAL_TARGET: @@ -3731,7 +3741,7 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions( } if (this->MSTools) { - if (this->GeneratorTarget->GetPropertyAsBool("WIN32_EXECUTABLE")) { + if (this->GeneratorTarget->IsWin32Executable(config)) { if (this->GlobalGenerator->TargetsWindowsCE()) { linkOptions.AddFlag("SubSystem", "WindowsCE"); if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) { diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index e4e09fa..5d4ffae 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -440,6 +440,10 @@ if(BUILD_TESTING) ADD_TEST_MACRO(CSharpOnly CSharpOnly) ADD_TEST_MACRO(CSharpLinkToCxx CSharpLinkToCxx) ADD_TEST_MACRO(CSharpLinkFromCxx CSharpLinkFromCxx) + 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\\." + ) endif() ADD_TEST_MACRO(COnly COnly) diff --git a/Tests/CSharpWin32GenEx/CMakeLists.txt b/Tests/CSharpWin32GenEx/CMakeLists.txt new file mode 100644 index 0000000..f4a8d00 --- /dev/null +++ b/Tests/CSharpWin32GenEx/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.18) +project(CSharpWin32GenEx CSharp) + +add_executable(CSharpWin32GenEx csharpwin32genex.cs) +set_property(TARGET CSharpWin32GenEx PROPERTY WIN32_EXECUTABLE $<1:1>) diff --git a/Tests/CSharpWin32GenEx/csharpwin32genex.cs b/Tests/CSharpWin32GenEx/csharpwin32genex.cs new file mode 100644 index 0000000..9892ee0 --- /dev/null +++ b/Tests/CSharpWin32GenEx/csharpwin32genex.cs @@ -0,0 +1,9 @@ +namespace CSharpWin32GenEx +{ + class CSharpWin32GenEx + { + public static void Main(string[] args) + { + } + } +} diff --git a/Tests/RunCMake/CMP0026/CMP0026-IMPORTED.cmake b/Tests/RunCMake/CMP0026/CMP0026-IMPORTED.cmake index 650c8a5..ae62e79 100644 --- a/Tests/RunCMake/CMP0026/CMP0026-IMPORTED.cmake +++ b/Tests/RunCMake/CMP0026/CMP0026-IMPORTED.cmake @@ -1,6 +1,7 @@ enable_language(CXX) +cmake_policy(SET CMP0111 OLD) add_library(someimportedlib SHARED IMPORTED) get_target_property(_loc someimportedlib LOCATION) diff --git a/Tests/RunCMake/CMP0111/CMP0111-Common.cmake b/Tests/RunCMake/CMP0111/CMP0111-Common.cmake new file mode 100644 index 0000000..564169d --- /dev/null +++ b/Tests/RunCMake/CMP0111/CMP0111-Common.cmake @@ -0,0 +1,9 @@ +# Prevent duplicate errors on some platforms. +set(CMAKE_IMPORT_LIBRARY_SUFFIX "placeholder") + +add_library(unknown_lib UNKNOWN IMPORTED) +add_library(static_lib STATIC IMPORTED) +add_library(shared_lib SHARED IMPORTED) + +add_executable(executable main.cpp) +target_link_libraries(executable unknown_lib static_lib shared_lib) diff --git a/Tests/RunCMake/CMP0111/CMP0111-NEW-result.txt b/Tests/RunCMake/CMP0111/CMP0111-NEW-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CMP0111/CMP0111-NEW-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMP0111/CMP0111-NEW-stderr.txt b/Tests/RunCMake/CMP0111/CMP0111-NEW-stderr.txt new file mode 100644 index 0000000..ba5d936 --- /dev/null +++ b/Tests/RunCMake/CMP0111/CMP0111-NEW-stderr.txt @@ -0,0 +1,7 @@ +CMake Error in CMakeLists.txt: + IMPORTED_LOCATION not set for imported target "static_lib"( configuration + ".+")?. ++ +CMake Error in CMakeLists.txt: + IMPORTED_IMPLIB not set for imported target "shared_lib"( configuration + ".+")?. diff --git a/Tests/RunCMake/CMP0111/CMP0111-NEW.cmake b/Tests/RunCMake/CMP0111/CMP0111-NEW.cmake new file mode 100644 index 0000000..d0c8dd3 --- /dev/null +++ b/Tests/RunCMake/CMP0111/CMP0111-NEW.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0111 NEW) +include(CMP0111-Common.cmake) diff --git a/Tests/RunCMake/CMP0111/CMP0111-OLD.cmake b/Tests/RunCMake/CMP0111/CMP0111-OLD.cmake new file mode 100644 index 0000000..d00847a --- /dev/null +++ b/Tests/RunCMake/CMP0111/CMP0111-OLD.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0111 OLD) +include(CMP0111-Common.cmake) diff --git a/Tests/RunCMake/CMP0111/CMP0111-WARN-stderr.txt b/Tests/RunCMake/CMP0111/CMP0111-WARN-stderr.txt new file mode 100644 index 0000000..2fe6cc8 --- /dev/null +++ b/Tests/RunCMake/CMP0111/CMP0111-WARN-stderr.txt @@ -0,0 +1,26 @@ +CMake Warning \(dev\) in CMakeLists.txt: + Policy CMP0111 is not set: An imported target with a missing location fails + during generation. Run "cmake --help-policy CMP0111" for policy details. + Use the cmake_policy command to set the policy and suppress this warning. + + IMPORTED_LOCATION not set for imported target "unknown_lib"( configuration + ".+")?. +This warning is for project developers. Use -Wno-dev to suppress it. ++ +CMake Warning \(dev\) in CMakeLists.txt: + Policy CMP0111 is not set: An imported target with a missing location fails + during generation. Run "cmake --help-policy CMP0111" for policy details. + Use the cmake_policy command to set the policy and suppress this warning. + + IMPORTED_LOCATION not set for imported target "static_lib"( configuration + ".+")?. +This warning is for project developers. Use -Wno-dev to suppress it. ++ +CMake Warning \(dev\) in CMakeLists.txt: + Policy CMP0111 is not set: An imported target with a missing location fails + during generation. Run "cmake --help-policy CMP0111" for policy details. + Use the cmake_policy command to set the policy and suppress this warning. + + IMPORTED_IMPLIB not set for imported target "shared_lib"( configuration + ".+")?. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CMP0111/CMP0111-WARN.cmake b/Tests/RunCMake/CMP0111/CMP0111-WARN.cmake new file mode 100644 index 0000000..0efe48c --- /dev/null +++ b/Tests/RunCMake/CMP0111/CMP0111-WARN.cmake @@ -0,0 +1 @@ +include(CMP0111-Common.cmake) diff --git a/Tests/RunCMake/CMP0111/CMakeLists.txt b/Tests/RunCMake/CMP0111/CMakeLists.txt new file mode 100644 index 0000000..9f19a75 --- /dev/null +++ b/Tests/RunCMake/CMP0111/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.17) +project(${RunCMake_TEST} CXX) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/CMP0111/RunCMakeTest.cmake b/Tests/RunCMake/CMP0111/RunCMakeTest.cmake new file mode 100644 index 0000000..02e420a --- /dev/null +++ b/Tests/RunCMake/CMP0111/RunCMakeTest.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +run_cmake(CMP0111-OLD) +run_cmake(CMP0111-NEW) +run_cmake(CMP0111-WARN) diff --git a/Tests/RunCMake/CMP0111/main.cpp b/Tests/RunCMake/CMP0111/main.cpp new file mode 100644 index 0000000..5047a34 --- /dev/null +++ b/Tests/RunCMake/CMP0111/main.cpp @@ -0,0 +1,3 @@ +int main() +{ +} diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index bbb1952..65e8b0b 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -124,6 +124,7 @@ if(CMake_TEST_CUDA) PROPERTY LABELS "CUDA") endif() add_RunCMake_test(CMP0106) +add_RunCMake_test(CMP0111) # The test for Policy 65 requires the use of the # CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS variable, which both the VS and Xcode @@ -732,3 +733,7 @@ add_RunCMake_test("CTestCommandExpandLists") add_RunCMake_test(PrecompileHeaders -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}) add_RunCMake_test("UnityBuild") + +if(WIN32) + add_RunCMake_test(Win32GenEx) +endif() diff --git a/Tests/RunCMake/FetchContent/DirOverrides.cmake b/Tests/RunCMake/FetchContent/DirOverrides.cmake index 50eef16..ad61a00 100644 --- a/Tests/RunCMake/FetchContent/DirOverrides.cmake +++ b/Tests/RunCMake/FetchContent/DirOverrides.cmake @@ -4,18 +4,23 @@ include(FetchContent) FetchContent_Declare( t1 SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/savedSrc - DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E make_directory <SOURCE_DIR> + BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/savedBin + DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E make_directory <SOURCE_DIR> <BINARY_DIR> ) FetchContent_Populate(t1) if(NOT IS_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/savedSrc) message(FATAL_ERROR "Saved details SOURCE_DIR override failed") endif() +if(NOT IS_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/savedBin) + message(FATAL_ERROR "Saved details BINARY_DIR override failed") +endif() # Test direct population FetchContent_Populate( t2 SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/directSrc - DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E make_directory <SOURCE_DIR> + BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/directBin + DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E make_directory <SOURCE_DIR> <BINARY_DIR> ) if(NOT IS_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/directSrc) message(FATAL_ERROR "Direct details SOURCE_DIR override failed") @@ -44,3 +49,19 @@ FetchContent_Populate( if(IS_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/savedNobuildDir-build) message(FATAL_ERROR "Direct details BINARY_DIR override failed") endif() + +# Test overriding the source directory by reusing the one from t1 +set(FETCHCONTENT_SOURCE_DIR_T5 ${CMAKE_CURRENT_BINARY_DIR}/savedSrc) +FetchContent_Declare( + t5 + SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/doesNotExist + BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/wontBeCreated + DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E false +) +FetchContent_Populate(t5) +if(NOT "${t5_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/savedSrc") + message(FATAL_ERROR "Wrong SOURCE_DIR returned: ${t5_SOURCE_DIR}") +endif() +if(NOT "${t5_BINARY_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/wontBeCreated") + message(FATAL_ERROR "Wrong BINARY_DIR returned: ${t5_BINARY_DIR}") +endif() diff --git a/Tests/RunCMake/FetchContent/DirOverridesDisconnected.cmake b/Tests/RunCMake/FetchContent/DirOverridesDisconnected.cmake new file mode 100644 index 0000000..768a82e --- /dev/null +++ b/Tests/RunCMake/FetchContent/DirOverridesDisconnected.cmake @@ -0,0 +1,18 @@ +include(FetchContent) + +# Test using saved details. We are re-using a SOURCE_DIR from a previous test +# so the download command should not be executed. +FetchContent_Declare( + t1 + SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/savedSrc + BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/savedBin + DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E false +) +FetchContent_Populate(t1) + +if(NOT "${t1_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/savedSrc") + message(FATAL_ERROR "Wrong SOURCE_DIR returned: ${t1_SOURCE_DIR}") +endif() +if(NOT "${t1_BINARY_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/savedBin") + message(FATAL_ERROR "Wrong BINARY_DIR returned: ${t1_BINARY_DIR}") +endif() diff --git a/Tests/RunCMake/FetchContent/RunCMakeTest.cmake b/Tests/RunCMake/FetchContent/RunCMakeTest.cmake index f3ed3e2..ad9e48e 100644 --- a/Tests/RunCMake/FetchContent/RunCMakeTest.cmake +++ b/Tests/RunCMake/FetchContent/RunCMakeTest.cmake @@ -10,12 +10,25 @@ run_cmake(DownloadFile) run_cmake(SameGenerator) run_cmake(VarDefinitions) run_cmake(GetProperties) -run_cmake(DirOverrides) run_cmake(UsesTerminalOverride) run_cmake(MakeAvailable) run_cmake(MakeAvailableTwice) run_cmake(MakeAvailableUndeclared) +function(run_FetchContent_DirOverrides) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/DirOverrides-build) + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + + run_cmake(DirOverrides) + + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_with_options(DirOverridesDisconnected + -D FETCHCONTENT_FULLY_DISCONNECTED=YES + ) +endfunction() +run_FetchContent_DirOverrides() + set(RunCMake_TEST_OUTPUT_MERGE 1) run_cmake(PreserveEmptyArgs) set(RunCMake_TEST_OUTPUT_MERGE 0) diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_exe.json index 312f4c5..451e8d4 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_exe.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_exe.json @@ -14,7 +14,7 @@ "backtrace": [ { "file": "^imported/CMakeLists\\.txt$", - "line": 5, + "line": 6, "command": "add_executable", "hasParent": true }, @@ -49,7 +49,7 @@ "backtrace": [ { "file": "^imported/CMakeLists\\.txt$", - "line": 5, + "line": 6, "command": "add_executable", "hasParent": true }, diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_interface_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_interface_exe.json index 7d0e6df..cbd4346 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_interface_exe.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_interface_exe.json @@ -14,7 +14,7 @@ "backtrace": [ { "file": "^imported/CMakeLists\\.txt$", - "line": 23, + "line": 29, "command": "add_executable", "hasParent": true }, @@ -49,7 +49,7 @@ "backtrace": [ { "file": "^imported/CMakeLists\\.txt$", - "line": 23, + "line": 29, "command": "add_executable", "hasParent": true }, diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_object_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_object_exe.json index 4aec524..d92a810 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_object_exe.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_object_exe.json @@ -14,7 +14,7 @@ "backtrace": [ { "file": "^imported/CMakeLists\\.txt$", - "line": 18, + "line": 24, "command": "add_executable", "hasParent": true }, @@ -49,7 +49,7 @@ "backtrace": [ { "file": "^imported/CMakeLists\\.txt$", - "line": 18, + "line": 24, "command": "add_executable", "hasParent": true }, diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_shared_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_shared_exe.json index f5846ec..1197a73 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_shared_exe.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_shared_exe.json @@ -14,7 +14,7 @@ "backtrace": [ { "file": "^imported/CMakeLists\\.txt$", - "line": 9, + "line": 14, "command": "add_executable", "hasParent": true }, @@ -49,7 +49,7 @@ "backtrace": [ { "file": "^imported/CMakeLists\\.txt$", - "line": 9, + "line": 14, "command": "add_executable", "hasParent": true }, diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_static_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_static_exe.json index 29a1695..42564e0 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_static_exe.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/link_imported_static_exe.json @@ -14,7 +14,7 @@ "backtrace": [ { "file": "^imported/CMakeLists\\.txt$", - "line": 13, + "line": 19, "command": "add_executable", "hasParent": true }, @@ -49,7 +49,7 @@ "backtrace": [ { "file": "^imported/CMakeLists\\.txt$", - "line": 13, + "line": 19, "command": "add_executable", "hasParent": true }, diff --git a/Tests/RunCMake/FileAPI/imported/CMakeLists.txt b/Tests/RunCMake/FileAPI/imported/CMakeLists.txt index d36d88b..f79d87c 100644 --- a/Tests/RunCMake/FileAPI/imported/CMakeLists.txt +++ b/Tests/RunCMake/FileAPI/imported/CMakeLists.txt @@ -1,15 +1,21 @@ project(Imported) add_library(imported_lib UNKNOWN IMPORTED) +set_target_properties(imported_lib PROPERTIES IMPORTED_LOCATION "imported_unk${CMAKE_STATIC_LIBRARY_SUFFIX}") add_executable(imported_exe IMPORTED) add_executable(link_imported_exe ../empty.c) target_link_libraries(link_imported_exe PRIVATE imported_lib) add_library(imported_shared_lib SHARED IMPORTED) +set_target_properties(imported_shared_lib PROPERTIES + IMPORTED_LOCATION "imported_shared${CMAKE_SHARED_LIBRARY_SUFFIX}" + IMPORTED_IMPLIB "imported_shared${CMAKE_IMPORT_LIBRARY_SUFFIX}" +) add_executable(link_imported_shared_exe ../empty.c) target_link_libraries(link_imported_shared_exe PRIVATE imported_shared_lib) add_library(imported_static_lib STATIC IMPORTED) +set_target_properties(imported_static_lib PROPERTIES IMPORTED_LOCATION "imported_static${CMAKE_STATIC_LIBRARY_SUFFIX}") add_executable(link_imported_static_exe ../empty.c) target_link_libraries(link_imported_static_exe PRIVATE imported_static_lib) diff --git a/Tests/RunCMake/File_Generate/RunCMakeTest.cmake b/Tests/RunCMake/File_Generate/RunCMakeTest.cmake index 770fc6e..48fb71c 100644 --- a/Tests/RunCMake/File_Generate/RunCMakeTest.cmake +++ b/Tests/RunCMake/File_Generate/RunCMakeTest.cmake @@ -33,6 +33,13 @@ foreach(l CXX C) endif() endforeach() +run_cmake(Target) +file(READ "${RunCMake_BINARY_DIR}/Target-build/sub1/output.txt" sub_1) +file(READ "${RunCMake_BINARY_DIR}/Target-build/sub2/output.txt" sub_2) +if(NOT sub_1 MATCHES "first" OR NOT sub_2 MATCHES "second") + message(SEND_ERROR "Wrong target used by TARGET argument! ${sub_1} ${sub_2}") +endif() + set(timeformat "%Y%j%H%M%S") file(REMOVE "${RunCMake_BINARY_DIR}/WriteIfDifferent-build/output_file.txt") diff --git a/Tests/RunCMake/File_Generate/Target.cmake b/Tests/RunCMake/File_Generate/Target.cmake new file mode 100644 index 0000000..16e8457 --- /dev/null +++ b/Tests/RunCMake/File_Generate/Target.cmake @@ -0,0 +1,2 @@ +add_subdirectory(sub1) +add_subdirectory(sub2) diff --git a/Tests/RunCMake/File_Generate/sub1/CMakeLists.txt b/Tests/RunCMake/File_Generate/sub1/CMakeLists.txt new file mode 100644 index 0000000..34c51a4 --- /dev/null +++ b/Tests/RunCMake/File_Generate/sub1/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(library IMPORTED STATIC) +set_property(TARGET library PROPERTY COMPILE_DEFINITIONS "first") + +file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output.txt" + CONTENT "$<TARGET_PROPERTY:COMPILE_DEFINITIONS>" + TARGET library +) diff --git a/Tests/RunCMake/File_Generate/sub2/CMakeLists.txt b/Tests/RunCMake/File_Generate/sub2/CMakeLists.txt new file mode 100644 index 0000000..09b81ac --- /dev/null +++ b/Tests/RunCMake/File_Generate/sub2/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(library IMPORTED STATIC) +set_property(TARGET library PROPERTY COMPILE_DEFINITIONS "second") + +file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output.txt" + CONTENT "$<TARGET_PROPERTY:COMPILE_DEFINITIONS>" + TARGET library +) diff --git a/Tests/RunCMake/Graphviz/GraphvizTestProject.cmake b/Tests/RunCMake/Graphviz/GraphvizTestProject.cmake index 8a628cf..2c7d5bf 100644 --- a/Tests/RunCMake/Graphviz/GraphvizTestProject.cmake +++ b/Tests/RunCMake/Graphviz/GraphvizTestProject.cmake @@ -60,6 +60,7 @@ target_link_libraries(ConsoleApplication CoreLibrary) # No one will ever notice... add_library(CryptoCurrencyMiningLibrary UNKNOWN IMPORTED) +set_target_properties(CryptoCurrencyMiningLibrary PROPERTIES IMPORTED_LOCATION "cryptomining${CMAKE_STATIC_LIBRARY_SUFFIX}") target_link_libraries(ConsoleApplication CryptoCurrencyMiningLibrary) add_custom_target(GenerateManPage COMMAND ${CMAKE_COMMAND} --version) diff --git a/Tests/RunCMake/Win32GenEx/CMakeLists.txt b/Tests/RunCMake/Win32GenEx/CMakeLists.txt new file mode 100644 index 0000000..b646c4a --- /dev/null +++ b/Tests/RunCMake/Win32GenEx/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.18) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/Win32GenEx/RunCMakeTest.cmake b/Tests/RunCMake/Win32GenEx/RunCMakeTest.cmake new file mode 100644 index 0000000..d5529b0 --- /dev/null +++ b/Tests/RunCMake/Win32GenEx/RunCMakeTest.cmake @@ -0,0 +1,28 @@ +include(RunCMake) + +if(RunCMake_GENERATOR_IS_MULTI_CONFIG) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Win32GenEx-build) + run_cmake(Win32GenEx) + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(Win32GenEx-debug-build ${CMAKE_COMMAND} --build ${RunCMake_TEST_BINARY_DIR} --config Debug) + run_cmake_command(Win32GenEx-release-build ${CMAKE_COMMAND} --build ${RunCMake_TEST_BINARY_DIR} --config Release) + unset(RunCMake_TEST_NO_CLEAN) +else() + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Win32GenEx-debug-build) + set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug) + run_cmake(Win32GenEx-debug) + unset(RunCMake_TEST_OPTIONS) + + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(Win32GenEx-debug-build ${CMAKE_COMMAND} --build ${RunCMake_TEST_BINARY_DIR}) + unset(RunCMake_TEST_NO_CLEAN) + + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Win32GenEx-release-build) + set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Release) + run_cmake(Win32GenEx-release) + unset(RunCMake_TEST_OPTIONS) + + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(Win32GenEx-release-build ${CMAKE_COMMAND} --build ${RunCMake_TEST_BINARY_DIR}) + unset(RunCMake_TEST_NO_CLEAN) +endif() diff --git a/Tests/RunCMake/Win32GenEx/Win32GenEx-debug.cmake b/Tests/RunCMake/Win32GenEx/Win32GenEx-debug.cmake new file mode 100644 index 0000000..74c5bd8 --- /dev/null +++ b/Tests/RunCMake/Win32GenEx/Win32GenEx-debug.cmake @@ -0,0 +1 @@ +include(Win32GenEx.cmake) diff --git a/Tests/RunCMake/Win32GenEx/Win32GenEx-release.cmake b/Tests/RunCMake/Win32GenEx/Win32GenEx-release.cmake new file mode 100644 index 0000000..74c5bd8 --- /dev/null +++ b/Tests/RunCMake/Win32GenEx/Win32GenEx-release.cmake @@ -0,0 +1 @@ +include(Win32GenEx.cmake) diff --git a/Tests/RunCMake/Win32GenEx/Win32GenEx.cmake b/Tests/RunCMake/Win32GenEx/Win32GenEx.cmake new file mode 100644 index 0000000..80f8b80 --- /dev/null +++ b/Tests/RunCMake/Win32GenEx/Win32GenEx.cmake @@ -0,0 +1,7 @@ +enable_language(C) + +add_executable(Win32GenEx main.c) +set_target_properties(Win32GenEx PROPERTIES + WIN32_EXECUTABLE $<CONFIG:Release> + ) +target_compile_definitions(Win32GenEx PRIVATE $<$<CONFIG:Release>:USE_WIN32_MAIN>) diff --git a/Tests/RunCMake/Win32GenEx/main.c b/Tests/RunCMake/Win32GenEx/main.c new file mode 100644 index 0000000..1cf9f81 --- /dev/null +++ b/Tests/RunCMake/Win32GenEx/main.c @@ -0,0 +1,14 @@ +#ifdef USE_WIN32_MAIN +# include <windows.h> + +int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, + LPSTR lpCmdLine, int nShowCmd) +{ + return 0; +} +#else +int main(void) +{ + return 0; +} +#endif diff --git a/Tests/RunCMake/target_link_libraries/SharedDepNotTarget.cmake b/Tests/RunCMake/target_link_libraries/SharedDepNotTarget.cmake index bab537e..d6ddfae 100644 --- a/Tests/RunCMake/target_link_libraries/SharedDepNotTarget.cmake +++ b/Tests/RunCMake/target_link_libraries/SharedDepNotTarget.cmake @@ -3,7 +3,8 @@ set(CMAKE_LINK_DEPENDENT_LIBRARY_DIRS 1) set(CMAKE_SHARED_LIBRARY_SUFFIX ".so") add_library(imported SHARED IMPORTED) set_target_properties(imported PROPERTIES - IMPORTED_LOCATION "imported" + IMPORTED_LOCATION "imported${CMAKE_SHARED_LIBRARY_SUFFIX}" + IMPORTED_IMPLIB "imported${CMAKE_IMPORT_LIBRARY_SUFFIX}" IMPORTED_LINK_DEPENDENT_LIBRARIES "/path/to/libSharedDep.so" ) add_executable(empty empty.c) diff --git a/Tests/RunCMake/target_link_libraries/UNKNOWN-IMPORTED-GLOBAL.cmake b/Tests/RunCMake/target_link_libraries/UNKNOWN-IMPORTED-GLOBAL.cmake index f52fa30..608f47b 100644 --- a/Tests/RunCMake/target_link_libraries/UNKNOWN-IMPORTED-GLOBAL.cmake +++ b/Tests/RunCMake/target_link_libraries/UNKNOWN-IMPORTED-GLOBAL.cmake @@ -1,4 +1,5 @@ enable_language(C) add_library(UnknownImportedGlobal UNKNOWN IMPORTED GLOBAL) +set_target_properties(UnknownImportedGlobal PROPERTIES IMPORTED_LOCATION "unknown.${CMAKE_SHARED_LIBRARY_SUFFIX}") add_library(mylib empty.c) target_link_libraries(mylib UnknownImportedGlobal) diff --git a/Utilities/Scripts/update-curl.bash b/Utilities/Scripts/update-curl.bash index 67e2728..94a42e9 100755 --- a/Utilities/Scripts/update-curl.bash +++ b/Utilities/Scripts/update-curl.bash @@ -8,7 +8,7 @@ readonly name="curl" readonly ownership="Curl Upstream <curl-library@cool.haxx.se>" readonly subtree="Utilities/cmcurl" readonly repo="https://github.com/curl/curl.git" -readonly tag="curl-7_71_1" +readonly tag="curl-7_72_0" readonly shortlog=false readonly paths=" CMake/* diff --git a/Utilities/cmcurl/CMake/FindZstd.cmake b/Utilities/cmcurl/CMake/FindZstd.cmake new file mode 100644 index 0000000..44c741a --- /dev/null +++ b/Utilities/cmcurl/CMake/FindZstd.cmake @@ -0,0 +1,69 @@ +#*************************************************************************** +# _ _ ____ _ +# Project ___| | | | _ \| | +# / __| | | | |_) | | +# | (__| |_| | _ <| |___ +# \___|\___/|_| \_\_____| +# +# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at https://curl.haxx.se/docs/copyright.html. +# +# You may opt to use, copy, modify, merge, publish, distribute and/or sell +# copies of the Software, and permit persons to whom the Software is +# furnished to do so, under the terms of the COPYING file. +# +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# KIND, either express or implied. +# +########################################################################### + +#[=======================================================================[.rst: +FindZstd +---------- + +Find the zstd library + +Result Variables +^^^^^^^^^^^^^^^^ + +``Zstd_FOUND`` + System has zstd +``Zstd_INCLUDE_DIRS`` + The zstd include directories. +``Zstd_LIBRARIES`` + The libraries needed to use zstd +#]=======================================================================] + +if(UNIX) + find_package(PkgConfig QUIET) + pkg_search_module(PC_Zstd libzstd) +endif() + +find_path(Zstd_INCLUDE_DIR zstd.h + HINTS + ${PC_Zstd_INCLUDEDIR} + ${PC_Zstd_INCLUDE_DIRS} +) + +find_library(Zstd_LIBRARY NAMES zstd + HINTS + ${PC_Zstd_LIBDIR} + ${PC_Zstd_LIBRARY_DIRS} +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(Zstd + REQUIRED_VARS + Zstd_LIBRARY + Zstd_INCLUDE_DIR +) + +if(Zstd_FOUND) + set(Zstd_LIBRARIES ${Zstd_LIBRARY}) + set(Zstd_INCLUDE_DIRS ${Zstd_INCLUDE_DIR}) +endif() + +mark_as_advanced(Zstd_INCLUDE_DIRS Zstd_LIBRARIES) diff --git a/Utilities/cmcurl/CMakeLists.txt b/Utilities/cmcurl/CMakeLists.txt index d327f55..4821656 100644 --- a/Utilities/cmcurl/CMakeLists.txt +++ b/Utilities/cmcurl/CMakeLists.txt @@ -7,6 +7,7 @@ set(CMAKE_USE_GSSAPI OFF CACHE INTERNAL "Disable curl gssapi") set(CMAKE_USE_LIBSSH2 OFF CACHE INTERNAL "Disable curl libssh2") set(CMAKE_USE_LIBSSH OFF) set(CMAKE_USE_OPENLDAP OFF CACHE INTERNAL "No curl OpenLDAP") +set(CURL_BROTLI OFF) set(CURL_DISABLE_COOKIES OFF CACHE INTERNAL "Do not disable curl cookie support") set(CURL_DISABLE_CRYPTO_AUTH OFF CACHE INTERNAL "Do not disable curl crypto auth") set(CURL_DISABLE_DICT ON CACHE INTERNAL "Disable curl dict protocol?") @@ -29,6 +30,7 @@ set(CURL_HIDDEN_SYMBOLS OFF CACHE INTERNAL "No curl hidden symbols") set(CURL_LTO OFF CACHE INTERNAL "Turn on compiler Link Time Optimizations") set(CURL_STATIC_CRT OFF CACHE INTERNAL "Set to ON to build libcurl with static CRT on Windows (/MT).") set(CURL_WERROR OFF CACHE INTERNAL "Turn compiler warnings into errors") +set(CURL_ZSTD OFF) set(DISABLED_THREADSAFE OFF CACHE INTERNAL "Curl can use thread-safe functions") set(ENABLE_ARES OFF CACHE INTERNAL "No curl c-ares support") set(ENABLE_ALT_SVC OFF) @@ -47,7 +49,8 @@ set(USE_QUICHE OFF) set(USE_WIN32_LDAP OFF CACHE INTERNAL "No curl Windows LDAP") if(CMAKE_USE_OPENSSL) elseif(WIN32) - set(CMAKE_USE_WINSSL ON CACHE INTERNAL "enable Windows native SSL/TLS") + unset(CMAKE_USE_WINSSL CACHE) + set(CMAKE_USE_SCHANNEL ON) set(CURL_WINDOWS_SSPI ON CACHE INTERNAL "Use windows libraries to allow NTLM authentication without openssl") elseif(APPLE) # Use OS X SSL/TLS native implementation if available on target version. @@ -183,12 +186,15 @@ if(WIN32) set(CURL_TARGET_WINDOWS_VERSION "" CACHE STRING "Minimum target Windows version as hex string") if(CURL_TARGET_WINDOWS_VERSION) add_definitions(-D_WIN32_WINNT=${CURL_TARGET_WINDOWS_VERSION}) + set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WIN32_WINNT=${CURL_TARGET_WINDOWS_VERSION}") elseif(ENABLE_INET_PTON) # _WIN32_WINNT_VISTA (0x0600) add_definitions(-D_WIN32_WINNT=0x0600) + set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WIN32_WINNT=0x0600") else() # _WIN32_WINNT_WINXP (0x0501) add_definitions(-D_WIN32_WINNT=0x0501) + set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WIN32_WINNT=0x0501") endif() endif() endif() @@ -205,7 +211,7 @@ option(ENABLE_CURLDEBUG "Set to ON to build with TrackMemory feature enabled" OF if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG) if(PICKY_COMPILER) - foreach(_CCOPT -pedantic -Wall -W -Wpointer-arith -Wwrite-strings -Wunused -Wshadow -Winline -Wnested-externs -Wmissing-declarations -Wmissing-prototypes -Wno-long-long -Wfloat-equal -Wno-multichar -Wsign-compare -Wundef -Wno-format-nonliteral -Wendif-labels -Wstrict-prototypes -Wdeclaration-after-statement -Wstrict-aliasing=3 -Wcast-align -Wtype-limits -Wold-style-declaration -Wmissing-parameter-type -Wempty-body -Wclobbered -Wignored-qualifiers -Wconversion -Wno-sign-conversion -Wvla -Wdouble-promotion -Wno-system-headers -Wno-pedantic-ms-format) + foreach(_CCOPT -pedantic -Wall -W -Wpointer-arith -Wwrite-strings -Wunused -Wshadow -Winline -Wnested-externs -Wmissing-declarations -Wmissing-prototypes -Wfloat-equal -Wsign-compare -Wundef -Wendif-labels -Wstrict-prototypes -Wdeclaration-after-statement -Wstrict-aliasing=3 -Wcast-align -Wtype-limits -Wold-style-declaration -Wmissing-parameter-type -Wempty-body -Wclobbered -Wignored-qualifiers -Wconversion -Wvla -Wdouble-promotion) # surprisingly, CHECK_C_COMPILER_FLAG needs a new variable to store each new # test result in. string(MAKE_C_IDENTIFIER "OPT${_CCOPT}" _optvarname) @@ -214,6 +220,15 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_CCOPT}") endif() endforeach() + foreach(_CCOPT long-long multichar format-nonliteral sign-conversion system-headers pedantic-ms-format) + # GCC only warns about unknown -Wno- options if there are also other diagnostic messages, + # so test for the positive form instead + string(MAKE_C_IDENTIFIER "OPT${_CCOPT}" _optvarname) + check_c_compiler_flag("-W${_CCOPT}" ${_optvarname}) + if(${_optvarname}) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-${_CCOPT}") + endif() + endforeach() endif() endif() @@ -322,8 +337,10 @@ if(ENABLE_IPV6 AND NOT WIN32) endif() if(0) # This code not needed for building within CMake. -# Required for building manual, docs, tests -curl_nroff_check() +if(USE_MANUAL) + #nroff is currently only used when USE_MANUAL is set, so we can prevent the warning of no *NROFF if USE_MANUAL is OFF (or not defined), by not even looking for NROFF.. + curl_nroff_check() +endif() find_package(Perl) cmake_dependent_option(ENABLE_MANUAL "to provide the built-in manual" @@ -416,14 +433,17 @@ endif() # check SSL libraries # TODO support GnuTLS +if(CMAKE_USE_WINSSL) + message(FATAL_ERROR "The cmake option CMAKE_USE_WINSSL was renamed to CMAKE_USE_SCHANNEL.") +endif() if(APPLE) option(CMAKE_USE_SECTRANSP "enable Apple OS native SSL/TLS" OFF) endif() if(WIN32) - option(CMAKE_USE_WINSSL "enable Windows native SSL/TLS" OFF) + option(CMAKE_USE_SCHANNEL "enable Windows native SSL/TLS" OFF) cmake_dependent_option(CURL_WINDOWS_SSPI "Use windows libraries to allow NTLM authentication without openssl" ON - CMAKE_USE_WINSSL OFF) + CMAKE_USE_SCHANNEL OFF) endif() option(CMAKE_USE_MBEDTLS "Enable mbedTLS for SSL/TLS" OFF) option(CMAKE_USE_BEARSSL "Enable BearSSL for SSL/TLS" OFF) @@ -431,12 +451,12 @@ option(CMAKE_USE_NSS "Enable NSS for SSL/TLS" OFF) option(CMAKE_USE_WOLFSSL "enable wolfSSL for SSL/TLS" OFF) set(openssl_default ON) -if(WIN32 OR CMAKE_USE_SECTRANSP OR CMAKE_USE_WINSSL OR CMAKE_USE_MBEDTLS OR CMAKE_USE_NSS OR CMAKE_USE_WOLFSSL) +if(WIN32 OR CMAKE_USE_SECTRANSP OR CMAKE_USE_SCHANNEL OR CMAKE_USE_MBEDTLS OR CMAKE_USE_NSS OR CMAKE_USE_WOLFSSL) set(openssl_default OFF) endif() count_true(enabled_ssl_options_count - CMAKE_USE_WINSSL + CMAKE_USE_SCHANNEL CMAKE_USE_SECTRANSP CMAKE_USE_OPENSSL CMAKE_USE_MBEDTLS @@ -448,10 +468,10 @@ if(enabled_ssl_options_count GREATER "1") set(CURL_WITH_MULTI_SSL ON) endif() -if(CMAKE_USE_WINSSL) +if(CMAKE_USE_SCHANNEL) set(SSL_ENABLED ON) set(USE_SCHANNEL ON) # Windows native SSL/TLS support - set(USE_WINDOWS_SSPI ON) # CMAKE_USE_WINSSL implies CURL_WINDOWS_SSPI + set(USE_WINDOWS_SSPI ON) # CMAKE_USE_SCHANNEL implies CURL_WINDOWS_SSPI list(APPEND CURL_LIBS "crypt32") endif() if(CURL_WINDOWS_SSPI) @@ -774,6 +794,22 @@ if(CURL_BROTLI) endif() endif() +option(CURL_ZSTD "Set to ON to enable building curl with zstd support." OFF) +set(HAVE_ZSTD OFF) +if(CURL_ZSTD) + find_package(Zstd REQUIRED) + cmake_push_check_state() + set(CMAKE_REQUIRED_INCLUDES ${Zstd_INCLUDE_DIRS}) + set(CMAKE_REQUIRED_LIBRARIES ${Zstd_LIBRARIES}) + check_symbol_exists(ZSTD_createDStream "zstd.h" HAVE_ZSTD_CREATEDSTREAM) + cmake_pop_check_state() + if(Zstd_FOUND AND HAVE_ZSTD_CREATEDSTREAM) + set(HAVE_ZSTD ON) + list(APPEND CURL_LIBS ${Zstd_LIBRARIES}) + include_directories(${Zstd_INCLUDE_DIRS}) + endif() +endif() + #libSSH2 option(CMAKE_USE_LIBSSH2 "Use libSSH2" ON) mark_as_advanced(CMAKE_USE_LIBSSH2) @@ -1459,11 +1495,13 @@ _add_if("SSL" SSL_ENABLED) _add_if("IPv6" ENABLE_IPV6) _add_if("unix-sockets" USE_UNIX_SOCKETS) _add_if("libz" HAVE_LIBZ) +_add_if("brotli" HAVE_BROTLI) +_add_if("zstd" HAVE_ZSTD) _add_if("AsynchDNS" USE_ARES OR USE_THREADS_POSIX OR USE_THREADS_WIN32) _add_if("IDN" HAVE_LIBIDN2) _add_if("Largefile" (CURL_SIZEOF_CURL_OFF_T GREATER 4) AND ((SIZEOF_OFF_T GREATER 4) OR USE_WIN32_LARGE_FILES)) -# TODO SSP1 (WinSSL) check is missing +# TODO SSP1 (Schannel) check is missing _add_if("SSPI" USE_WINDOWS_SSPI) _add_if("GSS-API" HAVE_GSSAPI) _add_if("alt-svc" ENABLE_ALT_SVC) @@ -1525,7 +1563,7 @@ message(STATUS "Enabled protocols: ${SUPPORT_PROTOCOLS}") # Clear list and collect SSL backends set(_items) -_add_if("WinSSL" SSL_ENABLED AND USE_WINDOWS_SSPI) +_add_if("Schannel" SSL_ENABLED AND USE_WINDOWS_SSPI) _add_if("OpenSSL" SSL_ENABLED AND USE_OPENSSL) _add_if("Secure Transport" SSL_ENABLED AND USE_SECTRANSP) _add_if("mbedTLS" SSL_ENABLED AND USE_MBEDTLS) diff --git a/Utilities/cmcurl/include/curl/curl.h b/Utilities/cmcurl/include/curl/curl.h index 194b578..e8e3ed1 100644 --- a/Utilities/cmcurl/include/curl/curl.h +++ b/Utilities/cmcurl/include/curl/curl.h @@ -2634,10 +2634,6 @@ typedef enum { CURLINFO_PROXY_SSL_VERIFYRESULT = CURLINFO_LONG + 47, CURLINFO_PROTOCOL = CURLINFO_LONG + 48, CURLINFO_SCHEME = CURLINFO_STRING + 49, - /* Fill in new entries below here! */ - - /* Preferably these would be defined conditionally based on the - sizeof curl_off_t being 64-bits */ CURLINFO_TOTAL_TIME_T = CURLINFO_OFF_T + 50, CURLINFO_NAMELOOKUP_TIME_T = CURLINFO_OFF_T + 51, CURLINFO_CONNECT_TIME_T = CURLINFO_OFF_T + 52, @@ -2646,8 +2642,9 @@ typedef enum { CURLINFO_REDIRECT_TIME_T = CURLINFO_OFF_T + 55, CURLINFO_APPCONNECT_TIME_T = CURLINFO_OFF_T + 56, CURLINFO_RETRY_AFTER = CURLINFO_OFF_T + 57, + CURLINFO_EFFECTIVE_METHOD = CURLINFO_STRING + 58, - CURLINFO_LASTONE = 57 + CURLINFO_LASTONE = 58 } CURLINFO; /* CURLINFO_RESPONSE_CODE is the new name for the option previously known as @@ -2748,6 +2745,7 @@ typedef enum { CURLVERSION_FIFTH, CURLVERSION_SIXTH, CURLVERSION_SEVENTH, + CURLVERSION_EIGHTH, CURLVERSION_LAST /* never actually use this */ } CURLversion; @@ -2756,7 +2754,7 @@ typedef enum { meant to be a built-in version number for what kind of struct the caller expects. If the struct ever changes, we redefine the NOW to another enum from above. */ -#define CURLVERSION_NOW CURLVERSION_SEVENTH +#define CURLVERSION_NOW CURLVERSION_EIGHTH struct curl_version_info_data { CURLversion age; /* age of the returned struct */ @@ -2802,6 +2800,11 @@ struct curl_version_info_data { const char *capath; /* the built-in default CURLOPT_CAPATH, might be NULL */ + /* These fields were added in CURLVERSION_EIGHTH */ + unsigned int zstd_ver_num; /* Numeric Zstd version + (MAJOR << 24) | (MINOR << 12) | PATCH */ + const char *zstd_version; /* human readable string. */ + }; typedef struct curl_version_info_data curl_version_info_data; @@ -2836,6 +2839,8 @@ typedef struct curl_version_info_data curl_version_info_data; #define CURL_VERSION_BROTLI (1<<23) /* Brotli features are present. */ #define CURL_VERSION_ALTSVC (1<<24) /* Alt-Svc handling built-in */ #define CURL_VERSION_HTTP3 (1<<25) /* HTTP3 support built-in */ +#define CURL_VERSION_ZSTD (1<<26) /* zstd features are present */ +#define CURL_VERSION_UNICODE (1<<27) /* Unicode support on Windows */ /* * NAME curl_version_info() diff --git a/Utilities/cmcurl/include/curl/curlver.h b/Utilities/cmcurl/include/curl/curlver.h index 97a8bd8..a881bb7 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.71.1" +#define LIBCURL_VERSION "7.72.0" /* The numeric version number is also available "in parts" by using these defines: */ #define LIBCURL_VERSION_MAJOR 7 -#define LIBCURL_VERSION_MINOR 71 -#define LIBCURL_VERSION_PATCH 1 +#define LIBCURL_VERSION_MINOR 72 +#define LIBCURL_VERSION_PATCH 0 /* 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 0x074701 +#define LIBCURL_VERSION_NUM 0x074800 /* * This is the date and time when the full source package was created. The diff --git a/Utilities/cmcurl/include/curl/multi.h b/Utilities/cmcurl/include/curl/multi.h index 2e6bb72..b911ba9 100644 --- a/Utilities/cmcurl/include/curl/multi.h +++ b/Utilities/cmcurl/include/curl/multi.h @@ -427,12 +427,14 @@ CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle, * Name: curl_push_callback * * Desc: This callback gets called when a new stream is being pushed by the - * server. It approves or denies the new stream. + * server. It approves or denies the new stream. It can also decide + * to completely fail the connection. * - * Returns: CURL_PUSH_OK or CURL_PUSH_DENY. + * Returns: CURL_PUSH_OK, CURL_PUSH_DENY or CURL_PUSH_ERROROUT */ -#define CURL_PUSH_OK 0 -#define CURL_PUSH_DENY 1 +#define CURL_PUSH_OK 0 +#define CURL_PUSH_DENY 1 +#define CURL_PUSH_ERROROUT 2 /* added in 7.72.0 */ struct curl_pushheaders; /* forward declaration only */ diff --git a/Utilities/cmcurl/lib/Makefile.inc b/Utilities/cmcurl/lib/Makefile.inc index 723b826..ae3f961 100644 --- a/Utilities/cmcurl/lib/Makefile.inc +++ b/Utilities/cmcurl/lib/Makefile.inc @@ -60,7 +60,8 @@ LIB_CFILES = altsvc.c amigaos.c asyn-ares.c asyn-thread.c base64.c \ sendf.c setopt.c sha256.c share.c slist.c smb.c smtp.c socketpair.c socks.c \ socks_gssapi.c socks_sspi.c speedcheck.c splay.c strcase.c strdup.c \ strerror.c strtok.c strtoofft.c system_win32.c telnet.c tftp.c timeval.c \ - transfer.c urlapi.c version.c warnless.c wildcard.c x509asn1.c dynbuf.c + transfer.c urlapi.c version.c warnless.c wildcard.c x509asn1.c dynbuf.c \ + version_win32.c LIB_HFILES = altsvc.h amigaos.h arpa_telnet.h asyn.h conncache.h connect.h \ content_encoding.h cookie.h curl_addrinfo.h curl_base64.h curl_ctype.h \ @@ -79,7 +80,7 @@ LIB_HFILES = altsvc.h amigaos.h arpa_telnet.h asyn.h conncache.h connect.h \ smb.h smtp.h sockaddr.h socketpair.h socks.h speedcheck.h splay.h strcase.h \ strdup.h strerror.h strtok.h strtoofft.h system_win32.h telnet.h tftp.h \ timeval.h transfer.h urlapi-int.h urldata.h warnless.h wildcard.h \ - x509asn1.h dynbuf.h + x509asn1.h dynbuf.h version_win32.h LIB_RCFILES = libcurl.rc diff --git a/Utilities/cmcurl/lib/asyn-ares.c b/Utilities/cmcurl/lib/asyn-ares.c index ba5160b..e651507 100644 --- a/Utilities/cmcurl/lib/asyn-ares.c +++ b/Utilities/cmcurl/lib/asyn-ares.c @@ -633,7 +633,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, *waitp = 0; /* default to synchronous response */ -#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */ +#ifdef ENABLE_IPV6 switch(conn->ip_version) { default: #if ARES_VERSION >= 0x010601 @@ -649,7 +649,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, family = PF_INET6; break; } -#endif /* CURLRES_IPV6 */ +#endif /* ENABLE_IPV6 */ bufp = strdup(hostname); if(bufp) { @@ -670,7 +670,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, /* initial status - failed */ res->last_status = ARES_ENOTFOUND; -#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */ +#ifdef ENABLE_IPV6 if(family == PF_UNSPEC) { if(Curl_ipv6works(conn)) { res->num_pending = 2; @@ -690,7 +690,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, } } else -#endif /* CURLRES_IPV6 */ +#endif /* ENABLE_IPV6 */ { res->num_pending = 1; diff --git a/Utilities/cmcurl/lib/asyn.h b/Utilities/cmcurl/lib/asyn.h index be2796c..bd3c3c1 100644 --- a/Utilities/cmcurl/lib/asyn.h +++ b/Utilities/cmcurl/lib/asyn.h @@ -164,7 +164,6 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, #define Curl_resolver_kill(x) Curl_nop_stmt #define Curl_resolver_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST #define Curl_resolver_wait_resolv(x,y) CURLE_COULDNT_RESOLVE_HOST -#define Curl_resolver_getsock(x,y,z) 0 #define Curl_resolver_duphandle(x,y,z) CURLE_OK #define Curl_resolver_init(x,y) CURLE_OK #define Curl_resolver_global_init() CURLE_OK diff --git a/Utilities/cmcurl/lib/connect.c b/Utilities/cmcurl/lib/connect.c index 29293f0..b000b1b 100644 --- a/Utilities/cmcurl/lib/connect.c +++ b/Utilities/cmcurl/lib/connect.c @@ -74,7 +74,7 @@ #include "warnless.h" #include "conncache.h" #include "multihandle.h" -#include "system_win32.h" +#include "version_win32.h" #include "quic.h" #include "socks.h" @@ -934,10 +934,10 @@ CURLcode Curl_is_connected(struct connectdata *conn, return CURLE_OK; } - infof(data, "Connection failed\n"); } - else if(rc & CURL_CSELECT_ERR) + else if(rc & CURL_CSELECT_ERR) { (void)verifyconnect(conn->tempsock[i], &error); + } /* * The connection failed here, we should attempt to connect to the "next @@ -1085,8 +1085,8 @@ void Curl_sndbufset(curl_socket_t sockfd) static int detectOsState = DETECT_OS_NONE; if(detectOsState == DETECT_OS_NONE) { - if(Curl_verify_windows_version(6, 0, PLATFORM_WINNT, - VERSION_GREATER_THAN_EQUAL)) + if(curlx_verify_windows_version(6, 0, PLATFORM_WINNT, + VERSION_GREATER_THAN_EQUAL)) detectOsState = DETECT_OS_VISTA_OR_LATER; else detectOsState = DETECT_OS_PREVISTA; @@ -1363,15 +1363,15 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ } struct connfind { - struct connectdata *tofind; - bool found; + long id_tofind; + struct connectdata *found; }; static int conn_is_conn(struct connectdata *conn, void *param) { struct connfind *f = (struct connfind *)param; - if(conn == f->tofind) { - f->found = TRUE; + if(conn->connection_id == f->id_tofind) { + f->found = conn; return 1; } return 0; @@ -1393,21 +1393,22 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data, * - that is associated with a multi handle, and whose connection * was detached with CURLOPT_CONNECT_ONLY */ - if(data->state.lastconnect && (data->multi_easy || data->multi)) { - struct connectdata *c = data->state.lastconnect; + if((data->state.lastconnect_id != -1) && (data->multi_easy || data->multi)) { + struct connectdata *c; struct connfind find; - find.tofind = data->state.lastconnect; - find.found = FALSE; + find.id_tofind = data->state.lastconnect_id; + find.found = NULL; Curl_conncache_foreach(data, data->multi_easy? &data->multi_easy->conn_cache: &data->multi->conn_cache, &find, conn_is_conn); if(!find.found) { - data->state.lastconnect = NULL; + data->state.lastconnect_id = -1; return CURL_SOCKET_BAD; } + c = find.found; if(connp) { /* only store this if the caller cares for it */ *connp = c; diff --git a/Utilities/cmcurl/lib/content_encoding.c b/Utilities/cmcurl/lib/content_encoding.c index e2e68a1..2fc3d43 100644 --- a/Utilities/cmcurl/lib/content_encoding.c +++ b/Utilities/cmcurl/lib/content_encoding.c @@ -38,6 +38,10 @@ #include <brotli/decode.h> #endif +#ifdef HAVE_ZSTD +#include <zstd.h> +#endif + #include "sendf.h" #include "http.h" #include "content_encoding.h" @@ -710,6 +714,95 @@ static const struct content_encoding brotli_encoding = { #endif +#ifdef HAVE_ZSTD +/* Writer parameters. */ +struct zstd_params { + ZSTD_DStream *zds; /* State structure for zstd. */ + void *decomp; +}; + +static CURLcode zstd_init_writer(struct connectdata *conn, + struct contenc_writer *writer) +{ + struct zstd_params *zp = (struct zstd_params *)&writer->params; + (void)conn; + + if(!writer->downstream) + return CURLE_WRITE_ERROR; + + zp->zds = ZSTD_createDStream(); + zp->decomp = NULL; + return zp->zds ? CURLE_OK : CURLE_OUT_OF_MEMORY; +} + +static CURLcode zstd_unencode_write(struct connectdata *conn, + struct contenc_writer *writer, + const char *buf, size_t nbytes) +{ + CURLcode result = CURLE_OK; + struct zstd_params *zp = (struct zstd_params *)&writer->params; + ZSTD_inBuffer in; + ZSTD_outBuffer out; + size_t errorCode; + + if(!zp->decomp) { + zp->decomp = malloc(DSIZ); + if(!zp->decomp) + return CURLE_OUT_OF_MEMORY; + } + in.pos = 0; + in.src = buf; + in.size = nbytes; + + for(;;) { + out.pos = 0; + out.dst = zp->decomp; + out.size = DSIZ; + + errorCode = ZSTD_decompressStream(zp->zds, &out, &in); + if(ZSTD_isError(errorCode)) { + return CURLE_BAD_CONTENT_ENCODING; + } + if(out.pos > 0) { + result = Curl_unencode_write(conn, writer->downstream, + zp->decomp, out.pos); + if(result) + break; + } + if((in.pos == nbytes) && (out.pos < out.size)) + break; + } + + return result; +} + +static void zstd_close_writer(struct connectdata *conn, + struct contenc_writer *writer) +{ + struct zstd_params *zp = (struct zstd_params *)&writer->params; + (void)conn; + + if(zp->decomp) { + free(zp->decomp); + zp->decomp = NULL; + } + if(zp->zds) { + ZSTD_freeDStream(zp->zds); + zp->zds = NULL; + } +} + +static const struct content_encoding zstd_encoding = { + "zstd", + NULL, + zstd_init_writer, + zstd_unencode_write, + zstd_close_writer, + sizeof(struct zstd_params) +}; +#endif + + /* Identity handler. */ static CURLcode identity_init_writer(struct connectdata *conn, struct contenc_writer *writer) @@ -752,6 +845,9 @@ static const struct content_encoding * const encodings[] = { #ifdef HAVE_BROTLI &brotli_encoding, #endif +#ifdef HAVE_ZSTD + &zstd_encoding, +#endif NULL }; diff --git a/Utilities/cmcurl/lib/curl_config.h.cmake b/Utilities/cmcurl/lib/curl_config.h.cmake index 00ae658..d5bf4fe 100644 --- a/Utilities/cmcurl/lib/curl_config.h.cmake +++ b/Utilities/cmcurl/lib/curl_config.h.cmake @@ -430,6 +430,9 @@ /* if brotli is available */ #cmakedefine HAVE_BROTLI 1 +/* if zstd is available */ +#cmakedefine HAVE_ZSTD 1 + /* Define to 1 if you have the <locale.h> header file. */ #cmakedefine HAVE_LOCALE_H 1 diff --git a/Utilities/cmcurl/lib/curl_setup.h b/Utilities/cmcurl/lib/curl_setup.h index dadfff9..45a093f 100644 --- a/Utilities/cmcurl/lib/curl_setup.h +++ b/Utilities/cmcurl/lib/curl_setup.h @@ -656,7 +656,7 @@ int netware_init(void); defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_SECTRANSP) || \ defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \ defined(USE_MBEDTLS) || \ - (defined(USE_WOLFSSL) && defined(HAVE_WOLFSSL_DES_SET_ODD_PARITY)) + (defined(USE_WOLFSSL) && defined(HAVE_WOLFSSL_DES_ECB_ENCRYPT)) #define USE_NTLM diff --git a/Utilities/cmcurl/lib/curl_sspi.c b/Utilities/cmcurl/lib/curl_sspi.c index 83ece9a..512ce24 100644 --- a/Utilities/cmcurl/lib/curl_sspi.c +++ b/Utilities/cmcurl/lib/curl_sspi.c @@ -28,6 +28,7 @@ #include "curl_sspi.h" #include "curl_multibyte.h" #include "system_win32.h" +#include "version_win32.h" #include "warnless.h" /* The last #include files should be: */ @@ -82,7 +83,7 @@ CURLcode Curl_sspi_global_init(void) * have both these DLLs (security.dll forwards calls to secur32.dll) */ /* Load SSPI dll into the address space of the calling process */ - if(Curl_verify_windows_version(4, 0, PLATFORM_WINNT, VERSION_EQUAL)) + if(curlx_verify_windows_version(4, 0, PLATFORM_WINNT, VERSION_EQUAL)) s_hSecDll = Curl_load_library(TEXT("security.dll")); else s_hSecDll = Curl_load_library(TEXT("secur32.dll")); diff --git a/Utilities/cmcurl/lib/curlx.h b/Utilities/cmcurl/lib/curlx.h index a8bae14..98e51bf 100644 --- a/Utilities/cmcurl/lib/curlx.h +++ b/Utilities/cmcurl/lib/curlx.h @@ -63,6 +63,9 @@ curlx_unicodefree() */ +#include "version_win32.h" +/* "version_win32.h" provides curlx_verify_windows_version() */ + /* Now setup curlx_ * names for the functions that are to become curlx_ and be removed from a future libcurl official API: curlx_getenv diff --git a/Utilities/cmcurl/lib/doh.c b/Utilities/cmcurl/lib/doh.c index ebb2c24..8bc3428 100644 --- a/Utilities/cmcurl/lib/doh.c +++ b/Utilities/cmcurl/lib/doh.c @@ -858,7 +858,7 @@ doh2ai(const struct dohentry *de, const char *hostname, int port) addr = (void *)ai->ai_addr; /* storage area for this info */ DEBUGASSERT(sizeof(struct in_addr) == sizeof(de->addr[i].ip.v4)); memcpy(&addr->sin_addr, &de->addr[i].ip.v4, sizeof(struct in_addr)); - addr->sin_family = (CURL_SA_FAMILY_T)addrtype; + addr->sin_family = addrtype; addr->sin_port = htons((unsigned short)port); break; @@ -867,7 +867,7 @@ doh2ai(const struct dohentry *de, const char *hostname, int port) addr6 = (void *)ai->ai_addr; /* storage area for this info */ DEBUGASSERT(sizeof(struct in6_addr) == sizeof(de->addr[i].ip.v6)); memcpy(&addr6->sin6_addr, &de->addr[i].ip.v6, sizeof(struct in6_addr)); - addr6->sin6_family = (CURL_SA_FAMILY_T)addrtype; + addr6->sin6_family = addrtype; addr6->sin6_port = htons((unsigned short)port); break; #endif diff --git a/Utilities/cmcurl/lib/dynbuf.h b/Utilities/cmcurl/lib/dynbuf.h index c80239e..ecc9957 100644 --- a/Utilities/cmcurl/lib/dynbuf.h +++ b/Utilities/cmcurl/lib/dynbuf.h @@ -53,11 +53,11 @@ size_t Curl_dyn_len(const struct dynbuf *s); #define DYN_HAXPROXY 2048 #define DYN_HTTP_REQUEST (128*1024) #define DYN_H2_HEADERS (128*1024) -#define DYN_H2_TRAILER 4096 +#define DYN_H2_TRAILERS (128*1024) #define DYN_APRINTF 8000000 #define DYN_RTSP_REQ_HEADER (64*1024) #define DYN_TRAILERS (64*1024) #define DYN_PROXY_CONNECT_HEADERS 16384 #define DYN_QLOG_NAME 1024 -#define DYN_H1_TRAILER DYN_H2_TRAILER +#define DYN_H1_TRAILER 4096 #endif diff --git a/Utilities/cmcurl/lib/easy.c b/Utilities/cmcurl/lib/easy.c index 292cca7..a69eb9e 100644 --- a/Utilities/cmcurl/lib/easy.c +++ b/Utilities/cmcurl/lib/easy.c @@ -838,8 +838,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) /* the connection cache is setup on demand */ outcurl->state.conn_cache = NULL; - - outcurl->state.lastconnect = NULL; + outcurl->state.lastconnect_id = -1; outcurl->progress.flags = data->progress.flags; outcurl->progress.callback = data->progress.callback; diff --git a/Utilities/cmcurl/lib/ftp.c b/Utilities/cmcurl/lib/ftp.c index cfd70a6..7d805fa 100644 --- a/Utilities/cmcurl/lib/ftp.c +++ b/Utilities/cmcurl/lib/ftp.c @@ -3251,9 +3251,9 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status, } if(conn->ssl[SECONDARYSOCKET].use) { - /* The secondary socket used SSL so we must close down that part first - before we close the socket for real */ - result = Curl_ssl_shutdown(conn, SECONDARYSOCKET); + /* The secondary socket is using SSL so we must close down that part + first before we close the socket for real */ + Curl_ssl_close(conn, SECONDARYSOCKET); /* Note that we keep "use" set to TRUE since that (next) connection is still requested to use SSL */ diff --git a/Utilities/cmcurl/lib/getinfo.c b/Utilities/cmcurl/lib/getinfo.c index 6d5bd5f..82691dc 100644 --- a/Utilities/cmcurl/lib/getinfo.c +++ b/Utilities/cmcurl/lib/getinfo.c @@ -78,6 +78,7 @@ CURLcode Curl_initinfo(struct Curl_easy *data) info->conn_local_ip[0] = '\0'; info->conn_primary_port = 0; info->conn_local_port = 0; + info->retry_after = 0; info->conn_scheme = 0; info->conn_protocol = 0; @@ -95,6 +96,34 @@ static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info, case CURLINFO_EFFECTIVE_URL: *param_charp = data->change.url?data->change.url:(char *)""; break; + case CURLINFO_EFFECTIVE_METHOD: { + const char *m = data->set.str[STRING_CUSTOMREQUEST]; + if(!m) { + if(data->set.opt_no_body) + m = "HEAD"; + else { + switch(data->state.httpreq) { + case HTTPREQ_POST: + case HTTPREQ_POST_FORM: + case HTTPREQ_POST_MIME: + m = "POST"; + break; + case HTTPREQ_PUT: + m = "PUT"; + break; + default: /* this should never happen */ + case HTTPREQ_GET: + m = "GET"; + break; + case HTTPREQ_HEAD: + m = "HEAD"; + break; + } + } + } + *param_charp = m; + } + break; case CURLINFO_CONTENT_TYPE: *param_charp = data->info.contenttype; break; diff --git a/Utilities/cmcurl/lib/http.c b/Utilities/cmcurl/lib/http.c index 28d66c2..8fcdd43 100644 --- a/Utilities/cmcurl/lib/http.c +++ b/Utilities/cmcurl/lib/http.c @@ -2014,9 +2014,6 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) case HTTPREQ_PUT: request = "PUT"; break; - case HTTPREQ_OPTIONS: - request = "OPTIONS"; - break; default: /* this should never happen */ case HTTPREQ_GET: request = "GET"; diff --git a/Utilities/cmcurl/lib/http.h b/Utilities/cmcurl/lib/http.h index 641bc0b..9ea3eb2 100644 --- a/Utilities/cmcurl/lib/http.h +++ b/Utilities/cmcurl/lib/http.h @@ -148,6 +148,7 @@ struct HTTP { struct dynbuf header_recvbuf; size_t nread_header_recvbuf; /* number of bytes in header_recvbuf fed into upper layer */ + struct dynbuf trailer_recvbuf; int status_code; /* HTTP status code */ const uint8_t *pausedata; /* pointer to data received in on_data_chunk */ size_t pauselen; /* the number of bytes left in data */ diff --git a/Utilities/cmcurl/lib/http2.c b/Utilities/cmcurl/lib/http2.c index 6cf651f..d316da8 100644 --- a/Utilities/cmcurl/lib/http2.c +++ b/Utilities/cmcurl/lib/http2.c @@ -514,7 +514,7 @@ static int push_promise(struct Curl_easy *data, struct connectdata *conn, const nghttp2_push_promise *frame) { - int rv; + int rv; /* one of the CURL_PUSH_* defines */ H2BUGF(infof(data, "PUSH_PROMISE received, stream %u!\n", frame->promised_stream_id)); if(data->multi->push_cb) { @@ -528,7 +528,7 @@ static int push_promise(struct Curl_easy *data, struct Curl_easy *newhandle = duphandle(data); if(!newhandle) { infof(data, "failed to duplicate handle\n"); - rv = 1; /* FAIL HARD */ + rv = CURL_PUSH_DENY; /* FAIL HARD */ goto fail; } @@ -541,13 +541,15 @@ static int push_promise(struct Curl_easy *data, if(!stream) { failf(data, "Internal NULL stream!\n"); (void)Curl_close(&newhandle); - rv = 1; + rv = CURL_PUSH_DENY; goto fail; } rv = set_transfer_url(newhandle, &heads); - if(rv) + if(rv) { + rv = CURL_PUSH_DENY; goto fail; + } Curl_set_in_callback(data, true); rv = data->multi->push_cb(data, newhandle, @@ -563,6 +565,7 @@ static int push_promise(struct Curl_easy *data, stream->push_headers_used = 0; if(rv) { + DEBUGASSERT((rv > CURL_PUSH_OK) && (rv <= CURL_PUSH_ERROROUT)); /* denied, kill off the new handle again */ http2_stream_free(newhandle->req.protop); newhandle->req.protop = NULL; @@ -583,7 +586,7 @@ static int push_promise(struct Curl_easy *data, http2_stream_free(newhandle->req.protop); newhandle->req.protop = NULL; Curl_close(&newhandle); - rv = 1; + rv = CURL_PUSH_DENY; goto fail; } @@ -595,12 +598,13 @@ static int push_promise(struct Curl_easy *data, infof(data, "failed to set user_data for stream %d\n", frame->promised_stream_id); DEBUGASSERT(0); + rv = CURL_PUSH_DENY; goto fail; } } else { H2BUGF(infof(data, "Got PUSH_PROMISE, ignore it!\n")); - rv = 1; + rv = CURL_PUSH_DENY; } fail: return rv; @@ -737,11 +741,16 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, case NGHTTP2_PUSH_PROMISE: rv = push_promise(data_s, conn, &frame->push_promise); if(rv) { /* deny! */ - rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, + int h2; + DEBUGASSERT((rv > CURL_PUSH_OK) && (rv <= CURL_PUSH_ERROROUT)); + h2 = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, frame->push_promise.promised_stream_id, NGHTTP2_CANCEL); - if(nghttp2_is_fatal(rv)) { - return rv; + if(nghttp2_is_fatal(h2)) + return NGHTTP2_ERR_CALLBACK_FAILURE; + else if(rv == CURL_PUSH_ERROROUT) { + DEBUGF(infof(data_s, "Fail the parent stream (too)\n")); + return NGHTTP2_ERR_CALLBACK_FAILURE; } } break; @@ -839,7 +848,7 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id, return 0; } H2BUGF(infof(data_s, "on_stream_close(), %s (err %d), stream %u\n", - nghttp2_strerror(error_code), error_code, stream_id)); + nghttp2_http2_strerror(error_code), error_code, stream_id)); stream = data_s->req.protop; if(!stream) return NGHTTP2_ERR_CALLBACK_FAILURE; @@ -1006,18 +1015,11 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, if(stream->bodystarted) { /* This is a trailer */ - struct dynbuf trail; H2BUGF(infof(data_s, "h2 trailer: %.*s: %.*s\n", namelen, name, valuelen, value)); - Curl_dyn_init(&trail, DYN_H2_TRAILER); - result = Curl_dyn_addf(&trail, + result = Curl_dyn_addf(&stream->trailer_recvbuf, "%.*s: %.*s\r\n", namelen, name, valuelen, value); - if(!result) - result = Curl_client_write(conn, CLIENTWRITE_HEADER, - Curl_dyn_ptr(&trail), - Curl_dyn_len(&trail)); - Curl_dyn_free(&trail); if(result) return NGHTTP2_ERR_CALLBACK_FAILURE; @@ -1165,6 +1167,7 @@ void Curl_http2_done(struct Curl_easy *data, bool premature) /* there might be allocated resources done before this got the 'h2' pointer setup */ Curl_dyn_free(&http->header_recvbuf); + Curl_dyn_free(&http->trailer_recvbuf); if(http->push_headers) { /* if they weren't used and then freed before */ for(; http->push_headers_used > 0; --http->push_headers_used) { @@ -1174,7 +1177,8 @@ void Curl_http2_done(struct Curl_easy *data, bool premature) http->push_headers = NULL; } - if(!httpc->h2) /* not HTTP/2 ? */ + if(!(data->conn->handler->protocol&PROTO_FAMILY_HTTP) || + !httpc->h2) /* not HTTP/2 ? */ return; if(premature) { @@ -1203,6 +1207,13 @@ void Curl_http2_done(struct Curl_easy *data, bool premature) } http->stream_id = 0; } + + if(0 == nghttp2_session_check_request_allowed(httpc->h2)) { + /* No more requests are allowed in the current session, so the connection + may not be reused. This is set when a GOAWAY frame has been received or + when the limit of stream identifiers has been reached. */ + connclose(data->conn, "http/2: No new requests allowed"); + } } /* @@ -1456,7 +1467,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn, } else if(httpc->error_code != NGHTTP2_NO_ERROR) { failf(data, "HTTP/2 stream %d was not closed cleanly: %s (err %u)", - stream->stream_id, nghttp2_strerror(httpc->error_code), + stream->stream_id, nghttp2_http2_strerror(httpc->error_code), httpc->error_code); *err = CURLE_HTTP2_STREAM; return -1; @@ -1470,6 +1481,31 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn, return -1; } + if(Curl_dyn_len(&stream->trailer_recvbuf)) { + char *trailp = Curl_dyn_ptr(&stream->trailer_recvbuf); + char *lf; + + do { + size_t len = 0; + CURLcode result; + /* each trailer line ends with a newline */ + lf = strchr(trailp, '\n'); + if(!lf) + break; + len = lf + 1 - trailp; + + if(data->set.verbose) + Curl_debug(data, CURLINFO_HEADER_IN, trailp, len); + /* pass the trailers one by one to the callback */ + result = Curl_client_write(conn, CLIENTWRITE_HEADER, trailp, len); + if(result) { + *err = result; + return -1; + } + trailp = ++lf; + } while(lf); + } + stream->close_handled = TRUE; H2BUGF(infof(data, "http2_recv returns 0, http2_handle_stream_close\n")); @@ -2075,6 +2111,9 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, h2_pri_spec(conn->data, &pri_spec); + H2BUGF(infof(conn->data, "http2_send request allowed %d (easy handle %p)\n", + nghttp2_session_check_request_allowed(h2), (void *)conn->data)); + switch(conn->data->state.httpreq) { case HTTPREQ_POST: case HTTPREQ_POST_FORM: @@ -2151,6 +2190,7 @@ CURLcode Curl_http2_setup(struct connectdata *conn) stream->stream_id = -1; Curl_dyn_init(&stream->header_recvbuf, DYN_H2_HEADERS); + Curl_dyn_init(&stream->trailer_recvbuf, DYN_H2_TRAILERS); if((conn->handler == &Curl_handler_http2_ssl) || (conn->handler == &Curl_handler_http2)) diff --git a/Utilities/cmcurl/lib/md4.c b/Utilities/cmcurl/lib/md4.c index 0fab52d..67119cd 100644 --- a/Utilities/cmcurl/lib/md4.c +++ b/Utilities/cmcurl/lib/md4.c @@ -102,7 +102,9 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx) #include <openssl/md4.h> #elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \ - (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \ + (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040) && \ + defined(__MAC_OS_X_VERSION_MIN_ALLOWED) && \ + (__MAC_OS_X_VERSION_MIN_ALLOWED < 101500)) || \ (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \ (__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000)) diff --git a/Utilities/cmcurl/lib/md5.c b/Utilities/cmcurl/lib/md5.c index 557a51e..d21625f 100644 --- a/Utilities/cmcurl/lib/md5.c +++ b/Utilities/cmcurl/lib/md5.c @@ -139,7 +139,9 @@ static void MD5_Final(unsigned char *digest, MD5_CTX *ctx) } #elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \ - (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \ + (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040) && \ + defined(__MAC_OS_X_VERSION_MIN_ALLOWED) && \ + (__MAC_OS_X_VERSION_MIN_ALLOWED < 101500)) || \ (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \ (__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000)) diff --git a/Utilities/cmcurl/lib/memdebug.c b/Utilities/cmcurl/lib/memdebug.c index 1c6b151..da75c9f 100644 --- a/Utilities/cmcurl/lib/memdebug.c +++ b/Utilities/cmcurl/lib/memdebug.c @@ -456,6 +456,16 @@ FILE *curl_dbg_fopen(const char *file, const char *mode, return res; } +FILE *curl_dbg_fdopen(int filedes, const char *mode, + int line, const char *source) +{ + FILE *res = fdopen(filedes, mode); + if(source) + curl_dbg_log("FILE %s:%d fdopen(\"%d\",\"%s\") = %p\n", + source, line, filedes, mode, (void *)res); + return res; +} + int curl_dbg_fclose(FILE *file, int line, const char *source) { int res; diff --git a/Utilities/cmcurl/lib/memdebug.h b/Utilities/cmcurl/lib/memdebug.h index 7ca4426..4edafdf 100644 --- a/Utilities/cmcurl/lib/memdebug.h +++ b/Utilities/cmcurl/lib/memdebug.h @@ -8,7 +8,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -79,6 +79,9 @@ CURL_EXTERN RECV_TYPE_RETV curl_dbg_recv(RECV_TYPE_ARG1 sockfd, /* FILE functions */ CURL_EXTERN FILE *curl_dbg_fopen(const char *file, const char *mode, int line, const char *source); +CURL_EXTERN FILE *curl_dbg_fdopen(int filedes, const char *mode, + int line, const char *source); + CURL_EXTERN int curl_dbg_fclose(FILE *file, int line, const char *source); #ifndef MEMDEBUG_NODEFINES diff --git a/Utilities/cmcurl/lib/mprintf.c b/Utilities/cmcurl/lib/mprintf.c index 63c9d11..80735be 100644 --- a/Utilities/cmcurl/lib/mprintf.c +++ b/Utilities/cmcurl/lib/mprintf.c @@ -178,12 +178,14 @@ static long dprintf_DollarString(char *input, char **end) { int number = 0; while(ISDIGIT(*input)) { - number *= 10; - number += *input-'0'; + if(number < MAX_PARAMETERS) { + number *= 10; + number += *input - '0'; + } input++; } - if(number && ('$'==*input++)) { - *end = input; + if(number <= MAX_PARAMETERS && ('$' == *input)) { + *end = ++input; return number; } return 0; @@ -377,6 +379,8 @@ static int dprintf_Pass1(const char *format, struct va_stack *vto, if(width > max_param) max_param = width; break; + case '\0': + fmt--; default: break; } @@ -458,6 +462,9 @@ static int dprintf_Pass1(const char *format, struct va_stack *vto, /* we have the width specified from a parameter, so we make that parameter's info setup properly */ long k = width - 1; + if((k < 0) || (k >= MAX_PARAMETERS)) + /* out of allowed range */ + return 1; vto[i].width = k; vto[k].type = FORMAT_WIDTH; vto[k].flags = FLAGS_NEW; @@ -469,6 +476,9 @@ static int dprintf_Pass1(const char *format, struct va_stack *vto, /* we have the precision specified from a parameter, so we make that parameter's info setup properly */ long k = precision - 1; + if((k < 0) || (k >= MAX_PARAMETERS)) + /* out of allowed range */ + return 1; vto[i].precision = k; vto[k].type = FORMAT_WIDTH; vto[k].flags = FLAGS_NEW; @@ -476,7 +486,7 @@ static int dprintf_Pass1(const char *format, struct va_stack *vto, vto[k].width = 0; vto[k].precision = 0; } - *endpos++ = fmt + 1; /* end of this sequence */ + *endpos++ = fmt + ((*fmt == '\0') ? 0 : 1); /* end of this sequence */ } } @@ -754,7 +764,7 @@ static int dprintf_formatf( if(prec > 0) { width -= prec; - while(prec-- > 0) + while(prec-- > 0 && w >= work) *w-- = '0'; } @@ -918,6 +928,8 @@ static int dprintf_formatf( precision */ size_t maxprec = sizeof(work) - 2; double val = p->data.dnum; + if(width > 0 && prec <= width) + maxprec -= width; while(val >= 10.0) { val /= 10; maxprec--; @@ -925,6 +937,8 @@ static int dprintf_formatf( if(prec > (long)maxprec) prec = (long)maxprec-1; + if(prec < 0) + prec = 0; /* RECURSIVE USAGE */ len = curl_msnprintf(fptr, left, ".%ld", prec); fptr += len; diff --git a/Utilities/cmcurl/lib/multi.c b/Utilities/cmcurl/lib/multi.c index 249e360..3c7fb85 100644 --- a/Utilities/cmcurl/lib/multi.c +++ b/Utilities/cmcurl/lib/multi.c @@ -455,6 +455,7 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi, data->state.conn_cache = &data->share->conn_cache; else data->state.conn_cache = &multi->conn_cache; + data->state.lastconnect_id = -1; #ifdef USE_LIBPSL /* Do the same for PSL. */ @@ -677,11 +678,11 @@ static CURLcode multi_done(struct Curl_easy *data, CONNCACHE_UNLOCK(data); if(Curl_conncache_return_conn(data, conn)) { /* remember the most recently used connection */ - data->state.lastconnect = conn; + data->state.lastconnect_id = conn->connection_id; infof(data, "%s\n", buffer); } else - data->state.lastconnect = NULL; + data->state.lastconnect_id = -1; } Curl_safefree(data->state.buffer); @@ -689,6 +690,26 @@ static CURLcode multi_done(struct Curl_easy *data, return result; } +static int close_connect_only(struct connectdata *conn, void *param) +{ + struct Curl_easy *data = param; + + if(data->state.lastconnect_id != conn->connection_id) + return 0; + + if(conn->data != data) + return 1; + conn->data = NULL; + + if(!conn->bits.connect_only) + return 1; + + connclose(conn, "Removing connect-only easy handle"); + conn->bits.connect_only = FALSE; + + return 1; +} + CURLMcode curl_multi_remove_handle(struct Curl_multi *multi, struct Curl_easy *data) { @@ -776,10 +797,6 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi, multi_done() as that may actually call Curl_expire that uses this */ Curl_llist_destroy(&data->state.timeoutlist, NULL); - /* as this was using a shared connection cache we clear the pointer to that - since we're not part of that multi handle anymore */ - data->state.conn_cache = NULL; - /* change state without using multistate(), only to make singlesocket() do what we want */ data->mstate = CURLM_STATE_COMPLETED; @@ -789,12 +806,22 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi, /* Remove the association between the connection and the handle */ Curl_detach_connnection(data); + if(data->state.lastconnect_id != -1) { + /* Mark any connect-only connection for closure */ + Curl_conncache_foreach(data, data->state.conn_cache, + data, &close_connect_only); + } + #ifdef USE_LIBPSL /* Remove the PSL association. */ if(data->psl == &multi->psl) data->psl = NULL; #endif + /* as this was using a shared connection cache we clear the pointer to that + since we're not part of that multi handle anymore */ + data->state.conn_cache = NULL; + data->multi = NULL; /* clear the association to this multi handle */ /* make sure there's no pending message in the queue sent from this easy @@ -958,19 +985,6 @@ static int multi_getsock(struct Curl_easy *data, switch(data->mstate) { default: -#if 0 /* switch back on these cases to get the compiler to check for all enums - to be present */ - case CURLM_STATE_TOOFAST: /* returns 0, so will not select. */ - case CURLM_STATE_COMPLETED: - case CURLM_STATE_MSGSENT: - case CURLM_STATE_INIT: - case CURLM_STATE_CONNECT: - case CURLM_STATE_WAITDO: - case CURLM_STATE_DONE: - case CURLM_STATE_LAST: - /* this will get called with CURLM_STATE_COMPLETED when a handle is - removed */ -#endif return 0; case CURLM_STATE_WAITRESOLVE: @@ -1255,7 +1269,7 @@ static CURLMcode Curl_multi_wait(struct Curl_multi *multi, sleep_ms = timeout_ms; /* when there are no easy handles in the multi, this holds a -1 timeout */ - else if((sleep_ms < 0) && extrawait) + else if(sleep_ms < 0) sleep_ms = timeout_ms; Curl_wait_ms(sleep_ms); } @@ -1808,7 +1822,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, multistate(data, CURLM_STATE_SENDPROTOCONNECT); } } - else if(result) + else stream_error = TRUE; break; #endif @@ -1858,7 +1872,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, multistate(data, CURLM_STATE_DO); rc = CURLM_CALL_MULTI_PERFORM; } - else if(result) { + else { /* failure detected */ Curl_posttransfer(data); multi_done(data, result, TRUE); @@ -2962,9 +2976,7 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi, long streams = va_arg(param, long); if(streams < 1) streams = 100; - multi->max_concurrent_streams = - (streams > (long)INITIAL_MAX_CONCURRENT_STREAMS)? - INITIAL_MAX_CONCURRENT_STREAMS : (unsigned int)streams; + multi->max_concurrent_streams = curlx_sltoui(streams); } break; default: diff --git a/Utilities/cmcurl/lib/multihandle.h b/Utilities/cmcurl/lib/multihandle.h index 91eca16..9d73df0 100644 --- a/Utilities/cmcurl/lib/multihandle.h +++ b/Utilities/cmcurl/lib/multihandle.h @@ -81,7 +81,7 @@ struct Curl_multi { this multi handle with an easy handle. Set this to CURL_MULTI_HANDLE. */ long type; - /* We have a doubly-linked circular list with easy handles */ + /* We have a doubly-linked list with easy handles */ struct Curl_easy *easyp; struct Curl_easy *easylp; /* last node */ diff --git a/Utilities/cmcurl/lib/parsedate.c b/Utilities/cmcurl/lib/parsedate.c index 585d7ea..4c7a40c 100644 --- a/Utilities/cmcurl/lib/parsedate.c +++ b/Utilities/cmcurl/lib/parsedate.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -624,6 +624,7 @@ CURLcode Curl_gmtime(time_t intime, struct tm *store) /* thread-safe version */ tm = (struct tm *)gmtime_r(&intime, store); #else + /* !checksrc! disable BANNEDFUNC 1 */ tm = gmtime(&intime); if(tm) *store = *tm; /* copy the pointed struct to the local copy */ diff --git a/Utilities/cmcurl/lib/rename.c b/Utilities/cmcurl/lib/rename.c index bb170d3..fe5f95d 100644 --- a/Utilities/cmcurl/lib/rename.c +++ b/Utilities/cmcurl/lib/rename.c @@ -27,6 +27,7 @@ #if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)) || \ defined(USE_ALTSVC) +#include "curl_multibyte.h" #include "timeval.h" /* The last 3 #include files should be in this order */ @@ -39,17 +40,25 @@ int Curl_rename(const char *oldpath, const char *newpath) { #ifdef WIN32 /* rename() on Windows doesn't overwrite, so we can't use it here. - MoveFileExA() will overwrite and is usually atomic, however it fails + MoveFileEx() will overwrite and is usually atomic, however it fails when there are open handles to the file. */ const int max_wait_ms = 1000; struct curltime start = Curl_now(); + TCHAR *tchar_oldpath = curlx_convert_UTF8_to_tchar((char *)oldpath); + TCHAR *tchar_newpath = curlx_convert_UTF8_to_tchar((char *)newpath); for(;;) { timediff_t diff; - if(MoveFileExA(oldpath, newpath, MOVEFILE_REPLACE_EXISTING)) + if(MoveFileEx(tchar_oldpath, tchar_newpath, MOVEFILE_REPLACE_EXISTING)) { + curlx_unicodefree(tchar_oldpath); + curlx_unicodefree(tchar_newpath); break; + } diff = Curl_timediff(Curl_now(), start); - if(diff < 0 || diff > max_wait_ms) + if(diff < 0 || diff > max_wait_ms) { + curlx_unicodefree(tchar_oldpath); + curlx_unicodefree(tchar_newpath); return 1; + } Sleep(1); } #else diff --git a/Utilities/cmcurl/lib/setopt.c b/Utilities/cmcurl/lib/setopt.c index 90edf6a..d621335 100644 --- a/Utilities/cmcurl/lib/setopt.c +++ b/Utilities/cmcurl/lib/setopt.c @@ -274,6 +274,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) if(data->set.opt_no_body) /* in HTTP lingo, no body means using the HEAD request... */ data->set.method = HTTPREQ_HEAD; + else if(data->set.method == HTTPREQ_HEAD) + data->set.method = HTTPREQ_GET; break; case CURLOPT_FAILONERROR: /* diff --git a/Utilities/cmcurl/lib/smtp.c b/Utilities/cmcurl/lib/smtp.c index 685513b..aea41bb 100644 --- a/Utilities/cmcurl/lib/smtp.c +++ b/Utilities/cmcurl/lib/smtp.c @@ -1760,8 +1760,10 @@ static CURLcode smtp_parse_address(struct connectdata *conn, const char *fqma, return CURLE_OUT_OF_MEMORY; length = strlen(dup); - if(dup[length - 1] == '>') - dup[length - 1] = '\0'; + if(length) { + if(dup[length - 1] == '>') + dup[length - 1] = '\0'; + } /* Extract the host name from the address (if we can) */ host->name = strpbrk(dup, "@"); diff --git a/Utilities/cmcurl/lib/socks.c b/Utilities/cmcurl/lib/socks.c index b2215fe..44783d0 100644 --- a/Utilities/cmcurl/lib/socks.c +++ b/Utilities/cmcurl/lib/socks.c @@ -327,18 +327,18 @@ CURLcode Curl_SOCKS4(const char *proxy_user, * Make connection */ { - ssize_t packetsize = 9 + + size_t packetsize = 9 + strlen((char *)socksreq + 8); /* size including NUL */ /* If SOCKS4a, set special invalid IP address 0.0.0.x */ if(protocol4a) { - ssize_t hostnamelen = 0; + size_t hostnamelen = 0; socksreq[4] = 0; socksreq[5] = 0; socksreq[6] = 0; socksreq[7] = 1; /* append hostname */ - hostnamelen = (ssize_t)strlen(hostname) + 1; /* length including NUL */ + hostnamelen = strlen(hostname) + 1; /* length including NUL */ if(hostnamelen <= 255) strcpy((char *)socksreq + packetsize, hostname); else { diff --git a/Utilities/cmcurl/lib/strdup.c b/Utilities/cmcurl/lib/strdup.c index 1ab10fd..7732802 100644 --- a/Utilities/cmcurl/lib/strdup.c +++ b/Utilities/cmcurl/lib/strdup.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -39,19 +39,14 @@ char *curlx_strdup(const char *str) if(!str) return (char *)NULL; - len = strlen(str); + len = strlen(str) + 1; - if(len >= ((size_t)-1) / sizeof(char)) - return (char *)NULL; - - newstr = malloc((len + 1)*sizeof(char)); + newstr = malloc(len); if(!newstr) return (char *)NULL; - memcpy(newstr, str, (len + 1)*sizeof(char)); - + memcpy(newstr, str, len); return newstr; - } #endif diff --git a/Utilities/cmcurl/lib/system_win32.c b/Utilities/cmcurl/lib/system_win32.c index b9587b5..2e59e03 100644 --- a/Utilities/cmcurl/lib/system_win32.c +++ b/Utilities/cmcurl/lib/system_win32.c @@ -26,6 +26,7 @@ #include <curl/curl.h> #include "system_win32.h" +#include "version_win32.h" #include "curl_sspi.h" #include "warnless.h" @@ -106,8 +107,8 @@ CURLcode Curl_win32_init(long flags) Curl_if_nametoindex = pIfNameToIndex; } - if(Curl_verify_windows_version(6, 0, PLATFORM_WINNT, - VERSION_GREATER_THAN_EQUAL)) { + if(curlx_verify_windows_version(6, 0, PLATFORM_WINNT, + VERSION_GREATER_THAN_EQUAL)) { Curl_isVistaOrGreater = TRUE; } else @@ -160,198 +161,6 @@ typedef HMODULE (APIENTRY *LOADLIBRARYEX_FN)(LPCTSTR, HANDLE, DWORD); #endif /* - * Curl_verify_windows_version() - * - * This is used to verify if we are running on a specific windows version. - * - * Parameters: - * - * majorVersion [in] - The major version number. - * minorVersion [in] - The minor version number. - * platform [in] - The optional platform identifier. - * condition [in] - The test condition used to specifier whether we are - * checking a version less then, equal to or greater than - * what is specified in the major and minor version - * numbers. - * - * Returns TRUE if matched; otherwise FALSE. - */ -bool Curl_verify_windows_version(const unsigned int majorVersion, - const unsigned int minorVersion, - const PlatformIdentifier platform, - const VersionCondition condition) -{ - bool matched = FALSE; - -#if defined(CURL_WINDOWS_APP) - /* We have no way to determine the Windows version from Windows apps, - so let's assume we're running on the target Windows version. */ - const WORD fullVersion = MAKEWORD(minorVersion, majorVersion); - const WORD targetVersion = (WORD)_WIN32_WINNT; - - switch(condition) { - case VERSION_LESS_THAN: - matched = targetVersion < fullVersion; - break; - - case VERSION_LESS_THAN_EQUAL: - matched = targetVersion <= fullVersion; - break; - - case VERSION_EQUAL: - matched = targetVersion == fullVersion; - break; - - case VERSION_GREATER_THAN_EQUAL: - matched = targetVersion >= fullVersion; - break; - - case VERSION_GREATER_THAN: - matched = targetVersion > fullVersion; - break; - } - - if(matched && (platform == PLATFORM_WINDOWS)) { - /* we're always running on PLATFORM_WINNT */ - matched = FALSE; - } -#elif !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \ - (_WIN32_WINNT < _WIN32_WINNT_WIN2K) - OSVERSIONINFO osver; - - memset(&osver, 0, sizeof(osver)); - osver.dwOSVersionInfoSize = sizeof(osver); - - /* Find out Windows version */ - if(GetVersionEx(&osver)) { - /* Verify the Operating System version number */ - switch(condition) { - case VERSION_LESS_THAN: - if(osver.dwMajorVersion < majorVersion || - (osver.dwMajorVersion == majorVersion && - osver.dwMinorVersion < minorVersion)) - matched = TRUE; - break; - - case VERSION_LESS_THAN_EQUAL: - if(osver.dwMajorVersion < majorVersion || - (osver.dwMajorVersion == majorVersion && - osver.dwMinorVersion <= minorVersion)) - matched = TRUE; - break; - - case VERSION_EQUAL: - if(osver.dwMajorVersion == majorVersion && - osver.dwMinorVersion == minorVersion) - matched = TRUE; - break; - - case VERSION_GREATER_THAN_EQUAL: - if(osver.dwMajorVersion > majorVersion || - (osver.dwMajorVersion == majorVersion && - osver.dwMinorVersion >= minorVersion)) - matched = TRUE; - break; - - case VERSION_GREATER_THAN: - if(osver.dwMajorVersion > majorVersion || - (osver.dwMajorVersion == majorVersion && - osver.dwMinorVersion > minorVersion)) - matched = TRUE; - break; - } - - /* Verify the platform identifier (if necessary) */ - if(matched) { - switch(platform) { - case PLATFORM_WINDOWS: - if(osver.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS) - matched = FALSE; - break; - - case PLATFORM_WINNT: - if(osver.dwPlatformId != VER_PLATFORM_WIN32_NT) - matched = FALSE; - - default: /* like platform == PLATFORM_DONT_CARE */ - break; - } - } - } -#else - ULONGLONG cm = 0; - OSVERSIONINFOEX osver; - BYTE majorCondition; - BYTE minorCondition; - BYTE spMajorCondition; - BYTE spMinorCondition; - - switch(condition) { - case VERSION_LESS_THAN: - majorCondition = VER_LESS; - minorCondition = VER_LESS; - spMajorCondition = VER_LESS_EQUAL; - spMinorCondition = VER_LESS_EQUAL; - break; - - case VERSION_LESS_THAN_EQUAL: - majorCondition = VER_LESS_EQUAL; - minorCondition = VER_LESS_EQUAL; - spMajorCondition = VER_LESS_EQUAL; - spMinorCondition = VER_LESS_EQUAL; - break; - - case VERSION_EQUAL: - majorCondition = VER_EQUAL; - minorCondition = VER_EQUAL; - spMajorCondition = VER_GREATER_EQUAL; - spMinorCondition = VER_GREATER_EQUAL; - break; - - case VERSION_GREATER_THAN_EQUAL: - majorCondition = VER_GREATER_EQUAL; - minorCondition = VER_GREATER_EQUAL; - spMajorCondition = VER_GREATER_EQUAL; - spMinorCondition = VER_GREATER_EQUAL; - break; - - case VERSION_GREATER_THAN: - majorCondition = VER_GREATER; - minorCondition = VER_GREATER; - spMajorCondition = VER_GREATER_EQUAL; - spMinorCondition = VER_GREATER_EQUAL; - break; - - default: - return FALSE; - } - - memset(&osver, 0, sizeof(osver)); - osver.dwOSVersionInfoSize = sizeof(osver); - osver.dwMajorVersion = majorVersion; - osver.dwMinorVersion = minorVersion; - if(platform == PLATFORM_WINDOWS) - osver.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS; - else if(platform == PLATFORM_WINNT) - osver.dwPlatformId = VER_PLATFORM_WIN32_NT; - - cm = VerSetConditionMask(cm, VER_MAJORVERSION, majorCondition); - cm = VerSetConditionMask(cm, VER_MINORVERSION, minorCondition); - cm = VerSetConditionMask(cm, VER_SERVICEPACKMAJOR, spMajorCondition); - cm = VerSetConditionMask(cm, VER_SERVICEPACKMINOR, spMinorCondition); - if(platform != PLATFORM_DONT_CARE) - cm = VerSetConditionMask(cm, VER_PLATFORMID, VER_EQUAL); - - if(VerifyVersionInfo(&osver, (VER_MAJORVERSION | VER_MINORVERSION | - VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR), - cm)) - matched = TRUE; -#endif - - return matched; -} - -/* * Curl_load_library() * * This is used to dynamically load DLLs using the most secure method available diff --git a/Utilities/cmcurl/lib/system_win32.h b/Utilities/cmcurl/lib/system_win32.h index d2882fc..2547bda 100644 --- a/Utilities/cmcurl/lib/system_win32.h +++ b/Utilities/cmcurl/lib/system_win32.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2016 - 2019, Steve Holme, <steve_holme@hotmail.com>. + * Copyright (C) 2016 - 2020, Steve Holme, <steve_holme@hotmail.com>. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -32,34 +32,12 @@ extern bool Curl_isVistaOrGreater; CURLcode Curl_win32_init(long flags); void Curl_win32_cleanup(long init_flags); -/* Version condition */ -typedef enum { - VERSION_LESS_THAN, - VERSION_LESS_THAN_EQUAL, - VERSION_EQUAL, - VERSION_GREATER_THAN_EQUAL, - VERSION_GREATER_THAN -} VersionCondition; - -/* Platform identifier */ -typedef enum { - PLATFORM_DONT_CARE, - PLATFORM_WINDOWS, - PLATFORM_WINNT -} PlatformIdentifier; - /* We use our own typedef here since some headers might lack this */ typedef unsigned int(WINAPI *IF_NAMETOINDEX_FN)(const char *); /* This is used instead of if_nametoindex if available on Windows */ extern IF_NAMETOINDEX_FN Curl_if_nametoindex; -/* This is used to verify if we are running on a specific windows version */ -bool Curl_verify_windows_version(const unsigned int majorVersion, - const unsigned int minorVersion, - const PlatformIdentifier platform, - const VersionCondition condition); - /* This is used to dynamically load DLLs */ HMODULE Curl_load_library(LPCTSTR filename); diff --git a/Utilities/cmcurl/lib/transfer.c b/Utilities/cmcurl/lib/transfer.c index 133a478..a07c7af 100644 --- a/Utilities/cmcurl/lib/transfer.c +++ b/Utilities/cmcurl/lib/transfer.c @@ -487,6 +487,12 @@ CURLcode Curl_readrewind(struct connectdata *conn) static int data_pending(const struct Curl_easy *data) { struct connectdata *conn = data->conn; + +#ifdef ENABLE_QUIC + if(conn->transport == TRNSPRT_QUIC) + return Curl_quic_data_pending(data); +#endif + /* in the case of libssh2, we can never be really sure that we have emptied its internal buffers so we MUST always try until we get EAGAIN back */ return conn->handler->protocol&(CURLPROTO_SCP|CURLPROTO_SFTP) || @@ -500,8 +506,6 @@ static int data_pending(const struct Curl_easy *data) be called and we cannot signal the HTTP/2 stream has closed. As a workaround, we return nonzero here to call http2_recv. */ ((conn->handler->protocol&PROTO_FAMILY_HTTP) && conn->httpversion >= 20); -#elif defined(ENABLE_QUIC) - Curl_ssl_data_pending(conn, FIRSTSOCKET) || Curl_quic_data_pending(data); #else Curl_ssl_data_pending(conn, FIRSTSOCKET); #endif @@ -1441,8 +1445,9 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) if(!data->change.url && data->set.uh) { CURLUcode uc; + free(data->set.str[STRING_SET_URL]); uc = curl_url_get(data->set.uh, - CURLUPART_URL, &data->set.str[STRING_SET_URL], 0); + CURLUPART_URL, &data->set.str[STRING_SET_URL], 0); if(uc) { failf(data, "No URL set!"); return CURLE_URL_MALFORMAT; @@ -1799,12 +1804,14 @@ CURLcode Curl_retry_request(struct connectdata *conn, } if(retry) { #define CONN_MAX_RETRIES 5 - if(conn->retrycount++ >= CONN_MAX_RETRIES) { + if(data->state.retrycount++ >= CONN_MAX_RETRIES) { failf(data, "Connection died, tried %d times before giving up", CONN_MAX_RETRIES); + data->state.retrycount = 0; return CURLE_SEND_ERROR; } - infof(conn->data, "Connection died, retrying a fresh connect\n"); + infof(conn->data, "Connection died, retrying a fresh connect\ +(retry count: %d)\n", data->state.retrycount); *url = strdup(conn->data->change.url); if(!*url) return CURLE_OUT_OF_MEMORY; diff --git a/Utilities/cmcurl/lib/url.c b/Utilities/cmcurl/lib/url.c index a1a6b69..150667a 100644 --- a/Utilities/cmcurl/lib/url.c +++ b/Utilities/cmcurl/lib/url.c @@ -630,7 +630,7 @@ CURLcode Curl_open(struct Curl_easy **curl) Curl_initinfo(data); /* most recent connection is not yet defined */ - data->state.lastconnect = NULL; + data->state.lastconnect_id = -1; data->progress.flags |= PGRS_HIDE; data->state.current_speed = -1; /* init to negative == impossible */ @@ -1836,11 +1836,12 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, CURLU *uh; CURLUcode uc; char *hostname; + bool use_set_uh = (data->set.uh && !data->state.this_is_a_follow); up_free(data); /* cleanup previous leftovers first */ /* parse the URL */ - if(data->set.uh) { + if(use_set_uh) { uh = data->state.uh = curl_url_dup(data->set.uh); } else { @@ -1863,7 +1864,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, data->change.url_alloc = TRUE; } - if(!data->set.uh) { + if(!use_set_uh) { char *newurl; uc = curl_url_set(uh, CURLUPART_URL, data->change.url, CURLU_GUESS_SCHEME | @@ -3170,7 +3171,7 @@ static CURLcode resolve_server(struct Curl_easy *data, else { /* this is a fresh connect */ int rc; - struct Curl_dns_entry *hostaddr; + struct Curl_dns_entry *hostaddr = NULL; #ifdef USE_UNIX_SOCKETS if(conn->unix_domain_socket) { diff --git a/Utilities/cmcurl/lib/urldata.h b/Utilities/cmcurl/lib/urldata.h index f80a02d..0ae9269 100644 --- a/Utilities/cmcurl/lib/urldata.h +++ b/Utilities/cmcurl/lib/urldata.h @@ -1090,7 +1090,6 @@ struct connectdata { struct http_connect_state *connect_state; /* for HTTP CONNECT */ struct connectbundle *bundle; /* The bundle we are member of */ int negnpn; /* APLN or NPN TLS negotiated protocol, CURL_HTTP_VERSION* */ - int retrycount; /* number of retries on a new connection */ #ifdef USE_UNIX_SOCKETS char *unix_domain_socket; #endif @@ -1195,7 +1194,6 @@ typedef enum { HTTPREQ_POST_MIME, /* we make a difference internally */ HTTPREQ_PUT, HTTPREQ_HEAD, - HTTPREQ_OPTIONS, HTTPREQ_LAST /* last in list */ } Curl_HttpReq; @@ -1297,10 +1295,12 @@ struct UrlState { /* Points to the connection cache */ struct conncache *conn_cache; + int retrycount; /* number of retries on a new connection */ + /* buffers to store authentication data in, as parsed from input options */ struct curltime keeps_speed; /* for the progress meter really */ - struct connectdata *lastconnect; /* The last connection, NULL if undefined */ + long lastconnect_id; /* The last connection, -1 if undefined */ struct dynbuf headerb; /* buffer to store headers in */ char *buffer; /* download buffer */ diff --git a/Utilities/cmcurl/lib/vauth/ntlm.c b/Utilities/cmcurl/lib/vauth/ntlm.c index 3b46e1a..ecfeacb 100644 --- a/Utilities/cmcurl/lib/vauth/ntlm.c +++ b/Utilities/cmcurl/lib/vauth/ntlm.c @@ -191,6 +191,7 @@ static CURLcode ntlm_decode_type2_target(struct Curl_easy *data, return CURLE_BAD_CONTENT_ENCODING; } + free(ntlm->target_info); /* replace any previous data */ ntlm->target_info = malloc(target_info_len); if(!ntlm->target_info) return CURLE_OUT_OF_MEMORY; diff --git a/Utilities/cmcurl/lib/version.c b/Utilities/cmcurl/lib/version.c index 14e5096..4f6dda2 100644 --- a/Utilities/cmcurl/lib/version.c +++ b/Utilities/cmcurl/lib/version.c @@ -66,6 +66,10 @@ #include <brotli/decode.h> #endif +#ifdef HAVE_ZSTD +#include <zstd.h> +#endif + #ifdef HAVE_BROTLI static size_t brotli_version(char *buf, size_t bufsz) { @@ -78,6 +82,20 @@ static size_t brotli_version(char *buf, size_t bufsz) } #endif +#ifdef HAVE_ZSTD +static size_t zstd_version(char *buf, size_t bufsz) +{ + unsigned long zstd_version = (unsigned long)ZSTD_versionNumber(); + unsigned int major = (unsigned int)(zstd_version / (100 * 100)); + unsigned int minor = (unsigned int)((zstd_version - + (major * 100 * 100)) / 100); + unsigned int patch = (unsigned int)(zstd_version - + (major * 100 * 100) - (minor * 100)); + + return msnprintf(buf, bufsz, "%u.%u.%u", major, minor, patch); +} +#endif + /* * curl_version() returns a pointer to a static buffer. * @@ -103,6 +121,9 @@ char *curl_version(void) #ifdef HAVE_BROTLI char br_version[40] = "brotli/"; #endif +#ifdef HAVE_ZSTD + char zst_version[40] = "zstd/"; +#endif #ifdef USE_ARES char cares_version[40]; #endif @@ -153,6 +174,10 @@ char *curl_version(void) brotli_version(&br_version[7], sizeof(br_version) - 7); src[i++] = br_version; #endif +#ifdef HAVE_ZSTD + zstd_version(&zst_version[5], sizeof(zst_version) - 5); + src[i++] = zst_version; +#endif #ifdef USE_ARES msnprintf(cares_version, sizeof(cares_version), "c-ares/%s", ares_version(NULL)); @@ -365,6 +390,9 @@ static curl_version_info_data version_info = { ( (SIZEOF_OFF_T > 4) || defined(USE_WIN32_LARGE_FILES) ) | CURL_VERSION_LARGEFILE #endif +#if defined(WIN32) && defined(UNICODE) && defined(_UNICODE) + | CURL_VERSION_UNICODE +#endif #if defined(CURL_DOES_CONVERSIONS) | CURL_VERSION_CONV #endif @@ -389,6 +417,9 @@ static curl_version_info_data version_info = { #if defined(HAVE_BROTLI) | CURL_VERSION_BROTLI #endif +#if defined(HAVE_ZSTD) + | CURL_VERSION_ZSTD +#endif #if defined(USE_ALTSVC) | CURL_VERSION_ALTSVC #endif @@ -413,10 +444,12 @@ static curl_version_info_data version_info = { NULL, #endif #ifdef CURL_CA_PATH - CURL_CA_PATH /* capath */ + CURL_CA_PATH, /* capath */ #else - NULL + NULL, #endif + 0, /* zstd_ver_num */ + NULL /* zstd version */ }; curl_version_info_data *curl_version_info(CURLversion stamp) @@ -434,6 +467,10 @@ curl_version_info_data *curl_version_info(CURLversion stamp) #ifdef HAVE_BROTLI static char brotli_buffer[80]; #endif +#ifdef HAVE_ZSTD + static char zstd_buffer[80]; +#endif + #ifdef USE_SSL Curl_ssl_version(ssl_buffer, sizeof(ssl_buffer)); @@ -485,6 +522,12 @@ curl_version_info_data *curl_version_info(CURLversion stamp) version_info.brotli_version = brotli_buffer; #endif +#ifdef HAVE_ZSTD + version_info.zstd_ver_num = (unsigned int)ZSTD_versionNumber(); + zstd_version(zstd_buffer, sizeof(zstd_buffer)); + version_info.zstd_version = zstd_buffer; +#endif + #ifdef USE_NGHTTP2 { nghttp2_info *h2 = nghttp2_version(0); diff --git a/Utilities/cmcurl/lib/version_win32.c b/Utilities/cmcurl/lib/version_win32.c new file mode 100644 index 0000000..6561d36 --- /dev/null +++ b/Utilities/cmcurl/lib/version_win32.c @@ -0,0 +1,226 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2016 - 2020, Steve Holme, <steve_holme@hotmail.com>. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(WIN32) + +#include <curl/curl.h> +#include "version_win32.h" + +/* The last #include files should be: */ +#include "curl_memory.h" +#include "memdebug.h" + +/* + * curlx_verify_windows_version() + * + * This is used to verify if we are running on a specific windows version. + * + * Parameters: + * + * majorVersion [in] - The major version number. + * minorVersion [in] - The minor version number. + * platform [in] - The optional platform identifier. + * condition [in] - The test condition used to specifier whether we are + * checking a version less then, equal to or greater than + * what is specified in the major and minor version + * numbers. + * + * Returns TRUE if matched; otherwise FALSE. + */ +bool curlx_verify_windows_version(const unsigned int majorVersion, + const unsigned int minorVersion, + const PlatformIdentifier platform, + const VersionCondition condition) +{ + bool matched = FALSE; + +#if defined(CURL_WINDOWS_APP) + /* We have no way to determine the Windows version from Windows apps, + so let's assume we're running on the target Windows version. */ + const WORD fullVersion = MAKEWORD(minorVersion, majorVersion); + const WORD targetVersion = (WORD)_WIN32_WINNT; + + switch(condition) { + case VERSION_LESS_THAN: + matched = targetVersion < fullVersion; + break; + + case VERSION_LESS_THAN_EQUAL: + matched = targetVersion <= fullVersion; + break; + + case VERSION_EQUAL: + matched = targetVersion == fullVersion; + break; + + case VERSION_GREATER_THAN_EQUAL: + matched = targetVersion >= fullVersion; + break; + + case VERSION_GREATER_THAN: + matched = targetVersion > fullVersion; + break; + } + + if(matched && (platform == PLATFORM_WINDOWS)) { + /* we're always running on PLATFORM_WINNT */ + matched = FALSE; + } +#elif !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \ + (_WIN32_WINNT < _WIN32_WINNT_WIN2K) + OSVERSIONINFO osver; + + memset(&osver, 0, sizeof(osver)); + osver.dwOSVersionInfoSize = sizeof(osver); + + /* Find out Windows version */ + if(GetVersionEx(&osver)) { + /* Verify the Operating System version number */ + switch(condition) { + case VERSION_LESS_THAN: + if(osver.dwMajorVersion < majorVersion || + (osver.dwMajorVersion == majorVersion && + osver.dwMinorVersion < minorVersion)) + matched = TRUE; + break; + + case VERSION_LESS_THAN_EQUAL: + if(osver.dwMajorVersion < majorVersion || + (osver.dwMajorVersion == majorVersion && + osver.dwMinorVersion <= minorVersion)) + matched = TRUE; + break; + + case VERSION_EQUAL: + if(osver.dwMajorVersion == majorVersion && + osver.dwMinorVersion == minorVersion) + matched = TRUE; + break; + + case VERSION_GREATER_THAN_EQUAL: + if(osver.dwMajorVersion > majorVersion || + (osver.dwMajorVersion == majorVersion && + osver.dwMinorVersion >= minorVersion)) + matched = TRUE; + break; + + case VERSION_GREATER_THAN: + if(osver.dwMajorVersion > majorVersion || + (osver.dwMajorVersion == majorVersion && + osver.dwMinorVersion > minorVersion)) + matched = TRUE; + break; + } + + /* Verify the platform identifier (if necessary) */ + if(matched) { + switch(platform) { + case PLATFORM_WINDOWS: + if(osver.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS) + matched = FALSE; + break; + + case PLATFORM_WINNT: + if(osver.dwPlatformId != VER_PLATFORM_WIN32_NT) + matched = FALSE; + + default: /* like platform == PLATFORM_DONT_CARE */ + break; + } + } + } +#else + ULONGLONG cm = 0; + OSVERSIONINFOEX osver; + BYTE majorCondition; + BYTE minorCondition; + BYTE spMajorCondition; + BYTE spMinorCondition; + + switch(condition) { + case VERSION_LESS_THAN: + majorCondition = VER_LESS; + minorCondition = VER_LESS; + spMajorCondition = VER_LESS_EQUAL; + spMinorCondition = VER_LESS_EQUAL; + break; + + case VERSION_LESS_THAN_EQUAL: + majorCondition = VER_LESS_EQUAL; + minorCondition = VER_LESS_EQUAL; + spMajorCondition = VER_LESS_EQUAL; + spMinorCondition = VER_LESS_EQUAL; + break; + + case VERSION_EQUAL: + majorCondition = VER_EQUAL; + minorCondition = VER_EQUAL; + spMajorCondition = VER_GREATER_EQUAL; + spMinorCondition = VER_GREATER_EQUAL; + break; + + case VERSION_GREATER_THAN_EQUAL: + majorCondition = VER_GREATER_EQUAL; + minorCondition = VER_GREATER_EQUAL; + spMajorCondition = VER_GREATER_EQUAL; + spMinorCondition = VER_GREATER_EQUAL; + break; + + case VERSION_GREATER_THAN: + majorCondition = VER_GREATER; + minorCondition = VER_GREATER; + spMajorCondition = VER_GREATER_EQUAL; + spMinorCondition = VER_GREATER_EQUAL; + break; + + default: + return FALSE; + } + + memset(&osver, 0, sizeof(osver)); + osver.dwOSVersionInfoSize = sizeof(osver); + osver.dwMajorVersion = majorVersion; + osver.dwMinorVersion = minorVersion; + if(platform == PLATFORM_WINDOWS) + osver.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS; + else if(platform == PLATFORM_WINNT) + osver.dwPlatformId = VER_PLATFORM_WIN32_NT; + + cm = VerSetConditionMask(cm, VER_MAJORVERSION, majorCondition); + cm = VerSetConditionMask(cm, VER_MINORVERSION, minorCondition); + cm = VerSetConditionMask(cm, VER_SERVICEPACKMAJOR, spMajorCondition); + cm = VerSetConditionMask(cm, VER_SERVICEPACKMINOR, spMinorCondition); + if(platform != PLATFORM_DONT_CARE) + cm = VerSetConditionMask(cm, VER_PLATFORMID, VER_EQUAL); + + if(VerifyVersionInfo(&osver, (VER_MAJORVERSION | VER_MINORVERSION | + VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR), + cm)) + matched = TRUE; +#endif + + return matched; +} + +#endif /* WIN32 */ diff --git a/Utilities/cmcurl/lib/version_win32.h b/Utilities/cmcurl/lib/version_win32.h new file mode 100644 index 0000000..94cc626 --- /dev/null +++ b/Utilities/cmcurl/lib/version_win32.h @@ -0,0 +1,53 @@ +#ifndef HEADER_CURL_VERSION_WIN32_H +#define HEADER_CURL_VERSION_WIN32_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2016 - 2020, Steve Holme, <steve_holme@hotmail.com>. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(WIN32) + +/* Version condition */ +typedef enum { + VERSION_LESS_THAN, + VERSION_LESS_THAN_EQUAL, + VERSION_EQUAL, + VERSION_GREATER_THAN_EQUAL, + VERSION_GREATER_THAN +} VersionCondition; + +/* Platform identifier */ +typedef enum { + PLATFORM_DONT_CARE, + PLATFORM_WINDOWS, + PLATFORM_WINNT +} PlatformIdentifier; + +/* This is used to verify if we are running on a specific windows version */ +bool curlx_verify_windows_version(const unsigned int majorVersion, + const unsigned int minorVersion, + const PlatformIdentifier platform, + const VersionCondition condition); + +#endif /* WIN32 */ + +#endif /* HEADER_CURL_VERSION_WIN32_H */ diff --git a/Utilities/cmcurl/lib/vquic/ngtcp2.c b/Utilities/cmcurl/lib/vquic/ngtcp2.c index d29cb37..20ee08d 100644 --- a/Utilities/cmcurl/lib/vquic/ngtcp2.c +++ b/Utilities/cmcurl/lib/vquic/ngtcp2.c @@ -150,9 +150,11 @@ quic_from_gtls_level(gnutls_record_encryption_level_t gtls_level) } #endif -static void qlog_callback(void *user_data, const void *data, size_t datalen) +static void qlog_callback(void *user_data, uint32_t flags, + const void *data, size_t datalen) { struct quicsocket *qs = (struct quicsocket *)user_data; + (void)flags; if(qs->qlogfd != -1) { ssize_t rc = write(qs->qlogfd, data, datalen); if(rc == -1) { @@ -826,9 +828,8 @@ CURLcode Curl_quic_connect(struct connectdata *conn, if(rv == -1) return CURLE_QUIC_CONNECT_ERROR; - ngtcp2_addr_init(&path.local, (uint8_t *)&qs->local_addr, qs->local_addrlen, - NULL); - ngtcp2_addr_init(&path.remote, (uint8_t*)addr, addrlen, NULL); + ngtcp2_addr_init(&path.local, &qs->local_addr, qs->local_addrlen, NULL); + ngtcp2_addr_init(&path.remote, addr, addrlen, NULL); #ifdef NGTCP2_PROTO_VER #define QUICVER NGTCP2_PROTO_VER @@ -1744,10 +1745,10 @@ static CURLcode ng_process_ingress(struct connectdata *conn, int sockfd, return CURLE_RECV_ERROR; } - ngtcp2_addr_init(&path.local, (uint8_t *)&qs->local_addr, + ngtcp2_addr_init(&path.local, &qs->local_addr, qs->local_addrlen, NULL); - ngtcp2_addr_init(&path.remote, (uint8_t *)&remote_addr, remote_addrlen, - NULL); + ngtcp2_addr_init(&path.remote, (struct sockaddr *)&remote_addr, + remote_addrlen, NULL); rv = ngtcp2_conn_read_pkt(qs->qconn, &path, buf, recvd, ts); if(rv != 0) { @@ -1778,7 +1779,7 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd, nghttp3_vec vec[16]; ssize_t ndatalen; - switch(qs->local_addr.ss_family) { + switch(qs->local_addr.sa_family) { case AF_INET: pktlen = NGTCP2_MAX_PKTLEN_IPV4; break; @@ -1834,7 +1835,7 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd, } continue; } - else if(outlen == NGTCP2_ERR_WRITE_STREAM_MORE) { + else if(outlen == NGTCP2_ERR_WRITE_MORE) { assert(ndatalen > 0); rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id, ndatalen); diff --git a/Utilities/cmcurl/lib/vquic/ngtcp2.h b/Utilities/cmcurl/lib/vquic/ngtcp2.h index e2f8b56..afdd01b 100644 --- a/Utilities/cmcurl/lib/vquic/ngtcp2.h +++ b/Utilities/cmcurl/lib/vquic/ngtcp2.h @@ -58,7 +58,7 @@ struct quicsocket { struct quic_handshake crypto_data[3]; /* the last TLS alert description generated by the local endpoint */ uint8_t tls_alert; - struct sockaddr_storage local_addr; + struct sockaddr local_addr; socklen_t local_addrlen; nghttp3_conn *h3conn; diff --git a/Utilities/cmcurl/lib/vquic/quiche.c b/Utilities/cmcurl/lib/vquic/quiche.c index be6f15c..fd9cb8b 100644 --- a/Utilities/cmcurl/lib/vquic/quiche.c +++ b/Utilities/cmcurl/lib/vquic/quiche.c @@ -95,8 +95,14 @@ static CURLcode qs_disconnect(struct quicsocket *qs) quiche_h3_config_free(qs->h3config); if(qs->h3c) quiche_h3_conn_free(qs->h3c); - quiche_config_free(qs->cfg); - quiche_conn_free(qs->conn); + if(qs->cfg) { + quiche_config_free(qs->cfg); + qs->cfg = NULL; + } + if(qs->conn) { + quiche_conn_free(qs->conn); + qs->conn = NULL; + } return CURLE_OK; } diff --git a/Utilities/cmcurl/lib/vssh/libssh2.c b/Utilities/cmcurl/lib/vssh/libssh2.c index 555afc9..4f56bb4 100644 --- a/Utilities/cmcurl/lib/vssh/libssh2.c +++ b/Utilities/cmcurl/lib/vssh/libssh2.c @@ -1256,7 +1256,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) result = CURLE_SSH; sshc->actualcode = result; DEBUGF(infof(data, "error = %d makes libcurl = %d\n", - ssherr, (int)result)); + sftperr, (int)result)); state(conn, SSH_STOP); break; } diff --git a/Utilities/cmcurl/lib/vtls/bearssl.c b/Utilities/cmcurl/lib/vtls/bearssl.c index 628e16a..44e7406 100644 --- a/Utilities/cmcurl/lib/vtls/bearssl.c +++ b/Utilities/cmcurl/lib/vtls/bearssl.c @@ -300,8 +300,12 @@ static CURLcode bearssl_connect_step1(struct connectdata *conn, int sockindex) struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); +#ifndef CURL_DISABLE_PROXY const char *hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name; +#else + const char *hostname = conn->host.name; +#endif const bool verifypeer = SSL_CONN_CONFIG(verifypeer); const bool verifyhost = SSL_CONN_CONFIG(verifyhost); CURLcode ret; @@ -386,8 +390,11 @@ static CURLcode bearssl_connect_step1(struct connectdata *conn, int sockindex) */ #ifdef USE_NGHTTP2 - if(data->set.httpversion >= CURL_HTTP_VERSION_2 && - (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) { + if(data->set.httpversion >= CURL_HTTP_VERSION_2 +#ifndef CURL_DISABLE_PROXY + && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy) +#endif + ) { backend->protocols[cur++] = NGHTTP2_PROTO_VERSION_ID; infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); } diff --git a/Utilities/cmcurl/lib/vtls/gtls.c b/Utilities/cmcurl/lib/vtls/gtls.c index 9b4c365..16b0bd6 100644 --- a/Utilities/cmcurl/lib/vtls/gtls.c +++ b/Utilities/cmcurl/lib/vtls/gtls.c @@ -399,10 +399,15 @@ gtls_connect_step1(struct connectdata *conn, #endif const char *prioritylist; const char *err = NULL; +#ifndef CURL_DISABLE_PROXY const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name; long * const certverifyresult = SSL_IS_PROXY() ? &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult; +#else + const char * const hostname = conn->host.name; + long * const certverifyresult = &data->set.ssl.certverifyresult; +#endif if(connssl->state == ssl_connection_complete) /* to make us tolerant against being called more than once for the @@ -620,8 +625,11 @@ gtls_connect_step1(struct connectdata *conn, gnutls_datum_t protocols[2]; #ifdef USE_NGHTTP2 - if(data->set.httpversion >= CURL_HTTP_VERSION_2 && - (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) { + if(data->set.httpversion >= CURL_HTTP_VERSION_2 +#ifndef CURL_DISABLE_PROXY + && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy) +#endif + ) { protocols[cur].data = (unsigned char *)NGHTTP2_PROTO_VERSION_ID; protocols[cur].size = NGHTTP2_PROTO_VERSION_ID_LEN; cur++; @@ -694,12 +702,15 @@ gtls_connect_step1(struct connectdata *conn, } } +#ifndef CURL_DISABLE_PROXY if(conn->proxy_ssl[sockindex].use) { transport_ptr = conn->proxy_ssl[sockindex].backend->session; gnutls_transport_push = Curl_gtls_push_ssl; gnutls_transport_pull = Curl_gtls_pull_ssl; } - else { + else +#endif + { /* file descriptor for the socket */ transport_ptr = &conn->sock[sockindex]; gnutls_transport_push = Curl_gtls_push; @@ -828,10 +839,15 @@ gtls_connect_step3(struct connectdata *conn, unsigned int bits; gnutls_protocol_t version = gnutls_protocol_get_version(session); #endif +#ifndef CURL_DISABLE_PROXY const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name; long * const certverifyresult = SSL_IS_PROXY() ? &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult; +#else + const char * const hostname = conn->host.name; + long * const certverifyresult = &data->set.ssl.certverifyresult; +#endif /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */ ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session), @@ -1112,8 +1128,12 @@ gtls_connect_step3(struct connectdata *conn, } #endif if(!rc) { +#ifndef CURL_DISABLE_PROXY const char * const dispname = SSL_IS_PROXY() ? conn->http_proxy.host.dispname : conn->host.dispname; +#else + const char * const dispname = conn->host.dispname; +#endif if(SSL_CONN_CONFIG(verifyhost)) { failf(data, "SSL: certificate subject name (%s) does not match " @@ -1216,20 +1236,23 @@ gtls_connect_step3(struct connectdata *conn, rc = gnutls_x509_crt_get_dn2(x509_cert, &certfields); - if(rc != 0) - return CURLE_OUT_OF_MEMORY; - infof(data, "\t subject: %s\n", certfields.data); + if(rc) + infof(data, "Failed to get certificate name\n"); + else { + infof(data, "\t subject: %s\n", certfields.data); - certclock = gnutls_x509_crt_get_activation_time(x509_cert); - showtime(data, "start date", certclock); + certclock = gnutls_x509_crt_get_activation_time(x509_cert); + showtime(data, "start date", certclock); - certclock = gnutls_x509_crt_get_expiration_time(x509_cert); - showtime(data, "expire date", certclock); + certclock = gnutls_x509_crt_get_expiration_time(x509_cert); + showtime(data, "expire date", certclock); + } rc = gnutls_x509_crt_get_issuer_dn2(x509_cert, &certfields); - if(rc != 0) - return CURLE_OUT_OF_MEMORY; - infof(data, "\t issuer: %s\n", certfields.data); + if(rc) + infof(data, "Failed to get certificate issuer\n"); + else + infof(data, "\t issuer: %s\n", certfields.data); #endif gnutls_x509_crt_deinit(x509_cert); @@ -1381,10 +1404,13 @@ static bool Curl_gtls_data_pending(const struct connectdata *conn, 0 != gnutls_record_check_pending(backend->session)) res = TRUE; +#ifndef CURL_DISABLE_PROXY connssl = &conn->proxy_ssl[connindex]; + backend = connssl->backend; if(backend->session && 0 != gnutls_record_check_pending(backend->session)) res = TRUE; +#endif return res; } @@ -1433,7 +1459,9 @@ static void close_one(struct ssl_connect_data *connssl) static void Curl_gtls_close(struct connectdata *conn, int sockindex) { close_one(&conn->ssl[sockindex]); +#ifndef CURL_DISABLE_PROXY close_one(&conn->proxy_ssl[sockindex]); +#endif } /* diff --git a/Utilities/cmcurl/lib/vtls/nss.c b/Utilities/cmcurl/lib/vtls/nss.c index fca2926..0f0d1ee 100644 --- a/Utilities/cmcurl/lib/vtls/nss.c +++ b/Utilities/cmcurl/lib/vtls/nss.c @@ -1027,9 +1027,11 @@ static SECStatus BadCertHandler(void *arg, PRFileDesc *sock) CERTCertificate *cert; /* remember the cert verification result */ +#ifndef CURL_DISABLE_PROXY if(SSL_IS_PROXY()) data->set.proxy_ssl.certverifyresult = err; else +#endif data->set.ssl.certverifyresult = err; if(err == SSL_ERROR_BAD_CERT_DOMAIN && !SSL_CONN_CONFIG(verifyhost)) @@ -1553,24 +1555,32 @@ static void nss_close(struct ssl_connect_data *connssl) static void Curl_nss_close(struct connectdata *conn, int sockindex) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; +#ifndef CURL_DISABLE_PROXY struct ssl_connect_data *connssl_proxy = &conn->proxy_ssl[sockindex]; +#endif struct ssl_backend_data *backend = connssl->backend; - if(backend->handle || connssl_proxy->backend->handle) { + if(backend->handle +#ifndef CURL_DISABLE_PROXY + || connssl_proxy->backend->handle +#endif + ) { /* NSS closes the socket we previously handed to it, so we must mark it as closed to avoid double close */ fake_sclose(conn->sock[sockindex]); conn->sock[sockindex] = CURL_SOCKET_BAD; } +#ifndef CURL_DISABLE_PROXY if(backend->handle) /* nss_close(connssl) will transitively close also connssl_proxy->backend->handle if both are used. Clear it to avoid a double close leading to crash. */ connssl_proxy->backend->handle = NULL; - nss_close(connssl); nss_close(connssl_proxy); +#endif + nss_close(connssl); } /* return true if NSS can provide error code (and possibly msg) for the @@ -1828,6 +1838,12 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) CURLcode result; bool second_layer = FALSE; SSLVersionRange sslver_supported; +#ifndef CURL_DISABLE_PROXY + const char *hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; +#else + const char *hostname = conn->host.name; +#endif SSLVersionRange sslver = { SSL_LIBRARY_VERSION_TLS_1_0, /* min */ @@ -1932,9 +1948,11 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) goto error; /* not checked yet */ +#ifndef CURL_DISABLE_PROXY if(SSL_IS_PROXY()) data->set.proxy_ssl.certverifyresult = 0; else +#endif data->set.ssl.certverifyresult = 0; if(SSL_BadCertHook(model, BadCertHandler, conn) != SECSuccess) @@ -1991,12 +2009,14 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) goto error; } +#ifndef CURL_DISABLE_PROXY if(conn->proxy_ssl[sockindex].use) { DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state); DEBUGASSERT(conn->proxy_ssl[sockindex].backend->handle != NULL); nspr_io = conn->proxy_ssl[sockindex].backend->handle; second_layer = TRUE; } +#endif else { /* wrap OS file descriptor by NSPR's file descriptor abstraction */ nspr_io = PR_ImportTCPSocket(sockfd); @@ -2077,8 +2097,11 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) unsigned char protocols[128]; #ifdef USE_NGHTTP2 - if(data->set.httpversion >= CURL_HTTP_VERSION_2 && - (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) { + if(data->set.httpversion >= CURL_HTTP_VERSION_2 +#ifndef CURL_DISABLE_PROXY + && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy) +#endif + ) { protocols[cur++] = NGHTTP2_PROTO_VERSION_ID_LEN; memcpy(&protocols[cur], NGHTTP2_PROTO_VERSION_ID, NGHTTP2_PROTO_VERSION_ID_LEN); @@ -2101,14 +2124,11 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) goto error; /* propagate hostname to the TLS layer */ - if(SSL_SetURL(backend->handle, SSL_IS_PROXY() ? conn->http_proxy.host.name : - conn->host.name) != SECSuccess) + if(SSL_SetURL(backend->handle, hostname) != SECSuccess) goto error; /* prevent NSS from re-using the session for a different hostname */ - if(SSL_SetSockPeerID(backend->handle, SSL_IS_PROXY() ? - conn->http_proxy.host.name : conn->host.name) - != SECSuccess) + if(SSL_SetSockPeerID(backend->handle, hostname) != SECSuccess) goto error; return CURLE_OK; @@ -2127,11 +2147,17 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex) struct Curl_easy *data = conn->data; CURLcode result = CURLE_SSL_CONNECT_ERROR; PRUint32 timeout; +#ifndef CURL_DISABLE_PROXY long * const certverifyresult = SSL_IS_PROXY() ? &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult; const char * const pinnedpubkey = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; +#else + long * const certverifyresult = &data->set.ssl.certverifyresult; + const char * const pinnedpubkey = + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; +#endif /* check timeout situation */ diff --git a/Utilities/cmcurl/lib/vtls/openssl.c b/Utilities/cmcurl/lib/vtls/openssl.c index 2e9f900..1685a4a 100644 --- a/Utilities/cmcurl/lib/vtls/openssl.c +++ b/Utilities/cmcurl/lib/vtls/openssl.c @@ -619,7 +619,9 @@ SSL_CTX_use_certificate_chain_bio(SSL_CTX *ctx, BIO* in, const char *key_passwd) { /* SSL_CTX_add1_chain_cert introduced in OpenSSL 1.0.2 */ -#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) /* 1.0.2 or later */ +#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && /* OpenSSL 1.0.2 or later */ \ + !(defined(LIBRESSL_VERSION_NUMBER) && \ + (LIBRESSL_VERSION_NUMBER < 0x2090100fL)) /* LibreSSL 2.9.1 or later */ int ret = 0; X509 *x = NULL; void *passwd_callback_userdata = (void *)key_passwd; @@ -2825,7 +2827,8 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) if((SSL_CONN_CONFIG(verifypeer) || SSL_CONN_CONFIG(verifyhost)) && (SSL_SET_OPTION(native_ca_store))) { X509_STORE *store = SSL_CTX_get_cert_store(backend->ctx); - HCERTSTORE hStore = CertOpenSystemStoreA((HCRYPTPROV_LEGACY)NULL, "ROOT"); + HCERTSTORE hStore = CertOpenSystemStore((HCRYPTPROV_LEGACY)NULL, + TEXT("ROOT")); if(hStore) { PCCERT_CONTEXT pContext = NULL; diff --git a/Utilities/cmcurl/lib/vtls/schannel.c b/Utilities/cmcurl/lib/vtls/schannel.c index 1996526..1c1432d 100644 --- a/Utilities/cmcurl/lib/vtls/schannel.c +++ b/Utilities/cmcurl/lib/vtls/schannel.c @@ -50,7 +50,7 @@ #include "x509asn1.h" #include "curl_printf.h" #include "multiif.h" -#include "system_win32.h" +#include "version_win32.h" /* The last #include file should be: */ #include "curl_memory.h" @@ -436,8 +436,8 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) "schannel: SSL/TLS connection with %s port %hu (step 1/3)\n", hostname, conn->remote_port)); - if(Curl_verify_windows_version(5, 1, PLATFORM_WINNT, - VERSION_LESS_THAN_EQUAL)) { + if(curlx_verify_windows_version(5, 1, PLATFORM_WINNT, + VERSION_LESS_THAN_EQUAL)) { /* Schannel in Windows XP (OS version 5.1) uses legacy handshakes and algorithms that may not be supported by all servers. */ infof(data, "schannel: Windows version is old and may not be able to " @@ -448,10 +448,10 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) /* ALPN is only supported on Windows 8.1 / Server 2012 R2 and above. Also it doesn't seem to be supported for Wine, see curl bug #983. */ BACKEND->use_alpn = conn->bits.tls_enable_alpn && - !GetProcAddress(GetModuleHandleA("ntdll"), + !GetProcAddress(GetModuleHandle(TEXT("ntdll")), "wine_get_version") && - Curl_verify_windows_version(6, 3, PLATFORM_WINNT, - VERSION_GREATER_THAN_EQUAL); + curlx_verify_windows_version(6, 3, PLATFORM_WINNT, + VERSION_GREATER_THAN_EQUAL); #else BACKEND->use_alpn = false; #endif @@ -467,8 +467,8 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) #else #ifdef HAS_MANUAL_VERIFY_API if(SSL_CONN_CONFIG(CAfile)) { - if(Curl_verify_windows_version(6, 1, PLATFORM_WINNT, - VERSION_GREATER_THAN_EQUAL)) { + if(curlx_verify_windows_version(6, 1, PLATFORM_WINNT, + VERSION_GREATER_THAN_EQUAL)) { BACKEND->use_manual_cred_validation = true; } else { @@ -2015,8 +2015,8 @@ schannel_recv(struct connectdata *conn, int sockindex, */ if(len && !BACKEND->decdata_offset && BACKEND->recv_connection_closed && !BACKEND->recv_sspi_close_notify) { - bool isWin2k = Curl_verify_windows_version(5, 0, PLATFORM_WINNT, - VERSION_EQUAL); + bool isWin2k = curlx_verify_windows_version(5, 0, PLATFORM_WINNT, + VERSION_EQUAL); if(isWin2k && sspi_status == SEC_E_OK) BACKEND->recv_sspi_close_notify = true; diff --git a/Utilities/cmcurl/lib/vtls/schannel_verify.c b/Utilities/cmcurl/lib/vtls/schannel_verify.c index bdd7199..ab7be39 100644 --- a/Utilities/cmcurl/lib/vtls/schannel_verify.c +++ b/Utilities/cmcurl/lib/vtls/schannel_verify.c @@ -45,7 +45,7 @@ #include "curl_multibyte.h" #include "curl_printf.h" #include "hostcheck.h" -#include "system_win32.h" +#include "version_win32.h" /* The last #include file should be: */ #include "curl_memory.h" @@ -317,8 +317,8 @@ static DWORD cert_get_name_string(struct Curl_easy *data, DWORD i; /* CERT_NAME_SEARCH_ALL_NAMES_FLAG is available from Windows 8 onwards. */ - if(Curl_verify_windows_version(6, 2, PLATFORM_WINNT, - VERSION_GREATER_THAN_EQUAL)) { + if(curlx_verify_windows_version(6, 2, PLATFORM_WINNT, + VERSION_GREATER_THAN_EQUAL)) { #ifdef CERT_NAME_SEARCH_ALL_NAMES_FLAG /* CertGetNameString will provide the 8-bit character string without * any decoding */ @@ -564,7 +564,7 @@ CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex) * trusted certificates. This is only supported on Windows 7+. */ - if(Curl_verify_windows_version(6, 1, PLATFORM_WINNT, VERSION_LESS_THAN)) { + if(curlx_verify_windows_version(6, 1, PLATFORM_WINNT, VERSION_LESS_THAN)) { failf(data, "schannel: this version of Windows is too old to support " "certificate verification via CA bundle file."); result = CURLE_SSL_CACERT_BADFILE; diff --git a/Utilities/cmcurl/lib/vtls/vtls.c b/Utilities/cmcurl/lib/vtls/vtls.c index c3a55fb..281043a 100644 --- a/Utilities/cmcurl/lib/vtls/vtls.c +++ b/Utilities/cmcurl/lib/vtls/vtls.c @@ -621,6 +621,7 @@ void Curl_ssl_close(struct connectdata *conn, int sockindex) { DEBUGASSERT((sockindex <= 1) && (sockindex >= -1)); Curl_ssl->close_one(conn, sockindex); + conn->ssl[sockindex].state = ssl_connection_none; } CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex) |